]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #91356 - GuillaumeGomez:improve-rustdoc-layout, r=jsha
authorbors <bors@rust-lang.org>
Sun, 5 Dec 2021 18:35:43 +0000 (18:35 +0000)
committerbors <bors@rust-lang.org>
Sun, 5 Dec 2021 18:35:43 +0000 (18:35 +0000)
Improve rustdoc layout

This is an overtake of https://github.com/rust-lang/rust/pull/89385 originally written by `@cynecx.`

I kept the original commit and simply added the missing fixes into a new one. You can test it online [here](https://rustdoc.crud.net/imperio/improve-rustdoc-layout/std/index.html).

r? `@jsha`

706 files changed:
Cargo.lock
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/asm.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/path.rs
compiler/rustc_ast_pretty/src/pprust/mod.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_borrowck/src/dataflow.rs
compiler/rustc_borrowck/src/def_use.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/invalidation.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_borrowck/src/type_check/input_output.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/cfg_eval.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_cranelift/scripts/cargo.rs
compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_gcc/src/abi.rs
compiler/rustc_codegen_gcc/src/asm.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs
compiler/rustc_codegen_ssa/src/mir/analyze.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/traits/asm.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/lib.rs
compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
compiler/rustc_const_eval/src/transform/check_consts/resolver.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_data_structures/src/lib.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/mbe/macro_rules.rs
compiler/rustc_expand/src/parse/tests.rs
compiler/rustc_expand/src/placeholders.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/fudge.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/resolve.rs
compiler/rustc_infer/src/lib.rs
compiler/rustc_infer/src/traits/structural_impls.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lexer/src/cursor.rs
compiler/rustc_lexer/src/lib.rs
compiler/rustc_lint/src/array_into_iter.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
compiler/rustc_lint/src/levels.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/traits.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/terminator.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/ty/adt.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/diagnostics.rs
compiler/rustc_middle/src/ty/erase_regions.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/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/build/expr/into.rs
compiler/rustc_mir_build/src/build/scope.rs
compiler/rustc_mir_dataflow/src/framework/direction.rs
compiler/rustc_mir_dataflow/src/framework/graphviz.rs
compiler/rustc_mir_dataflow/src/framework/mod.rs
compiler/rustc_mir_dataflow/src/framework/tests.rs
compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
compiler/rustc_mir_dataflow/src/impls/init_locals.rs
compiler/rustc_mir_dataflow/src/impls/liveness.rs
compiler/rustc_mir_dataflow/src/impls/mod.rs
compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
compiler/rustc_mir_dataflow/src/lib.rs
compiler/rustc_mir_dataflow/src/move_paths/builder.rs
compiler/rustc_mir_dataflow/src/rustc_peek.rs
compiler/rustc_mir_transform/src/add_retag.rs
compiler/rustc_mir_transform/src/check_const_item_mutation.rs
compiler/rustc_mir_transform/src/check_packed_ref.rs
compiler/rustc_mir_transform/src/check_unsafety.rs
compiler/rustc_mir_transform/src/const_debuginfo.rs
compiler/rustc_mir_transform/src/const_goto.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/coverage/mod.rs
compiler/rustc_mir_transform/src/deduplicate_blocks.rs
compiler/rustc_mir_transform/src/dest_prop.rs
compiler/rustc_mir_transform/src/early_otherwise_branch.rs
compiler/rustc_mir_transform/src/elaborate_drops.rs
compiler/rustc_mir_transform/src/function_item_references.rs
compiler/rustc_mir_transform/src/generator.rs
compiler/rustc_mir_transform/src/inline.rs
compiler/rustc_mir_transform/src/instcombine.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/lower_slice_len.rs
compiler/rustc_mir_transform/src/marker.rs [new file with mode: 0644]
compiler/rustc_mir_transform/src/match_branches.rs
compiler/rustc_mir_transform/src/multiple_return_terminators.rs
compiler/rustc_mir_transform/src/normalize_array_len.rs
compiler/rustc_mir_transform/src/nrvo.rs
compiler/rustc_mir_transform/src/pass_manager.rs [new file with mode: 0644]
compiler/rustc_mir_transform/src/remove_false_edges.rs [new file with mode: 0644]
compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
compiler/rustc_mir_transform/src/remove_storage_markers.rs
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/remove_zsts.rs
compiler/rustc_mir_transform/src/reveal_all.rs
compiler/rustc_mir_transform/src/separate_const_switch.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_mir_transform/src/simplify.rs
compiler/rustc_mir_transform/src/simplify_branches.rs
compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
compiler/rustc_mir_transform/src/unreachable_prop.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_passes/src/check_attr.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_query_system/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/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/filesearch.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_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/lib.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_trait_selection/src/lib.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_traits/src/chalk/db.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/chalk/mod.rs
compiler/rustc_traits/src/lib.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/astconv/mod.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/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/writeback.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/collect/type_of.rs
compiler/rustc_typeck/src/hir_wf_check.rs
compiler/rustc_typeck/src/lib.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/lib.rs
library/alloc/src/raw_vec.rs
library/alloc/src/vec/mod.rs
library/core/src/any.rs
library/core/src/array/iter.rs
library/core/src/array/mod.rs
library/core/src/future/future.rs
library/core/src/future/into_future.rs
library/core/src/intrinsics.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/mem/maybe_uninit.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/primitive_docs.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/time.rs
library/core/tests/array.rs
library/core/tests/iter/adapters/flatten.rs
library/core/tests/iter/traits/iterator.rs
library/core/tests/lib.rs
library/core/tests/slice.rs
library/std/Cargo.toml
library/std/src/collections/hash/map.rs
library/std/src/collections/hash/set.rs
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/primitive_docs.rs
library/std/src/sys/unix/os.rs
library/std/src/thread/local.rs
library/std/src/thread/mod.rs
library/unwind/build.rs
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/doc/unstable-book/src/compiler-flags/instrument-coverage.md
src/doc/unstable-book/src/library-features/asm.md
src/etc/htmldocck.py
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/templates/page.html
src/librustdoc/lib.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/asm-may_unwind.rs [new file with mode: 0644]
src/test/codegen/auxiliary/thread_local_aux.rs
src/test/codegen/sparc-struct-abi.rs
src/test/codegen/thread-local.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/early_otherwise_branch_noopt.rs
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/pretty/ast-stmt-expr-attr.rs
src/test/pretty/attr-derive.rs
src/test/pretty/auto-trait.rs
src/test/pretty/block-comment-trailing-whitespace2.rs
src/test/pretty/closure-reform-pretty.rs
src/test/pretty/disamb-stmt-expr.rs
src/test/pretty/enum-variant-vis.rs
src/test/pretty/example1.rs
src/test/pretty/example2.pp
src/test/pretty/example2.rs
src/test/pretty/expanded-and-path-remap-80832.pp
src/test/pretty/fn-return.rs
src/test/pretty/fn-types.rs
src/test/pretty/fn-variadic.rs
src/test/pretty/if-attr.rs
src/test/pretty/issue-12590-a.rs
src/test/pretty/issue-12590-c.pp
src/test/pretty/issue-12590-c.rs
src/test/pretty/issue-19077.rs
src/test/pretty/issue-30731.rs
src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs
src/test/pretty/lifetime.rs
src/test/pretty/macro.rs
src/test/pretty/macro_rules.rs
src/test/pretty/nested-item-vis-defaultness.rs
src/test/pretty/path-type-bounds.rs
src/test/pretty/qpath-associated-type-bound.rs
src/test/pretty/stmt_expr_attributes.rs
src/test/pretty/tag-blank-lines.rs
src/test/pretty/trait-inner-attr.rs
src/test/pretty/trait-polarity.rs
src/test/pretty/trait-safety.rs
src/test/pretty/where-clauses.rs
src/test/run-make-fulldeps/coverage-llvmir/Makefile
src/test/run-make-fulldeps/coverage-reports/Makefile
src/test/rustdoc-js/summaries.rs
src/test/rustdoc-ui/auxiliary/overflow.rs [new file with mode: 0644]
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/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/mixing-doc-comments-and-attrs.S1_top-doc.html [new file with mode: 0644]
src/test/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html [new file with mode: 0644]
src/test/rustdoc/mixing-doc-comments-and-attrs.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/titles.rs
src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
src/test/ui/asm/aarch64/bad-options.stderr
src/test/ui/asm/aarch64/may_unwind.rs [new file with mode: 0644]
src/test/ui/asm/aarch64/parse-error.stderr
src/test/ui/asm/may_unwind.rs [new file with mode: 0644]
src/test/ui/asm/x86_64/bad-options.stderr
src/test/ui/asm/x86_64/may_unwind.rs [new file with mode: 0644]
src/test/ui/asm/x86_64/parse-error.stderr
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-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-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/issue-70594.stderr
src/test/ui/async-await/issues/issue-60674.stdout
src/test/ui/async-await/issues/issue-62009-1.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.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/cast/issue-88621.rs [new file with mode: 0644]
src/test/ui/cast/issue-88621.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
src/test/ui/const-generics/generic_const_exprs/closures.stderr
src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs
src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-83249.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-83249.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-83288.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-87470.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-87964.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-89146.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-89320.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-90455.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-90455.stderr [new file with mode: 0644]
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/drop_zst.rs [new file with mode: 0644]
src/test/ui/consts/drop_zst.stderr [new file with mode: 0644]
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/derives/issue-36617.rs
src/test/ui/derives/issue-36617.stderr
src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
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/feature-gates/feature-gate-asm_unwind.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_unwind.stderr [new file with mode: 0644]
src/test/ui/feature-gates/issue-43106-gating-of-bench.rs
src/test/ui/feature-gates/issue-43106-gating-of-bench.stderr
src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
src/test/ui/feature-gates/issue-43106-gating-of-test.rs
src/test/ui/feature-gates/issue-43106-gating-of-test.stderr
src/test/ui/feature-gates/thread-local-const-init.rs [deleted file]
src/test/ui/feature-gates/thread-local-const-init.stderr [deleted file]
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/generator/issue-91477.rs [new file with mode: 0644]
src/test/ui/generator/issue-91477.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87748.rs [deleted file]
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/hygiene/unpretty-debug.stdout
src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
src/test/ui/imports/issue-28134.rs
src/test/ui/imports/issue-28134.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/issues-71798.stderr
src/test/ui/issues/issue-37131.stderr
src/test/ui/issues/issue-38821.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-50480.rs
src/test/ui/issues/issue-50480.stderr
src/test/ui/issues/issue-88150.rs [new file with mode: 0644]
src/test/ui/keyword/keyword-self-as-type-param.rs
src/test/ui/keyword/keyword-self-as-type-param.stderr
src/test/ui/lifetimes/issue-76168-hr-outlives.rs [new file with mode: 0644]
src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
src/test/ui/lint/force-warn/allowed-by-default-lint.stderr
src/test/ui/lint/future-incompat-test.rs
src/test/ui/lint/issue-87308.stdout
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/macros/macro-pat-pattern-followed-by-or-in-2021.stderr
src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr
src/test/ui/macros/nonterminal-matching.rs
src/test/ui/macros/nonterminal-matching.stderr
src/test/ui/numeric/numeric-cast.stderr
src/test/ui/optimization-remark.rs
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/proc-macro/allowed-attr-stmt-expr.stdout
src/test/ui/proc-macro/attr-complex-fn.stdout
src/test/ui/proc-macro/attr-stmt-expr.stdout
src/test/ui/proc-macro/attribute-after-derive.stdout
src/test/ui/proc-macro/auxiliary/attr-args.rs
src/test/ui/proc-macro/auxiliary/attr-on-trait.rs
src/test/ui/proc-macro/auxiliary/custom-quote.rs
src/test/ui/proc-macro/cfg-eval-inner.stdout
src/test/ui/proc-macro/crate-attrs-multiple.rs [new file with mode: 0644]
src/test/ui/proc-macro/derive-expand-order.stdout
src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
src/test/ui/proc-macro/inner-attrs.stdout
src/test/ui/proc-macro/input-interpolated.stdout
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/proc-macro/issue-75734-pp-paren.stdout
src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
src/test/ui/proc-macro/issue-81007-item-attrs.stdout
src/test/ui/proc-macro/nested-macro-rules.stdout
src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
src/test/ui/proc-macro/trailing-plus.stdout
src/test/ui/proc-macro/weird-braces.stdout
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/repr/issue-83921-pretty.pretty.stdout
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-2497-if-let-chains/ast-pretty-check.stdout
src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs
src/test/ui/rust-2018/uniform-paths/deadlock.rs
src/test/ui/rust-2018/uniform-paths/deadlock.stderr
src/test/ui/span/issue-43927-non-ADT-derive.rs
src/test/ui/span/issue-43927-non-ADT-derive.stderr
src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/suggestions/derive-macro-missing-bounds.rs [new file with mode: 0644]
src/test/ui/suggestions/derive-macro-missing-bounds.stderr [new file with mode: 0644]
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/type/issue-91268.rs [new file with mode: 0644]
src/test/ui/type/issue-91268.stderr [new file with mode: 0644]
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/typeck/issue-91450-inner-ty-error.rs [new file with mode: 0644]
src/test/ui/typeck/issue-91450-inner-ty-error.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/tools/cargo
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/matches.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/redundant_clone.rs
src/tools/clippy/clippy_lints/src/self_named_constructors.rs
src/tools/clippy/clippy_lints/src/unused_self.rs
src/tools/compiletest/src/runtest.rs
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]

index b2536c5cda11977b626e6b58dfd4dcc026f0f942..2233162be3b6b464749f9d474f7d189064dbcd10 100644 (file)
@@ -678,9 +678,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.53"
+version = "0.1.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2467ff455350a4df7d02f1ed1449d0279605a763de5d586dcf6aa7d732508bcb"
+checksum = "c9ac60765140c97aaf531dae151a287646b0805ec725805da9e2a3ee31cd501c"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
index 55b243a84a9a342768b8387294b050bcbe85b003..03b957adeda9d36a748908846eac282a5d3b2f59 100644 (file)
@@ -517,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.
@@ -1979,7 +1981,7 @@ pub enum InlineAsmRegOrRegClass {
 
 bitflags::bitflags! {
     #[derive(Encodable, Decodable, HashStable_Generic)]
-    pub struct InlineAsmOptions: u8 {
+    pub struct InlineAsmOptions: u16 {
         const PURE = 1 << 0;
         const NOMEM = 1 << 1;
         const READONLY = 1 << 2;
@@ -1988,6 +1990,7 @@ pub struct InlineAsmOptions: u8 {
         const NOSTACK = 1 << 5;
         const ATT_SYNTAX = 1 << 6;
         const RAW = 1 << 7;
+        const MAY_UNWIND = 1 << 8;
     }
 }
 
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 cfa97ff84ec498910e0e1a9fea3dd8e716967274..9f27ace25ab4b442aade416279123f6db49939d6 100644 (file)
@@ -49,6 +49,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
                 .emit();
         }
+        if asm.options.contains(InlineAsmOptions::MAY_UNWIND)
+            && !self.sess.features_untracked().asm_unwind
+        {
+            feature_err(
+                &self.sess.parse_sess,
+                sym::asm_unwind,
+                sp,
+                "the `may_unwind` option is unstable",
+            )
+            .emit();
+        }
 
         let mut clobber_abis = FxHashMap::default();
         if let Some(asm_arch) = asm_arch {
index 9c579209fe51c448d952952c7888388279191670..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(
index 2b3a538772ecbc62d57ae5cea8eb7e34665a9e46..d0fbc2d0f11d48db3227db024e3299f2ceb41eee 100644 (file)
 use tracing::{debug, trace};
 
 macro_rules! arena_vec {
-    ($this:expr; $($x:expr),*) => ({
-        let a = [$($x),*];
-        $this.arena.alloc_from_iter(std::array::IntoIter::new(a))
-    });
+    ($this:expr; $($x:expr),*) => (
+        $this.arena.alloc_from_iter([$($x),*])
+    );
 }
 
 mod asm;
@@ -162,6 +161,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 +320,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 +1787,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 +1928,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 +2291,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 +2323,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 +2344,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 +2387,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 +2538,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 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 f1f2387866d0d3d71afbcc6807919d9df11ec6a5..593dca1b405d85f0df8a77bbcff4eb2756eb7836 100644 (file)
@@ -263,14 +263,17 @@ fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F)
         self.strsep(",", false, b, elts, op)
     }
 
-    fn maybe_print_comment(&mut self, pos: BytePos) {
+    fn maybe_print_comment(&mut self, pos: BytePos) -> bool {
+        let mut has_comment = false;
         while let Some(ref cmnt) = self.next_comment() {
             if cmnt.pos < pos {
+                has_comment = true;
                 self.print_comment(cmnt);
             } else {
                 break;
             }
         }
+        has_comment
     }
 
     fn print_comment(&mut self, cmnt: &Comment) {
@@ -570,7 +573,10 @@ fn print_mac_common(
         self.print_tts(tts, convert_dollar_crate);
         self.end();
         match delim {
-            DelimToken::Brace => self.bclose(span),
+            DelimToken::Brace => {
+                let empty = tts.is_empty();
+                self.bclose(span, empty);
+            }
             _ => {
                 let token_str = self.token_kind_to_string(&token::CloseDelim(delim));
                 self.word(token_str)
@@ -642,17 +648,20 @@ fn bopen(&mut self) {
         self.end(); // Close the head-box.
     }
 
-    fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
-        self.maybe_print_comment(span.hi());
-        self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
+    fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) {
+        let has_comment = self.maybe_print_comment(span.hi());
+        if !empty || has_comment {
+            self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
+        }
         self.word("}");
         if close_box {
             self.end(); // Close the outer-box.
         }
     }
 
-    fn bclose(&mut self, span: rustc_span::Span) {
-        self.bclose_maybe_open(span, true)
+    fn bclose(&mut self, span: rustc_span::Span, empty: bool) {
+        let close_box = true;
+        self.bclose_maybe_open(span, empty, close_box)
     }
 
     fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
@@ -1196,7 +1205,8 @@ fn print_associated_type(
                         for item in items {
                             self.print_item(item);
                         }
-                        self.bclose(item.span);
+                        let empty = item.attrs.is_empty() && items.is_empty();
+                        self.bclose(item.span, empty);
                     }
                     ModKind::Unloaded => {
                         self.s.word(";");
@@ -1216,7 +1226,8 @@ fn print_associated_type(
                 }
                 self.bopen();
                 self.print_foreign_mod(nmod, &item.attrs);
-                self.bclose(item.span);
+                let empty = item.attrs.is_empty() && nmod.items.is_empty();
+                self.bclose(item.span, empty);
             }
             ast::ItemKind::GlobalAsm(ref asm) => {
                 self.head(visibility_qualified(&item.vis, "global_asm!"));
@@ -1291,7 +1302,8 @@ fn print_associated_type(
                 for impl_item in items {
                     self.print_assoc_item(impl_item);
                 }
-                self.bclose(item.span);
+                let empty = item.attrs.is_empty() && items.is_empty();
+                self.bclose(item.span, empty);
             }
             ast::ItemKind::Trait(box ast::Trait {
                 is_auto,
@@ -1326,7 +1338,8 @@ fn print_associated_type(
                 for trait_item in items {
                     self.print_assoc_item(trait_item);
                 }
-                self.bclose(item.span);
+                let empty = item.attrs.is_empty() && items.is_empty();
+                self.bclose(item.span, empty);
             }
             ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
                 self.head("");
@@ -1410,7 +1423,8 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
             self.end();
             self.maybe_print_trailing_comment(v.span, None);
         }
-        self.bclose(span)
+        let empty = variants.is_empty();
+        self.bclose(span, empty)
     }
 
     crate fn print_visibility(&mut self, vis: &ast::Visibility) {
@@ -1441,20 +1455,24 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
     crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
         self.nbsp();
         self.bopen();
-        self.hardbreak_if_not_bol();
 
-        for field in fields {
+        let empty = fields.is_empty();
+        if !empty {
             self.hardbreak_if_not_bol();
-            self.maybe_print_comment(field.span.lo());
-            self.print_outer_attributes(&field.attrs);
-            self.print_visibility(&field.vis);
-            self.print_ident(field.ident.unwrap());
-            self.word_nbsp(":");
-            self.print_type(&field.ty);
-            self.s.word(",");
+
+            for field in fields {
+                self.hardbreak_if_not_bol();
+                self.maybe_print_comment(field.span.lo());
+                self.print_outer_attributes(&field.attrs);
+                self.print_visibility(&field.vis);
+                self.print_ident(field.ident.unwrap());
+                self.word_nbsp(":");
+                self.print_type(&field.ty);
+                self.s.word(",");
+            }
         }
 
-        self.bclose(span)
+        self.bclose(span, empty);
     }
 
     crate fn print_struct(
@@ -1633,7 +1651,8 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
             }
         }
 
-        self.bclose_maybe_open(blk.span, close_box);
+        let empty = attrs.is_empty() && blk.stmts.is_empty();
+        self.bclose_maybe_open(blk.span, empty, close_box);
         self.ann.post(self, AnnNode::Block(blk))
     }
 
@@ -2010,7 +2029,8 @@ fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
                 for arm in arms {
                     self.print_arm(arm);
                 }
-                self.bclose(expr.span);
+                let empty = attrs.is_empty() && arms.is_empty();
+                self.bclose(expr.span, empty);
             }
             ast::ExprKind::Closure(
                 capture_clause,
@@ -2338,6 +2358,9 @@ enum AsmArg<'a> {
                 if opts.contains(InlineAsmOptions::RAW) {
                     options.push("raw");
                 }
+                if opts.contains(InlineAsmOptions::MAY_UNWIND) {
+                    options.push("may_unwind");
+                }
                 s.commasep(Inconsistent, &options, |s, &opt| {
                     s.word(opt);
                 });
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 7db8d4520d406def6cad28a596f682e62fb70f0d..15372ec1534fe164fb6d9f162a27e46c7eada66c 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
 use rustc_mir_dataflow::ResultsVisitable;
-use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
+use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill};
 use rustc_mir_dataflow::{Analysis, Direction, Results};
 use std::fmt;
 use std::iter;
@@ -434,9 +434,7 @@ fn call_return_effect(
         &self,
         _trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        _dest_place: mir::Place<'tcx>,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
     }
 }
index 689ec249a2fb4f5c708fc3ffa1e244483a3fe97c..70acbc9ee2dbc4024fd77bd4504ca8ef3ea0a1b7 100644 (file)
@@ -17,7 +17,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::MutatingUse(MutatingUseContext::Store) |
 
         // This is potentially both a def and a use...
-        PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
+        PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput) |
 
         // We let Call define the result in both the success and
         // unwind cases. This is not really correct, however it
@@ -26,6 +26,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         // the def in call only to the input from the success
         // path and not the unwind path. -nmatsakis
         PlaceContext::MutatingUse(MutatingUseContext::Call) |
+        PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
         PlaceContext::MutatingUse(MutatingUseContext::Yield) |
 
         // Storage live and storage dead aren't proper defines, but we can ignore
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 a0f8aabbe0e72351b8d34471f3266a572a6191ca..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));
 
@@ -763,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 efd34f4e0a58e38b6098f47333c0a22165ce2599..c03e4d8a448900996b3091e97993b474fc431fef 100644 (file)
@@ -199,6 +199,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 options: _,
                 line_spans: _,
                 destination: _,
+                cleanup: _,
             } => {
                 for op in operands {
                     match *op {
index 76d3a83b48daa45d7a4da26c3b847ef5ccbdd0d1..88fab269109f998973e76b89829c4155119b89bb 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)]
@@ -792,6 +791,7 @@ fn visit_terminator_before_primary_effect(
                 options: _,
                 line_spans: _,
                 destination: _,
+                cleanup: _,
             } => {
                 for op in operands {
                     match *op {
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 92d2d04f23f239e87873a2dd5f7e73f2cd573a17..bc740de5150659cc48f1954c0a17b8036fec98a9 100644 (file)
@@ -117,9 +117,29 @@ pub(super) fn equate_inputs_and_outputs(
             }
         }
 
-        assert!(body.yield_ty().is_some() == universal_regions.yield_ty.is_some());
-        if let Some(mir_yield_ty) = body.yield_ty() {
-            let ur_yield_ty = universal_regions.yield_ty.unwrap();
+        debug!(
+            "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
+            body.yield_ty(),
+            universal_regions.yield_ty
+        );
+
+        // We will not have a universal_regions.yield_ty if we yield (by accident)
+        // outside of a generator and return an `impl Trait`, so emit a delay_span_bug
+        // because we don't want to panic in an assert here if we've already got errors.
+        if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
+            self.tcx().sess.delay_span_bug(
+                body.span,
+                &format!(
+                    "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
+                    body.yield_ty(),
+                    universal_regions.yield_ty,
+                ),
+            );
+        }
+
+        if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
+            (body.yield_ty(), universal_regions.yield_ty)
+        {
             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
         }
index da26d9c7b87790e85e784cf889e28fc92796f187..6a263bd63ada8c63f99e7e81ec43b8cd72b1a139 100644 (file)
@@ -1828,10 +1828,16 @@ fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tc
                     self.assert_iscleanup(body, block_data, unwind, true);
                 }
             }
-            TerminatorKind::InlineAsm { destination, .. } => {
+            TerminatorKind::InlineAsm { destination, cleanup, .. } => {
                 if let Some(target) = destination {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
+                if let Some(cleanup) = cleanup {
+                    if is_cleanup {
+                        span_mirbug!(self, block_data, "cleanup on cleanup block")
+                    }
+                    self.assert_iscleanup(body, block_data, cleanup, true);
+                }
             }
         }
     }
index 41662f46f115296e821e0a932a1601ceee4bf42d..b374769cbea250baf8caf109ef3ffdb95c292d14 100644 (file)
@@ -420,6 +420,8 @@ fn parse_options<'a>(
             try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
         } else if p.eat_keyword(kw::Raw) {
             try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
+        } else if p.eat_keyword(sym::may_unwind) {
+            try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND);
         } else {
             return p.unexpected();
         }
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 994a74a5a9b9f939190f50b3bcfa5184b3f9f4bb..1427a2aada3fc485d77d326b6c9ad25391dd9d74 100644 (file)
@@ -567,8 +567,11 @@ fn create_derived_impl(
             })
         });
 
-        let Generics { mut params, mut where_clause, span } =
+        let Generics { mut params, mut where_clause, .. } =
             self.generics.to_generics(cx, self.span, type_ident, generics);
+        where_clause.span = generics.where_clause.span;
+        let ctxt = self.span.ctxt();
+        let span = generics.span.with_ctxt(ctxt);
 
         // Create the generic parameters
         params.extend(generics.params.iter().map(|param| match &param.kind {
@@ -589,12 +592,12 @@ fn create_derived_impl(
                         param.bounds.iter().cloned()
                     ).collect();
 
-                cx.typaram(self.span, param.ident, vec![], bounds, None)
+                cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, vec![], bounds, None)
             }
             GenericParamKind::Const { ty, kw_span, .. } => {
                 let const_nodefault_kind = GenericParamKind::Const {
                     ty: ty.clone(),
-                    kw_span: *kw_span,
+                    kw_span: kw_span.with_ctxt(ctxt),
 
                     // We can't have default values inside impl block
                     default: None,
@@ -607,28 +610,27 @@ fn create_derived_impl(
 
         // and similarly for where clauses
         where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
-            match *clause {
-                ast::WherePredicate::BoundPredicate(ref wb) => {
+            match clause {
+                ast::WherePredicate::BoundPredicate(wb) => {
+                    let span = wb.span.with_ctxt(ctxt);
                     ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
-                        span: self.span,
-                        bound_generic_params: wb.bound_generic_params.clone(),
-                        bounded_ty: wb.bounded_ty.clone(),
-                        bounds: wb.bounds.to_vec(),
+                        span,
+                        ..wb.clone()
                     })
                 }
-                ast::WherePredicate::RegionPredicate(ref rb) => {
+                ast::WherePredicate::RegionPredicate(wr) => {
+                    let span = wr.span.with_ctxt(ctxt);
                     ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
-                        span: self.span,
-                        lifetime: rb.lifetime,
-                        bounds: rb.bounds.to_vec(),
+                        span,
+                        ..wr.clone()
                     })
                 }
-                ast::WherePredicate::EqPredicate(ref we) => {
+                ast::WherePredicate::EqPredicate(we) => {
+                    let span = we.span.with_ctxt(ctxt);
                     ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
                         id: ast::DUMMY_NODE_ID,
-                        span: self.span,
-                        lhs_ty: we.lhs_ty.clone(),
-                        rhs_ty: we.rhs_ty.clone(),
+                        span,
+                        ..we.clone()
                     })
                 }
             }
@@ -691,13 +693,13 @@ fn create_derived_impl(
             .iter()
             .map(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => {
-                    GenericArg::Lifetime(cx.lifetime(self.span, param.ident))
+                    GenericArg::Lifetime(cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident))
                 }
                 GenericParamKind::Type { .. } => {
-                    GenericArg::Type(cx.ty_ident(self.span, param.ident))
+                    GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident))
                 }
                 GenericParamKind::Const { .. } => {
-                    GenericArg::Const(cx.const_ident(self.span, param.ident))
+                    GenericArg::Const(cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident))
                 }
             })
             .collect();
@@ -845,16 +847,17 @@ fn call_substructure_method(
         nonself_args: &[P<Expr>],
         fields: &SubstructureFields<'_>,
     ) -> P<Expr> {
+        let span = trait_.span;
         let substructure = Substructure {
             type_ident,
-            method_ident: Ident::new(self.name, trait_.span),
+            method_ident: Ident::new(self.name, span),
             self_args,
             nonself_args,
             fields,
         };
         let mut f = self.combine_substructure.borrow_mut();
         let f: &mut CombineSubstructureFunc<'_> = &mut *f;
-        f(cx, trait_.span, &substructure)
+        f(cx, span, &substructure)
     }
 
     fn get_ret_ty(
@@ -882,9 +885,10 @@ fn split_self_nonself_args(
         let mut nonself_args = Vec::new();
         let mut arg_tys = Vec::new();
         let mut nonstatic = false;
+        let span = trait_.span;
 
         let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| {
-            let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr);
+            let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr);
 
             self_args.push(self_expr);
             nonstatic = true;
@@ -893,11 +897,11 @@ fn split_self_nonself_args(
         });
 
         for (ty, name) in self.args.iter() {
-            let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = Ident::new(*name, trait_.span);
+            let ast_ty = ty.to_ty(cx, span, type_ident, generics);
+            let ident = Ident::new(*name, span);
             arg_tys.push((ident, ast_ty));
 
-            let arg_expr = cx.expr_ident(trait_.span, ident);
+            let arg_expr = cx.expr_ident(span, ident);
 
             match *ty {
                 // for static methods, just treat any Self
@@ -906,7 +910,7 @@ fn split_self_nonself_args(
                     self_args.push(arg_expr);
                 }
                 Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => {
-                    self_args.push(cx.expr_deref(trait_.span, arg_expr))
+                    self_args.push(cx.expr_deref(span, arg_expr))
                 }
                 _ => {
                     nonself_args.push(arg_expr);
@@ -927,33 +931,33 @@ fn create_method(
         arg_types: Vec<(Ident, P<ast::Ty>)>,
         body: P<Expr>,
     ) -> P<ast::AssocItem> {
+        let span = trait_.span;
         // Create the generics that aren't for `Self`.
-        let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
+        let fn_generics = self.generics.to_generics(cx, span, type_ident, generics);
 
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
-                let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span);
+                let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(span);
                 ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident)
             });
-            let nonself_args =
-                arg_types.into_iter().map(|(name, ty)| cx.param(trait_.span, name, ty));
+            let nonself_args = arg_types.into_iter().map(|(name, ty)| cx.param(span, name, ty));
             self_args.into_iter().chain(nonself_args).collect()
         };
 
         let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
 
-        let method_ident = Ident::new(self.name, trait_.span);
+        let method_ident = Ident::new(self.name, span);
         let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type));
         let body_block = cx.block_expr(body);
 
-        let unsafety = if self.is_unsafe { ast::Unsafe::Yes(trait_.span) } else { ast::Unsafe::No };
+        let unsafety = if self.is_unsafe { ast::Unsafe::Yes(span) } else { ast::Unsafe::No };
 
-        let trait_lo_sp = trait_.span.shrink_to_lo();
+        let trait_lo_sp = span.shrink_to_lo();
 
         let sig = ast::FnSig {
             header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() },
             decl: fn_decl,
-            span: trait_.span,
+            span,
         };
         let defaultness = ast::Defaultness::Final;
 
@@ -961,7 +965,7 @@ fn create_method(
         P(ast::AssocItem {
             id: ast::DUMMY_NODE_ID,
             attrs: self.attributes.clone(),
-            span: trait_.span,
+            span,
             vis: ast::Visibility {
                 span: trait_lo_sp,
                 kind: ast::VisibilityKind::Inherited,
@@ -1024,11 +1028,11 @@ fn expand_struct_method_body<'b>(
         nonself_args: &[P<Expr>],
         use_temporaries: bool,
     ) -> P<Expr> {
-        let mut raw_fields = Vec::new(); // Vec<[fields of self],
-        // [fields of next Self arg], [etc]>
+        let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]>
+        let span = trait_.span;
         let mut patterns = Vec::new();
         for i in 0..self_args.len() {
-            let struct_path = cx.path(trait_.span, vec![type_ident]);
+            let struct_path = cx.path(span, vec![type_ident]);
             let (pat, ident_expr) = trait_.create_struct_pattern(
                 cx,
                 struct_path,
@@ -1048,7 +1052,7 @@ fn expand_struct_method_body<'b>(
             let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect();
             first_field
                 .map(|(span, opt_id, field, attrs)| FieldInfo {
-                    span,
+                    span: span.with_ctxt(trait_.span.ctxt()),
                     name: opt_id,
                     self_: field,
                     other: other_fields
@@ -1062,7 +1066,7 @@ fn expand_struct_method_body<'b>(
                 })
                 .collect()
         } else {
-            cx.span_bug(trait_.span, "no `self` parameter for method in generic `derive`")
+            cx.span_bug(span, "no `self` parameter for method in generic `derive`")
         };
 
         // body of the inner most destructuring match
@@ -1079,11 +1083,7 @@ fn expand_struct_method_body<'b>(
         // structs. This is actually right-to-left, but it shouldn't
         // matter.
         for (arg_expr, pat) in iter::zip(self_args, patterns) {
-            body = cx.expr_match(
-                trait_.span,
-                arg_expr.clone(),
-                vec![cx.arm(trait_.span, pat.clone(), body)],
-            )
+            body = cx.expr_match(span, arg_expr.clone(), vec![cx.arm(span, pat.clone(), body)])
         }
 
         body
@@ -1193,7 +1193,7 @@ fn build_enum_match_tuple<'b>(
         mut self_args: Vec<P<Expr>>,
         nonself_args: &[P<Expr>],
     ) -> P<Expr> {
-        let sp = trait_.span;
+        let span = trait_.span;
         let variants = &enum_def.variants;
 
         let self_arg_names = iter::once("__self".to_string())
@@ -1208,7 +1208,7 @@ fn build_enum_match_tuple<'b>(
 
         let self_arg_idents = self_arg_names
             .iter()
-            .map(|name| Ident::from_str_and_span(name, sp))
+            .map(|name| Ident::from_str_and_span(name, span))
             .collect::<Vec<Ident>>();
 
         // The `vi_idents` will be bound, solely in the catch-all, to
@@ -1218,7 +1218,7 @@ fn build_enum_match_tuple<'b>(
             .iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                Ident::from_str_and_span(&vi_suffix, trait_.span)
+                Ident::from_str_and_span(&vi_suffix, span)
             })
             .collect::<Vec<Ident>>();
 
@@ -1248,7 +1248,7 @@ fn build_enum_match_tuple<'b>(
                         self_arg_name,
                         ast::Mutability::Not,
                     );
-                    (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Not)), idents)
+                    (cx.pat(span, PatKind::Ref(p, ast::Mutability::Not)), idents)
                 };
 
                 // A single arm has form (&VariantK, &VariantK, ...) => BodyK
@@ -1267,7 +1267,7 @@ fn build_enum_match_tuple<'b>(
                 }
 
                 // Here is the pat = `(&VariantK, &VariantK, ...)`
-                let single_pat = cx.pat_tuple(sp, subpats);
+                let single_pat = cx.pat_tuple(span, subpats);
 
                 // For the BodyK, we need to delegate to our caller,
                 // passing it an EnumMatching to indicate which case
@@ -1284,7 +1284,7 @@ fn build_enum_match_tuple<'b>(
                     .into_iter()
                     .enumerate()
                     // For each arg field of self, pull out its getter expr ...
-                    .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| {
+                    .map(|(field_index, (span, opt_ident, self_getter_expr, attrs))| {
                         // ... but FieldInfo also wants getter expr
                         // for matching other arguments of Self type;
                         // so walk across the *other* self_pats_idents
@@ -1307,7 +1307,7 @@ fn build_enum_match_tuple<'b>(
                             .collect::<Vec<P<Expr>>>();
 
                         FieldInfo {
-                            span: sp,
+                            span,
                             name: opt_ident,
                             self_: self_getter_expr,
                             other: others,
@@ -1330,7 +1330,7 @@ fn build_enum_match_tuple<'b>(
                     &substructure,
                 );
 
-                cx.arm(sp, single_pat, arm_expr)
+                cx.arm(span, single_pat, arm_expr)
             })
             .collect();
 
@@ -1353,12 +1353,12 @@ fn build_enum_match_tuple<'b>(
                 // Since we know that all the arguments will match if we reach
                 // the match expression we add the unreachable intrinsics as the
                 // result of the catch all which should help llvm in optimizing it
-                Some(deriving::call_unreachable(cx, sp))
+                Some(deriving::call_unreachable(cx, span))
             }
             _ => None,
         };
         if let Some(arm) = default {
-            match_arms.push(cx.arm(sp, cx.pat_wild(sp), arm));
+            match_arms.push(cx.arm(span, cx.pat_wild(span), arm));
         }
 
         // We will usually need the catch-all after matching the
@@ -1392,23 +1392,23 @@ fn build_enum_match_tuple<'b>(
 
             // We also build an expression which checks whether all discriminants are equal
             // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
-            let mut discriminant_test = cx.expr_bool(sp, true);
+            let mut discriminant_test = cx.expr_bool(span, true);
 
             let mut first_ident = None;
             for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) {
-                let self_addr = cx.expr_addr_of(sp, self_arg.clone());
+                let self_addr = cx.expr_addr_of(span, self_arg.clone());
                 let variant_value =
-                    deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]);
-                let let_stmt = cx.stmt_let(sp, false, ident, variant_value);
+                    deriving::call_intrinsic(cx, span, sym::discriminant_value, vec![self_addr]);
+                let let_stmt = cx.stmt_let(span, false, ident, variant_value);
                 index_let_stmts.push(let_stmt);
 
                 match first_ident {
                     Some(first) => {
-                        let first_expr = cx.expr_ident(sp, first);
-                        let id = cx.expr_ident(sp, ident);
-                        let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id);
+                        let first_expr = cx.expr_ident(span, first);
+                        let id = cx.expr_ident(span, ident);
+                        let test = cx.expr_binary(span, BinOpKind::Eq, first_expr, id);
                         discriminant_test =
-                            cx.expr_binary(sp, BinOpKind::And, discriminant_test, test)
+                            cx.expr_binary(span, BinOpKind::And, discriminant_test, test)
                     }
                     None => {
                         first_ident = Some(ident);
@@ -1430,8 +1430,8 @@ fn build_enum_match_tuple<'b>(
             // them when they are fed as r-values into a tuple
             // expression; here add a layer of borrowing, turning
             // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
-            self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg));
-            let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args));
+            self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg));
+            let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args));
 
             // Lastly we create an expression which branches on all discriminants being equal
             //  if discriminant_test {
@@ -1445,10 +1445,10 @@ fn build_enum_match_tuple<'b>(
             //  else {
             //      <delegated expression referring to __self0_vi, et al.>
             //  }
-            let all_match = cx.expr_match(sp, match_arg, match_arms);
-            let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr));
+            let all_match = cx.expr_match(span, match_arg, match_arms);
+            let arm_expr = cx.expr_if(span, discriminant_test, all_match, Some(arm_expr));
             index_let_stmts.push(cx.stmt_expr(arm_expr));
-            cx.expr_block(cx.block(sp, index_let_stmts))
+            cx.expr_block(cx.block(span, index_let_stmts))
         } else if variants.is_empty() {
             // As an additional wrinkle, For a zero-variant enum A,
             // currently the compiler
@@ -1499,16 +1499,16 @@ fn build_enum_match_tuple<'b>(
             // derive Debug on such a type could here generate code
             // that needs the feature gate enabled.)
 
-            deriving::call_unreachable(cx, sp)
+            deriving::call_unreachable(cx, span)
         } else {
             // Final wrinkle: the self_args are expressions that deref
             // down to desired places, but we cannot actually deref
             // them when they are fed as r-values into a tuple
             // expression; here add a layer of borrowing, turning
             // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
-            self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg));
-            let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args));
-            cx.expr_match(sp, match_arg, match_arms)
+            self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg));
+            let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args));
+            cx.expr_match(span, match_arg, match_arms)
         }
     }
 
@@ -1556,11 +1556,9 @@ fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> St
 
         let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
         match (just_spans.is_empty(), named_idents.is_empty()) {
-            (false, false) => cx.span_bug(
-                self.span,
-                "a struct with named and unnamed \
-                                          fields in generic `derive`",
-            ),
+            (false, false) => {
+                cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`")
+            }
             // named fields
             (_, false) => Named(named_idents),
             // unnamed fields
index 00d75be4399649987e9b491aa19fb81cf36e7838..7a418003250841fdb2e1fbe71777a495f3b5c4c6 100644 (file)
@@ -211,14 +211,6 @@ fn mk_ty_param(
     cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None)
 }
 
-fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
-    Generics {
-        params,
-        where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
-        span,
-    }
-}
-
 /// Bounds on type parameters.
 #[derive(Clone)]
 pub struct Bounds {
@@ -236,7 +228,7 @@ pub fn to_generics(
         self_ty: Ident,
         self_generics: &Generics,
     ) -> Generics {
-        let generic_params = self
+        let params = self
             .bounds
             .iter()
             .map(|t| {
@@ -245,7 +237,11 @@ pub fn to_generics(
             })
             .collect();
 
-        mk_generics(generic_params, span)
+        Generics {
+            params,
+            where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
+            span,
+        }
     }
 }
 
index 70e125d6887878bbb1967d8af115d2482e4b8760..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;
                         }
                     }
@@ -774,11 +774,7 @@ fn into_expr(self) -> P<ast::Expr> {
             // (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 89ec8da77d3ec5f6a1ade1ba67fe7aeb7500bac6..41d82b581cd8cc07111c7f5b6a6f491a178dc801 100644 (file)
@@ -42,7 +42,7 @@ fn main() {
                 "RUSTFLAGS",
                 env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
             );
-            std::array::IntoIter::new(["rustc".to_string()])
+            IntoIterator::into_iter(["rustc".to_string()])
                 .chain(env::args().skip(2))
                 .chain([
                     "--".to_string(),
@@ -56,7 +56,7 @@ fn main() {
                 "RUSTFLAGS",
                 env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
             );
-            std::array::IntoIter::new(["rustc".to_string()])
+            IntoIterator::into_iter(["rustc".to_string()])
                 .chain(env::args().skip(2))
                 .chain([
                     "--".to_string(),
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 1b30edd293862b1d221cbfb4529c1b9f8883a52e..371c71de62fbbb421c18707e08b5f83b4524ecc1 100644 (file)
@@ -1,6 +1,7 @@
 //! Codegen of a single function
 
 use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
+use rustc_ast::InlineAsmOptions;
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::layout::FnAbiOf;
@@ -239,7 +240,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
             fx.add_comment(inst, terminator_head);
         }
 
-        fx.set_debug_loc(bb_data.terminator().source_info);
+        let source_info = bb_data.terminator().source_info;
+        fx.set_debug_loc(source_info);
 
         match &bb_data.terminator().kind {
             TerminatorKind::Goto { target } => {
@@ -295,19 +297,19 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
                         let len = codegen_operand(fx, len).load_scalar(fx);
                         let index = codegen_operand(fx, index).load_scalar(fx);
                         let location = fx
-                            .get_caller_location(bb_data.terminator().source_info.span)
+                            .get_caller_location(source_info.span)
                             .load_scalar(fx);
 
                         codegen_panic_inner(
                             fx,
                             rustc_hir::LangItem::PanicBoundsCheck,
                             &[index, len, location],
-                            bb_data.terminator().source_info.span,
+                            source_info.span,
                         );
                     }
                     _ => {
                         let msg_str = msg.description();
-                        codegen_panic(fx, msg_str, bb_data.terminator().source_info.span);
+                        codegen_panic(fx, msg_str, source_info.span);
                     }
                 }
             }
@@ -378,10 +380,18 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
                 options,
                 destination,
                 line_spans: _,
+                cleanup: _,
             } => {
+                if options.contains(InlineAsmOptions::MAY_UNWIND) {
+                    fx.tcx.sess.span_fatal(
+                        source_info.span,
+                        "cranelift doesn't support unwinding from inline assembly.",
+                    );
+                }
+
                 crate::inline_asm::codegen_inline_asm(
                     fx,
-                    bb_data.terminator().source_info.span,
+                    source_info.span,
                     template,
                     operands,
                     *options,
@@ -415,7 +425,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
             }
             TerminatorKind::Drop { place, target, unwind: _ } => {
                 let drop_place = codegen_place(fx, *place);
-                crate::abi::codegen_drop(fx, bb_data.terminator().source_info.span, drop_place);
+                crate::abi::codegen_drop(fx, source_info.span, drop_place);
 
                 let target_block = fx.get_block(*target);
                 fx.bcx.ins().jump(target_block, &[]);
index 2bbb199c8998285a06d689753102c0be6a0bb4e6..a8b1e70e2bb801e432b5940d126bd4cad33eca63 100644 (file)
@@ -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 7c3ed3c5ee9db8d68b0aea669111bd1e9216ad8f..6a3b94a0d7018311a6979d04cd7aa4dca320a56b 100644 (file)
@@ -118,7 +118,14 @@ fn codegen_llvm_inline_asm(&mut self, _ia: &LlvmInlineAsmInner, _outputs: Vec<Pl
         true
     }
 
-    fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span], _instance: Instance<'_>) {
+    fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) {
+        if options.contains(InlineAsmOptions::MAY_UNWIND) {
+            self.sess()
+                .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm")
+                .emit();
+            return;
+        }
+
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
         let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64);
         let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX);
index 07adfff0901a1963af2da03b8349c7dc72785088..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);
                 }
             }
         }
index 02096f4abfa5f60d48ef115a1287c27edfb6d321..83c5cb6f1cf51ee28f975668cf55237301ca49da 100644 (file)
@@ -1,6 +1,8 @@
 use crate::builder::Builder;
+use crate::common::Funclet;
 use crate::context::CodegenCx;
 use crate::llvm;
+use crate::llvm_util;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
@@ -98,6 +100,8 @@ fn codegen_llvm_inline_asm(
             ia.alignstack,
             ia.dialect,
             &[span],
+            false,
+            None,
         );
         if r.is_none() {
             return false;
@@ -121,6 +125,7 @@ fn codegen_inline_asm(
         options: InlineAsmOptions,
         line_spans: &[Span],
         instance: Instance<'_>,
+        dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
     ) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
@@ -355,6 +360,8 @@ fn codegen_inline_asm(
             alignstack,
             dialect,
             line_spans,
+            options.contains(InlineAsmOptions::MAY_UNWIND),
+            dest_catch_funclet,
         )
         .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed"));
 
@@ -447,9 +454,16 @@ pub(crate) fn inline_asm_call(
     alignstack: bool,
     dia: LlvmAsmDialect,
     line_spans: &[Span],
+    unwind: bool,
+    dest_catch_funclet: Option<(
+        &'ll llvm::BasicBlock,
+        &'ll llvm::BasicBlock,
+        Option<&Funclet<'ll>>,
+    )>,
 ) -> Option<&'ll Value> {
     let volatile = if volatile { llvm::True } else { llvm::False };
     let alignstack = if alignstack { llvm::True } else { llvm::False };
+    let can_throw = if unwind { llvm::True } else { llvm::False };
 
     let argtys = inputs
         .iter()
@@ -466,6 +480,13 @@ pub(crate) fn inline_asm_call(
         let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len());
         debug!("constraint verification result: {:?}", constraints_ok);
         if constraints_ok {
+            if unwind && llvm_util::get_version() < (13, 0, 0) {
+                bx.cx.sess().span_fatal(
+                    line_spans[0],
+                    "unwinding from inline assembly is only supported on llvm >= 13.",
+                );
+            }
+
             let v = llvm::LLVMRustInlineAsm(
                 fty,
                 asm.as_ptr().cast(),
@@ -475,8 +496,14 @@ pub(crate) fn inline_asm_call(
                 volatile,
                 alignstack,
                 llvm::AsmDialect::from_generic(dia),
+                can_throw,
             );
-            let call = bx.call(fty, v, inputs, None);
+
+            let call = if let Some((dest, catch, funclet)) = dest_catch_funclet {
+                bx.invoke(fty, v, inputs, dest, catch, funclet)
+            } else {
+                bx.call(fty, v, inputs, None)
+            };
 
             // Store mark in a metadata node so we can map LLVM errors
             // back to source locations.  See #17552.
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 a7e34b080594bc1005f9dabcc9a63e1982441236..5e7d7552daf10ad8e4a42a3fa8b3f480618ac023 100644 (file)
@@ -350,6 +350,8 @@ fn codegen_intrinsic_call(
                     false,
                     ast::LlvmAsmDialect::Att,
                     &[span],
+                    false,
+                    None,
                 )
                 .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
 
index 6eb0fb560467f40a3ccdbbf8a60e4799c08d171c..d9a6723fe27fde21a2515e2a377b1b0186ee5494 100644 (file)
@@ -685,7 +685,7 @@ struct InvariantOpaque<'a> {
 pub mod coverageinfo {
     use super::coverage_map;
 
-    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/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 {
@@ -704,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
@@ -721,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.
@@ -758,6 +767,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter,
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -768,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)]
@@ -781,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,
@@ -803,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,
@@ -826,6 +863,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter,
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -1809,6 +1847,7 @@ pub fn LLVMRustInlineAsm(
         SideEffects: Bool,
         AlignStack: Bool,
         Dialect: AsmDialect,
+        CanThrow: Bool,
     ) -> &Value;
     pub fn LLVMRustInlineAsmVerify(
         Ty: &Type,
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 8d75b2e7a3d4c62a92519e00cf503310c9cc0a75..0447c02fdecc4fdc2e9791d374439cc978290899 100644 (file)
@@ -211,6 +211,7 @@ fn visit_local(&mut self, &local: &mir::Local, context: PlaceContext, location:
 
             PlaceContext::MutatingUse(
                 MutatingUseContext::Store
+                | MutatingUseContext::LlvmAsmOutput
                 | MutatingUseContext::AsmOutput
                 | MutatingUseContext::Borrow
                 | MutatingUseContext::AddressOf
@@ -275,9 +276,9 @@ fn discover_masters<'tcx>(
                 | TerminatorKind::SwitchInt { .. }
                 | TerminatorKind::Yield { .. }
                 | TerminatorKind::FalseEdge { .. }
-                | TerminatorKind::FalseUnwind { .. }
-                | TerminatorKind::InlineAsm { .. } => { /* nothing to do */ }
+                | TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ }
                 TerminatorKind::Call { cleanup: unwind, .. }
+                | TerminatorKind::InlineAsm { cleanup: unwind, .. }
                 | TerminatorKind::Assert { cleanup: unwind, .. }
                 | TerminatorKind::DropAndReplace { unwind, .. }
                 | TerminatorKind::Drop { unwind, .. } => {
index c8f388bfa1d5ab920bdbedf8171407aa8e52cb03..e914e4932693215ea8f9718e3636416b2781c473 100644 (file)
@@ -10,6 +10,7 @@
 use crate::MemFlags;
 
 use rustc_ast as ast;
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::AssertKind;
@@ -174,6 +175,45 @@ fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
             }
         }
     }
+
+    /// Generates inline assembly with optional `destination` and `cleanup`.
+    fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
+        &self,
+        fx: &mut FunctionCx<'a, 'tcx, Bx>,
+        bx: &mut Bx,
+        template: &[InlineAsmTemplatePiece],
+        operands: &[InlineAsmOperandRef<'tcx, Bx>],
+        options: InlineAsmOptions,
+        line_spans: &[Span],
+        destination: Option<mir::BasicBlock>,
+        cleanup: Option<mir::BasicBlock>,
+        instance: Instance<'_>,
+    ) {
+        if let Some(cleanup) = cleanup {
+            let ret_llbb = if let Some(target) = destination {
+                fx.llbb(target)
+            } else {
+                fx.unreachable_block()
+            };
+
+            bx.codegen_inline_asm(
+                template,
+                &operands,
+                options,
+                line_spans,
+                instance,
+                Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))),
+            );
+        } else {
+            bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None);
+
+            if let Some(target) = destination {
+                self.funclet_br(fx, bx, target);
+            } else {
+                bx.unreachable();
+            }
+        }
+    }
 }
 
 /// Codegen implementations for some terminator variants.
@@ -877,6 +917,7 @@ fn codegen_asm_terminator(
         options: ast::InlineAsmOptions,
         line_spans: &[Span],
         destination: Option<mir::BasicBlock>,
+        cleanup: Option<mir::BasicBlock>,
         instance: Instance<'_>,
     ) {
         let span = terminator.source_info.span;
@@ -931,13 +972,17 @@ fn codegen_asm_terminator(
             })
             .collect();
 
-        bx.codegen_inline_asm(template, &operands, options, line_spans, instance);
-
-        if let Some(target) = destination {
-            helper.funclet_br(self, &mut bx, target);
-        } else {
-            bx.unreachable();
-        }
+        helper.do_inlineasm(
+            self,
+            &mut bx,
+            template,
+            &operands,
+            options,
+            line_spans,
+            destination,
+            cleanup,
+            instance,
+        );
     }
 }
 
@@ -1041,6 +1086,7 @@ fn codegen_terminator(
                 options,
                 line_spans,
                 destination,
+                cleanup,
             } => {
                 self.codegen_asm_terminator(
                     helper,
@@ -1051,6 +1097,7 @@ fn codegen_terminator(
                     options,
                     line_spans,
                     destination,
+                    cleanup,
                     self.instance,
                 );
             }
index 31f539e1b03dba8f3cdeb548e3f91ca2dff0c477..65f3c754d2dccf408f5d84bee432c260f4bb58bf 100644 (file)
@@ -59,6 +59,7 @@ fn codegen_inline_asm(
         options: InlineAsmOptions,
         line_spans: &[Span],
         instance: Instance<'_>,
+        dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
     );
 }
 
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 0d36466f6e3e73153e2498e393c608614cc367da..f308e764e861d0422e76464c39014aea20b59d09 100644 (file)
@@ -23,7 +23,6 @@
 #![feature(trusted_len)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
-#![feature(unwrap_infallible)]
 #![recursion_limit = "256"]
 
 #[macro_use]
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 b70b38754c956584ccacb244e409be91cd6b4e57..249b4ea0602c19cba7cef1324a16d391953dac87 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementKind};
 use rustc_mir_dataflow::fmt::DebugWithContext;
 use rustc_mir_dataflow::JoinSemiLattice;
+use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces};
 use rustc_span::DUMMY_SP;
 
 use std::fmt;
@@ -80,18 +81,18 @@ fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, mut value: bool) {
     fn apply_call_return_effect(
         &mut self,
         _block: BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        // We cannot reason about another function's internals, so use conservative type-based
-        // qualification for the result of a function call.
-        let return_ty = return_place.ty(self.ccx.body, self.ccx.tcx).ty;
-        let qualif = Q::in_any_value_of_ty(self.ccx, return_ty);
+        return_places.for_each(|place| {
+            // We cannot reason about another function's internals, so use conservative type-based
+            // qualification for the result of a function call.
+            let return_ty = place.ty(self.ccx.body, self.ccx.tcx).ty;
+            let qualif = Q::in_any_value_of_ty(self.ccx, return_ty);
 
-        if !return_place.is_indirect() {
-            self.assign_qualif_direct(&return_place, qualif);
-        }
+            if !place.is_indirect() {
+                self.assign_qualif_direct(&place, qualif);
+            }
+        });
     }
 
     fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool {
@@ -329,7 +330,7 @@ fn join(&mut self, other: &Self) -> bool {
     }
 }
 
-impl<Q> rustc_mir_dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+impl<Q> AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
 where
     Q: Qualif,
 {
@@ -349,7 +350,7 @@ fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut Self::Doma
     }
 }
 
-impl<Q> rustc_mir_dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+impl<Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
 where
     Q: Qualif,
 {
@@ -375,10 +376,8 @@ fn apply_call_return_effect(
         &self,
         state: &mut Self::Domain,
         block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        self.transfer_function(state).apply_call_return_effect(block, func, args, return_place)
+        self.transfer_function(state).apply_call_return_effect(block, return_places)
     }
 }
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..3c06074a1b33f3444135479ead69243299b626cc 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.
 ///
@@ -42,6 +41,10 @@ pub struct PromoteTemps<'tcx> {
 }
 
 impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
+    fn phase_change(&self) -> Option<MirPhase> {
+        Some(MirPhase::ConstPromotion)
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // There's not really any point in promoting errorful MIR.
         //
index 0ab077cf2bf404335d81a5488792adf8e2d25065..448a04f76b10ae5f3be154f1c1ccf35e44ef092a 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;
@@ -95,8 +94,7 @@ pub fn equal_up_to_regions(
                 // Leave consts and types unchanged.
                 ct_op: |ct| ct,
                 ty_op: |ty| ty,
-            })
-            .into_ok(),
+            }),
         )
     };
     tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok())
@@ -497,10 +495,13 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                     self.check_edge(location, *unwind, EdgeKind::Unwind);
                 }
             }
-            TerminatorKind::InlineAsm { destination, .. } => {
+            TerminatorKind::InlineAsm { destination, cleanup, .. } => {
                 if let Some(destination) = destination {
                     self.check_edge(location, *destination, EdgeKind::Normal);
                 }
+                if let Some(cleanup) = cleanup {
+                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
+                }
             }
             // Nothing to validate for these.
             TerminatorKind::Resume
index 920f7b1ed0a543c15dac3c272f59edad8243464e..71ff762c714bfab9095f00c3fcf60c4d32e69054 100644 (file)
@@ -4,14 +4,6 @@
 pub trait IdFunctor: Sized {
     type Inner;
 
-    #[inline]
-    fn map_id<F>(self, mut f: F) -> Self
-    where
-        F: FnMut(Self::Inner) -> Self::Inner,
-    {
-        self.try_map_id::<_, !>(|value| Ok(f(value))).into_ok()
-    }
-
     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
         F: FnMut(Self::Inner) -> Result<Self::Inner, E>;
@@ -31,11 +23,9 @@ fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E>
             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)?)
         })
     }
 }
index d4eb622e780ce1857af21276d6d4fcb5df8f9a7d..77784bf1705234d0018ef5aca044267902dd6735 100644 (file)
@@ -25,7 +25,6 @@
 #![feature(once_cell)]
 #![feature(test)]
 #![feature(thread_id_value)]
-#![feature(unwrap_infallible)]
 #![allow(rustc::default_hash_types)]
 #![deny(unaligned_references)]
 
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 d64a589bd9b2a37b1db629e6e10d7112c206ea36..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
@@ -736,7 +736,9 @@ fn render_source_line(
 
         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()
@@ -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) {
@@ -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;
             }
@@ -2083,7 +2094,7 @@ fn num_decimal_digits(num: usize) -> usize {
     ('\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}', ""),
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 f8491654f39e31301bd74aad8465c9a0e80aa708..537a10e98e59de2dcf0c11c0beac366c47de7511 100644 (file)
@@ -1027,6 +1027,24 @@ fn check_matcher_core(
                                 ),
                             );
                             err.span_label(sp, format!("not allowed after `{}` fragments", kind));
+
+                            if kind == NonterminalKind::PatWithOr
+                                && sess.edition == Edition::Edition2021
+                                && next_token.is_token(&BinOp(token::BinOpToken::Or))
+                            {
+                                let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
+                                    span,
+                                    name,
+                                    Some(NonterminalKind::PatParam { inferred: false }),
+                                ));
+                                err.span_suggestion(
+                                    span,
+                                    &format!("try a `pat_param` fragment specifier instead"),
+                                    suggestion,
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+
                             let msg = "allowed there are: ";
                             match possible {
                                 &[] => {}
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 fa9e98be9e881f6b0c1bdd51aa4dae4e784a2319..b7e47e4da6f944b5f1f2fe2e93e09e382dd3337d 100644 (file)
@@ -466,13 +466,12 @@ fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStrea
             ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
                 ast::ExprKind::Lit(l) => match l.token {
                     token::Lit { kind: token::Integer | token::Float, .. } => {
-                        Ok(std::array::IntoIter::new([
+                        Ok(Self::TokenStream::from_iter([
                             // FIXME: The span of the `-` token is lost when
                             // parsing, so we cannot faithfully recover it here.
                             tokenstream::TokenTree::token(token::BinOp(token::Minus), e.span),
                             tokenstream::TokenTree::token(token::Literal(l.token), l.span),
-                        ])
-                        .collect())
+                        ]))
                     }
                     _ => Err(()),
                 },
index 7860f92f96f9647d2367a74bd16ca10f0cff5f1f..640c4bba6dafb43022f32959aff3075f164b9cbd 100644 (file)
@@ -290,6 +290,8 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (active, asm_experimental_arch, "1.58.0", Some(72016), None),
     /// Allows using `sym` operands in inline assembly.
     (active, asm_sym, "1.58.0", Some(72016), None),
+    /// Allows the `may_unwind` option in inline assembly.
+    (active, asm_unwind, "1.58.0", Some(72016), None),
     /// Allows the user of associated type bounds.
     (active, associated_type_bounds, "1.34.0", Some(52662), None),
     /// Allows associated type defaults.
index 60761a05de8270180810ca2d6995fab17eb59dac..405aaf1f4e5277f6e1acb79b0451fd4d0dbc075e 100644 (file)
@@ -443,11 +443,11 @@ pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
     }
 
     pub fn into_iter(self) -> IntoIter<T, 3> {
-        IntoIter::new([self.value_ns, self.type_ns, self.macro_ns])
+        [self.value_ns, self.type_ns, self.macro_ns].into_iter()
     }
 
     pub fn iter(&self) -> IntoIter<&T, 3> {
-        IntoIter::new([&self.value_ns, &self.type_ns, &self.macro_ns])
+        [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter()
     }
 }
 
@@ -481,7 +481,7 @@ pub fn is_empty(&self) -> bool {
 
     /// Returns an iterator over the items which are `Some`.
     pub fn present_items(self) -> impl Iterator<Item = T> {
-        IntoIter::new([self.type_ns, self.value_ns, self.macro_ns]).flatten()
+        [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten()
     }
 }
 
index c67d3df3dedd85b9d4457e50ecdcf9b669809ebd..487ae87052ba30f0206ec1662bce2bcdb8ccf387 100644 (file)
@@ -17,8 +17,7 @@
 use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{def_id::LocalDefId, BytePos};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP};
 use rustc_target::asm::InlineAsmRegOrRegClass;
 use rustc_target::spec::abi::Abi;
 
@@ -92,7 +91,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 +123,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 +134,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
@@ -524,12 +525,20 @@ pub struct GenericParam<'hir> {
 }
 
 impl GenericParam<'hir> {
-    pub fn bounds_span(&self) -> Option<Span> {
-        self.bounds.iter().fold(None, |span, bound| {
-            let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
-
-            Some(span)
-        })
+    pub fn bounds_span_for_suggestions(&self) -> Option<Span> {
+        self.bounds
+            .iter()
+            .fold(None, |span: Option<Span>, bound| {
+                // We include bounds that come from a `#[derive(_)]` but point at the user's code,
+                // as we use this method to get a span appropriate for suggestions.
+                if !bound.span().can_be_used_for_suggestions() {
+                    None
+                } else {
+                    let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
+                    Some(span)
+                }
+            })
+            .map(|sp| sp.shrink_to_hi())
     }
 }
 
@@ -3298,7 +3307,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 05659e976dd44c3c2f0f4ced66daa17f9c1865d9..a03c561861e2b58a6df22560399dce137d59487d 100644 (file)
@@ -348,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 9c2927111a66c9f40df85bde1462725fa6bd524f..449430a7d28ef77c044b740c631be3844efffab9 100644 (file)
@@ -1433,6 +1433,9 @@ enum AsmArg<'a> {
                 if opts.contains(ast::InlineAsmOptions::RAW) {
                     options.push("raw");
                 }
+                if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) {
+                    options.push("may_unwind");
+                }
                 s.commasep(Inconsistent, &options, |s, &opt| {
                     s.word(opt);
                 });
@@ -2171,7 +2174,7 @@ fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId)
         match decl.output {
             hir::FnRetTy::Return(ref ty) => {
                 self.print_type(&ty);
-                self.maybe_print_comment(ty.span.lo())
+                self.maybe_print_comment(ty.span.lo());
             }
             hir::FnRetTy::DefaultReturn(..) => unreachable!(),
         }
@@ -2365,7 +2368,7 @@ pub fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) {
         self.end();
 
         if let hir::FnRetTy::Return(ref output) = decl.output {
-            self.maybe_print_comment(output.span.lo())
+            self.maybe_print_comment(output.span.lo());
         }
     }
 
index 27e73738b7f351bf07bd4bd56298cd90477ecaee..934ada9932e71ad91d9b737b0ed38ff145696d17 100644 (file)
@@ -278,7 +278,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error>
+    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -288,13 +288,13 @@ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx,
         t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(index, ..) => {
                 if index >= self.binder_index {
                     bug!("escaping late-bound region during canonicalization");
                 } else {
-                    Ok(r)
+                    r
                 }
             }
 
@@ -311,7 +311,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                     vid, r
                 );
                 let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
-                Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r))
+                self.canonicalize_region_mode.canonicalize_free_region(self, r)
             }
 
             ty::ReStatic
@@ -319,11 +319,11 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
             | ty::ReFree(_)
             | ty::ReEmpty(_)
             | ty::RePlaceholder(..)
-            | ty::ReErased => Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r)),
+            | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
             ty::Infer(ty::TyVar(vid)) => {
                 debug!("canonical: type var found with vid {:?}", vid);
@@ -339,40 +339,40 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     Err(mut ui) => {
                         // FIXME: perf problem described in #55921.
                         ui = ty::UniverseIndex::ROOT;
-                        Ok(self.canonicalize_ty_var(
+                        self.canonicalize_ty_var(
                             CanonicalVarInfo {
                                 kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
                             },
                             t,
-                        ))
+                        )
                     }
                 }
             }
 
-            ty::Infer(ty::IntVar(_)) => Ok(self.canonicalize_ty_var(
+            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
                 CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
                 t,
-            )),
+            ),
 
-            ty::Infer(ty::FloatVar(_)) => Ok(self.canonicalize_ty_var(
+            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
                 CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
                 t,
-            )),
+            ),
 
             ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("encountered a fresh type during canonicalization")
             }
 
-            ty::Placeholder(placeholder) => Ok(self.canonicalize_ty_var(
+            ty::Placeholder(placeholder) => self.canonicalize_ty_var(
                 CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
                 t,
-            )),
+            ),
 
             ty::Bound(debruijn, _) => {
                 if debruijn >= self.binder_index {
                     bug!("escaping bound type during canonicalization")
                 } else {
-                    Ok(t)
+                    t
                 }
             }
 
@@ -403,16 +403,13 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 if t.flags().intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
-                    Ok(t)
+                    t
                 }
             }
         }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match ct.val {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 debug!("canonical: const var found with vid {:?}", vid);
@@ -427,10 +424,10 @@ fn fold_const(
                     Err(mut ui) => {
                         // FIXME: perf problem described in #55921.
                         ui = ty::UniverseIndex::ROOT;
-                        return Ok(self.canonicalize_const_var(
+                        return self.canonicalize_const_var(
                             CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
                             ct,
-                        ));
+                        );
                     }
                 }
             }
@@ -441,20 +438,20 @@ fn fold_const(
                 if debruijn >= self.binder_index {
                     bug!("escaping bound type during canonicalization")
                 } else {
-                    return Ok(ct);
+                    return ct;
                 }
             }
             ty::ConstKind::Placeholder(placeholder) => {
-                return Ok(self.canonicalize_const_var(
+                return self.canonicalize_const_var(
                     CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
                     ct,
-                ));
+                );
             }
             _ => {}
         }
 
         let flags = FlagComputation::for_const(ct);
-        if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { Ok(ct) }
+        if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct }
     }
 }
 
@@ -503,7 +500,7 @@ fn canonicalize<V>(
             indices: FxHashMap::default(),
             binder_index: ty::INNERMOST,
         };
-        let out_value = value.fold_with(&mut canonicalizer).into_ok();
+        let out_value = value.fold_with(&mut canonicalizer);
 
         // Once we have canonicalized `out_value`, it should not
         // contain anything that ties it to this inference context
@@ -621,7 +618,7 @@ fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>
         let infcx = self.infcx;
         let bound_to = infcx.shallow_resolve(ty_var);
         if bound_to != ty_var {
-            self.fold_ty(bound_to).into_ok()
+            self.fold_ty(bound_to)
         } else {
             let var = self.canonical_var(info, ty_var.into());
             self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
@@ -640,12 +637,12 @@ fn canonicalize_const_var(
         let infcx = self.infcx;
         let bound_to = infcx.shallow_resolve(const_var);
         if bound_to != const_var {
-            self.fold_const(bound_to).into_ok()
+            self.fold_const(bound_to)
         } else {
             let var = self.canonical_var(info, const_var.into());
             self.tcx().mk_const(ty::Const {
                 val: ty::ConstKind::Bound(self.binder_index, var),
-                ty: self.fold_ty(const_var.ty).into_ok(),
+                ty: self.fold_ty(const_var.ty),
             })
         }
     }
index a7e019a53ee13586c835b1991c38109fa0e32915..32c02033dc9b93e4c1f77abbe944ce5d2774c5b5 100644 (file)
@@ -1,5 +1,6 @@
 use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::infer::InferCtxt;
+use crate::rustc_middle::ty::TypeFoldable;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
@@ -400,36 +401,75 @@ pub fn extract_inference_diagnostics_data(
                 }
             }
             GenericArgKind::Const(ct) => {
-                if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
-                    let origin =
-                        self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
-                    if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
-                        origin.kind
-                    {
-                        return InferenceDiagnosticsData {
-                            name: name.to_string(),
+                match ct.val {
+                    ty::ConstKind::Infer(InferConst::Var(vid)) => {
+                        let origin = self
+                            .inner
+                            .borrow_mut()
+                            .const_unification_table()
+                            .probe_value(vid)
+                            .origin;
+                        if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
+                            origin.kind
+                        {
+                            return InferenceDiagnosticsData {
+                                name: name.to_string(),
+                                span: Some(origin.span),
+                                kind: UnderspecifiedArgKind::Const { is_parameter: true },
+                                parent: InferenceDiagnosticsParentData::for_def_id(
+                                    self.tcx, def_id,
+                                ),
+                            };
+                        }
+
+                        debug_assert!(!origin.span.is_dummy());
+                        let mut s = String::new();
+                        let mut printer =
+                            ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
+                        if let Some(highlight) = highlight {
+                            printer.region_highlight_mode = highlight;
+                        }
+                        let _ = ct.print(printer);
+                        InferenceDiagnosticsData {
+                            name: s,
                             span: Some(origin.span),
-                            kind: UnderspecifiedArgKind::Const { is_parameter: true },
-                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
-                        };
+                            kind: UnderspecifiedArgKind::Const { is_parameter: false },
+                            parent: None,
+                        }
                     }
-
-                    debug_assert!(!origin.span.is_dummy());
-                    let mut s = String::new();
-                    let mut printer =
-                        ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
-                    if let Some(highlight) = highlight {
-                        printer.region_highlight_mode = highlight;
+                    ty::ConstKind::Unevaluated(ty::Unevaluated {
+                        substs_: Some(substs), ..
+                    }) => {
+                        assert!(substs.has_infer_types_or_consts());
+
+                        // FIXME: We only use the first inference variable we encounter in
+                        // `substs` here, this gives insufficiently informative diagnostics
+                        // in case there are multiple inference variables
+                        for s in substs.iter() {
+                            match s.unpack() {
+                                GenericArgKind::Type(t) => match t.kind() {
+                                    ty::Infer(_) => {
+                                        return self.extract_inference_diagnostics_data(s, None);
+                                    }
+                                    _ => {}
+                                },
+                                GenericArgKind::Const(c) => match c.val {
+                                    ty::ConstKind::Infer(InferConst::Var(_)) => {
+                                        return self.extract_inference_diagnostics_data(s, None);
+                                    }
+                                    _ => {}
+                                },
+                                _ => {}
+                            }
+                        }
+                        bug!(
+                            "expected an inference variable in substs of unevaluated const {:?}",
+                            ct
+                        );
                     }
-                    let _ = ct.print(printer);
-                    InferenceDiagnosticsData {
-                        name: s,
-                        span: Some(origin.span),
-                        kind: UnderspecifiedArgKind::Const { is_parameter: false },
-                        parent: None,
+                    _ => {
+                        bug!("unexpect const: {:?}", ct);
                     }
-                } else {
-                    bug!("unexpect const: {:?}", ct);
                 }
             }
             GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
index 7599e98167fb5c04e6c8e2839ae394a4f3761c68..c40e409891bc25cb76a7612fbab231493c67de98 100644 (file)
@@ -72,7 +72,7 @@ fn freshen_ty<F>(
         F: FnOnce(u32) -> ty::InferTy,
     {
         if let Some(ty) = opt_ty {
-            return ty.fold_with(self).into_ok();
+            return ty.fold_with(self);
         }
 
         match self.ty_freshen_map.entry(key) {
@@ -98,7 +98,7 @@ fn freshen_const<F>(
         F: FnOnce(u32) -> ty::InferConst<'tcx>,
     {
         if let Some(ct) = opt_ct {
-            return ct.fold_with(self).into_ok();
+            return ct.fold_with(self);
         }
 
         match self.const_freshen_map.entry(key) {
@@ -119,11 +119,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(..) => {
                 // leave bound regions alone
-                Ok(r)
+                r
             }
 
             ty::ReEarlyBound(..)
@@ -133,21 +133,21 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
             | ty::ReEmpty(_)
             | ty::ReErased => {
                 // replace all free regions with 'erased
-                Ok(self.tcx().lifetimes.re_erased)
+                self.tcx().lifetimes.re_erased
             }
             ty::ReStatic => {
                 if self.keep_static {
-                    Ok(r)
+                    r
                 } else {
-                    Ok(self.tcx().lifetimes.re_erased)
+                    self.tcx().lifetimes.re_erased
                 }
             }
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
-            return Ok(t);
+            return t;
         }
 
         let tcx = self.infcx.tcx;
@@ -155,10 +155,10 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *t.kind() {
             ty::Infer(ty::TyVar(v)) => {
                 let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
-                Ok(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy))
+                self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
             }
 
-            ty::Infer(ty::IntVar(v)) => Ok(self.freshen_ty(
+            ty::Infer(ty::IntVar(v)) => self.freshen_ty(
                 self.infcx
                     .inner
                     .borrow_mut()
@@ -167,9 +167,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     .map(|v| v.to_type(tcx)),
                 ty::IntVar(v),
                 ty::FreshIntTy,
-            )),
+            ),
 
-            ty::Infer(ty::FloatVar(v)) => Ok(self.freshen_ty(
+            ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
                 self.infcx
                     .inner
                     .borrow_mut()
@@ -178,7 +178,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     .map(|v| v.to_type(tcx)),
                 ty::FloatVar(v),
                 ty::FreshFloatTy,
-            )),
+            ),
 
             ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => {
                 if ct >= self.ty_freshen_count {
@@ -189,7 +189,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                         self.ty_freshen_count
                     );
                 }
-                Ok(t)
+                t
             }
 
             ty::Generator(..)
@@ -221,10 +221,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match ct.val {
             ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
                 let opt_ct = self
@@ -235,12 +232,12 @@ fn fold_const(
                     .probe_value(v)
                     .val
                     .known();
-                return Ok(self.freshen_const(
+                return self.freshen_const(
                     opt_ct,
                     ty::InferConst::Var(v),
                     ty::InferConst::Fresh,
                     ct.ty,
-                ));
+                );
             }
             ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
                 if i >= self.const_freshen_count {
@@ -251,7 +248,7 @@ fn fold_const(
                         self.const_freshen_count,
                     );
                 }
-                return Ok(ct);
+                return ct;
             }
 
             ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
index 4e6f1315d102437ecf565992403cf0548181c6a4..773753a0363264400be63ce562bae19850ffa3e8 100644 (file)
@@ -161,7 +161,7 @@ pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
         {
             Ok(value)
         } else {
-            Ok(value.fold_with(&mut fudger).into_ok())
+            Ok(value.fold_with(&mut fudger))
         }
     }
 }
@@ -180,7 +180,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match *ty.kind() {
             ty::Infer(ty::InferTy::TyVar(vid)) => {
                 if self.type_vars.0.contains(&vid) {
@@ -188,7 +188,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     // Recreate it with a fresh variable here.
                     let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize;
                     let origin = self.type_vars.1[idx];
-                    Ok(self.infcx.next_ty_var(origin))
+                    self.infcx.next_ty_var(origin)
                 } else {
                     // This variable was created before the
                     // "fudging". Since we refresh all type
@@ -198,43 +198,48 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     debug_assert!(
                         self.infcx.inner.borrow_mut().type_variables().probe(vid).is_unknown()
                     );
-                    Ok(ty)
+                    ty
                 }
             }
             ty::Infer(ty::InferTy::IntVar(vid)) => {
-                Ok(if self.int_vars.contains(&vid) { self.infcx.next_int_var() } else { ty })
+                if self.int_vars.contains(&vid) {
+                    self.infcx.next_int_var()
+                } else {
+                    ty
+                }
             }
             ty::Infer(ty::InferTy::FloatVar(vid)) => {
-                Ok(if self.float_vars.contains(&vid) { self.infcx.next_float_var() } else { ty })
+                if self.float_vars.contains(&vid) {
+                    self.infcx.next_float_var()
+                } else {
+                    ty
+                }
             }
             _ => ty.super_fold_with(self),
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         if let ty::ReVar(vid) = *r {
             if self.region_vars.0.contains(&vid) {
                 let idx = vid.index() - self.region_vars.0.start.index();
                 let origin = self.region_vars.1[idx];
-                return Ok(self.infcx.next_region_var(origin));
+                return self.infcx.next_region_var(origin);
             }
         }
-        Ok(r)
+        r
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ty::Const { val: ty::ConstKind::Infer(ty::InferConst::Var(vid)), ty } = ct {
             if self.const_vars.0.contains(&vid) {
                 // This variable was created during the fudging.
                 // Recreate it with a fresh variable here.
                 let idx = (vid.index - self.const_vars.0.start.index) as usize;
                 let origin = self.const_vars.1[idx];
-                Ok(self.infcx.next_const_var(ty, origin))
+                self.infcx.next_const_var(ty, origin)
             } else {
-                Ok(ct)
+                ct
             }
         } else {
             ct.super_fold_with(self)
index 4a9a63e1c76029357a4f14f033ff386c4560c6f6..48dfa0b6342d9d90734943ba038904ba6039ffae 100644 (file)
@@ -21,6 +21,7 @@
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::mir::interpret::EvalToConstValueResult;
 use rustc_middle::traits::select;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -681,7 +682,7 @@ pub fn is_in_snapshot(&self) -> bool {
     }
 
     pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
-        t.fold_with(&mut self.freshener()).into_ok()
+        t.fold_with(&mut self.freshener())
     }
 
     /// Returns the origin of the type variable identified by `vid`, or `None`
@@ -1381,7 +1382,7 @@ pub fn shallow_resolve<T>(&self, value: T) -> T
     where
         T: TypeFoldable<'tcx>,
     {
-        value.fold_with(&mut ShallowResolver { infcx: self }).into_ok()
+        value.fold_with(&mut ShallowResolver { infcx: self })
     }
 
     pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@@ -1402,7 +1403,7 @@ pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
             return value; // Avoid duplicated subst-folding.
         }
         let mut r = resolve::OpportunisticVarResolver::new(self);
-        value.fold_with(&mut r).into_ok()
+        value.fold_with(&mut r)
     }
 
     /// Returns the first unresolved variable contained in `T`. In the
@@ -1584,13 +1585,27 @@ pub fn const_eval_resolve(
         unevaluated: ty::Unevaluated<'tcx>,
         span: Option<Span>,
     ) -> EvalToConstValueResult<'tcx> {
-        let mut original_values = OriginalQueryValues::default();
-        let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values);
+        let mut substs = unevaluated.substs(self.tcx);
+        substs = self.resolve_vars_if_possible(substs);
+
+        // Postpone the evaluation of constants whose substs depend on inference
+        // variables
+        if substs.has_infer_types_or_consts() {
+            return Err(ErrorHandled::TooGeneric);
+        }
+
+        let param_env_erased = self.tcx.erase_regions(param_env);
+        let substs_erased = self.tcx.erase_regions(substs);
+
+        let unevaluated = ty::Unevaluated {
+            def: unevaluated.def,
+            substs_: Some(substs_erased),
+            promoted: unevaluated.promoted,
+        };
 
-        let (param_env, unevaluated) = canonical.value;
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
-        self.tcx.const_eval_resolve(param_env, unevaluated, span)
+        self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
     }
 
     /// If `typ` is a type variable of some kind, resolve it one level
@@ -1745,15 +1760,12 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        Ok(self.infcx.shallow_resolve_ty(ty))
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.infcx.shallow_resolve_ty(ty)
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-        Ok(if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
             self.infcx
                 .inner
                 .borrow_mut()
@@ -1764,7 +1776,7 @@ fn fold_const(
                 .unwrap_or(ct)
         } else {
             ct
-        })
+        }
     }
 }
 
index 932f26d5550108df9dcc679cd84ddf5bb547cc2a..89c14bcc2ce2bd76beac8d879eddfac2f3e73afa 100644 (file)
@@ -418,94 +418,91 @@ struct Instantiator<'a, 'tcx> {
 impl<'a, 'tcx> Instantiator<'a, 'tcx> {
     fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
         let tcx = self.infcx.tcx;
-        value
-            .fold_with(&mut BottomUpFolder {
-                tcx,
-                ty_op: |ty| {
-                    if ty.references_error() {
-                        return tcx.ty_error();
-                    } else if let ty::Opaque(def_id, substs) = ty.kind() {
-                        // Check that this is `impl Trait` type is
-                        // declared by `parent_def_id` -- i.e., one whose
-                        // value we are inferring.  At present, this is
-                        // always true during the first phase of
-                        // type-check, but not always true later on during
-                        // NLL. Once we support named opaque types more fully,
-                        // this same scenario will be able to arise during all phases.
-                        //
-                        // Here is an example using type alias `impl Trait`
-                        // that indicates the distinction we are checking for:
-                        //
-                        // ```rust
-                        // mod a {
-                        //   pub type Foo = impl Iterator;
-                        //   pub fn make_foo() -> Foo { .. }
-                        // }
-                        //
-                        // mod b {
-                        //   fn foo() -> a::Foo { a::make_foo() }
-                        // }
-                        // ```
-                        //
-                        // Here, the return type of `foo` references an
-                        // `Opaque` indeed, but not one whose value is
-                        // presently being inferred. You can get into a
-                        // similar situation with closure return types
-                        // today:
-                        //
-                        // ```rust
-                        // fn foo() -> impl Iterator { .. }
-                        // fn bar() {
-                        //     let x = || foo(); // returns the Opaque assoc with `foo`
-                        // }
-                        // ```
-                        if let Some(def_id) = def_id.as_local() {
-                            let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                            let parent_def_id = self.infcx.defining_use_anchor;
-                            let def_scope_default = || {
-                                let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
-                                parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
-                            };
-                            let (in_definition_scope, origin) =
-                                match tcx.hir().expect_item(opaque_hir_id).kind {
-                                    // Anonymous `impl Trait`
-                                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                        impl_trait_fn: Some(parent),
-                                        origin,
-                                        ..
-                                    }) => (parent == parent_def_id.to_def_id(), origin),
-                                    // Named `type Foo = impl Bar;`
-                                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                        impl_trait_fn: None,
-                                        origin,
-                                        ..
-                                    }) => (
-                                        may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
-                                        origin,
-                                    ),
-                                    _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
-                                };
-                            if in_definition_scope {
-                                let opaque_type_key =
-                                    OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
-                                return self.fold_opaque_ty(ty, opaque_type_key, origin);
+        value.fold_with(&mut BottomUpFolder {
+            tcx,
+            ty_op: |ty| {
+                if ty.references_error() {
+                    return tcx.ty_error();
+                } else if let ty::Opaque(def_id, substs) = ty.kind() {
+                    // Check that this is `impl Trait` type is
+                    // declared by `parent_def_id` -- i.e., one whose
+                    // value we are inferring.  At present, this is
+                    // always true during the first phase of
+                    // type-check, but not always true later on during
+                    // NLL. Once we support named opaque types more fully,
+                    // this same scenario will be able to arise during all phases.
+                    //
+                    // Here is an example using type alias `impl Trait`
+                    // that indicates the distinction we are checking for:
+                    //
+                    // ```rust
+                    // mod a {
+                    //   pub type Foo = impl Iterator;
+                    //   pub fn make_foo() -> Foo { .. }
+                    // }
+                    //
+                    // mod b {
+                    //   fn foo() -> a::Foo { a::make_foo() }
+                    // }
+                    // ```
+                    //
+                    // Here, the return type of `foo` references an
+                    // `Opaque` indeed, but not one whose value is
+                    // presently being inferred. You can get into a
+                    // similar situation with closure return types
+                    // today:
+                    //
+                    // ```rust
+                    // fn foo() -> impl Iterator { .. }
+                    // fn bar() {
+                    //     let x = || foo(); // returns the Opaque assoc with `foo`
+                    // }
+                    // ```
+                    if let Some(def_id) = def_id.as_local() {
+                        let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                        let parent_def_id = self.infcx.defining_use_anchor;
+                        let def_scope_default = || {
+                            let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
+                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
+                        };
+                        let (in_definition_scope, origin) = match tcx.hir().expect_item(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 };
+                            return self.fold_opaque_ty(ty, opaque_type_key, origin);
+                        }
 
-                            debug!(
-                                "instantiate_opaque_types_in_map: \
+                        debug!(
+                            "instantiate_opaque_types_in_map: \
                              encountered opaque outside its definition scope \
                              def_id={:?}",
-                                def_id,
-                            );
-                        }
+                            def_id,
+                        );
                     }
+                }
 
-                    ty
-                },
-                lt_op: |lt| lt,
-                ct_op: |ct| ct,
-            })
-            .into_ok()
+                ty
+            },
+            lt_op: |lt| lt,
+            ct_op: |ct| ct,
+        })
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -558,23 +555,21 @@ fn fold_opaque_ty(
             debug!(?predicate);
 
             // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
-            let predicate = predicate
-                .fold_with(&mut BottomUpFolder {
-                    tcx,
-                    ty_op: |ty| match ty.kind() {
-                        ty::Projection(projection_ty) => infcx.infer_projection(
-                            self.param_env,
-                            *projection_ty,
-                            traits::ObligationCause::misc(self.value_span, self.body_id),
-                            0,
-                            &mut self.obligations,
-                        ),
-                        _ => ty,
-                    },
-                    lt_op: |lt| lt,
-                    ct_op: |ct| ct,
-                })
-                .into_ok();
+            let predicate = predicate.fold_with(&mut BottomUpFolder {
+                tcx,
+                ty_op: |ty| match ty.kind() {
+                    ty::Projection(projection_ty) => infcx.infer_projection(
+                        self.param_env,
+                        *projection_ty,
+                        traits::ObligationCause::misc(self.value_span, self.body_id),
+                        0,
+                        &mut self.obligations,
+                    ),
+                    _ => ty,
+                },
+                lt_op: |lt| lt,
+                ct_op: |ct| ct,
+            });
             debug!(?predicate);
 
             if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
index cccdfb7452a77fd7db25cda5f59171172640f610..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;
@@ -30,28 +30,25 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if !t.has_infer_types_or_consts() {
-            Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
+            t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
             t.super_fold_with(self)
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> Result<&'tcx Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
         if !ct.has_infer_types_or_consts() {
-            Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects...
+            ct // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let ct = self.infcx.shallow_resolve(ct);
             ct.super_fold_with(self)
         }
     }
 
-    fn fold_mir_const(
-        &mut self,
-        constant: mir::ConstantKind<'tcx>,
-    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+    fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
         constant.super_fold_with(self)
     }
 }
@@ -78,16 +75,16 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if !t.has_infer_regions() {
-            Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
+            t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             t.super_fold_with(self)
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        Ok(match *r {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match *r {
             ty::ReVar(rid) => {
                 let resolved = self
                     .infcx
@@ -98,15 +95,12 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                 self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
             }
             _ => r,
-        })
+        }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if !ct.has_infer_regions() {
-            Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects...
+            ct // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             ct.super_fold_with(self)
         }
@@ -181,7 +175,7 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> Fixu
 where
     T: TypeFoldable<'tcx>,
 {
-    value.fold_with(&mut FullTypeResolver { infcx })
+    value.try_fold_with(&mut FullTypeResolver { infcx })
 }
 
 // N.B. This type is not public because the protocol around checking the
@@ -196,8 +190,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
+}
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+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() {
             Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
@@ -209,12 +205,12 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 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>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReVar(rid) => Ok(self
                 .infcx
@@ -227,7 +223,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
         }
     }
 
-    fn fold_const(
+    fn try_fold_const(
         &mut self,
         c: &'tcx ty::Const<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
@@ -244,7 +240,7 @@ fn fold_const(
                 }
                 _ => {}
             }
-            c.super_fold_with(self)
+            c.try_super_fold_with(self)
         }
     }
 }
index 5153427954ccc723f761dbf1f79ab274146b8f1f..e4b407e7c112d838057df364b0d4de3c1f13e5d3 100644 (file)
@@ -24,7 +24,6 @@
 #![feature(control_flow_enum)]
 #![feature(min_specialization)]
 #![feature(label_break_value)]
-#![feature(unwrap_infallible)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
index 544b89397790a0f6b321228f346771ec6e95e49a..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,12 +60,15 @@ 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) -> Result<Self, F::Error> {
+    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)?,
         })
     }
 
index d3917dfb14ab3126bd4cedf61c2e79a2a175617d..dbee92cf598b5b855e9fa25a4354feeb1966e346 100644 (file)
@@ -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)
         };
index 6147311af6159a0e36616714b4d8b67f87ed6b01..c651feaaa66f62cf5b0d1718ce6eb193bc5833d0 100644 (file)
@@ -651,7 +651,6 @@ macro_rules! untracked {
     untracked!(dump_mir_dir, String::from("abc"));
     untracked!(dump_mir_exclude_pass_number, true);
     untracked!(dump_mir_graphviz, true);
-    untracked!(emit_future_incompat_report, true);
     untracked!(emit_stack_sizes, true);
     untracked!(future_incompat_test, true);
     untracked!(hir_stats, true);
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 44b002fa93f42d1843095450b593413e8956ef5e..5b8300ab530f92632b22fa65f03282118b89833b 100644 (file)
@@ -227,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)
     })
 }
 
@@ -832,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 d8883b0e66dba77be936bb086f2197af5d384880..4a24f803e8463b2c15bb765e54661389050539ad 100644 (file)
@@ -79,9 +79,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
             let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
             let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
 
-            let target = match adjustments.last() {
-                Some(Adjustment { kind: Adjust::Borrow(_), target }) => target,
-                _ => return,
+            let Some(Adjustment { kind: Adjust::Borrow(_), target }) = adjustments.last() else {
+                return
             };
 
             let types =
index f2e4e70a197796923fb8eae72e799cb39d829d74..5dbcc1655c906f354b4046f0cbed2195ab663a38 100644 (file)
@@ -609,14 +609,12 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
                 // If the trait is private, add the impl items to `private_traits` so they don't get
                 // reported for missing docs.
                 let real_trait = trait_ref.path.res.def_id();
-                if let Some(def_id) = real_trait.as_local() {
-                    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
-                    if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) {
-                        if let hir::VisibilityKind::Inherited = item.vis.node {
-                            for impl_item_ref in items {
-                                self.private_traits.insert(impl_item_ref.id.hir_id());
-                            }
-                        }
+                let Some(def_id) = real_trait.as_local() else { return };
+                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+                let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) else { return };
+                if let hir::VisibilityKind::Inherited = item.vis.node {
+                    for impl_item_ref in items {
+                        self.private_traits.insert(impl_item_ref.id.hir_id());
                     }
                 }
                 return;
@@ -829,9 +827,8 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
             _ => return,
         }
 
-        let debug = match cx.tcx.get_diagnostic_item(sym::Debug) {
-            Some(debug) => debug,
-            None => return,
+        let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else {
+            return
         };
 
         if self.impling_types.is_none() {
@@ -1079,6 +1076,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! {
@@ -1505,9 +1506,8 @@ fn visit_qpath(&mut self, qpath: &'v hir::QPath<'v>, id: hir::HirId, span: Span)
 
 impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        let (ty, type_alias_generics) = match item.kind {
-            hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics),
-            _ => return,
+        let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else {
+            return
         };
         if let hir::TyKind::OpaqueDef(..) = ty.kind {
             // Bounds are respected for `type X = impl Trait`
@@ -2262,16 +2262,15 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
                         // and should check for them here.
                         match predicate.bounded_ty.kind {
                             hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
-                                if let Res::Def(DefKind::TyParam, def_id) = path.res {
-                                    let index = ty_generics.param_def_id_to_index[&def_id];
-                                    (
-                                        Self::lifetimes_outliving_type(inferred_outlives, index),
-                                        &predicate.bounds,
-                                        predicate.span,
-                                    )
-                                } else {
-                                    continue;
-                                }
+                                let Res::Def(DefKind::TyParam, def_id) = path.res else {
+                                    continue
+                                };
+                                let index = ty_generics.param_def_id_to_index[&def_id];
+                                (
+                                    Self::lifetimes_outliving_type(inferred_outlives, index),
+                                    &predicate.bounds,
+                                    predicate.span,
+                                )
                             }
                             _ => {
                                 continue;
@@ -3011,7 +3010,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
@@ -3212,18 +3211,17 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
                     for (idx, _) in statement.match_indices(':') {
                         let possible_label = statement[start_idx..idx].trim();
                         let mut chars = possible_label.chars();
-                        if let Some(c) = chars.next() {
-                            // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
-                            if (c.is_alphabetic() || matches!(c, '.' | '_'))
-                                && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
-                            {
-                                found_labels.push(possible_label);
-                            } else {
-                                // If we encounter a non-label, there cannot be any further labels, so stop checking
-                                break;
-                            }
-                        } else {
+                        let Some(c) = chars.next() else {
                             // Empty string means a leading ':' in this section, which is not a label
+                            break
+                        };
+                        // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
+                        if (c.is_alphabetic() || matches!(c, '.' | '_'))
+                            && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
+                        {
+                            found_labels.push(possible_label);
+                        } else {
+                            // If we encounter a non-label, there cannot be any further labels, so stop checking
                             break;
                         }
 
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 b6d66eb12d08314e19aa0e65fee5e343a18aa408..485728cbfd39d3e0ff85141702d6d0aae1d8dcc9 100644 (file)
@@ -227,14 +227,12 @@ pub(crate) fn push(
         let sess = self.sess;
         let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
         for attr in attrs {
-            let level = match Level::from_symbol(attr.name_or_empty()) {
-                None => continue,
-                Some(lvl) => lvl,
+            let Some(level) = Level::from_symbol(attr.name_or_empty()) else {
+                continue
             };
 
-            let mut metas = match attr.meta_item_list() {
-                Some(x) => x,
-                None => continue,
+            let Some(mut metas) = attr.meta_item_list() else {
+                continue
             };
 
             if metas.is_empty() {
@@ -481,9 +479,8 @@ pub(crate) fn push(
                     continue;
                 }
 
-                let (lint_attr_name, lint_attr_span) = match *src {
-                    LintLevelSource::Node(name, span, _) => (name, span),
-                    _ => continue,
+                let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else {
+                    continue
                 };
 
                 let lint = builtin::UNUSED_ATTRIBUTES;
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..600504f7c1280973c018386ecc2afacba0fb2fbc 100644 (file)
@@ -40,9 +40,8 @@
 impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // We only care about method calls.
-        let (call, elements) = match expr.kind {
-            ExprKind::MethodCall(call, _, elements, _) => (call, elements),
-            _ => return,
+        let ExprKind::MethodCall(call, _, elements, _) = &expr.kind else {
+            return
         };
         // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
         // traits and ignore any other method call.
@@ -70,43 +69,40 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         }
         let param_env = cx.tcx.param_env(trait_id);
         // Resolve the trait method instance.
-        let i = match ty::Instance::resolve(cx.tcx, param_env, did, substs) {
-            Ok(Some(i)) => i,
-            _ => return,
+        let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) else {
+            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 5435ff1396de800c0841de33c4c74ae4dbfb9df0..dafff640b36ef3d1bee3d26eb87e14931807e1ed 100644 (file)
@@ -91,9 +91,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
 
         let predicates = cx.tcx.explicit_predicates_of(item.def_id);
         for &(predicate, span) in predicates.predicates {
-            let trait_predicate = match predicate.kind().skip_binder() {
-                Trait(trait_predicate) => trait_predicate,
-                _ => continue,
+            let Trait(trait_predicate) = predicate.kind().skip_binder() else {
+                continue
             };
             if trait_predicate.constness == ty::BoundConstness::ConstIfConst {
                 // `~const Drop` definitely have meanings so avoid linting here.
@@ -106,9 +105,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                     continue;
                 }
                 cx.struct_span_lint(DROP_BOUNDS, span, |lint| {
-                    let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) {
-                        Some(needs_drop) => needs_drop,
-                        None => return,
+                    let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
+                        return
                     };
                     let msg = format!(
                         "bounds on `{}` are most likely incorrect, consider instead \
@@ -123,17 +121,15 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
     }
 
     fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
-        let bounds = match &ty.kind {
-            hir::TyKind::TraitObject(bounds, _lifetime, _syntax) => bounds,
-            _ => return,
+        let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else {
+            return
         };
         for bound in &bounds[..] {
             let def_id = bound.trait_ref.trait_def_id();
             if cx.tcx.lang_items().drop_trait() == def_id {
                 cx.struct_span_lint(DYN_DROP, bound.span, |lint| {
-                    let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) {
-                        Some(needs_drop) => needs_drop,
-                        None => return,
+                    let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
+                        return
                     };
                     let msg = format!(
                         "types that do not implement `Drop` can still have drop glue, consider \
index 708cd56e068b537c40be4088eb3d961194443b2f..32ed6dad7f8c349b5f411924759610e540b26a6c 100644 (file)
@@ -1337,14 +1337,15 @@ 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 {
-                Variants::Multiple {
+            let Variants::Multiple {
                     tag_encoding: TagEncoding::Direct, tag, ref variants, ..
-                } => (variants, tag),
-                _ => return,
+                } = &layout.variants else {
+                return
             };
 
             let tag_size = tag.value.size(&cx.tcx).bytes();
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 94d2a4b8e4c9be23d2b505b48e576fbc6c1c79d7..3fbf020c552d741842f715b26b2bbd23854a2e2c 100644 (file)
@@ -445,11 +445,20 @@ extern "C" LLVMValueRef
 LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
                   char *Constraints, size_t ConstraintsLen,
                   LLVMBool HasSideEffects, LLVMBool IsAlignStack,
-                  LLVMRustAsmDialect Dialect) {
+                  LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
+#if LLVM_VERSION_GE(13, 0)
+  return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
+                             StringRef(AsmString, AsmStringLen),
+                             StringRef(Constraints, ConstraintsLen),
+                             HasSideEffects, IsAlignStack,
+                             fromRust(Dialect), CanThrow));
+#else
   return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
                              StringRef(AsmString, AsmStringLen),
                              StringRef(Constraints, ConstraintsLen),
-                             HasSideEffects, IsAlignStack, fromRust(Dialect)));
+                             HasSideEffects, IsAlignStack,
+                             fromRust(Dialect)));
+#endif
 }
 
 extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
index 769f009b492067c7141a871334025929f9b912aa..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,7 +25,7 @@ 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
             ) -> Result<Self, __F::Error> {
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 b67ad8b770ea1537ca2e8264d2a36a5eeb50cb30..66d1ae1420a143d11f46ff2aaaae422cb38e4862 100644 (file)
@@ -51,7 +51,6 @@
 #![feature(control_flow_enum)]
 #![feature(associated_type_defaults)]
 #![feature(iter_zip)]
-#![feature(thread_local_const_init)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![feature(try_reserve_kind)]
index c0cf265b2287957f1edd0fb8eb5513d00f2c165d..4e927f00acd5eda6cc42bf9c773746e402ee6676 100644 (file)
@@ -52,7 +52,7 @@ 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
                 ) -> ::std::result::Result<$ty, F::Error> {
@@ -95,7 +95,7 @@ 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,
             ) -> ::std::result::Result<Self, V::Error> {
@@ -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)*
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 a05b8a1da8d7f008a8b9def9e6395eccff64ac93..75edcaadfdff26adf39425a16d88f3531ca2f496 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};
@@ -16,6 +16,7 @@
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::{self, GeneratorKind};
 use rustc_hir::{self as hir, HirId};
+use rustc_session::Session;
 use rustc_target::abi::{Size, VariantIdx};
 
 use polonius_engine::Atom;
@@ -99,7 +100,21 @@ fn name(&self) -> Cow<'_, str> {
         }
     }
 
+    /// Returns `true` if this pass is enabled with the current combination of compiler flags.
+    fn is_enabled(&self, _sess: &Session) -> bool {
+        true
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
+
+    /// If this pass causes the MIR to enter a new phase, return that phase.
+    fn phase_change(&self) -> Option<MirPhase> {
+        None
+    }
+
+    fn is_mir_dump_enabled(&self) -> bool {
+        true
+    }
 }
 
 /// The various "big phases" that MIR goes through.
@@ -1803,6 +1818,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
@@ -2760,10 +2785,13 @@ pub(crate) fn variant(
 TrivialTypeFoldableAndLiftImpls! { ProjectionKind, }
 
 impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         Ok(UserTypeProjection {
-            base: self.base.fold_with(folder)?,
-            projs: self.projs.fold_with(folder)?,
+            base: self.base.try_fold_with(folder)?,
+            projs: self.projs.try_fold_with(folder)?,
         })
     }
 
index e78b6fd092de2695b71d6ce9a762275237d55168..a82f98d28e723f8dbfd19258ee1771919d105ec9 100644 (file)
@@ -260,6 +260,10 @@ pub enum TerminatorKind<'tcx> {
         /// Destination block after the inline assembly returns, unless it is
         /// diverging (InlineAsmOptions::NORETURN).
         destination: Option<BasicBlock>,
+
+        /// Cleanup to be done if the inline assembly unwinds. This is present
+        /// if and only if InlineAsmOptions::MAY_UNWIND is set.
+        cleanup: Option<BasicBlock>,
     },
 }
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -309,7 +313,7 @@ pub fn successors(&self) -> Successors<'_> {
             | Return
             | Unreachable
             | Call { destination: None, cleanup: None, .. }
-            | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]),
+            | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]),
             Goto { target: ref t }
             | Call { destination: None, cleanup: Some(ref t), .. }
             | Call { destination: Some((_, ref t)), cleanup: None, .. }
@@ -318,13 +322,17 @@ pub fn successors(&self) -> Successors<'_> {
             | Drop { target: ref t, unwind: None, .. }
             | Assert { target: ref t, cleanup: None, .. }
             | FalseUnwind { real_target: ref t, unwind: None }
-            | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]),
+            | InlineAsm { destination: Some(ref t), cleanup: None, .. }
+            | InlineAsm { destination: None, cleanup: Some(ref t), .. } => {
+                Some(t).into_iter().chain(&[])
+            }
             Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. }
             | Yield { resume: ref t, drop: Some(ref u), .. }
             | DropAndReplace { target: ref t, unwind: Some(ref u), .. }
             | Drop { target: ref t, unwind: Some(ref u), .. }
             | Assert { target: ref t, cleanup: Some(ref u), .. }
-            | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
+            | FalseUnwind { real_target: ref t, unwind: Some(ref u) }
+            | InlineAsm { destination: Some(ref t), cleanup: Some(ref u), .. } => {
                 Some(t).into_iter().chain(slice::from_ref(u))
             }
             SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets[..]),
@@ -343,7 +351,7 @@ pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
             | Return
             | Unreachable
             | Call { destination: None, cleanup: None, .. }
-            | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []),
+            | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
             Goto { target: ref mut t }
             | Call { destination: None, cleanup: Some(ref mut t), .. }
             | Call { destination: Some((_, ref mut t)), cleanup: None, .. }
@@ -352,13 +360,17 @@ pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
             | Drop { target: ref mut t, unwind: None, .. }
             | Assert { target: ref mut t, cleanup: None, .. }
             | FalseUnwind { real_target: ref mut t, unwind: None }
-            | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []),
+            | InlineAsm { destination: Some(ref mut t), cleanup: None, .. }
+            | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => {
+                Some(t).into_iter().chain(&mut [])
+            }
             Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
             | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
             | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
             | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
             | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
-            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
+            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) }
+            | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => {
                 Some(t).into_iter().chain(slice::from_mut(u))
             }
             SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets[..]),
@@ -378,13 +390,13 @@ pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::InlineAsm { .. } => None,
+            | TerminatorKind::FalseEdge { .. } => None,
             TerminatorKind::Call { cleanup: ref unwind, .. }
             | TerminatorKind::Assert { cleanup: ref unwind, .. }
             | TerminatorKind::DropAndReplace { ref unwind, .. }
             | TerminatorKind::Drop { ref unwind, .. }
-            | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
+            | TerminatorKind::FalseUnwind { ref unwind, .. }
+            | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind),
         }
     }
 
@@ -398,13 +410,13 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::InlineAsm { .. } => None,
+            | TerminatorKind::FalseEdge { .. } => None,
             TerminatorKind::Call { cleanup: ref mut unwind, .. }
             | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
             | TerminatorKind::DropAndReplace { ref mut unwind, .. }
             | TerminatorKind::Drop { ref mut unwind, .. }
-            | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind),
+            | TerminatorKind::FalseUnwind { ref mut unwind, .. }
+            | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind),
         }
     }
 
@@ -583,8 +595,12 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
             FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
             FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
             FalseUnwind { unwind: None, .. } => vec!["real".into()],
-            InlineAsm { destination: Some(_), .. } => vec!["".into()],
-            InlineAsm { destination: None, .. } => vec![],
+            InlineAsm { destination: Some(_), cleanup: Some(_), .. } => {
+                vec!["return".into(), "unwind".into()]
+            }
+            InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
+            InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
+            InlineAsm { destination: None, cleanup: None, .. } => vec![],
         }
     }
 }
index df7c6d9cf66501a41b67d809f66a4999f259af78..901f3bf4f7d41b84603a6d89a04acfd670a59fee 100644 (file)
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+    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).map(|loc| (loc, dest))))
+                    .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,
@@ -58,16 +61,19 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F:
             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 +84,16 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F:
                 FalseEdge { real_target, imaginary_target }
             }
             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
-            InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
-                template,
-                operands: operands.fold_with(folder)?,
-                options,
-                line_spans,
-                destination,
-            },
+            InlineAsm { template, operands, options, line_spans, destination, cleanup } => {
+                InlineAsm {
+                    template,
+                    operands: operands.try_fold_with(folder)?,
+                    options,
+                    line_spans,
+                    destination,
+                    cleanup,
+                }
+            }
         };
         Ok(Terminator { source_info: self.source_info, kind })
     }
@@ -142,7 +151,7 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
         Ok(self)
     }
 
@@ -152,10 +161,13 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         Ok(Place {
-            local: self.local.fold_with(folder)?,
-            projection: self.projection.fold_with(folder)?,
+            local: self.local.try_fold_with(folder)?,
+            projection: self.projection.try_fold_with(folder)?,
         })
     }
 
@@ -166,7 +178,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) -> Result<Self, F::Error> {
+    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))
     }
 
@@ -176,48 +191,56 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::mir::Rvalue::*;
         Ok(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)?)))
+            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.try_map_id(|kind| {
                     Ok(match kind {
-                        AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)?),
+                        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.fold_with(folder)?,
-                            user_ty.fold_with(folder)?,
+                            substs.try_fold_with(folder)?,
+                            user_ty.try_fold_with(folder)?,
                             n,
                         ),
                         AggregateKind::Closure(id, substs) => {
-                            AggregateKind::Closure(id, substs.fold_with(folder)?)
+                            AggregateKind::Closure(id, substs.try_fold_with(folder)?)
                         }
                         AggregateKind::Generator(id, substs, movablity) => {
-                            AggregateKind::Generator(id, substs.fold_with(folder)?, movablity)
+                            AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity)
                         }
                     })
                 })?;
-                Aggregate(kind, fields.fold_with(folder)?)
+                Aggregate(kind, fields.try_fold_with(folder)?)
+            }
+            ShallowInitBox(op, ty) => {
+                ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?)
             }
-            ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder)?, ty.fold_with(folder)?),
         })
     }
 
@@ -272,11 +295,14 @@ 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) -> Result<Self, F::Error> {
+    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.fold_with(folder)?),
-            Operand::Move(place) => Operand::Move(place.fold_with(folder)?),
-            Operand::Constant(c) => Operand::Constant(c.fold_with(folder)?),
+            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)?),
         })
     }
 
@@ -289,13 +315,16 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::mir::ProjectionElem::*;
 
         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 }
@@ -319,7 +348,7 @@ fn super_visit_with<Vs: TypeVisitor<'tcx>>(
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Field {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+    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> {
@@ -328,7 +357,7 @@ 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) -> Result<Self, F::Error> {
+    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> {
@@ -337,7 +366,7 @@ 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) -> Result<Self, F::Error> {
+    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> {
@@ -346,11 +375,14 @@ 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) -> Result<Self, F::Error> {
+    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> {
@@ -361,14 +393,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) -> Result<Self, F::Error> {
-        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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         match self {
-            ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.fold_with(folder)?)),
-            ConstantKind::Val(v, t) => Ok(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..d783b6330e8e5dd0ad5d75bbc8d812cd517f7897 100644 (file)
@@ -412,7 +412,7 @@ fn super_statement(&mut self,
                         for output in & $($mutability)? asm.outputs[..] {
                             self.visit_place(
                                 output,
-                                PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
+                                PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput),
                                 location
                             );
                         }
@@ -581,6 +581,7 @@ fn super_terminator(&mut self,
                         options: _,
                         line_spans: _,
                         destination: _,
+                        cleanup: _,
                     } => {
                         for op in operands {
                             match op {
@@ -590,7 +591,7 @@ fn super_terminator(&mut self,
                                 InlineAsmOperand::Out { place: Some(place), .. } => {
                                     self.visit_place(
                                         place,
-                                        PlaceContext::MutatingUse(MutatingUseContext::Store),
+                                        PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                         location,
                                     );
                                 }
@@ -599,7 +600,7 @@ fn super_terminator(&mut self,
                                     if let Some(out_place) = out_place {
                                         self.visit_place(
                                             out_place,
-                                            PlaceContext::MutatingUse(MutatingUseContext::Store),
+                                            PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                             location,
                                         );
                                     }
@@ -1004,8 +1005,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,
@@ -1174,8 +1179,10 @@ pub enum MutatingUseContext {
     /// Appears as LHS of an assignment.
     Store,
     /// Can often be treated as a `Store`, but needs to be separate because
-    /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
+    /// ASM is allowed to read outputs as well, so a `Store`-`LlvmAsmOutput` sequence
     /// cannot be simplified the way a `Store`-`Store` can be.
+    LlvmAsmOutput,
+    /// Output operand of an inline assembly block.
     AsmOutput,
     /// Destination of a call.
     Call,
@@ -1264,6 +1271,7 @@ pub fn is_place_assignment(&self) -> bool {
             PlaceContext::MutatingUse(
                 MutatingUseContext::Store
                     | MutatingUseContext::Call
+                    | MutatingUseContext::LlvmAsmOutput
                     | MutatingUseContext::AsmOutput,
             )
         )
index ca93efbf19b7b14a472bae608aa8cd70d163860c..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)
         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 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 1b32c8a66989f7b8ded38db6a847e1170b292616..8803370251b38929f5acf2123573cb394db12f68 100644 (file)
@@ -270,7 +270,7 @@ pub fn suggest_constraining_type_param(
         // `where` clause instead of `trait Base<T: Copy = String>: Super<T>`.
         && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
     {
-        if let Some(bounds_span) = param.bounds_span() {
+        if let Some(span) = param.bounds_span_for_suggestions() {
             // If user has provided some bounds, suggest restricting them:
             //
             //   fn foo<T: Foo>(t: T) { ... }
@@ -284,7 +284,7 @@ pub fn suggest_constraining_type_param(
             //          --
             //          |
             //          replace with: `T: Bar +`
-            suggest_restrict(bounds_span.shrink_to_hi());
+            suggest_restrict(span);
         } else {
             // If user hasn't provided any bounds, suggest adding a new one:
             //
index 25b460cf16d3c7f5cfddbb7775fc1e566a306ed0..63eb55ed1a6208121d0e479810ae80209b0bce03 100644 (file)
@@ -9,7 +9,7 @@ pub(super) fn provide(providers: &mut ty::query::Providers) {
 fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     // N.B., use `super_fold_with` here. If we used `fold_with`, it
     // could invoke the `erase_regions_ty` query recursively.
-    ty.super_fold_with(&mut RegionEraserVisitor { tcx }).into_ok()
+    ty.super_fold_with(&mut RegionEraserVisitor { tcx })
 }
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -27,7 +27,7 @@ pub fn erase_regions<T>(self, value: T) -> T
             return value;
         }
         debug!("erase_regions({:?})", value);
-        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }).into_ok();
+        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
         debug!("erase_regions = {:?}", value1);
         value1
     }
@@ -42,11 +42,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        if ty.needs_infer() { ty.super_fold_with(self) } else { Ok(self.tcx.erase_regions_ty(ty)) }
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) }
     }
 
-    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error>
+    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -54,7 +54,7 @@ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx,
         u.super_fold_with(self)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         // because late-bound regions affect subtyping, we can't
         // erase the bound/free distinction, but we can replace
         // all free regions with 'erased.
@@ -64,15 +64,12 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
         // away. In codegen, they will always be erased to 'erased
         // whenever a substitution occurs.
         match *r {
-            ty::ReLateBound(..) => Ok(r),
-            _ => Ok(self.tcx.lifetimes.re_erased),
+            ty::ReLateBound(..) => r,
+            _ => self.tcx.lifetimes.re_erased,
         }
     }
 
-    fn fold_mir_const(
-        &mut self,
-        c: mir::ConstantKind<'tcx>,
-    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
         c.super_fold_with(self)
     }
 }
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 31055c03a5d36c73e551ddbf76377ef6699f081d..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) -> Result<Self, F::Error>;
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        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,7 +200,7 @@ fn still_further_specializable(&self) -> bool {
 }
 
 impl TypeFoldable<'tcx> for hir::Constness {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+    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> {
@@ -192,41 +213,102 @@ 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>) -> Result<Binder<'tcx, T>, Self::Error>
+    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>) -> Result<Ty<'tcx>, Self::Error> {
+    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>) -> Result<ty::Region<'tcx>, Self::Error> {
+    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(
+    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>
+    where
+        Self: TypeFolder<'tcx, Error = !>,
+    {
+        p.super_fold_with(self)
+    }
+
+    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.super_fold_with(self)
+        c.try_super_fold_with(self)
     }
 
-    fn fold_predicate(
+    fn try_fold_predicate(
         &mut self,
         p: ty::Predicate<'tcx>,
     ) -> Result<ty::Predicate<'tcx>, Self::Error> {
-        p.super_fold_with(self)
+        p.try_super_fold_with(self)
     }
 
-    fn fold_mir_const(
+    fn try_fold_mir_const(
         &mut self,
         c: mir::ConstantKind<'tcx>,
     ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
@@ -234,6 +316,49 @@ fn fold_mir_const(
     }
 }
 
+// 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
@@ -301,22 +426,19 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        let t = ty.super_fold_with(self)?;
-        Ok((self.ty_op)(t))
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        let t = ty.super_fold_with(self);
+        (self.ty_op)(t)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        let r = r.super_fold_with(self)?;
-        Ok((self.lt_op)(r))
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        let r = r.super_fold_with(self);
+        (self.lt_op)(r)
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-        let ct = ct.super_fold_with(self)?;
-        Ok((self.ct_op)(ct))
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        let ct = ct.super_fold_with(self);
+        (self.ct_op)(ct)
     }
 }
 
@@ -336,7 +458,7 @@ pub fn fold_regions<T>(
     where
         T: TypeFoldable<'tcx>,
     {
-        value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)).into_ok()
+        value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
     }
 
     /// Invoke `callback` on every region appearing free in `value`.
@@ -484,7 +606,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
@@ -492,16 +614,16 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
                 debug!(?self.current_index, "skipped bound region");
                 *self.skipped_regions = true;
-                Ok(r)
+                r
             }
             _ => {
                 debug!(?self.current_index, "folding free region");
-                Ok((self.fold_region_fn)(r, self.current_index))
+                (self.fold_region_fn)(r, self.current_index)
             }
         }
     }
@@ -542,19 +664,19 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
             ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
                 if let Some(fld_t) = self.fld_t.as_mut() {
                     let ty = fld_t(bound_ty);
-                    return Ok(ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32()));
+                    return ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32());
                 }
             }
             _ if t.has_vars_bound_at_or_above(self.current_index) => {
@@ -562,10 +684,10 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
             }
             _ => {}
         }
-        Ok(t)
+        t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
                 if let Some(fld_r) = self.fld_r.as_mut() {
@@ -576,28 +698,25 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                         // debruijn index. Then we adjust it to the
                         // correct depth.
                         assert_eq!(debruijn1, ty::INNERMOST);
-                        Ok(self.tcx.mk_region(ty::ReLateBound(debruijn, br)))
+                        self.tcx.mk_region(ty::ReLateBound(debruijn, br))
                     } else {
-                        Ok(region)
+                        region
                     };
                 }
             }
             _ => {}
         }
-        Ok(r)
+        r
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match *ct {
             ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty }
                 if debruijn == self.current_index =>
             {
                 if let Some(fld_c) = self.fld_c.as_mut() {
                     let ct = fld_c(bound_const, ty);
-                    return Ok(ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32()));
+                    return ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32());
                 }
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => {
@@ -605,7 +724,7 @@ fn fold_const(
             }
             _ => {}
         }
-        Ok(ct)
+        ct
     }
 }
 
@@ -638,7 +757,7 @@ pub fn replace_late_bound_regions<T, F>(
             value
         } else {
             let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None);
-            value.fold_with(&mut replacer).into_ok()
+            value.fold_with(&mut replacer)
         };
         (value, region_map)
     }
@@ -664,7 +783,7 @@ pub fn replace_escaping_bound_vars<T, F, G, H>(
         } else {
             let mut replacer =
                 BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c));
-            value.fold_with(&mut replacer).into_ok()
+            value.fold_with(&mut replacer)
         }
     }
 
@@ -955,36 +1074,36 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, br) => {
                 if self.amount == 0 || debruijn < self.current_index {
-                    Ok(r)
+                    r
                 } else {
                     let debruijn = debruijn.shifted_in(self.amount);
                     let shifted = ty::ReLateBound(debruijn, br);
-                    Ok(self.tcx.mk_region(shifted))
+                    self.tcx.mk_region(shifted)
                 }
             }
-            _ => Ok(r),
+            _ => r,
         }
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match *ty.kind() {
             ty::Bound(debruijn, bound_ty) => {
                 if self.amount == 0 || debruijn < self.current_index {
-                    Ok(ty)
+                    ty
                 } else {
                     let debruijn = debruijn.shifted_in(self.amount);
-                    Ok(self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)))
+                    self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
                 }
             }
 
@@ -992,18 +1111,13 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct {
             if self.amount == 0 || debruijn < self.current_index {
-                Ok(ct)
+                ct
             } else {
                 let debruijn = debruijn.shifted_in(self.amount);
-                Ok(self
-                    .tcx
-                    .mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty }))
+                self.tcx.mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty })
             }
         } else {
             ct.super_fold_with(self)
@@ -1030,7 +1144,7 @@ pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
 {
     debug!("shift_vars(value={:?}, amount={})", value, amount);
 
-    value.fold_with(&mut Shifter::new(tcx, amount)).into_ok()
+    value.fold_with(&mut Shifter::new(tcx, amount))
 }
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -1293,7 +1407,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// FIXME(@lcnr): explain this function a bit more
     pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T {
-        v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self }).into_ok()
+        v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self })
     }
 }
 
@@ -1306,22 +1420,19 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
             ty.super_fold_with(self)
         } else {
-            Ok(ty)
+            ty
         }
     }
 
-    fn fold_predicate(
-        &mut self,
-        pred: ty::Predicate<'tcx>,
-    ) -> Result<ty::Predicate<'tcx>, Self::Error> {
+    fn fold_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
         if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
             pred.super_fold_with(self)
         } else {
-            Ok(pred)
+            pred
         }
     }
 }
index 15931b8d2c86a85d0129437e207e9255cf26b0e9..4b38105e44717e52300e5b6f9e789e58f8093d12 100644 (file)
@@ -622,7 +622,7 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
             self.tcx
         }
 
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             debug!("fold_ty: ty={:?}", ty);
             match ty.kind {
                 ty::Closure(def_id, substs) => {
@@ -631,11 +631,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                         ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
                         substs,
                     );
-                    Ok(if substs == polymorphized_substs {
+                    if substs == polymorphized_substs {
                         ty
                     } else {
                         self.tcx.mk_closure(def_id, polymorphized_substs)
-                    })
+                    }
                 }
                 ty::Generator(def_id, substs, movability) => {
                     let polymorphized_substs = polymorphize(
@@ -643,11 +643,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                         ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
                         substs,
                     );
-                    Ok(if substs == polymorphized_substs {
+                    if substs == polymorphized_substs {
                         ty
                     } else {
                         self.tcx.mk_generator(def_id, polymorphized_substs, movability)
-                    })
+                    }
                 }
                 _ => ty.super_fold_with(self),
             }
@@ -669,7 +669,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     // ..and polymorphize any closures/generators captured as upvars.
                     let upvars_ty = upvars_ty.unwrap();
                     let polymorphized_upvars_ty = upvars_ty.fold_with(
-                        &mut PolymorphizationFolder { tcx }).into_ok();
+                        &mut PolymorphizationFolder { tcx });
                     debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty);
                     ty::GenericArg::from(polymorphized_upvars_ty)
                 },
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 2d6926703726c63e146b1d93f3555cdbe35ffd55..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,11 +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>>(
+    fn try_super_fold_with<F: ty::fold::FallibleTypeFolder<'tcx>>(
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        Ok(ParamEnv::new(self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?))
+        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> {
@@ -1708,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 e6f67adae93daadd92bbce9674bddfe3f5fc844a..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,12 +50,45 @@ 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 {
-            value
-                .fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
-                .into_ok()
+            value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
+        }
+    }
+
+    /// 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)
         }
     }
 
@@ -91,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)
     }
 }
@@ -105,24 +159,79 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        Ok(self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty())
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty()
     }
 
-    fn fold_const(
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()
+    }
+
+    #[inline]
+    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+        // FIXME: This *probably* needs canonicalization too!
+        let arg = self.param_env.and(c);
+        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> {
-        Ok(self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const())
+        match self.try_normalize_generic_arg_after_erasing_regions(c.into()) {
+            Ok(t) => Ok(t.expect_const()),
+            Err(_) => Err(NormalizationError::Const(*c)),
+        }
     }
 
-    #[inline]
-    fn fold_mir_const(
+    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);
-        Ok(self.tcx.normalize_mir_const_after_erasing_regions(arg))
+        match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) {
+            Ok(c) => Ok(c),
+            Err(_) => Err(NormalizationError::ConstantKind(c)),
+        }
     }
 }
index f454b95862bab57b319630ac74d2115c083f3abb..175295b3199e8e2e2c1bf0cc5115ba53133d8657 100644 (file)
@@ -2016,24 +2016,24 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
             _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => {
                 return t.super_fold_with(self);
             }
             _ => {}
         }
-        Ok(t)
+        t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         let name = &mut self.name;
         let region = match *r {
             ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)),
@@ -2049,13 +2049,13 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                     }
                 }
             }
-            _ => return Ok(r),
+            _ => return r,
         };
         if let ty::ReLateBound(debruijn1, br) = *region {
             assert_eq!(debruijn1, ty::INNERMOST);
-            Ok(self.tcx.mk_region(ty::ReLateBound(self.current_index, br)))
+            self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
         } else {
-            Ok(region)
+            region
         }
     }
 }
@@ -2193,7 +2193,7 @@ fn name_by_region_index(index: usize) -> Symbol {
                 name: &mut name,
                 region_map: BTreeMap::new(),
             };
-            let new_value = value.clone().skip_binder().fold_with(&mut folder).into_ok();
+            let new_value = value.clone().skip_binder().fold_with(&mut folder);
             let region_map = folder.region_map;
             start_or_continue(&mut self, "", "> ");
             (new_value, region_map)
index ee6eed0f39b2d33dfe044c3bf3bdcf1b8a866d3c..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,7 +669,10 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        _folder: &mut F,
+    ) -> Result<Self, F::Error> {
         Ok(self)
     }
 
@@ -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) -> Result<(T, U), F::Error> {
-        Ok((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) -> Result<(A, B, C), F::Error> {
-        Ok((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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         // FIXME: Reuse the `Rc` here.
-        Ok(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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         // FIXME: Reuse the `Arc` here.
-        Ok(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) -> Result<Self, F::Error> {
-        self.try_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) -> Result<Self, F::Error> {
-        self.try_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) -> Result<Self, F::Error> {
-        self.try_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) -> Result<Self, F::Error> {
-        self.try_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) -> Result<Self, F::Error> {
-        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) -> Result<Self, F::Error> {
+    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) -> Result<Self, F::Error> {
+    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) -> Result<Self, F::Error> {
+    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,22 +858,31 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
         use crate::ty::InstanceDef::*;
         Ok(Self {
-            substs: self.substs.fold_with(folder)?,
+            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)?),
             },
         })
     }
@@ -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) -> Result<Self, F::Error> {
-        Ok(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) -> Result<Self, F::Error> {
+    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
@@ -909,8 +966,8 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F:
         Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) })
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        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) -> Result<Self, F::Error> {
+    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) -> Result<Self, F::Error> {
-        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,12 +1039,15 @@ 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) -> Result<Self, F::Error> {
-        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) -> Result<Self, F::Error> {
-        let new = self.inner.kind.fold_with(folder)?;
+    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))
     }
 
@@ -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) -> Result<Self, F::Error> {
+    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) -> Result<Self, F::Error> {
-        self.try_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,9 +1095,12 @@ 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) -> Result<Self, F::Error> {
-        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 {
             Ok(folder.tcx().mk_const(ty::Const { ty, val }))
         } else {
@@ -1036,8 +1108,8 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F:
         }
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        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,11 +1123,14 @@ 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) -> Result<Self, F::Error> {
+    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.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)?),
+            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(..)
@@ -1077,7 +1152,10 @@ 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) -> Result<Self, F::Error> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        _folder: &mut F,
+    ) -> Result<Self, F::Error> {
         Ok(self)
     }
 
@@ -1087,10 +1165,13 @@ 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) -> Result<Self, F::Error> {
+    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,
         })
     }
@@ -1112,10 +1193,13 @@ 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) -> Result<Self, F::Error> {
+    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,
         })
     }
index fcbf15b3bca47adbbdf71c79dd693cf89f75b0c0..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"),
         }
     }
index ffa495ce4803fba8217d5a0ddd86eb0dfb227ab6..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) -> Result<Self, F::Error> {
+    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).map(Into::into),
-            GenericArgKind::Type(ty) => ty.fold_with(folder).map(Into::into),
-            GenericArgKind::Const(ct) => ct.fold_with(folder).map(Into::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) -> Result<Self, F::Error> {
+    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,12 +387,12 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F:
         // calling `intern_substs`.
         match self.len() {
             1 => {
-                let param0 = self[0].fold_with(folder)?;
+                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] {
                     Ok(self)
                 } else {
@@ -396,7 +402,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F:
             0 => Ok(self),
             _ => {
                 let params: SmallVec<[_; 8]> =
-                    self.iter().map(|k| k.fold_with(folder)).collect::<Result<_, _>>()?;
+                    self.iter().map(|k| k.try_fold_with(folder)).collect::<Result<_, _>>()?;
                 if params[..] == self[..] {
                     Ok(self)
                 } else {
@@ -439,7 +445,7 @@ fn subst_spanned(
         span: Option<Span>,
     ) -> T {
         let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 };
-        self.fold_with(&mut folder).into_ok()
+        self.fold_with(&mut folder)
     }
 }
 
@@ -465,14 +471,14 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.binders_passed += 1;
-        let t = t.super_fold_with(self)?;
+        let t = t.super_fold_with(self);
         self.binders_passed -= 1;
-        Ok(t)
+        t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         // Note: This routine only handles regions that are bound on
         // type declarations and other outer declarations, not those
         // bound in *fn types*. Region substitution of the bound
@@ -482,7 +488,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
             ty::ReEarlyBound(data) => {
                 let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
                 match rk {
-                    Some(GenericArgKind::Lifetime(lt)) => Ok(self.shift_region_through_binders(lt)),
+                    Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
                     _ => {
                         let span = self.span.unwrap_or(DUMMY_SP);
                         let msg = format!(
@@ -494,37 +500,31 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                     }
                 }
             }
-            _ => Ok(r),
+            _ => r,
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if !t.potentially_needs_subst() {
-            return Ok(t);
+            return t;
         }
 
         match *t.kind() {
-            ty::Param(p) => Ok(self.ty_for_param(p, t)),
+            ty::Param(p) => self.ty_for_param(p, t),
             _ => t.super_fold_with(self),
         }
     }
 
-    fn fold_const(
-        &mut self,
-        c: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ty::ConstKind::Param(p) = c.val {
-            Ok(self.const_for_param(p, c))
+            self.const_for_param(p, c)
         } else {
             c.super_fold_with(self)
         }
     }
 
     #[inline]
-    fn fold_mir_const(
-        &mut self,
-        c: mir::ConstantKind<'tcx>,
-    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
         c.super_fold_with(self)
     }
 }
index 5137f9650633a38dcdfc09009a359ee1fcdc98c7..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};
@@ -574,14 +574,14 @@ fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option
         if self.found_any_recursion {
             return None;
         }
-        let substs = substs.fold_with(self).into_ok();
+        let substs = substs.fold_with(self);
         if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
             let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
                 Some(expanded_ty) => expanded_ty,
                 None => {
                     let generic_ty = self.tcx.type_of(def_id);
                     let concrete_ty = generic_ty.subst(self.tcx, substs);
-                    let expanded_ty = self.fold_ty(concrete_ty).into_ok();
+                    let expanded_ty = self.fold_ty(concrete_ty);
                     self.expanded_cache.insert((def_id, substs), expanded_ty);
                     expanded_ty
                 }
@@ -605,13 +605,13 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if let ty::Opaque(def_id, substs) = t.kind {
-            Ok(self.expand_opaque_ty(def_id, substs).unwrap_or(t))
+            self.expand_opaque_ty(def_id, substs).unwrap_or(t)
         } else if t.has_opaque_types() {
             t.super_fold_with(self)
         } else {
-            Ok(t)
+            t
         }
     }
 }
@@ -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))
             }
         }
     }
@@ -1048,12 +1052,12 @@ pub fn fold_list<'tcx, F, T>(
     intern: impl FnOnce(TyCtxt<'tcx>, &[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
-    match iter.by_ref().enumerate().find_map(|(i, t)| match t.fold_with(folder) {
+    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)),
     }) {
@@ -1063,7 +1067,7 @@ pub fn fold_list<'tcx, F, T>(
             new_list.extend_from_slice(&list[..i]);
             new_list.push(new_t);
             for t in iter {
-                new_list.push(t.fold_with(folder)?)
+                new_list.push(t.try_fold_with(folder)?)
             }
             Ok(intern(folder.tcx(), &new_list))
         }
@@ -1092,7 +1096,7 @@ pub fn normalize_opaque_types(
         check_recursion: false,
         tcx,
     };
-    val.fold_with(&mut visitor).into_ok()
+    val.fold_with(&mut visitor)
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
index 53868f285576392751518368d4168bfe39dd81a1..abec67af08bff17a5f2ba93f45069e21b1528013 100644 (file)
@@ -467,8 +467,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         } else {
                             Some(destination_block)
                         },
+                        cleanup: None,
                     },
                 );
+                if options.contains(InlineAsmOptions::MAY_UNWIND) {
+                    this.diverge_from(block);
+                }
                 destination_block.unit()
             }
 
index 8dadbf5f02bd1bd2a6a5a339cb56730867d30f08..fc46c54c2fc35033769aa4b7d577c4b123acad45 100644 (file)
@@ -1034,6 +1034,7 @@ fn diverge_cleanup(&mut self) -> DropIdx {
                     | TerminatorKind::Call { .. }
                     | TerminatorKind::DropAndReplace { .. }
                     | TerminatorKind::FalseUnwind { .. }
+                    | TerminatorKind::InlineAsm { .. }
             ),
             "diverge_from called on block with terminator that cannot unwind."
         );
@@ -1373,7 +1374,8 @@ fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
             | TerminatorKind::DropAndReplace { unwind, .. }
             | TerminatorKind::FalseUnwind { unwind, .. }
             | TerminatorKind::Call { cleanup: unwind, .. }
-            | TerminatorKind::Assert { cleanup: unwind, .. } => {
+            | TerminatorKind::Assert { cleanup: unwind, .. }
+            | TerminatorKind::InlineAsm { cleanup: unwind, .. } => {
                 *unwind = Some(to);
             }
             TerminatorKind::Goto { .. }
@@ -1384,8 +1386,7 @@ fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::InlineAsm { .. } => {
+            | TerminatorKind::FalseEdge { .. } => {
                 span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind)
             }
         }
index 8a9ced91eb3763c66d15f6799f6c7a78e1408526..6131ee7981829fdd7fceb2294eb534c0f18c0847 100644 (file)
@@ -4,7 +4,9 @@
 use std::ops::RangeInclusive;
 
 use super::visitor::{ResultsVisitable, ResultsVisitor};
-use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget};
+use super::{
+    Analysis, CallReturnPlaces, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget,
+};
 
 pub trait Direction {
     fn is_forward() -> bool;
@@ -235,14 +237,26 @@ fn join_state_into_successors_of<A>(
                 // Apply terminator-specific edge effects.
                 //
                 // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
-                mir::TerminatorKind::Call {
-                    destination: Some((return_place, dest)),
-                    ref func,
-                    ref args,
-                    ..
+                mir::TerminatorKind::Call { destination: Some((return_place, dest)), .. }
+                    if dest == bb =>
+                {
+                    let mut tmp = exit_state.clone();
+                    analysis.apply_call_return_effect(
+                        &mut tmp,
+                        pred,
+                        CallReturnPlaces::Call(return_place),
+                    );
+                    propagate(pred, &tmp);
+                }
+                mir::TerminatorKind::InlineAsm {
+                    destination: Some(dest), ref operands, ..
                 } if dest == bb => {
                     let mut tmp = exit_state.clone();
-                    analysis.apply_call_return_effect(&mut tmp, pred, func, args, return_place);
+                    analysis.apply_call_return_effect(
+                        &mut tmp,
+                        pred,
+                        CallReturnPlaces::InlineAsm(operands),
+                    );
                     propagate(pred, &tmp);
                 }
 
@@ -258,6 +272,7 @@ fn join_state_into_successors_of<A>(
                 | mir::TerminatorKind::Drop { unwind: Some(unwind), .. }
                 | mir::TerminatorKind::DropAndReplace { unwind: Some(unwind), .. }
                 | mir::TerminatorKind::FalseUnwind { unwind: Some(unwind), .. }
+                | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. }
                     if unwind == bb =>
                 {
                     if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
@@ -467,7 +482,7 @@ fn join_state_into_successors_of<A>(
                 propagate(target, exit_state);
             }
 
-            Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => {
+            Call { cleanup, destination, func: _, args: _, from_hir_call: _, fn_span: _ } => {
                 if let Some(unwind) = cleanup {
                     if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
                         propagate(unwind, exit_state);
@@ -477,13 +492,37 @@ fn join_state_into_successors_of<A>(
                 if let Some((dest_place, target)) = destination {
                     // N.B.: This must be done *last*, otherwise the unwind path will see the call
                     // return effect.
-                    analysis.apply_call_return_effect(exit_state, bb, func, args, dest_place);
+                    analysis.apply_call_return_effect(
+                        exit_state,
+                        bb,
+                        CallReturnPlaces::Call(dest_place),
+                    );
                     propagate(target, exit_state);
                 }
             }
 
-            InlineAsm { template: _, operands: _, options: _, line_spans: _, destination } => {
+            InlineAsm {
+                template: _,
+                ref operands,
+                options: _,
+                line_spans: _,
+                destination,
+                cleanup,
+            } => {
+                if let Some(unwind) = cleanup {
+                    if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
+                        propagate(unwind, exit_state);
+                    }
+                }
+
                 if let Some(target) = destination {
+                    // N.B.: This must be done *last*, otherwise the unwind path will see the call
+                    // return effect.
+                    analysis.apply_call_return_effect(
+                        exit_state,
+                        bb,
+                        CallReturnPlaces::InlineAsm(operands),
+                    );
                     propagate(target, exit_state);
                 }
             }
index a370f8e40f9aed237bb23ccca902a51cab82246f..517bc086ef683451b27108158b4936dfcbd24dc2 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_middle::mir::{self, BasicBlock, Body, Location};
 
 use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
-use super::{Analysis, Direction, Results, ResultsRefCursor, ResultsVisitor};
+use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor};
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum OutputStyle {
@@ -231,16 +231,15 @@ fn write_node_label(
         // for the basic block itself. That way, we could display terminator-specific effects for
         // backward dataflow analyses as well as effects for `SwitchInt` terminators.
         match terminator.kind {
-            mir::TerminatorKind::Call {
-                destination: Some((return_place, _)),
-                ref func,
-                ref args,
-                ..
-            } => {
+            mir::TerminatorKind::Call { destination: Some((return_place, _)), .. } => {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
                     let state_on_unwind = this.results.get().clone();
                     this.results.apply_custom_effect(|analysis, state| {
-                        analysis.apply_call_return_effect(state, block, func, args, return_place);
+                        analysis.apply_call_return_effect(
+                            state,
+                            block,
+                            CallReturnPlaces::Call(return_place),
+                        );
                     });
 
                     write!(
@@ -278,6 +277,31 @@ fn write_node_label(
                 })?;
             }
 
+            mir::TerminatorKind::InlineAsm { destination: Some(_), ref operands, .. } => {
+                self.write_row(w, "", "(on successful return)", |this, w, fmt| {
+                    let state_on_unwind = this.results.get().clone();
+                    this.results.apply_custom_effect(|analysis, state| {
+                        analysis.apply_call_return_effect(
+                            state,
+                            block,
+                            CallReturnPlaces::InlineAsm(operands),
+                        );
+                    });
+
+                    write!(
+                        w,
+                        r#"<td balign="left" colspan="{colspan}" {fmt} align="left">{diff}</td>"#,
+                        colspan = this.style.num_state_columns(),
+                        fmt = fmt,
+                        diff = diff_pretty(
+                            this.results.get(),
+                            &state_on_unwind,
+                            this.results.analysis()
+                        ),
+                    )
+                })?;
+            }
+
             _ => {}
         };
 
index f0c9ac4c504a384557b36b40883ac49f73d66a96..500fba8b1142cb364822428df8d2d038d6c66764 100644 (file)
@@ -160,9 +160,7 @@ fn apply_call_return_effect(
         &self,
         state: &mut Self::Domain,
         block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     );
 
     /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator.
@@ -276,9 +274,7 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     );
 
     /// See `Analysis::apply_yield_resume_effect`.
@@ -347,11 +343,9 @@ fn apply_call_return_effect(
         &self,
         state: &mut A::Domain,
         block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        self.call_return_effect(state, block, func, args, return_place);
+        self.call_return_effect(state, block, return_places);
     }
 
     fn apply_yield_resume_effect(
@@ -542,5 +536,29 @@ pub trait SwitchIntEdgeEffects<D> {
     fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget));
 }
 
+/// List of places that are written to after a successful (non-unwind) return
+/// from a `Call` or `InlineAsm`.
+pub enum CallReturnPlaces<'a, 'tcx> {
+    Call(mir::Place<'tcx>),
+    InlineAsm(&'a [mir::InlineAsmOperand<'tcx>]),
+}
+
+impl<'tcx> CallReturnPlaces<'_, 'tcx> {
+    pub fn for_each(&self, mut f: impl FnMut(mir::Place<'tcx>)) {
+        match *self {
+            Self::Call(place) => f(place),
+            Self::InlineAsm(operands) => {
+                for op in operands {
+                    match *op {
+                        mir::InlineAsmOperand::Out { place: Some(place), .. }
+                        | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place),
+                        _ => {}
+                    }
+                }
+            }
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests;
index 6efa8daec489a9e1da66a566e11bc7bb7ff8eb74..01ca8ca9258fb769f3e3ae3032a75d6db780af10 100644 (file)
@@ -220,9 +220,7 @@ fn apply_call_return_effect(
         &self,
         _state: &mut Self::Domain,
         _block: BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        _return_place: mir::Place<'tcx>,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
     }
 }
index d38b567a95849be35d1995a6e2e8c3707dd2e1e4..6df2c8df3cea0840af30fda3e4dd48a53389277a 100644 (file)
@@ -1,6 +1,6 @@
 use super::*;
 
-use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
+use crate::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis};
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 
@@ -84,9 +84,7 @@ fn call_return_effect(
         &self,
         _trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        _dest_place: mir::Place<'tcx>,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
     }
 }
index 07570e764f5e087369b944156429366497d13761..df13b5c33940a0fe4e28a3d86dcadf2b9105c8ca 100644 (file)
@@ -2,7 +2,7 @@
 //!
 //! A local will be maybe initialized if *any* projections of that local might be initialized.
 
-use crate::GenKill;
+use crate::{CallReturnPlaces, GenKill};
 
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
@@ -53,11 +53,9 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         _block: BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        trans.gen(return_place.local)
+        return_places.for_each(|place| trans.gen(place.local));
     }
 
     /// See `Analysis::apply_yield_resume_effect`.
@@ -83,7 +81,11 @@ fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
         use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext};
         match context {
             // These are handled specially in `call_return_effect` and `yield_resume_effect`.
-            PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => {}
+            PlaceContext::MutatingUse(
+                MutatingUseContext::Call
+                | MutatingUseContext::AsmOutput
+                | MutatingUseContext::Yield,
+            ) => {}
 
             // Otherwise, when a place is mutated, we must consider it possibly initialized.
             PlaceContext::MutatingUse(_) => self.trans.gen(local),
index 3e2548845e20f693f9d4bd6031dcf2c68abdc570..5be9df6c452a2214235ffa5e889aa1af1379c489 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Local, Location};
 
-use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis};
+use crate::{AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis};
 
 /// A [live-variable dataflow analysis][liveness].
 ///
@@ -94,13 +94,13 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        dest_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        if let Some(local) = dest_place.as_local() {
-            trans.kill(local);
-        }
+        return_places.for_each(|place| {
+            if let Some(local) = place.as_local() {
+                trans.kill(local);
+            }
+        });
     }
 
     fn yield_resume_effect(
@@ -167,12 +167,16 @@ fn for_place(context: PlaceContext) -> Option<DefUse> {
             // destination place for a `Call` return or `Yield` resume respectively. Since this is
             // only a `Def` when the function returns successfully, we handle this case separately
             // in `call_return_effect` above.
-            PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => None,
+            PlaceContext::MutatingUse(
+                MutatingUseContext::Call
+                | MutatingUseContext::AsmOutput
+                | MutatingUseContext::Yield,
+            ) => None,
 
             // All other contexts are uses...
             PlaceContext::MutatingUse(
                 MutatingUseContext::AddressOf
-                | MutatingUseContext::AsmOutput
+                | MutatingUseContext::LlvmAsmOutput
                 | MutatingUseContext::Borrow
                 | MutatingUseContext::Drop
                 | MutatingUseContext::Retag,
index 2585701f60c66b5ff2e0c90f4d418f98bd973a44..5659fd2dc70750c62903799b906b7786fe19db10 100644 (file)
@@ -11,7 +11,7 @@
 use crate::drop_flag_effects_for_function_entry;
 use crate::drop_flag_effects_for_location;
 use crate::elaborate_drops::DropFlagState;
-use crate::framework::SwitchIntEdgeEffects;
+use crate::framework::{CallReturnPlaces, SwitchIntEdgeEffects};
 use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
 use crate::on_lookup_result_bits;
 use crate::MoveDataParamEnv;
@@ -354,21 +354,21 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        dest_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        // when a call returns successfully, that means we need to set
-        // the bits for that dest_place to 1 (initialized).
-        on_lookup_result_bits(
-            self.tcx,
-            self.body,
-            self.move_data(),
-            self.move_data().rev_lookup.find(dest_place.as_ref()),
-            |mpi| {
-                trans.gen(mpi);
-            },
-        );
+        return_places.for_each(|place| {
+            // when a call returns successfully, that means we need to set
+            // the bits for that dest_place to 1 (initialized).
+            on_lookup_result_bits(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                self.move_data().rev_lookup.find(place.as_ref()),
+                |mpi| {
+                    trans.gen(mpi);
+                },
+            );
+        });
     }
 
     fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
@@ -472,21 +472,21 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        dest_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        // when a call returns successfully, that means we need to set
-        // the bits for that dest_place to 0 (initialized).
-        on_lookup_result_bits(
-            self.tcx,
-            self.body,
-            self.move_data(),
-            self.move_data().rev_lookup.find(dest_place.as_ref()),
-            |mpi| {
-                trans.kill(mpi);
-            },
-        );
+        return_places.for_each(|place| {
+            // when a call returns successfully, that means we need to set
+            // the bits for that dest_place to 0 (initialized).
+            on_lookup_result_bits(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                self.move_data().rev_lookup.find(place.as_ref()),
+                |mpi| {
+                    trans.kill(mpi);
+                },
+            );
+        });
     }
 
     fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
@@ -591,21 +591,21 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        dest_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        // when a call returns successfully, that means we need to set
-        // the bits for that dest_place to 1 (initialized).
-        on_lookup_result_bits(
-            self.tcx,
-            self.body,
-            self.move_data(),
-            self.move_data().rev_lookup.find(dest_place.as_ref()),
-            |mpi| {
-                trans.gen(mpi);
-            },
-        );
+        return_places.for_each(|place| {
+            // when a call returns successfully, that means we need to set
+            // the bits for that dest_place to 1 (initialized).
+            on_lookup_result_bits(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                self.move_data().rev_lookup.find(place.as_ref()),
+                |mpi| {
+                    trans.gen(mpi);
+                },
+            );
+        });
     }
 }
 
@@ -679,9 +679,7 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        _dest_place: mir::Place<'tcx>,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         let move_data = self.move_data();
         let init_loc_map = &move_data.init_loc_map;
index b468e50b391ca87a0ff39d2c1ad6f61e566e83b8..108357abc0de02886d3aba76941daf2aa006b0ea 100644 (file)
@@ -1,7 +1,7 @@
 pub use super::*;
 
 use crate::storage::AlwaysLiveLocals;
-use crate::{GenKill, Results, ResultsRefCursor};
+use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use std::cell::RefCell;
@@ -68,9 +68,7 @@ fn call_return_effect(
         &self,
         _trans: &mut impl GenKill<Self::Idx>,
         _block: BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        _return_place: mir::Place<'tcx>,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         // Nothing to do when a call returns successfully
     }
@@ -226,7 +224,7 @@ fn terminator_effect(
         terminator: &mir::Terminator<'tcx>,
         loc: Location,
     ) {
-        match &terminator.kind {
+        match terminator.kind {
             // For call terminators the destination requires storage for the call
             // and after the call returns successfully, but not after a panic.
             // Since `propagate_call_unwind` doesn't exist, we have to kill the
@@ -235,6 +233,11 @@ fn terminator_effect(
                 trans.kill(place.local);
             }
 
+            // The same applies to InlineAsm outputs.
+            TerminatorKind::InlineAsm { ref operands, .. } => {
+                CallReturnPlaces::InlineAsm(operands).for_each(|place| trans.kill(place.local));
+            }
+
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Call { destination: None, .. }
@@ -247,7 +250,6 @@ fn terminator_effect(
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::InlineAsm { .. }
             | TerminatorKind::Resume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
@@ -261,11 +263,9 @@ fn call_return_effect(
         &self,
         trans: &mut impl GenKill<Self::Idx>,
         _block: BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        return_place: mir::Place<'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        trans.gen(return_place.local);
+        return_places.for_each(|place| trans.gen(place.local));
     }
 
     fn yield_resume_effect(
index 77a72ce63ce5ee53ccc2ed8e74ce159fcafc1d27..10d2cf6eba03de5869efc52f0eebf04a61aecfe2 100644 (file)
@@ -28,9 +28,9 @@
     on_lookup_result_bits,
 };
 pub use self::framework::{
-    fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine,
-    Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
-    ResultsVisitable, ResultsVisitor,
+    fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces,
+    Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor,
+    ResultsRefCursor, ResultsVisitable, ResultsVisitor,
 };
 
 use self::move_paths::MoveData;
index e404b49ecb93173f33ca1062399967f3f6a6075b..feb85d4ffdfa881126ea178fc02d136df323d56e 100644 (file)
@@ -419,6 +419,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
                 options: _,
                 line_spans: _,
                 destination: _,
+                cleanup: _,
             } => {
                 for op in operands {
                     match *op {
index 28e5d76783aa4015cb8af5bc2cce5b2a618cf584..1746d5ee38b926808fa9b04fb2c1bff079c2fb10 100644 (file)
@@ -20,6 +20,7 @@
 
 pub struct SanityCheck;
 
+// FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first.
 impl<'tcx> MirPass<'tcx> for SanityCheck {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         use crate::has_rustc_mir_with;
index 7a8dee09c29f098b1924b913a1850daa29ed1dd9..84ae2a2fbd094efcfdc0053bfebee2344e672fbf 100644 (file)
@@ -58,11 +58,11 @@ fn may_be_reference(ty: Ty<'tcx>) -> bool {
 }
 
 impl<'tcx> MirPass<'tcx> for AddRetag {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if !tcx.sess.opts.debugging_opts.mir_emit_retag {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.debugging_opts.mir_emit_retag
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // We need an `AllCallEdges` pass before we can do any work.
         super::add_call_guards::AllCallEdges.run_pass(tcx, body);
 
index 27fe80a456f7de06b71a6157c7055ddb8182fb75..6f0d03068f566aa4b4b742bef3ba0fb4bea089ce 100644 (file)
@@ -6,12 +6,12 @@
 use rustc_session::lint::builtin::CONST_ITEM_MUTATION;
 use rustc_span::def_id::DefId;
 
-use crate::MirPass;
+use crate::MirLint;
 
 pub struct CheckConstItemMutation;
 
-impl<'tcx> MirPass<'tcx> for CheckConstItemMutation {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+impl<'tcx> MirLint<'tcx> for CheckConstItemMutation {
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
         let mut checker = ConstMutationChecker { body, tcx, target_local: None };
         checker.visit_body(&body);
     }
index 49be34c7a284562bbb0ff247ffa6460ea3290828..31d547103095f7f6e9fe2e2b73cbf70facbeee5b 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_span::symbol::sym;
 
 use crate::util;
-use crate::MirPass;
+use crate::MirLint;
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { unsafe_derive_on_repr_packed, ..*providers };
@@ -15,8 +15,8 @@ pub(crate) fn provide(providers: &mut Providers) {
 
 pub struct CheckPackedRef;
 
-impl<'tcx> MirPass<'tcx> for CheckPackedRef {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+impl<'tcx> MirLint<'tcx> for CheckPackedRef {
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
         let param_env = tcx.param_env(body.source.def_id());
         let source_info = SourceInfo::outermost(body.span);
         let mut checker = PackedRefChecker { body, tcx, param_env, source_info };
index 1ff9bd157210874391deafc577a31eb4dd435c42..cdfeb957df9b1f1c38eff3d3a1dcf35e35ae8141 100644 (file)
@@ -208,6 +208,7 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location:
                             MutatingUseContext::Store
                                 | MutatingUseContext::Drop
                                 | MutatingUseContext::AsmOutput
+                                | MutatingUseContext::LlvmAsmOutput
                         )
                     );
                 // If this is just an assignment, determine if the assigned type needs dropping.
index b613634560fbd42e8f615fd1fdd1c010477e87f5..3613fa4560d6c1ebbe9a947858977c317cce259f 100644 (file)
 pub struct ConstDebugInfo;
 
 impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0
+    }
 
+    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running ConstDebugInfo on {:?}", body.source);
 
         for (local, constant) in find_optimization_oportunities(body) {
index d319fdcaa6b7e2b2c22383e0918bd963a70cf195..beb158dd25828da7aa54f748d6ac1786f13a69ac 100644 (file)
 pub struct ConstGoto;
 
 impl<'tcx> MirPass<'tcx> for ConstGoto {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 4
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 4 {
-            return;
-        }
         trace!("Running ConstGoto on {:?}", body.source);
         let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         let mut opt_finder =
index 63c637af5c21a39ae94067abde5c52efc531b007..e3377f5953aadace7d689525e01769274a384dcd 100644 (file)
@@ -62,6 +62,13 @@ impl rustc_middle::mir::interpret::MachineStopType for Zst {}
 pub struct ConstProp;
 
 impl<'tcx> MirPass<'tcx> for ConstProp {
+    fn is_enabled(&self, _sess: &rustc_session::Session) -> bool {
+        // FIXME(#70073): Unlike the other passes in "optimizations", this one emits errors, so it
+        // runs even when MIR optimizations are disabled. We should separate the lint out from the
+        // transform and move the lint as early in the pipeline as possible.
+        true
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // will be evaluated by miri and produce its errors there
         if body.source.promoted.is_some() {
@@ -1022,6 +1029,7 @@ fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
             // These are just stores, where the storing is not propagatable, but there may be later
             // mutations of the same local via `Store`
             | MutatingUse(MutatingUseContext::Call)
+            | MutatingUse(MutatingUseContext::AsmOutput)
             // Actual store that can possibly even propagate a value
             | MutatingUse(MutatingUseContext::Store) => {
                 if !self.found_assignment.insert(local) {
@@ -1052,7 +1060,7 @@ fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
 
             // These could be propagated with a smarter analysis or just some careful thinking about
             // whether they'd be fine right now.
-            MutatingUse(MutatingUseContext::AsmOutput)
+            MutatingUse(MutatingUseContext::LlvmAsmOutput)
             | MutatingUse(MutatingUseContext::Yield)
             | MutatingUse(MutatingUseContext::Drop)
             | MutatingUse(MutatingUseContext::Retag)
index 6807d02519e2b3305f46278f1b33f861fafb14bd..bba188bd3935075a77b6788c25f0c69c39119fec 100644 (file)
@@ -49,6 +49,10 @@ pub fn from_string<T>(message: String) -> Result<T, Error> {
 pub struct InstrumentCoverage;
 
 impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.instrument_coverage()
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) {
         let mir_source = mir_body.source;
 
index 8d2413433a92be5386ec7f5aea3cd8b03efe8775..993c8eef711ce66224308c807c259abb2a5930c9 100644 (file)
 pub struct DeduplicateBlocks;
 
 impl<'tcx> MirPass<'tcx> for DeduplicateBlocks {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 4
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 4 {
-            return;
-        }
         debug!("Running DeduplicateBlocks on `{:?}`", body.source);
         let duplicates = find_duplicates(body);
         let has_opts_to_apply = !duplicates.is_empty();
index 790d9243fbaec874db7488ff817c615d5068cb1e..256f7fbd7592351b15777e411eed4ec2273ff7ec 100644 (file)
 pub struct DestinationPropagation;
 
 impl<'tcx> MirPass<'tcx> for DestinationPropagation {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        //  FIXME(#79191, #82678)
-        if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
-            return;
-        }
-
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        //  FIXME(#79191, #82678): This is unsound.
+        //
         // Only run at mir-opt-level=3 or higher for now (we don't fix up debuginfo and remove
         // storage statements at the moment).
-        if tcx.sess.mir_opt_level() < 3 {
-            return;
-        }
+        sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() >= 3
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
 
         let candidates = find_candidates(tcx, body);
@@ -316,28 +313,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.
@@ -646,6 +621,7 @@ fn record_terminator_conflicts(&mut self, term: &Terminator<'_>) {
                 options: _,
                 line_spans: _,
                 destination: _,
+                cleanup: _,
             } => {
                 // The intended semantics here aren't documented, we just assume that nothing that
                 // could be written to by the assembly may overlap with any other operands.
index f191911a6c7c1d797485aa76b1c862b58daf308d..62e82aca262073cb99b17bda75865d42569d6ab7 100644 (file)
 pub struct EarlyOtherwiseBranch;
 
 impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         //  FIXME(#78496)
-        if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
-            return;
-        }
+        sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() >= 3
+    }
 
-        if tcx.sess.mir_opt_level() < 3 {
-            return;
-        }
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running EarlyOtherwiseBranch on {:?}", body.source);
+
         // we are only interested in this bb if the terminator is a switchInt
         let bbs_with_switch =
             body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator()));
index b9a48197a351a65ed9ce6cd0ef0c9708ee2bc252..af13c734e5b9a399720552ffd3fcc4e88f675403 100644 (file)
 pub struct ElaborateDrops;
 
 impl<'tcx> MirPass<'tcx> for ElaborateDrops {
+    fn phase_change(&self) -> Option<MirPhase> {
+        Some(MirPhase::DropLowering)
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
 
index 996c158c062fb89918dc8c0cebd0f2074e106b19..c05dc39afc47e329cae2c583bd19baadba8d8eaa 100644 (file)
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
 
-use crate::MirPass;
+use crate::MirLint;
 
 pub struct FunctionItemReferences;
 
-impl<'tcx> MirPass<'tcx> for FunctionItemReferences {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+impl<'tcx> MirLint<'tcx> for FunctionItemReferences {
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
         let mut checker = FunctionItemRefChecker { tcx, body };
         checker.visit_body(&body);
     }
index bc72e9d94a95301388fabcc2f773e96795fd017e..5376855035e71d3f1f35bd78ba0dfd2edac39e1a 100644 (file)
@@ -1232,6 +1232,10 @@ fn create_cases<'tcx>(
 }
 
 impl<'tcx> MirPass<'tcx> for StateTransform {
+    fn phase_change(&self) -> Option<MirPhase> {
+        Some(MirPhase::GeneratorLowering)
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let yield_ty = if let Some(yield_ty) = body.yield_ty() {
             yield_ty
index 84a1e3fb600fdb42d9d4283be8cab5642577e4e1..81454cc4070bdf3649d321042ca9bf267a8d5b2c 100644 (file)
@@ -37,21 +37,16 @@ struct CallSite<'tcx> {
     source_info: SourceInfo,
 }
 
-/// Returns true if MIR inlining is enabled in the current compilation session.
-crate fn is_enabled(tcx: TyCtxt<'_>) -> bool {
-    if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir {
-        return enabled;
-    }
-
-    tcx.sess.mir_opt_level() >= 3
-}
-
 impl<'tcx> MirPass<'tcx> for Inline {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if !is_enabled(tcx) {
-            return;
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        if let Some(enabled) = sess.opts.debugging_opts.inline_mir {
+            return enabled;
         }
 
+        sess.opts.mir_opt_level() >= 3
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let span = trace_span!("inline", body = %tcx.def_path_str(body.source.def_id()));
         let _guard = span.enter();
         if inline(tcx, body) {
@@ -441,6 +436,13 @@ fn check_mir_body(
                     }
                 }
                 TerminatorKind::Resume => cost += RESUME_PENALTY,
+                TerminatorKind::InlineAsm { cleanup, .. } => {
+                    cost += INSTR_COST;
+
+                    if cleanup.is_some() {
+                        cost += LANDINGPAD_PENALTY;
+                    }
+                }
                 _ => cost += INSTR_COST,
             }
 
@@ -954,9 +956,13 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, loc: Location)
             {
                 bug!("False unwinds should have been removed before inlining")
             }
-            TerminatorKind::InlineAsm { ref mut destination, .. } => {
+            TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
                 if let Some(ref mut tgt) = *destination {
                     *tgt = self.map_block(*tgt);
+                } else if !self.in_cleanup_block {
+                    // Unless this inline asm is in a cleanup block, add an unwind edge to
+                    // the original call's cleanup block
+                    *cleanup = self.cleanup_block;
                 }
             }
         }
index e15a69c95ae9c6904da0be721fa9d53ea4634a5e..c5adc241664d246ff17831f073bd8e7432927bee 100644 (file)
 pub struct InstCombine;
 
 impl<'tcx> MirPass<'tcx> for InstCombine {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         let ctx = InstCombineContext { tcx, local_decls };
index f9ef31462780731a9375aa0ec7f4f379c17da875..a7e003a55b4007e3fe4f901aa1be8dc9b57fd878 100644 (file)
 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::{traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
 
+#[macro_use]
+mod pass_manager;
+
+use pass_manager::{self as pm, Lint, MirLint, WithMinOptLevel};
+
 mod abort_unwinding_calls;
 mod add_call_guards;
 mod add_moves_for_packed_drops;
 mod instcombine;
 mod lower_intrinsics;
 mod lower_slice_len;
+mod marker;
 mod match_branches;
 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) {
@@ -167,66 +174,6 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
     set
 }
 
-fn run_passes(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    mir_phase: MirPhase,
-    passes: &[&[&dyn MirPass<'tcx>]],
-) {
-    let phase_index = mir_phase.phase_index();
-    let validate = tcx.sess.opts.debugging_opts.validate_mir;
-
-    if body.phase >= mir_phase {
-        return;
-    }
-
-    if validate {
-        validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase }
-            .run_pass(tcx, body);
-    }
-
-    let mut index = 0;
-    let mut run_pass = |pass: &dyn MirPass<'tcx>| {
-        let run_hooks = |body: &_, index, is_after| {
-            let disambiguator = if is_after { "after" } else { "before" };
-            dump_mir(
-                tcx,
-                Some(&format_args!("{:03}-{:03}", phase_index, index)),
-                &pass.name(),
-                &disambiguator,
-                body,
-                |_, _| Ok(()),
-            );
-        };
-        run_hooks(body, index, false);
-        pass.run_pass(tcx, body);
-        run_hooks(body, index, true);
-
-        if validate {
-            validate::Validator {
-                when: format!("after {} in phase {:?}", pass.name(), mir_phase),
-                mir_phase,
-            }
-            .run_pass(tcx, body);
-        }
-
-        index += 1;
-    };
-
-    for pass_group in passes {
-        for pass in *pass_group {
-            run_pass(*pass);
-        }
-    }
-
-    body.phase = mir_phase;
-
-    if mir_phase == MirPhase::Optimization {
-        validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase }
-            .run_pass(tcx, body);
-    }
-}
-
 fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
     let const_kind = tcx.hir().body_const_context(def.did);
 
@@ -278,19 +225,19 @@ fn mir_const<'tcx>(
 
     rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
 
-    run_passes(
+    pm::run_passes(
         tcx,
         &mut body,
-        MirPhase::Const,
-        &[&[
+        &[
             // MIR-level lints.
-            &check_packed_ref::CheckPackedRef,
-            &check_const_item_mutation::CheckConstItemMutation,
-            &function_item_references::FunctionItemReferences,
+            &Lint(check_packed_ref::CheckPackedRef),
+            &Lint(check_const_item_mutation::CheckConstItemMutation),
+            &Lint(function_item_references::FunctionItemReferences),
             // What we need to do constant evaluation.
             &simplify::SimplifyCfg::new("initial"),
-            &rustc_peek::SanityCheck,
-        ]],
+            &rustc_peek::SanityCheck, // Just a lint
+            &marker::PhaseChange(MirPhase::Const),
+        ],
     );
     tcx.alloc_steal_mir(body)
 }
@@ -317,17 +264,17 @@ fn mir_promoted(
     }
     body.required_consts = required_consts;
 
+    // What we need to run borrowck etc.
     let promote_pass = promote_consts::PromoteTemps::default();
-    let promote: &[&dyn MirPass<'tcx>] = &[
-        // What we need to run borrowck etc.
-        &promote_pass,
-        &simplify::SimplifyCfg::new("promote-consts"),
-    ];
-
-    let opt_coverage: &[&dyn MirPass<'tcx>] =
-        if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] };
-
-    run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]);
+    pm::run_passes(
+        tcx,
+        &mut body,
+        &[
+            &promote_pass,
+            &simplify::SimplifyCfg::new("promote-consts"),
+            &coverage::InstrumentCoverage,
+        ],
+    );
 
     let promoted = promote_pass.promoted_fragments.into_inner();
     (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
@@ -389,19 +336,10 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
         // Technically we want to not run on regular const items, but oli-obk doesn't know how to
         // conveniently detect that at this point without looking at the HIR.
         hir::ConstContext::Const => {
-            #[rustfmt::skip]
-            let optimizations: &[&dyn MirPass<'_>] = &[
-                &const_prop::ConstProp,
-            ];
-
-            #[rustfmt::skip]
-            run_passes(
+            pm::run_passes(
                 tcx,
                 &mut body,
-                MirPhase::Optimization,
-                &[
-                    optimizations,
-                ],
+                &[&const_prop::ConstProp, &marker::PhaseChange(MirPhase::Optimization)],
             );
         }
     }
@@ -437,7 +375,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
         let def = ty::WithOptConstParam::unknown(did);
 
         // Do not compute the mir call graph without said call graph actually being used.
-        if inline::is_enabled(tcx) {
+        if inline::Inline.is_enabled(&tcx.sess) {
             let _ = tcx.mir_inliner_callees(ty::InstanceDef::Item(def));
         }
     }
@@ -445,8 +383,24 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
     let (body, _) = tcx.mir_promoted(def);
     let mut body = body.steal();
 
+    // IMPORTANT
+    pm::run_passes(tcx, &mut body, &[&remove_false_edges::RemoveFalseEdges]);
+
+    // Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled.
+    if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) {
+        pm::run_passes(
+            tcx,
+            &mut body,
+            &[
+                &simplify::SimplifyCfg::new("remove-false-edges"),
+                &remove_uninit_drops::RemoveUninitDrops,
+            ],
+        );
+        check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint
+    }
+
     run_post_borrowck_cleanup_passes(tcx, &mut body);
-    check_consts::post_drop_elaboration::check_live_drops(tcx, &body);
+    assert!(body.phase == MirPhase::DropLowering);
     tcx.alloc_steal_mir(body)
 }
 
@@ -456,7 +410,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"),
@@ -480,95 +434,73 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
         &deaggregator::Deaggregator,
     ];
 
-    run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]);
+    pm::run_passes(tcx, body, post_borrowck_cleanup);
 }
 
 fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let mir_opt_level = tcx.sess.mir_opt_level();
+    fn o1<T>(x: T) -> WithMinOptLevel<T> {
+        WithMinOptLevel(1, x)
+    }
 
     // Lowering generator control-flow and variables has to happen before we do anything else
     // to them. We run some optimizations before that, because they may be harder to do on the state
     // machine than on MIR with async primitives.
-    let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[
-        &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
-        &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
-        &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
-        &unreachable_prop::UnreachablePropagation,
-        &uninhabited_enum_branching::UninhabitedEnumBranching,
-        &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
-        &inline::Inline,
-        &generator::StateTransform,
-    ];
-
-    // Even if we don't do optimizations, we still have to lower generators for codegen.
-    let no_optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[&generator::StateTransform];
-
-    // The main optimizations that we do on MIR.
-    let optimizations: &[&dyn MirPass<'tcx>] = &[
-        &remove_storage_markers::RemoveStorageMarkers,
-        &remove_zsts::RemoveZsts,
-        &const_goto::ConstGoto,
-        &remove_unneeded_drops::RemoveUnneededDrops,
-        &match_branches::MatchBranchSimplification,
-        // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
-        &multiple_return_terminators::MultipleReturnTerminators,
-        &instcombine::InstCombine,
-        &separate_const_switch::SeparateConstSwitch,
-        &const_prop::ConstProp,
-        &simplify_branches::SimplifyBranches::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"),
-        &remove_noop_landing_pads::RemoveNoopLandingPads,
-        &simplify::SimplifyCfg::new("final"),
-        &nrvo::RenameReturnPlace,
-        &const_debuginfo::ConstDebugInfo,
-        &simplify::SimplifyLocals,
-        &multiple_return_terminators::MultipleReturnTerminators,
-        &deduplicate_blocks::DeduplicateBlocks,
-    ];
-
-    // Optimizations to run even if mir optimizations have been disabled.
-    let no_optimizations: &[&dyn MirPass<'tcx>] = &[
-        // FIXME(#70073): This pass is responsible for both optimization as well as some lints.
-        &const_prop::ConstProp,
-    ];
-
-    // Some cleanup necessary at least for LLVM and potentially other codegen backends.
-    let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[
-        &add_call_guards::CriticalCallEdges,
-        // Dump the end result for testing and debugging purposes.
-        &dump_mir::Marker("PreCodegen"),
-    ];
-
-    // End of pass declarations, now actually run the passes.
-    // Generator Lowering
-    #[rustfmt::skip]
-    run_passes(
+    pm::run_passes(
         tcx,
         body,
-        MirPhase::GeneratorLowering,
         &[
-            if mir_opt_level > 0 {
-                optimizations_with_generators
-            } else {
-                no_optimizations_with_generators
-            }
+            &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
+            &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
+            &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
+            &unreachable_prop::UnreachablePropagation,
+            &uninhabited_enum_branching::UninhabitedEnumBranching,
+            &o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")),
+            &inline::Inline,
+            &generator::StateTransform,
         ],
     );
 
-    // Main optimization passes
-    #[rustfmt::skip]
-    run_passes(
+    assert!(body.phase == MirPhase::GeneratorLowering);
+
+    // The main optimizations that we do on MIR.
+    pm::run_passes(
         tcx,
         body,
-        MirPhase::Optimization,
         &[
-            if mir_opt_level > 0 { optimizations } else { no_optimizations },
-            pre_codegen_cleanup,
+            &remove_storage_markers::RemoveStorageMarkers,
+            &remove_zsts::RemoveZsts,
+            &const_goto::ConstGoto,
+            &remove_unneeded_drops::RemoveUnneededDrops,
+            &match_branches::MatchBranchSimplification,
+            // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
+            &multiple_return_terminators::MultipleReturnTerminators,
+            &instcombine::InstCombine,
+            &separate_const_switch::SeparateConstSwitch,
+            //
+            // FIXME(#70073): This pass is responsible for both optimization as well as some lints.
+            &const_prop::ConstProp,
+            //
+            // FIXME: The old pass manager ran this only at mir-opt-level >= 1, but
+            // const-prop runs unconditionally. Should this run unconditionally as well?
+            &o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")),
+            &early_otherwise_branch::EarlyOtherwiseBranch,
+            &simplify_comparison_integral::SimplifyComparisonIntegral,
+            &simplify_try::SimplifyArmIdentity,
+            &simplify_try::SimplifyBranchSame,
+            &dest_prop::DestinationPropagation,
+            &o1(simplify_branches::SimplifyConstCondition::new("final")),
+            &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
+            &o1(simplify::SimplifyCfg::new("final")),
+            &nrvo::RenameReturnPlace,
+            &const_debuginfo::ConstDebugInfo,
+            &simplify::SimplifyLocals,
+            &multiple_return_terminators::MultipleReturnTerminators,
+            &deduplicate_blocks::DeduplicateBlocks,
+            // Some cleanup necessary at least for LLVM and potentially other codegen backends.
+            &add_call_guards::CriticalCallEdges,
+            &marker::PhaseChange(MirPhase::Optimization),
+            // Dump the end result for testing and debugging purposes.
+            &dump_mir::Marker("PreCodegen"),
         ],
     );
 }
index 822a372d8ce90fa1a11d043fe96da70e1072f750..c8297744873087256dc9c4e2eb66582303b37af5 100644 (file)
 pub struct LowerSliceLenCalls;
 
 impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         lower_slice_len_calls(tcx, body)
     }
diff --git a/compiler/rustc_mir_transform/src/marker.rs b/compiler/rustc_mir_transform/src/marker.rs
new file mode 100644 (file)
index 0000000..06819fc
--- /dev/null
@@ -0,0 +1,20 @@
+use std::borrow::Cow;
+
+use crate::MirPass;
+use rustc_middle::mir::{Body, MirPhase};
+use rustc_middle::ty::TyCtxt;
+
+/// Changes the MIR phase without changing the MIR itself.
+pub struct PhaseChange(pub MirPhase);
+
+impl<'tcx> MirPass<'tcx> for PhaseChange {
+    fn phase_change(&self) -> Option<MirPhase> {
+        Some(self.0)
+    }
+
+    fn name(&self) -> Cow<'_, str> {
+        Cow::from(format!("PhaseChange-{:?}", self.0))
+    }
+
+    fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
+}
index c618abe9d059963898ce1bfb1db5708926687a48..3c14a324c36ff2bacac3a60ee3e41efa393429da 100644 (file)
 /// ```
 
 impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 3 {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 3
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
         let param_env = tcx.param_env(def_id);
 
index b614917a88369ddced2445c4a4953de9a7aee194..22b6dead99c501972358f35be9f8df0d9f42a1d8 100644 (file)
@@ -9,11 +9,11 @@
 pub struct MultipleReturnTerminators;
 
 impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 4 {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 4
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // find basic blocks with no statement and a return terminator
         let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len());
         let def_id = body.source.def_id();
index a04a0b51531509bf5ad7d3e16a9437b90cccb4e8..0fd9e0352a24978a6a39d9abb3c1dedb62a00d35 100644 (file)
 pub struct NormalizeArrayLen;
 
 impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 4 {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 4
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // early returns for edge cases of highly unrolled functions
         if body.basic_blocks().len() > MAX_NUM_BLOCKS {
             return;
index 3ac4e77cf9a751fe190fd47fc7e750f5d7bee1a5..88ec34b73ec401a833e4bb5a9777492731130c8f 100644 (file)
 pub struct RenameReturnPlace;
 
 impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
-        if tcx.sess.mir_opt_level() == 0 {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
         let def_id = body.source.def_id();
         let returned_local = match local_eligible_for_nrvo(body) {
             Some(l) => l,
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
new file mode 100644 (file)
index 0000000..729b8ca
--- /dev/null
@@ -0,0 +1,144 @@
+use std::borrow::Cow;
+
+use rustc_middle::mir::{self, Body, MirPhase};
+use rustc_middle::ty::TyCtxt;
+use rustc_session::Session;
+
+use crate::{validate, MirPass};
+
+/// Just like `MirPass`, except it cannot mutate `Body`.
+pub trait MirLint<'tcx> {
+    fn name(&self) -> Cow<'_, str> {
+        let name = std::any::type_name::<Self>();
+        if let Some(tail) = name.rfind(':') {
+            Cow::from(&name[tail + 1..])
+        } else {
+            Cow::from(name)
+        }
+    }
+
+    fn is_enabled(&self, _sess: &Session) -> bool {
+        true
+    }
+
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>);
+}
+
+/// An adapter for `MirLint`s that implements `MirPass`.
+#[derive(Debug, Clone)]
+pub struct Lint<T>(pub T);
+
+impl<T> MirPass<'tcx> for Lint<T>
+where
+    T: MirLint<'tcx>,
+{
+    fn name(&self) -> Cow<'_, str> {
+        self.0.name()
+    }
+
+    fn is_enabled(&self, sess: &Session) -> bool {
+        self.0.is_enabled(sess)
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        self.0.run_lint(tcx, body)
+    }
+
+    fn is_mir_dump_enabled(&self) -> bool {
+        false
+    }
+}
+
+pub struct WithMinOptLevel<T>(pub u32, pub T);
+
+impl<T> MirPass<'tcx> for WithMinOptLevel<T>
+where
+    T: MirPass<'tcx>,
+{
+    fn name(&self) -> Cow<'_, str> {
+        self.1.name()
+    }
+
+    fn is_enabled(&self, sess: &Session) -> bool {
+        sess.mir_opt_level() >= self.0 as usize
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        self.1.run_pass(tcx, body)
+    }
+
+    fn phase_change(&self) -> Option<MirPhase> {
+        self.1.phase_change()
+    }
+}
+
+pub fn run_passes(tcx: TyCtxt<'tcx>, body: &'mir mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) {
+    let start_phase = body.phase;
+    let mut cnt = 0;
+
+    let validate = tcx.sess.opts.debugging_opts.validate_mir;
+
+    if validate {
+        validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase));
+    }
+
+    for pass in passes {
+        if !pass.is_enabled(&tcx.sess) {
+            continue;
+        }
+
+        let name = pass.name();
+        let dump_enabled = pass.is_mir_dump_enabled();
+
+        if dump_enabled {
+            dump_mir(tcx, body, start_phase, &name, cnt, false);
+        }
+
+        pass.run_pass(tcx, body);
+
+        if dump_enabled {
+            dump_mir(tcx, body, start_phase, &name, cnt, true);
+            cnt += 1;
+        }
+
+        if let Some(new_phase) = pass.phase_change() {
+            if body.phase >= new_phase {
+                panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase);
+            }
+
+            body.phase = new_phase;
+        }
+
+        if validate {
+            validate_body(tcx, body, format!("after pass {}", pass.name()));
+        }
+    }
+
+    if validate || body.phase == MirPhase::Optimization {
+        validate_body(tcx, body, format!("end of phase transition to {:?}", body.phase));
+    }
+}
+
+pub fn validate_body(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) {
+    validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
+}
+
+pub fn dump_mir(
+    tcx: TyCtxt<'tcx>,
+    body: &Body<'tcx>,
+    phase: MirPhase,
+    pass_name: &str,
+    cnt: usize,
+    is_after: bool,
+) {
+    let phase_index = phase as u32;
+
+    mir::dump_mir(
+        tcx,
+        Some(&format_args!("{:03}-{:03}", phase_index, cnt)),
+        pass_name,
+        if is_after { &"after" } else { &"before" },
+        body,
+        |_, _| Ok(()),
+    );
+}
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,
+            }
+        }
+    }
+}
index 298bcd9dc24f98664f981b91e47186d8c0056ca1..2a73e341f1653f77984b618e1d6e05501a1b7ee5 100644 (file)
 /// code for these.
 pub struct RemoveNoopLandingPads;
 
-pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    if tcx.sess.panic_strategy() == PanicStrategy::Abort {
-        return;
+impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.panic_strategy() != PanicStrategy::Abort
     }
-    debug!("remove_noop_landing_pads({:?})", body);
-
-    RemoveNoopLandingPads.remove_nop_landing_pads(body)
-}
 
-impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        remove_noop_landing_pads(tcx, body);
+    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        debug!("remove_noop_landing_pads({:?})", body);
+        self.remove_nop_landing_pads(body)
     }
 }
 
index 0c7323cbac5b1d039886c53a003af72eb2169136..c9b6e1459d3233e2017ad35a336893b117a01688 100644 (file)
@@ -7,6 +7,10 @@
 pub struct RemoveStorageMarkers;
 
 impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         if tcx.sess.emit_lifetime_markers() {
             return;
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 d93ffa38c69066f40a5cced0b7bcf479b6993cea..1d912e6140989b7205866dc5433d587d8aac821e 100644 (file)
@@ -8,6 +8,10 @@
 pub struct RemoveZsts;
 
 impl<'tcx> MirPass<'tcx> for RemoveZsts {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // Avoid query cycles (generators require optimized MIR for layout).
         if tcx.type_of(body.source.def_id()).is_generator() {
index 6c423a2bb5756c79476adf6a8186781b61c29914..a717dd3e0cd8a6686de92de311770ff0c179d7ec 100644 (file)
@@ -8,15 +8,18 @@
 pub struct RevealAll;
 
 impl<'tcx> MirPass<'tcx> for RevealAll {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.mir_opt_level() >= 3 || super::inline::Inline.is_enabled(sess)
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        // This pass must run before inlining, since we insert callee bodies in RevealAll mode.
         // Do not apply this transformation to generators.
-        if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx))
-            && body.generator.is_none()
-        {
-            let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
-            RevealAllVisitor { tcx, param_env }.visit_body(body);
+        if body.generator.is_some() {
+            return;
         }
+
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        RevealAllVisitor { tcx, param_env }.visit_body(body);
     }
 }
 
@@ -35,24 +38,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 3002e7041b0247dacd18e868907799cbe39b37fa..7450d53ba717ee3ee3cb6d025b51e88cc51d374a 100644 (file)
 pub struct SeparateConstSwitch;
 
 impl<'tcx> MirPass<'tcx> for SeparateConstSwitch {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 4 {
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 4
+    }
 
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // If execution did something, applying a simplification layer
         // helps later passes optimize the copy away.
         if separate_const_switch(body) > 0 {
index f59aaa664f3ad02f1d150a09ee65087462e02373..193a9e6ad291fe98adb4785d26fd7e5cb8488811 100644 (file)
@@ -17,8 +17,8 @@
 
 use crate::util::expand_aggregate;
 use crate::{
-    abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads,
-    run_passes, simplify,
+    abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, marker, pass_manager as pm,
+    remove_noop_landing_pads, simplify,
 };
 use rustc_middle::mir::patch::MirPatch;
 use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
@@ -75,17 +75,25 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
     };
     debug!("make_shim({:?}) = untransformed {:?}", instance, result);
 
-    run_passes(
+    // In some of the above cases, we seem to be invoking the passes for non-shim MIR bodies.
+    // If that happens, there's no need to run them again.
+    //
+    // FIXME: Is this intentional?
+    if result.phase >= MirPhase::Const {
+        return result;
+    }
+
+    pm::run_passes(
         tcx,
         &mut result,
-        MirPhase::Const,
-        &[&[
+        &[
             &add_moves_for_packed_drops::AddMovesForPackedDrops,
             &remove_noop_landing_pads::RemoveNoopLandingPads,
             &simplify::SimplifyCfg::new("make_shim"),
             &add_call_guards::CriticalCallEdges,
             &abort_unwinding_calls::AbortUnwindingCalls,
-        ]],
+            &marker::PhaseChange(MirPhase::Const),
+        ],
     );
 
     debug!("make_shim({:?}) = {:?}", instance, result);
index d6cd505cbb569d281ef85fb16cb49ef896071b00..677869a0bdb6ad4add198e258b318c12d1026cc1 100644 (file)
@@ -368,6 +368,10 @@ fn save_unreachable_coverage(
 pub struct SimplifyLocals;
 
 impl<'tcx> MirPass<'tcx> for SimplifyLocals {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running SimplifyLocals on {:?}", body.source);
         simplify_locals(body, tcx);
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 948fcd9f4550f4e6ec0a7cbdbb606240978b494b..3bd68e8210d5b1663f925c24d70cd17208a2777a 100644 (file)
 pub struct SimplifyComparisonIntegral;
 
 impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("Running SimplifyComparisonIntegral on {:?}", body.source);
 
index 2aa506112909d6241cdc6840d94cad79c3509031..77bc209539b34133a3aaff29739ae22dce4bc276 100644 (file)
@@ -70,6 +70,10 @@ fn variant_discriminants<'tcx>(
 }
 
 impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         if body.source.promoted.is_some() {
             return;
index 64cd6f56a9ffa0a15d254c302587bb0f4e9cccc6..37071ba611708dda99ccd2d9b09ed72ebeb5abe0 100644 (file)
 pub struct UnreachablePropagation;
 
 impl MirPass<'_> for UnreachablePropagation {
-    fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if tcx.sess.mir_opt_level() < 4 {
-            // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt
-            // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
-            return;
-        }
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt
+        // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
+        sess.mir_opt_level() >= 4
+    }
 
+    fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let mut unreachable_blocks = FxHashSet::default();
         let mut replacements = FxHashMap::default();
 
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 ce39d07656f2a529adde22f0bbdc8386512cbf20..55af2c9ddd32f1cb9a5455e443a0e76b364d530a 100644 (file)
@@ -1,6 +1,9 @@
+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;
@@ -19,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 =
@@ -2075,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 f7ee874c8316738b00345bc8c2aa20bd493f1cdd..1dbd7bad0f0236d416885e9b74123d52b9942916 100644 (file)
@@ -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 a9ab2cd3f68ef77278f97e72961d5ed30bd8aa0b..07887a7a59c1db8321c026a43cda4ecb97b6562c 100644 (file)
@@ -92,6 +92,19 @@ pub(super) fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericPar
             let attrs = self.parse_outer_attributes()?;
             let param =
                 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
+                    if this.eat_keyword_noexpect(kw::SelfUpper) {
+                        // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
+                        // as if `Self` never existed.
+                        this.struct_span_err(
+                            this.prev_token.span,
+                            "unexpected keyword `Self` in generic parameters",
+                        )
+                        .note("you cannot use `Self` as a generic parameter because it is reserved for associated items")
+                        .emit();
+
+                        this.eat(&token::Comma);
+                    }
+
                     let param = if this.check_lifetime() {
                         let lifetime = this.expect_lifetime();
                         // Parse lifetime parameter.
index 24a8df49ac7eefb20653314af14b2372d899f5dc..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.
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 f761eaae5ab73652822d584ac0c4b0fd0ef7f92b..49e6a7df103012e7f773ca32555d05ff899fa08d 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";
@@ -1953,7 +1953,12 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
     }
 }
 
+// FIXME: Fix "Cannot determine resolution" error and remove built-in macros
+// from this check.
 fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
+    // Check for builtin attributes at the crate level
+    // which were unsuccessfully resolved due to cannot determine
+    // resolution for the attribute macro error.
     const ATTRS_TO_CHECK: &[Symbol] = &[
         sym::macro_export,
         sym::repr,
@@ -1961,20 +1966,39 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         sym::automatically_derived,
         sym::start,
         sym::rustc_main,
+        sym::derive,
+        sym::test,
+        sym::test_case,
+        sym::global_allocator,
+        sym::bench,
     ];
 
     for attr in attrs {
-        for attr_to_check in ATTRS_TO_CHECK {
-            if attr.has_name(*attr_to_check) {
-                tcx.sess
-                    .struct_span_err(
+        // This function should only be called with crate attributes
+        // which are inner attributes always but lets check to make sure
+        if attr.style == AttrStyle::Inner {
+            for attr_to_check in ATTRS_TO_CHECK {
+                if attr.has_name(*attr_to_check) {
+                    let mut err = tcx.sess.struct_span_err(
                         attr.span,
                         &format!(
                             "`{}` attribute cannot be used at crate level",
                             attr_to_check.to_ident_string()
                         ),
-                    )
-                    .emit();
+                    );
+                    // Only emit an error with a suggestion if we can create a
+                    // string out of the attribute span
+                    if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) {
+                        let replacement = src.replace("#!", "#");
+                        err.span_suggestion_verbose(
+                            attr.span,
+                            "perhaps you meant to use an outer attribute",
+                            replacement,
+                            rustc_errors::Applicability::MachineApplicable,
+                        );
+                    }
+                    err.emit()
+                }
             }
         }
     }
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 b1295ba48ccb96e0824498f02c4f4a5113e9951f..0da141f6836f68a3281c963124009697b81c4eeb 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(iter_zip)]
 #![feature(let_else)]
 #![feature(min_specialization)]
-#![feature(thread_local_const_init)]
 #![feature(extern_types)]
 
 #[macro_use]
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 d506931b516e73d3f6d72c234021ed433861a8bf..72ba3f7b980cbc464de015724d1e2d31d27e7db0 100644 (file)
@@ -1735,7 +1735,7 @@ fn suggest_using_enum_variant(
                         (generics.span, format!("<{}>", ident))
                     };
                     // Do not suggest if this is coming from macro expansion.
-                    if !span.from_expansion() {
+                    if span.can_be_used_for_suggestions() {
                         return Some((
                             span.shrink_to_hi(),
                             msg,
@@ -1803,7 +1803,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         );
         err.span_label(lifetime_ref.span, "undeclared lifetime");
         let mut suggests_in_band = false;
-        let mut suggest_note = true;
+        let mut suggested_spans = vec![];
         for missing in &self.missing_named_lifetime_spots {
             match missing {
                 MissingLifetimeSpot::Generics(generics) => {
@@ -1821,23 +1821,17 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         suggests_in_band = true;
                         (generics.span, format!("<{}>", lifetime_ref))
                     };
-                    if !span.from_expansion() {
+                    if suggested_spans.contains(&span) {
+                        continue;
+                    }
+                    suggested_spans.push(span);
+                    if span.can_be_used_for_suggestions() {
                         err.span_suggestion(
                             span,
                             &format!("consider introducing lifetime `{}` here", lifetime_ref),
                             sugg,
                             Applicability::MaybeIncorrect,
                         );
-                    } else if suggest_note {
-                        suggest_note = false; // Avoid displaying the same help multiple times.
-                        err.span_label(
-                            span,
-                            &format!(
-                                "lifetime `{}` is missing in item created through this procedural \
-                                 macro",
-                                lifetime_ref,
-                            ),
-                        );
                     }
                 }
                 MissingLifetimeSpot::HigherRanked { span, span_type } => {
@@ -1871,6 +1865,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 +2402,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..87e8e57611765ab053b69a42c4e4f0339a1bc7eb 100644 (file)
@@ -746,6 +746,7 @@ fn default() -> Options {
             edition: DEFAULT_EDITION,
             json_artifact_notifications: false,
             json_unused_externs: false,
+            json_future_incompat: false,
             pretty: None,
             working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
         }
@@ -833,6 +834,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 {
@@ -1250,6 +1258,7 @@ pub struct JsonConfig {
     pub json_rendered: HumanReadableErrorType,
     pub json_artifact_notifications: bool,
     pub json_unused_externs: bool,
+    pub json_future_incompat: bool,
 }
 
 /// Parse the `--json` flag.
@@ -1262,6 +1271,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
     let mut json_color = ColorConfig::Never;
     let mut json_artifact_notifications = false;
     let mut json_unused_externs = false;
+    let mut json_future_incompat = false;
     for option in matches.opt_strs("json") {
         // For now conservatively forbid `--color` with `--json` since `--json`
         // won't actually be emitting any colors and anything colorized is
@@ -1279,6 +1289,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
                 "diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
                 "artifacts" => json_artifact_notifications = true,
                 "unused-externs" => json_unused_externs = true,
+                "future-incompat" => json_future_incompat = true,
                 s => early_error(
                     ErrorOutputType::default(),
                     &format!("unknown `--json` option `{}`", s),
@@ -1291,6 +1302,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
         json_rendered: json_rendered(json_color),
         json_artifact_notifications,
         json_unused_externs,
+        json_future_incompat,
     }
 }
 
@@ -2004,8 +2016,12 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let edition = parse_crate_edition(matches);
 
-    let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } =
-        parse_json(matches);
+    let JsonConfig {
+        json_rendered,
+        json_artifact_notifications,
+        json_unused_externs,
+        json_future_incompat,
+    } = parse_json(matches);
 
     let error_format = parse_error_format(matches, color, json_rendered);
 
@@ -2241,6 +2257,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         edition,
         json_artifact_notifications,
         json_unused_externs,
+        json_future_incompat,
         pretty,
         working_dir,
     }
index 9359a55e55a9c74845c6a539f30abb43b3016056..357190178ce014a01041fcbe685bb5c470c6515e 100644 (file)
@@ -4,6 +4,7 @@
 
 use std::env;
 use std::fs;
+use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
 use crate::search_paths::{PathKind, SearchPath, SearchPathFile};
@@ -91,8 +92,7 @@ pub fn search_path_dirs(&self) -> Vec<PathBuf> {
 
 pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
     let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
-    std::array::IntoIter::new([sysroot, Path::new(&rustlib_path), Path::new("lib")])
-        .collect::<PathBuf>()
+    PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
 }
 
 /// This function checks if sysroot is found using env::args().next(), and if it
index 4165e750df50f4bbdcf5145171d1456691796575..bd7b1639613eb7963a776fcb38b2e779cf95cb74 100644 (file)
@@ -101,6 +101,29 @@ pub fn dep_tracking_hash(&self, for_crate_hash: bool) -> u64 {
     );
 }
 
+impl Options {
+    pub fn mir_opt_level(&self) -> usize {
+        self.debugging_opts
+            .mir_opt_level
+            .unwrap_or_else(|| if self.optimize != OptLevel::No { 2 } else { 1 })
+    }
+
+    pub fn instrument_coverage(&self) -> bool {
+        self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off)
+            != InstrumentCoverage::Off
+    }
+
+    pub fn instrument_coverage_except_unused_generics(&self) -> bool {
+        self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off)
+            == InstrumentCoverage::ExceptUnusedGenerics
+    }
+
+    pub fn instrument_coverage_except_unused_functions(&self) -> bool {
+        self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off)
+            == InstrumentCoverage::ExceptUnusedFunctions
+    }
+}
+
 top_level_options!(
     /// The top-level command-line options struct.
     ///
@@ -205,6 +228,9 @@ pub struct Options {
         /// `true` if we're emitting a JSON blob containing the unused externs
         json_unused_externs: bool [UNTRACKED],
 
+        /// `true` if we're emitting a JSON job containg a future-incompat report for lints
+        json_future_incompat: bool [TRACKED],
+
         pretty: Option<PpMode> [UNTRACKED],
 
         /// The (potentially remapped) working directory
@@ -567,7 +593,7 @@ mod parse {
             v => {
                 let mut passes = vec![];
                 if parse_list(&mut passes, v) {
-                    *slot = Passes::Some(passes);
+                    slot.extend(passes);
                     true
                 } else {
                     false
@@ -1124,8 +1150,6 @@ mod parse {
         computed `block` spans (one span encompassing a block's terminator and \
         all statements). If `-Z instrument-coverage` is also enabled, create \
         an additional `.html` file showing the computed coverage spans."),
-    emit_future_incompat_report: bool = (false, parse_bool, [UNTRACKED],
-        "emits a future-incompatibility report for lints (RFC 2834)"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
         "emit a section containing stack size metadata (default: no)"),
     fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
index 54109559a3bb2fd777c493c067a7f2214b5e5166..730e79a56470ea95e23e313caaab0af9583c58f1 100644 (file)
@@ -280,7 +280,7 @@ pub fn finish_diagnostics(&self, registry: &Registry) {
     }
 
     fn emit_future_breakage(&self) {
-        if !self.opts.debugging_opts.emit_future_incompat_report {
+        if !self.opts.json_future_incompat {
             return;
         }
 
@@ -562,10 +562,7 @@ pub fn binary_dep_depinfo(&self) -> bool {
         self.opts.debugging_opts.binary_dep_depinfo
     }
     pub fn mir_opt_level(&self) -> usize {
-        self.opts
-            .debugging_opts
-            .mir_opt_level
-            .unwrap_or_else(|| if self.opts.optimize != config::OptLevel::No { 2 } else { 1 })
+        self.opts.mir_opt_level()
     }
 
     /// Gets the features enabled for the current compilation session.
@@ -795,12 +792,11 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
     /// Returns a list of directories where target-specific tool binaries are located.
     pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
         let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple());
-        let p = std::array::IntoIter::new([
+        let p = PathBuf::from_iter([
             Path::new(&self.sysroot),
             Path::new(&rustlib_path),
             Path::new("bin"),
-        ])
-        .collect::<PathBuf>();
+        ]);
         if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
     }
 
@@ -1047,18 +1043,15 @@ pub fn link_dead_code(&self) -> bool {
     }
 
     pub fn instrument_coverage(&self) -> bool {
-        self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
-            != config::InstrumentCoverage::Off
+        self.opts.instrument_coverage()
     }
 
     pub fn instrument_coverage_except_unused_generics(&self) -> bool {
-        self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
-            == config::InstrumentCoverage::ExceptUnusedGenerics
+        self.opts.instrument_coverage_except_unused_generics()
     }
 
     pub fn instrument_coverage_except_unused_functions(&self) -> bool {
-        self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
-            == config::InstrumentCoverage::ExceptUnusedFunctions
+        self.opts.instrument_coverage_except_unused_functions()
     }
 
     pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
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 66c01140abc17e1e8c1360f92633933cb4931f3f..ea3d3363b80655edbfb5eb15f7e0b885356600a0 100644 (file)
@@ -20,7 +20,6 @@
 #![feature(negative_impls)]
 #![feature(nll)]
 #![feature(min_specialization)]
-#![feature(thread_local_const_init)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -551,6 +550,16 @@ pub fn in_derive_expansion(self) -> bool {
         matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
     }
 
+    /// Gate suggestions that would not be appropriate in a context the user didn't write.
+    pub fn can_be_used_for_suggestions(self) -> bool {
+        !self.from_expansion()
+        // FIXME: If this span comes from a `derive` macro but it points at code the user wrote,
+        // the callsite span and the span will be pointing at different places. It also means that
+        // we can safely provide suggestions on this span.
+            || (matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
+                && self.parent_callsite().map(|p| (p.lo(), p.hi())) != Some((self.lo(), self.hi())))
+    }
+
     #[inline]
     pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
         Span::new(lo, hi, SyntaxContext::root(), None)
index 247d69d6ee97bdb26e50e8861ca96173e3336df3..309c305293fd6e54e6ffe3d6af4b229d214b67bc 100644 (file)
         Implied,
         Input,
         Into,
+        IntoFuture,
         IntoIterator,
         IoRead,
         IoWrite,
         asm_const,
         asm_experimental_arch,
         asm_sym,
+        asm_unwind,
         assert,
         assert_inhabited,
         assert_macro,
         inout,
         instruction_set,
         intel,
+        into_future,
         into_iter,
         intra_doc_pointers,
         intrinsics,
         maxnumf32,
         maxnumf64,
         may_dangle,
+        may_unwind,
         maybe_uninit,
         maybe_uninit_uninit,
         maybe_uninit_zeroed,
@@ -1716,8 +1720,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,
@@ -1743,14 +1748,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 23d5d575d9447d7b97cd7cbb4ae1a42115dd18cb..b18d17c1b7d1ff7a02e81d05c405acba101824c9 100644 (file)
@@ -16,6 +16,7 @@
 #![feature(min_specialization)]
 #![feature(step_trait)]
 
+use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
 #[macro_use]
@@ -47,12 +48,11 @@ pub trait HashStableContext {}
 /// `"lib*/rustlib/x86_64-unknown-linux-gnu"`.
 pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
     let libdir = find_libdir(sysroot);
-    std::array::IntoIter::new([
+    PathBuf::from_iter([
         Path::new(libdir.as_ref()),
         Path::new(RUST_LIB_DIR),
         Path::new(target_triple),
     ])
-    .collect::<PathBuf>()
 }
 
 /// The name of the directory rustc expects libraries to be located.
index 0d49c7f6ee8b96417f9cec71d98744a79c6a5a3d..72d9b5015451cd3ba14e9d5096e2a97eccce7a7a 100644 (file)
@@ -42,6 +42,7 @@
 use rustc_span::symbol::{sym, Symbol};
 use std::collections::BTreeMap;
 use std::convert::TryFrom;
+use std::iter::FromIterator;
 use std::ops::{Deref, DerefMut};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
@@ -2173,12 +2174,11 @@ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
                 // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
                 // as a fallback.
                 let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple);
-                let p = std::array::IntoIter::new([
+                let p = PathBuf::from_iter([
                     Path::new(sysroot),
                     Path::new(&rustlib_path),
                     Path::new("target.json"),
-                ])
-                .collect::<PathBuf>();
+                ]);
                 if p.is_file() {
                     return load_file(&p);
                 }
index ecc352c1a49b5bc5f1de2d98b30ed34212a9ac4b..1820e33b19bf4fc0ae332bc78aeb3ab8e6359d23 100644 (file)
@@ -22,7 +22,6 @@
 #![feature(never_type)]
 #![feature(crate_visibility_modifier)]
 #![feature(control_flow_enum)]
-#![feature(unwrap_infallible)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
index 9052dff0aaa837514b2eadfe507eb6184c079b4e..75d57d78e3b0294be8d2138590248c775ddb6048 100644 (file)
@@ -65,16 +65,14 @@ fn infer_opaque_definition_from_instantiation(
         // Convert the type from the function into a type valid outside
         // the function, by replacing invalid regions with 'static,
         // after producing an error for each of them.
-        let definition_ty = instantiated_ty
-            .fold_with(&mut ReverseMapper::new(
-                self.tcx,
-                self.is_tainted_by_errors(),
-                def_id,
-                map,
-                instantiated_ty,
-                span,
-            ))
-            .into_ok();
+        let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
+            self.tcx,
+            self.is_tainted_by_errors(),
+            def_id,
+            map,
+            instantiated_ty,
+            span,
+        ));
         debug!(?definition_ty);
 
         definition_ty
@@ -125,14 +123,14 @@ fn fold_kind_mapping_missing_regions_to_empty(
     ) -> GenericArg<'tcx> {
         assert!(!self.map_missing_regions_to_empty);
         self.map_missing_regions_to_empty = true;
-        let kind = kind.fold_with(self).into_ok();
+        let kind = kind.fold_with(self);
         self.map_missing_regions_to_empty = false;
         kind
     }
 
     fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
         assert!(!self.map_missing_regions_to_empty);
-        kind.fold_with(self).into_ok()
+        kind.fold_with(self)
     }
 }
 
@@ -142,17 +140,17 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match r {
             // Ignore bound regions and `'static` regions that appear in the
             // type, we only need to remap regions that reference lifetimes
             // from the function declaraion.
             // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
-            ty::ReLateBound(..) | ty::ReStatic => return Ok(r),
+            ty::ReLateBound(..) | ty::ReStatic => return r,
 
             // If regions have been erased (by writeback), don't try to unerase
             // them.
-            ty::ReErased => return Ok(r),
+            ty::ReErased => return r,
 
             // The regions that we expect from borrow checking.
             ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
@@ -167,10 +165,10 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
 
         let generics = self.tcx().generics_of(self.opaque_type_def_id);
         match self.map.get(&r.into()).map(|k| k.unpack()) {
-            Some(GenericArgKind::Lifetime(r1)) => Ok(r1),
+            Some(GenericArgKind::Lifetime(r1)) => r1,
             Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
             None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
-                Ok(self.tcx.lifetimes.re_root_empty)
+                self.tcx.lifetimes.re_root_empty
             }
             None if generics.parent.is_some() => {
                 if let Some(hidden_ty) = self.hidden_ty.take() {
@@ -182,7 +180,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                     )
                     .emit();
                 }
-                Ok(self.tcx.lifetimes.re_root_empty)
+                self.tcx.lifetimes.re_root_empty
             }
             None => {
                 self.tcx
@@ -198,12 +196,12 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                     )
                     .emit();
 
-                Ok(self.tcx().lifetimes.re_static)
+                self.tcx().lifetimes.re_static
             }
         }
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match *ty.kind() {
             ty::Closure(def_id, substs) => {
                 // I am a horrible monster and I pray for death. When
@@ -241,7 +239,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     }
                 }));
 
-                Ok(self.tcx.mk_closure(def_id, substs))
+                self.tcx.mk_closure(def_id, substs)
             }
 
             ty::Generator(def_id, substs, movability) => {
@@ -256,7 +254,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                     }
                 }));
 
-                Ok(self.tcx.mk_generator(def_id, substs, movability))
+                self.tcx.mk_generator(def_id, substs, movability)
             }
 
             ty::Param(param) => {
@@ -264,7 +262,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 match self.map.get(&ty.into()).map(|k| k.unpack()) {
                     // Found it in the substitution list; replace with the parameter from the
                     // opaque type.
-                    Some(GenericArgKind::Type(t1)) => Ok(t1),
+                    Some(GenericArgKind::Type(t1)) => t1,
                     Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
                     None => {
                         debug!(?param, ?self.map);
@@ -280,7 +278,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                             )
                             .emit();
 
-                        Ok(self.tcx().ty_error())
+                        self.tcx().ty_error()
                     }
                 }
             }
@@ -289,13 +287,10 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         trace!("checking const {:?}", ct);
         // Find a const parameter
-        Ok(match ct.val {
+        match ct.val {
             ty::ConstKind::Param(..) => {
                 // Look it up in the substitution list.
                 match self.map.get(&ct.into()).map(|k| k.unpack()) {
@@ -322,7 +317,7 @@ fn fold_const(
             }
 
             _ => ct,
-        })
+        }
     }
 }
 
index 7af32b2f3b17462867835e27194859303f7aa1f0..54f7b91080dd9fb0a9cae74dea7ecd43517972a5 100644 (file)
@@ -860,11 +860,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        Ok((match r {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        (match r {
             ty::ReVar(vid) => self.vid_to_region.get(vid).cloned(),
             _ => None,
         })
-        .unwrap_or_else(|| r.super_fold_with(self).into_ok()))
+        .unwrap_or_else(|| r.super_fold_with(self))
     }
 }
index 6b5d37c0f43086516d57425d66807dd3b6ca72b7..0ea3a18ca34fa2af5317beb4e552dc15594a4e0d 100644 (file)
@@ -399,13 +399,25 @@ fn recurse_build(&mut self, node: thir::ExprId) -> Result<NodeId, ErrorReported>
                 let arg = self.recurse_build(source)?;
                 self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
             }
-
+            ExprKind::Borrow{ arg, ..} => {
+                let arg_node = &self.body.exprs[*arg];
+
+                // Skip reborrows for now until we allow Deref/Borrow/AddressOf
+                // expressions.
+                // FIXME(generic_const_exprs): Verify/explain why this is sound
+                if let ExprKind::Deref {arg} = arg_node.kind {
+                    self.recurse_build(arg)?
+                } else {
+                    self.maybe_supported_error(
+                        node.span,
+                        "borrowing is not supported in generic constants",
+                    )?
+                }
+            }
             // FIXME(generic_const_exprs): We may want to support these.
-            ExprKind::AddressOf { .. }
-            | ExprKind::Borrow { .. }
-            | ExprKind::Deref { .. } => self.maybe_supported_error(
+            ExprKind::AddressOf { .. } | ExprKind::Deref {..}=> self.maybe_supported_error(
                 node.span,
-                "dereferencing is not supported in generic constants",
+                "dereferencing or taking the address is not supported in generic constants",
             )?,
             ExprKind::Repeat { .. } | ExprKind::Array { .. } =>  self.maybe_supported_error(
                 node.span,
index 866bcde1bfd4f11a4f1c76369cba0f4e779ad2a2..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;
                         }
@@ -1898,15 +1898,15 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
                 self.infcx.tcx
             }
 
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() {
                     let infcx = self.infcx;
-                    Ok(self.var_map.entry(ty).or_insert_with(|| {
+                    self.var_map.entry(ty).or_insert_with(|| {
                         infcx.next_ty_var(TypeVariableOrigin {
                             kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
                             span: DUMMY_SP,
                         })
-                    }))
+                    })
                 } else {
                     ty.super_fold_with(self)
                 }
@@ -1916,9 +1916,8 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         self.probe(|_| {
             let mut selcx = SelectionContext::new(self);
 
-            let cleaned_pred = pred
-                .fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() })
-                .into_ok();
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
 
             let cleaned_pred = super::project::normalize(
                 &mut selcx,
@@ -2026,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 a90140a9b50b924ded3a3ec7e52e5c2b3bbbcb45..2e87d6fdd3dc20e787ac0a3a4405b4c5e4272ade 100644 (file)
@@ -262,8 +262,8 @@ fn suggest_restriction(
             match generics
                 .params
                 .iter()
-                .map(|p| p.bounds_span().unwrap_or(p.span))
-                .filter(|&span| generics.span.contains(span) && span.desugaring_kind().is_none())
+                .map(|p| p.bounds_span_for_suggestions().unwrap_or(p.span.shrink_to_hi()))
+                .filter(|&span| generics.span.contains(span) && span.can_be_used_for_suggestions())
                 .max_by_key(|span| span.hi())
             {
                 // `fn foo(t: impl Trait)`
@@ -271,7 +271,7 @@ fn suggest_restriction(
                 None => (generics.span, format!("<{}>", type_param)),
                 // `fn foo<A>(t: impl Trait)`
                 //        ^^^ suggest `<A, T: Trait>` here
-                Some(span) => (span.shrink_to_hi(), format!(", {}", type_param)),
+                Some(span) => (span, format!(", {}", type_param)),
             },
             // `fn foo(t: impl Trait)`
             //                       ^ suggest `where <T as Trait>::A: Bound`
index afc546540d2e262d99c2818a6125805a07746eb6..2ad8dc82a84dceb5e5cef88b4d621e67ce2c698d 100644 (file)
@@ -25,7 +25,6 @@
 use rustc_span::{MultiSpan, Span};
 use smallvec::SmallVec;
 
-use std::array;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -692,11 +691,8 @@ fn receiver_is_dispatchable<'tcx>(
                 .to_predicate(tcx)
         };
 
-        let caller_bounds: Vec<Predicate<'tcx>> = param_env
-            .caller_bounds()
-            .iter()
-            .chain(array::IntoIter::new([unsize_predicate, trait_predicate]))
-            .collect();
+        let caller_bounds: Vec<Predicate<'tcx>> =
+            param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect();
 
         ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal())
     };
index 0911b2c529ab25b00bc520c58cf4f1fdad1c4864..b8c66931cbe52ef093ce8cfb2629d29f72ec7268 100644 (file)
@@ -339,7 +339,7 @@ fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
         if !needs_normalization(&value, self.param_env.reveal()) {
             value
         } else {
-            value.fold_with(self).into_ok()
+            value.fold_with(self)
         }
     }
 }
@@ -352,16 +352,16 @@ fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.universes.push(None);
         let t = t.super_fold_with(self);
         self.universes.pop();
         t
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         if !needs_normalization(&ty, self.param_env.reveal()) {
-            return Ok(ty);
+            return ty;
         }
 
         // We try to be a little clever here as a performance optimization in
@@ -387,14 +387,14 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         // replace bound vars if the current type is a `Projection` and we need
         // to make sure we don't forget to fold the substs regardless.
 
-        Ok(match *ty.kind() {
+        match *ty.kind() {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
             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.super_fold_with(self),
 
                     Reveal::All => {
                         let recursion_limit = self.tcx().recursion_limit();
@@ -408,11 +408,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                             self.selcx.infcx().report_overflow_error(&obligation, true);
                         }
 
-                        let substs = substs.super_fold_with(self)?;
+                        let substs = substs.super_fold_with(self);
                         let generic_ty = self.tcx().type_of(def_id);
                         let concrete_ty = generic_ty.subst(self.tcx(), substs);
                         self.depth += 1;
-                        let folded_ty = self.fold_ty(concrete_ty)?;
+                        let folded_ty = self.fold_ty(concrete_ty);
                         self.depth -= 1;
                         folded_ty
                     }
@@ -426,7 +426,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 // register an obligation to *later* project, since we know
                 // there won't be bound vars there.
 
-                let data = data.super_fold_with(self)?;
+                let data = data.super_fold_with(self);
                 let normalized_ty = normalize_projection_type(
                     self.selcx,
                     self.param_env,
@@ -461,7 +461,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 let infcx = self.selcx.infcx();
                 let (data, mapped_regions, mapped_types, mapped_consts) =
                     BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
-                let data = data.super_fold_with(self)?;
+                let data = data.super_fold_with(self);
                 let normalized_ty = opt_normalize_projection_type(
                     self.selcx,
                     self.param_env,
@@ -473,18 +473,16 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 .ok()
                 .flatten()
                 .map(|normalized_ty| {
-                    Ok({
-                        PlaceholderReplacer::replace_placeholders(
-                            infcx,
-                            mapped_regions,
-                            mapped_types,
-                            mapped_consts,
-                            &self.universes,
-                            normalized_ty,
-                        )
-                    })
+                    PlaceholderReplacer::replace_placeholders(
+                        infcx,
+                        mapped_regions,
+                        mapped_types,
+                        mapped_consts,
+                        &self.universes,
+                        normalized_ty,
+                    )
                 })
-                .unwrap_or_else(|| ty.super_fold_with(self))?;
+                .unwrap_or_else(|| ty.super_fold_with(self));
 
                 debug!(
                     ?self.depth,
@@ -496,19 +494,16 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 normalized_ty
             }
 
-            _ => ty.super_fold_with(self)?,
-        })
+            _ => ty.super_fold_with(self),
+        }
     }
 
-    fn fold_const(
-        &mut self,
-        constant: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if self.selcx.tcx().lazy_normalization() {
-            Ok(constant)
+            constant
         } else {
-            let constant = constant.super_fold_with(self)?;
-            Ok(constant.eval(self.selcx.tcx(), self.param_env))
+            let constant = constant.super_fold_with(self);
+            constant.eval(self.selcx.tcx(), self.param_env)
         }
     }
 }
@@ -555,7 +550,7 @@ pub fn replace_bound_vars<T: TypeFoldable<'tcx>>(
             universe_indices,
         };
 
-        let value = value.super_fold_with(&mut replacer).into_ok();
+        let value = value.super_fold_with(&mut replacer);
 
         (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
     }
@@ -582,14 +577,14 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, _)
                 if debruijn.as_usize() + 1
@@ -601,13 +596,13 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self:
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, name: br.kind };
                 self.mapped_regions.insert(p, br);
-                Ok(self.infcx.tcx.mk_region(ty::RePlaceholder(p)))
+                self.infcx.tcx.mk_region(ty::RePlaceholder(p))
             }
-            _ => Ok(r),
+            _ => r,
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
             ty::Bound(debruijn, _)
                 if debruijn.as_usize() + 1
@@ -619,17 +614,14 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderType { universe, name: bound_ty.var };
                 self.mapped_types.insert(p, bound_ty);
-                Ok(self.infcx.tcx.mk_ty(ty::Placeholder(p)))
+                self.infcx.tcx.mk_ty(ty::Placeholder(p))
             }
             _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
-            _ => Ok(t),
+            _ => t,
         }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match *ct {
             ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ }
                 if debruijn.as_usize() + 1
@@ -646,10 +638,10 @@ fn fold_const(
                     name: ty::BoundConst { var: bound_const, ty },
                 };
                 self.mapped_consts.insert(p, bound_const);
-                Ok(self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }))
+                self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
-            _ => Ok(ct),
+            _ => ct,
         }
     }
 }
@@ -681,7 +673,7 @@ pub fn replace_placeholders<T: TypeFoldable<'tcx>>(
             universe_indices,
             current_index: ty::INNERMOST,
         };
-        value.super_fold_with(&mut replacer).into_ok()
+        value.super_fold_with(&mut replacer)
     }
 }
 
@@ -693,9 +685,9 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
+    ) -> ty::Binder<'tcx, T> {
         if !t.has_placeholders() && !t.has_infer_regions() {
-            return Ok(t);
+            return t;
         }
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
@@ -703,7 +695,7 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
         t
     }
 
-    fn fold_region(&mut self, r0: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
         let r1 = match r0 {
             ty::ReVar(_) => self
                 .infcx
@@ -737,10 +729,10 @@ fn fold_region(&mut self, r0: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self
 
         debug!(?r0, ?r1, ?r2, "fold_region");
 
-        Ok(r2)
+        r2
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match *ty.kind() {
             ty::Placeholder(p) => {
                 let replace_var = self.mapped_types.get(&p);
@@ -754,21 +746,18 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                         let db = ty::DebruijnIndex::from_usize(
                             self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                         );
-                        Ok(self.tcx().mk_ty(ty::Bound(db, *replace_var)))
+                        self.tcx().mk_ty(ty::Bound(db, *replace_var))
                     }
-                    None => Ok(ty),
+                    None => ty,
                 }
             }
 
             _ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self),
-            _ => Ok(ty),
+            _ => ty,
         }
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct {
             let replace_var = self.mapped_consts.get(&p);
             match replace_var {
@@ -781,11 +770,10 @@ fn fold_const(
                     let db = ty::DebruijnIndex::from_usize(
                         self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                     );
-                    Ok(self
-                        .tcx()
-                        .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }))
+                    self.tcx()
+                        .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty })
                 }
-                None => Ok(ct),
+                None => ct,
             }
         } else {
             ct.super_fold_with(self)
@@ -1546,8 +1534,7 @@ fn confirm_candidate<'cx, 'tcx>(
     // when possible for this to work. See `auto-trait-projection-recursion.rs`
     // for a case where this matters.
     if progress.ty.has_infer_regions() {
-        progress.ty =
-            OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty).into_ok();
+        progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty);
     }
     progress
 }
index af507feffba5b5ed615b24f7dac83074c41166d2..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};
 
@@ -87,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>(),
@@ -176,19 +176,21 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
     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>,
     ) -> 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>) -> Result<Ty<'tcx>, Self::Error> {
+    fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !needs_normalization(&ty, self.param_env.reveal()) {
             return Ok(ty);
         }
@@ -208,10 +210,10 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
             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(
@@ -236,7 +238,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                                 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
                     }
@@ -248,7 +250,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 // 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,
@@ -287,7 +289,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                         &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,
@@ -322,24 +324,24 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 ))
             }
 
-            _ => ty.super_fold_with(self),
+            _ => ty.try_super_fold_with(self),
         })()?;
         self.cache.insert(ty, res);
         Ok(res)
     }
 
-    fn fold_const(
+    fn try_fold_const(
         &mut self,
         constant: &'tcx ty::Const<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-        let constant = constant.super_fold_with(self)?;
+        let constant = constant.try_super_fold_with(self)?;
         Ok(constant.eval(self.infcx.tcx, self.param_env))
     }
 
-    fn fold_mir_const(
+    fn try_fold_mir_const(
         &mut self,
         constant: mir::ConstantKind<'tcx>,
     ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
-        constant.super_fold_with(self)
+        constant.try_super_fold_with(self)
     }
 }
index 767cb1618bb67d35239db630af41e98e8bad37e3..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)
@@ -2222,7 +2226,6 @@ fn push_stack<'o>(
             .predicate
             .to_poly_trait_ref()
             .fold_with(&mut self.freshener)
-            .into_ok()
             .with_constness(obligation.predicate.skip_binder().constness);
 
         let dfn = previous_stack.cache.next_dfn();
index fdff07302c2407fbe7e8c72c5844870e5f1b715d..1d457d6761fd084c1e0c7bab1c98ba5f0746921b 100644 (file)
@@ -45,7 +45,7 @@ fn where_clauses_for(
         predicates
             .iter()
             .map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars))
-            .map(|wc| wc.fold_with(&mut regions_substitutor).into_ok())
+            .map(|wc| wc.fold_with(&mut regions_substitutor))
             .filter_map(|wc| LowerInto::<Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>>::lower_into(wc, &self.interner)).collect()
     }
 
@@ -287,7 +287,7 @@ fn impl_datum(
         let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars);
         let mut regions_substitutor =
             lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
-        let trait_ref = trait_ref.fold_with(&mut regions_substitutor).into_ok();
+        let trait_ref = trait_ref.fold_with(&mut regions_substitutor);
 
         let where_clauses = self.where_clauses_for(def_id, bound_vars);
 
@@ -335,7 +335,7 @@ fn impls_for_trait(
             let self_ty = self_ty.subst(self.interner.tcx, bound_vars);
             let mut regions_substitutor =
                 lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
-            let self_ty = self_ty.fold_with(&mut regions_substitutor).into_ok();
+            let self_ty = self_ty.fold_with(&mut regions_substitutor);
             let lowered_ty = self_ty.lower_into(&self.interner);
 
             parameters[0].assert_ty_ref(&self.interner).could_match(
@@ -501,24 +501,22 @@ fn opaque_ty_data(
                 .iter()
                 .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
                 .map(|bound| {
-                    bound
-                        .fold_with(&mut ty::fold::BottomUpFolder {
-                            tcx: self.interner.tcx,
-                            ty_op: |ty| {
-                                if let ty::Opaque(def_id, substs) = *ty.kind() {
-                                    if def_id == opaque_ty_id.0 && substs == identity_substs {
-                                        return self.interner.tcx.mk_ty(ty::Bound(
-                                            ty::INNERMOST,
-                                            ty::BoundTy::from(ty::BoundVar::from_u32(0)),
-                                        ));
-                                    }
+                    bound.fold_with(&mut ty::fold::BottomUpFolder {
+                        tcx: self.interner.tcx,
+                        ty_op: |ty| {
+                            if let ty::Opaque(def_id, substs) = *ty.kind() {
+                                if def_id == opaque_ty_id.0 && substs == identity_substs {
+                                    return self.interner.tcx.mk_ty(ty::Bound(
+                                        ty::INNERMOST,
+                                        ty::BoundTy::from(ty::BoundVar::from_u32(0)),
+                                    ));
                                 }
-                                ty
-                            },
-                            lt_op: |lt| lt,
-                            ct_op: |ct| ct,
-                        })
-                        .into_ok()
+                            }
+                            ty
+                        },
+                        lt_op: |lt| lt,
+                        ct_op: |ct| ct,
+                    })
                 })
                 .filter_map(|bound| {
                     LowerInto::<
index 66073facf4b0c1f10bfa59e3ed2ea39ac1053c25..e24f699adf6b398d9ec8ee263fa037f6a532752f 100644 (file)
@@ -817,7 +817,7 @@ fn lower_into(
         .collect();
 
     let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters);
-    let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor).into_ok();
+    let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor);
 
     for var in named_parameters.values() {
         parameters.insert(*var, chalk_ir::VariableKind::Lifetime);
@@ -943,23 +943,20 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_binder<T: TypeFoldable<'tcx>>(
-        &mut self,
-        t: Binder<'tcx, T>,
-    ) -> Result<Binder<'tcx, T>, Self::Error> {
+    fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
         self.binder_index.shift_in(1);
         let result = t.super_fold_with(self);
         self.binder_index.shift_out(1);
         result
     }
 
-    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
         match r {
             ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
                     Some(idx) => {
                         let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
-                        return Ok(self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)));
+                        return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br));
                     }
                     None => panic!("Missing `BrNamed`."),
                 },
@@ -1002,35 +999,32 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_binder<T: TypeFoldable<'tcx>>(
-        &mut self,
-        t: Binder<'tcx, T>,
-    ) -> Result<Binder<'tcx, T>, Self::Error> {
+    fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
         self.binder_index.shift_in(1);
         let result = t.super_fold_with(self);
         self.binder_index.shift_out(1);
         result
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
             // FIXME(chalk): currently we convert params to placeholders starting at
             // index `0`. To support placeholders, we'll actually need to do a
             // first pass to collect placeholders. Then we can insert params after.
             ty::Placeholder(_) => unimplemented!(),
             ty::Param(param) => match self.list.iter().position(|r| r == &param) {
-                Some(idx) => Ok(self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+                Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::from_usize(0),
                     name: ty::BoundVar::from_usize(idx),
-                }))),
+                })),
                 None => {
                     self.list.push(param);
                     let idx = self.list.len() - 1 + self.next_ty_placeholder;
                     self.params.insert(idx, param);
-                    Ok(self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+                    self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                         universe: ty::UniverseIndex::from_usize(0),
                         name: ty::BoundVar::from_usize(idx),
-                    })))
+                    }))
                 }
             },
 
@@ -1038,7 +1032,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         }
     }
 
-    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
         match r {
             // FIXME(chalk) - jackh726 - this currently isn't hit in any tests.
             // This covers any region variables in a goal, right?
@@ -1048,14 +1042,14 @@ fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error>
                         var: ty::BoundVar::from_u32(*idx),
                         kind: ty::BrAnon(*idx),
                     };
-                    Ok(self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)))
+                    self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
                 }
                 None => {
                     let idx = self.named_regions.len() as u32;
                     let br =
                         ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
                     self.named_regions.insert(_re.def_id, idx);
-                    Ok(self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)))
+                    self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
                 }
             },
 
@@ -1131,11 +1125,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
         match r {
             ty::ReEmpty(ui) => {
                 assert_eq!(ui.as_usize(), 0);
-                Ok(self.reempty_placeholder)
+                self.reempty_placeholder
             }
 
             _ => r.super_fold_with(self),
index a6f7c4d7988f697ed0fb37dd39c5cdcd5d04b20e..b7275bac19048f701feeae31fb0f31654a51bf7a 100644 (file)
 
     let mut params_substitutor =
         ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
-    let obligation = obligation.fold_with(&mut params_substitutor).into_ok();
+    let obligation = obligation.fold_with(&mut params_substitutor);
     // FIXME(chalk): we really should be substituting these back in the solution
     let _params: FxHashMap<usize, ParamTy> = params_substitutor.params;
 
     let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder);
-    let obligation = obligation.fold_with(&mut regions_substitutor).into_ok();
+    let obligation = obligation.fold_with(&mut regions_substitutor);
 
     let max_universe = obligation.max_universe.index();
 
index ea70a8d9e3a0d30fd9504f496e21b3cebee49669..8612499623be628ea17c66230ed0cc2af5b3dd0a 100644 (file)
@@ -4,7 +4,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(unwrap_infallible)]
 #![recursion_limit = "256"]
 
 #[macro_use]
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 da751f2075399cef877e49ae73c661a34c2a03a6..08261fedd4a254460d4dae2035cbd602e9f1d878 100644 (file)
@@ -35,7 +35,6 @@
 use rustc_trait_selection::traits::wf::object_region_bounds;
 
 use smallvec::SmallVec;
-use std::array;
 use std::collections::BTreeSet;
 use std::slice;
 
@@ -1635,7 +1634,7 @@ fn one_bound_for_assoc_type<I>(
             debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
 
             let is_equality = is_equality();
-            let bounds = array::IntoIter::new([bound, bound2]).chain(matching_candidates);
+            let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
             let mut err = if is_equality.is_some() {
                 // More specific Error Index entry.
                 struct_span_err!(
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 77f7cccc04ba4fe5a5fa0995f8530454b39cea63..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();
@@ -1637,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 12cd7ad184892968db333849816429badd9be776..b210c78cae007989d7ea08f895bebc42dab1da13 100644 (file)
@@ -1223,7 +1223,7 @@ pub fn check_for_cast(
                     // Missing try_into implementation for `{integer}` to `{float}`
                     err.multipart_suggestion_verbose(
                         &format!(
-                            "{}, producing the floating point representation of the integer,
+                            "{}, producing the floating point representation of the integer, \
                                  rounded if necessary",
                             cast_msg,
                         ),
index eb997b014c77b7a04644911545984e524d384f23..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> {
@@ -2063,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 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 1c4e0522bef8fac63307ddb78ce3355b0f507128..f83209f57a897cf54145fd76295746c45faa4e65 100644 (file)
@@ -442,8 +442,8 @@ fn check_overloaded_binop(
                             let mut eraser = TypeParamEraser(self, expr.span);
                             let needs_bound = self
                                 .lookup_op_method(
-                                    eraser.fold_ty(lhs_ty).into_ok(),
-                                    &[eraser.fold_ty(rhs_ty).into_ok()],
+                                    eraser.fold_ty(lhs_ty),
+                                    &[eraser.fold_ty(rhs_ty)],
                                     Op::Binary(op, is_assign),
                                 )
                                 .is_ok();
@@ -1015,12 +1015,12 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.0.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match ty.kind() {
-            ty::Param(_) => Ok(self.0.next_ty_var(TypeVariableOrigin {
+            ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin {
                 kind: TypeVariableOriginKind::MiscVariable,
                 span: self.1,
-            })),
+            }),
             _ => ty.super_fold_with(self),
         }
     }
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 78088b9bd0c38463d5a2265eaea7dac9a1f70166..1fc88829c779cdba1182cc46c85862c68a27d364 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),
@@ -1336,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`
@@ -1829,7 +1822,7 @@ pub(super) fn impl_implied_bounds(
                 // Inherent impl: take implied bounds from the `self` type.
                 let self_ty = self.tcx.type_of(impl_def_id);
                 let self_ty = self.normalize_associated_types_in(span, self_ty);
-                std::array::IntoIter::new([self_ty]).collect()
+                FxHashSet::from_iter([self_ty])
             }
         }
     }
index a5965411020a4a429c4dd6e865b69c2639aa7ecc..fdc8b6b5e64519d57642ad6549ec858d880fcc89 100644 (file)
@@ -658,7 +658,7 @@ fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
         T: TypeFoldable<'tcx>,
     {
         let mut resolver = Resolver::new(self.fcx, span, self.body);
-        let x = x.fold_with(&mut resolver).into_ok();
+        let x = x.fold_with(&mut resolver);
         if cfg!(debug_assertions) && x.needs_infer() {
             span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
         }
@@ -749,15 +749,15 @@ impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
             ty.super_fold_with(self)
         } else {
-            Ok(ty)
+            ty
         }
     }
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        Ok(if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased })
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased }
     }
 }
 
@@ -766,7 +766,7 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match self.infcx.fully_resolve(t) {
             Ok(t) => {
                 // Do not anonymize late-bound regions
@@ -779,21 +779,18 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_type_error(t);
                 self.replaced_with_error = true;
-                Ok(self.tcx().ty_error())
+                self.tcx().ty_error()
             }
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
-        Ok(self.tcx.lifetimes.re_erased)
+        self.tcx.lifetimes.re_erased
     }
 
-    fn fold_const(
-        &mut self,
-        ct: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-        Ok(match self.infcx.fully_resolve(ct) {
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        match self.infcx.fully_resolve(ct) {
             Ok(ct) => self.infcx.tcx.erase_regions(ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
@@ -801,7 +798,7 @@ fn fold_const(
                 self.replaced_with_error = true;
                 self.tcx().const_error(ct.ty)
             }
-        })
+        }
     }
 }
 
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 39fac12e297431f06fe24dd3f1aaad3e5a2e32df..67a3053c60786b60303a0126e922edfdfe621f12 100644 (file)
@@ -41,7 +41,7 @@
 use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt};
-use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
+use rustc_middle::ty::{ReprOptions, ToPredicate, TypeFoldable, WithConstness};
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -177,11 +177,9 @@ struct CollectItemTypesVisitor<'tcx> {
         sugg.push((arg.span, (*type_name).to_string()));
     } else {
         let last = generics.iter().last().unwrap();
-        sugg.push((
-            // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
-            last.bounds_span().unwrap_or(last.span).shrink_to_hi(),
-            format!(", {}", type_name),
-        ));
+        // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
+        let span = last.bounds_span_for_suggestions().unwrap_or(last.span.shrink_to_hi());
+        sugg.push((span, format!(", {}", type_name)));
     }
 
     let mut err = bad_placeholder_type(tcx, placeholder_types, kind);
@@ -431,7 +429,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)
@@ -1184,8 +1182,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),
@@ -1780,7 +1777,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     visitor.visit_ty(ty);
                     let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
                     let ret_ty = fn_sig.skip_binder().output();
-                    if ret_ty != tcx.ty_error() {
+                    if !ret_ty.references_error() {
                         if !ret_ty.is_closure() {
                             let ret_ty_str = match ret_ty.kind() {
                                 // Suggest a function pointer return type instead of a unique function definition
@@ -1880,9 +1877,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)
@@ -1892,9 +1887,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),
@@ -3225,7 +3219,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 1ea379c57389a1035052985f142ba5c71c11bf22..04a68250ced0cd0a44387b6fa7d3abf868b03351 100644 (file)
@@ -729,17 +729,17 @@ fn tcx(&self) -> TyCtxt<'tcx> {
             self.tcx
         }
 
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             if !self.success {
-                return Ok(ty);
+                return ty;
             }
 
             match ty.kind() {
-                ty::FnDef(def_id, _) => Ok(self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id))),
+                ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
                 // FIXME: non-capturing closures should also suggest a function pointer
                 ty::Closure(..) | ty::Generator(..) => {
                     self.success = false;
-                    Ok(ty)
+                    ty
                 }
                 _ => ty.super_fold_with(self),
             }
@@ -761,7 +761,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
 
                 // Suggesting unnameable types won't help.
                 let mut mk_nameable = MakeNameable::new(tcx);
-                let ty = mk_nameable.fold_ty(ty).into_ok();
+                let ty = mk_nameable.fold_ty(ty);
                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
                 if let Some(sugg_ty) = sugg_ty {
                     err.span_suggestion(
@@ -785,7 +785,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
 
             if !ty.references_error() {
                 let mut mk_nameable = MakeNameable::new(tcx);
-                let ty = mk_nameable.fold_ty(ty).into_ok();
+                let ty = mk_nameable.fold_ty(ty);
                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
                 if let Some(sugg_ty) = sugg_ty {
                     diag.span_suggestion(
index f9de6376b0ff5e572964c8edc8c3b7abd6469d4e..a49eda6572de2cb3cf3248d6a5e317a3ab8ee893 100644 (file)
@@ -71,11 +71,8 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
             self.tcx.infer_ctxt().enter(|infcx| {
                 let mut fulfill = traits::FulfillmentContext::new();
-                let tcx_ty = self
-                    .icx
-                    .to_ty(ty)
-                    .fold_with(&mut EraseAllBoundRegions { tcx: self.tcx })
-                    .into_ok();
+                let tcx_ty =
+                    self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
                 let cause = traits::ObligationCause::new(
                     ty.span,
                     self.hir_id,
@@ -186,7 +183,7 @@ impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
-        if let ty::ReLateBound(..) = r { Ok(&ty::ReErased) } else { Ok(r) }
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+        if let ty::ReLateBound(..) = r { &ty::ReErased } else { r }
     }
 }
index c0f0b3fe7046ec2c34fe78af4dbf93b43a44b3e7..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)]
@@ -71,7 +70,6 @@
 #![feature(slice_partition_dedup)]
 #![feature(control_flow_enum)]
 #![feature(hash_drain_filter)]
-#![feature(unwrap_infallible)]
 #![recursion_limit = "256"]
 
 #[macro_use]
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 7d87974b47e17725b8b2b18723b98dfa12150b11..76fbfa9fc59f76a1d3764d2f03d86943c0eabffc 100644 (file)
@@ -1500,7 +1500,7 @@ fn from(vec: Vec<T>) -> BinaryHeap<T> {
     /// }
     /// ```
     fn from(arr: [T; N]) -> Self {
-        core::array::IntoIter::new(arr).collect()
+        Self::from_iter(arr)
     }
 }
 
index 2ff7b0fbb759c0c64cbb46210b749bc142afc94f..3bd5b8ddf08ca2149def1b0674b7422800369d5f 100644 (file)
@@ -1305,11 +1305,11 @@ pub fn into_values(self) -> IntoValues<K, V> {
     pub(crate) fn bulk_build_from_sorted_iter<I>(iter: I) -> Self
     where
         K: Ord,
-        I: Iterator<Item = (K, V)>,
+        I: IntoIterator<Item = (K, V)>,
     {
         let mut root = Root::new();
         let mut length = 0;
-        root.bulk_push(DedupSortedIter::new(iter), &mut length);
+        root.bulk_push(DedupSortedIter::new(iter.into_iter()), &mut length);
         BTreeMap { root: Some(root), length }
     }
 }
@@ -1944,7 +1944,7 @@ fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
 
         // use stable sort to preserve the insertion order.
         inputs.sort_by(|a, b| a.0.cmp(&b.0));
-        BTreeMap::bulk_build_from_sorted_iter(inputs.into_iter())
+        BTreeMap::bulk_build_from_sorted_iter(inputs)
     }
 }
 
@@ -2061,7 +2061,7 @@ fn index(&self, key: &Q) -> &V {
 
         // use stable sort to preserve the insertion order.
         arr.sort_by(|a, b| a.0.cmp(&b.0));
-        BTreeMap::bulk_build_from_sorted_iter(core::array::IntoIter::new(arr))
+        BTreeMap::bulk_build_from_sorted_iter(arr)
     }
 }
 
index 0322cabccde4b0f830acaf9f423de435cc36f9db..4a83cdb917c85c9ac8bc71e6919874b0a07c64bc 100644 (file)
@@ -1106,7 +1106,7 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
 
         // use stable sort to preserve the insertion order.
         arr.sort();
-        let iter = core::array::IntoIter::new(arr).map(|k| (k, ()));
+        let iter = IntoIterator::into_iter(arr).map(|k| (k, ()));
         let map = BTreeMap::bulk_build_from_sorted_iter(iter);
         BTreeSet { map }
     }
index e4913b16adbe7722b14e755f25e5954ecda47168..c8aad4877e9822dfe73d776d3246d58bbead429b 100644 (file)
@@ -1961,7 +1961,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     /// assert_eq!(list1, list2);
     /// ```
     fn from(arr: [T; N]) -> Self {
-        core::array::IntoIter::new(arr).collect()
+        Self::from_iter(arr)
     }
 }
 
index de607c8fdab31dd098a5ee88c1f76dd81f41ac85..42eae6a54b5311c1e6d9a3c22c6982a70bf9e207 100644 (file)
@@ -2148,6 +2148,37 @@ pub fn append(&mut self, other: &mut Self) {
     pub fn retain<F>(&mut self, mut f: F)
     where
         F: FnMut(&T) -> bool,
+    {
+        self.retain_mut(|elem| f(elem));
+    }
+
+    /// Retains only the elements specified by the predicate.
+    ///
+    /// In other words, remove all elements `e` such that `f(&e)` returns false.
+    /// This method operates in place, visiting each element exactly once in the
+    /// original order, and preserves the order of the retained elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_retain_mut)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut buf = VecDeque::new();
+    /// buf.extend(1..5);
+    /// buf.retain_mut(|x| if *x % 2 == 0 {
+    ///     *x += 1;
+    ///     true
+    /// } else {
+    ///     false
+    /// });
+    /// assert_eq!(buf, [3, 5]);
+    /// ```
+    #[unstable(feature = "vec_retain_mut", issue = "90829")]
+    pub fn retain_mut<F>(&mut self, mut f: F)
+    where
+        F: FnMut(&mut T) -> bool,
     {
         let len = self.len();
         let mut idx = 0;
@@ -2155,7 +2186,7 @@ pub fn retain<F>(&mut self, mut f: F)
 
         // Stage 1: All values are retained.
         while cur < len {
-            if !f(&self[cur]) {
+            if !f(&mut self[cur]) {
                 cur += 1;
                 break;
             }
@@ -2164,7 +2195,7 @@ pub fn retain<F>(&mut self, mut f: F)
         }
         // Stage 2: Swap retained value into current idx.
         while cur < len {
-            if !f(&self[cur]) {
+            if !f(&mut self[cur]) {
                 cur += 1;
                 continue;
             }
@@ -2173,25 +2204,27 @@ pub fn retain<F>(&mut self, mut f: F)
             cur += 1;
             idx += 1;
         }
-        // Stage 3: Trancate all values after idx.
+        // Stage 3: Truncate all values after idx.
         if cur != idx {
             self.truncate(idx);
         }
     }
 
+    // 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 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 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 5d63cf03fcbc4fa0bc8c2a126bbb584ee8acd078..fe7b3576e2f5fdd2b770e93e53a21df7bd18d167 100644 (file)
@@ -34,30 +34,23 @@ pub struct IntoIter<T, const N: usize> {
     alive: Range<usize>,
 }
 
-impl<T, const N: usize> IntoIter<T, N> {
-    /// Creates a new iterator over the given `array`.
-    ///
-    /// *Note*: this method might be deprecated in the future,
-    /// since [`IntoIterator`] is now implemented for arrays.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::array;
+// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator`
+// hides this implementation from explicit `.into_iter()` calls on editions < 2021,
+// so those calls will still resolve to the slice implementation, by reference.
+#[stable(feature = "array_into_iter_impl", since = "1.53.0")]
+impl<T, const N: usize> IntoIterator for [T; N] {
+    type Item = T;
+    type IntoIter = IntoIter<T, N>;
+
+    /// Creates a consuming iterator, that is, one that moves each value out of
+    /// the array (from start to end). The array cannot be used after calling
+    /// this unless `T` implements `Copy`, so the whole array is copied.
     ///
-    /// for value in array::IntoIter::new([1, 2, 3, 4, 5]) {
-    ///     // The type of `value` is an `i32` here, instead of `&i32`
-    ///     let _: i32 = value;
-    /// }
+    /// Arrays have special behavior when calling `.into_iter()` prior to the
+    /// 2021 edition -- see the [array] Editions section for more information.
     ///
-    /// // Since Rust 1.53, arrays implement IntoIterator directly:
-    /// for value in [1, 2, 3, 4, 5] {
-    ///     // The type of `value` is an `i32` here, instead of `&i32`
-    ///     let _: i32 = value;
-    /// }
-    /// ```
-    #[stable(feature = "array_value_iter", since = "1.51.0")]
-    pub fn new(array: [T; N]) -> Self {
+    /// [array]: prim@array
+    fn into_iter(self) -> Self::IntoIter {
         // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
         // promise:
         //
@@ -76,11 +69,20 @@ impl<T, const N: usize> IntoIter<T, N> {
         // Until then, we can use `mem::transmute_copy` to create a bitwise copy
         // as a different type, then forget `array` so that it is not dropped.
         unsafe {
-            let iter = Self { data: mem::transmute_copy(&array), alive: 0..N };
-            mem::forget(array);
+            let iter = IntoIter { data: mem::transmute_copy(&self), alive: 0..N };
+            mem::forget(self);
             iter
         }
     }
+}
+
+impl<T, const N: usize> IntoIter<T, N> {
+    /// Creates a new iterator over the given `array`.
+    #[stable(feature = "array_value_iter", since = "1.51.0")]
+    #[rustc_deprecated(since = "1.59.0", reason = "use `IntoIterator::into_iter` instead")]
+    pub fn new(array: [T; N]) -> Self {
+        IntoIterator::into_iter(array)
+    }
 
     /// Returns an immutable slice of all elements that have not been yielded
     /// yet.
index 09bb4519170dae3a4891a55182104cd72610952e..23fd1453e54d1bedfa3d4907b10975f062da371e 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).
@@ -232,27 +243,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator`
-// hides this implementation from explicit `.into_iter()` calls on editions < 2021,
-// so those calls will still resolve to the slice implementation, by reference.
-#[stable(feature = "array_into_iter_impl", since = "1.53.0")]
-impl<T, const N: usize> IntoIterator for [T; N] {
-    type Item = T;
-    type IntoIter = IntoIter<T, N>;
-
-    /// Creates a consuming iterator, that is, one that moves each value out of
-    /// the array (from start to end). The array cannot be used after calling
-    /// this unless `T` implements `Copy`, so the whole array is copied.
-    ///
-    /// Arrays have special behavior when calling `.into_iter()` prior to the
-    /// 2021 edition -- see the [array] Editions section for more information.
-    ///
-    /// [array]: prim@array
-    fn into_iter(self) -> Self::IntoIter {
-        IntoIter::new(self)
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
     type Item = &'a T;
@@ -330,11 +320,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 +336,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 +349,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 +434,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 +650,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 +699,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 +732,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 +754,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 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 23b28766d70ea78cae57724116f9f61de749f3c2..edbc250eb0d0c2a243da0244046d1cfad5c82c48 100644 (file)
@@ -860,12 +860,14 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// 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 f3ef6b3d0185e3fc1917ba35691fa64605e5b45b..267fa4067983693c6c043e19533a477190484ae2 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};
@@ -1023,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
@@ -2215,6 +2216,86 @@ fn reduce<F>(mut self, f: F) -> Option<Self::Item>
         Some(self.fold(first, f))
     }
 
+    /// Reduces the elements to a single one by repeatedly applying a reducing operation. If the
+    /// closure returns a failure, the failure is propagated back to the caller immediately.
+    ///
+    /// The return type of this method depends on the return type of the closure. If the closure
+    /// returns `Result<Self::Item, E>`, then this function will return `Result<Option<Self::Item>,
+    /// E>`. If the closure returns `Option<Self::Item>`, then this function will return
+    /// `Option<Option<Self::Item>>`.
+    ///
+    /// When called on an empty iterator, this function will return either `Some(None)` or
+    /// `Ok(None)` depending on the type of the provided closure.
+    ///
+    /// For iterators with at least one element, this is essentially the same as calling
+    /// [`try_fold()`] with the first element of the iterator as the initial accumulator value.
+    ///
+    /// [`try_fold()`]: Iterator::try_fold
+    ///
+    /// # Examples
+    ///
+    /// Safely calculate the sum of a series of numbers:
+    ///
+    /// ```
+    /// #![feature(iterator_try_reduce)]
+    ///
+    /// let numbers: Vec<usize> = vec![10, 20, 5, 23, 0];
+    /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
+    /// assert_eq!(sum, Some(Some(58)));
+    /// ```
+    ///
+    /// Determine when a reduction short circuited:
+    ///
+    /// ```
+    /// #![feature(iterator_try_reduce)]
+    ///
+    /// let numbers = vec![1, 2, 3, usize::MAX, 4, 5];
+    /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
+    /// assert_eq!(sum, None);
+    /// ```
+    ///
+    /// Determine when a reduction was not performed because there are no elements:
+    ///
+    /// ```
+    /// #![feature(iterator_try_reduce)]
+    ///
+    /// let numbers: Vec<usize> = Vec::new();
+    /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
+    /// assert_eq!(sum, Some(None));
+    /// ```
+    ///
+    /// Use a [`Result`] instead of an [`Option`]:
+    ///
+    /// ```
+    /// #![feature(iterator_try_reduce)]
+    ///
+    /// let numbers = vec!["1", "2", "3", "4", "5"];
+    /// let max: Result<Option<_>, <usize as std::str::FromStr>::Err> =
+    ///     numbers.into_iter().try_reduce(|x, y| {
+    ///         if x.parse::<usize>()? > y.parse::<usize>()? { Ok(x) } else { Ok(y) }
+    ///     });
+    /// assert_eq!(max, Ok(Some("5")));
+    /// ```
+    #[inline]
+    #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
+    fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>>
+    where
+        Self: Sized,
+        F: FnMut(Self::Item, Self::Item) -> R,
+        R: Try<Output = Self::Item>,
+        R::Residual: Residual<Option<Self::Item>>,
+    {
+        let first = match self.next() {
+            Some(i) => i,
+            None => return Try::from_output(None),
+        };
+
+        match self.try_fold(first, f).branch() {
+            ControlFlow::Break(r) => FromResidual::from_residual(r),
+            ControlFlow::Continue(i) => Try::from_output(Some(i)),
+        }
+    }
+
     /// Tests if every element of the iterator matches a predicate.
     ///
     /// `all()` takes a closure that returns `true` or `false`. It applies
@@ -2417,6 +2498,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
     ///
     /// ```
@@ -2434,32 +2519,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 102e6f89eb82a52db3d87322e1754db978433c61..b0f9368b0c068587764a754bad5ced58c91dbbf8 100644 (file)
 #![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)]
@@ -408,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 a6e31452edcfcc04840919f325bb18cf1b33bce9..9a29094b52c468d336512a919fc5a2be4b1942c0 100644 (file)
@@ -789,7 +789,6 @@ pub unsafe fn assume_init_drop(&mut self) {
     /// ```
     #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
     #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_raw_ptr_deref))]
     #[inline(always)]
     pub const unsafe fn assume_init_ref(&self) -> &T {
         // SAFETY: the caller must guarantee that `self` is initialized.
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 b527c4b04ad7f8a9bdc3c804c4e69d523c60c3f1..52a2e464e3a7ce1c908c87f8411570d9597b7633 100644 (file)
@@ -82,7 +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.
-    #[cfg_attr(not(bootstrap), lang = "generator_return")]
+    #[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 f47a30c9b5d7dc109b4d402f1c918378615aa373..8fcd8cdeb1042db43170e0d58a80622f05088c57 100644 (file)
@@ -606,8 +606,7 @@ mod prim_pointer {}
 ///     println!("array[{}] = {}", i, x);
 /// }
 ///
-/// // You can explicitly iterate an array by value using
-/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`:
+/// // You can explicitly iterate an array by value using `IntoIterator::into_iter`
 /// for item in IntoIterator::into_iter(array).enumerate() {
 ///     let (i, x): (usize, i32) = item;
 ///     println!("array[{}] = {}", i, x);
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 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 cd6513327f00e242728906e3b99dae2c7f534cc5..f8ab8c9d4447b79d8bd82465ea4e2ce9800b0290 100644 (file)
@@ -1,5 +1,4 @@
 use super::*;
-use core::array;
 use core::iter::*;
 
 #[test]
@@ -134,7 +133,7 @@ fn test_double_ended_flatten() {
 #[test]
 fn test_trusted_len_flatten() {
     fn assert_trusted_len<T: TrustedLen>(_: &T) {}
-    let mut iter = array::IntoIter::new([[0; 3]; 4]).flatten();
+    let mut iter = IntoIterator::into_iter([[0; 3]; 4]).flatten();
     assert_trusted_len(&iter);
 
     assert_eq!(iter.size_hint(), (12, Some(12)));
@@ -143,21 +142,21 @@ fn assert_trusted_len<T: TrustedLen>(_: &T) {}
     iter.next_back();
     assert_eq!(iter.size_hint(), (10, Some(10)));
 
-    let iter = array::IntoIter::new([[(); usize::MAX]; 1]).flatten();
+    let iter = IntoIterator::into_iter([[(); usize::MAX]; 1]).flatten();
     assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX)));
 
-    let iter = array::IntoIter::new([[(); usize::MAX]; 2]).flatten();
+    let iter = IntoIterator::into_iter([[(); usize::MAX]; 2]).flatten();
     assert_eq!(iter.size_hint(), (usize::MAX, None));
 
     let mut a = [(); 10];
     let mut b = [(); 10];
 
-    let iter = array::IntoIter::new([&mut a, &mut b]).flatten();
+    let iter = IntoIterator::into_iter([&mut a, &mut b]).flatten();
     assert_trusted_len(&iter);
     assert_eq!(iter.size_hint(), (20, Some(20)));
     core::mem::drop(iter);
 
-    let iter = array::IntoIter::new([&a, &b]).flatten();
+    let iter = IntoIterator::into_iter([&a, &b]).flatten();
     assert_trusted_len(&iter);
     assert_eq!(iter.size_hint(), (20, Some(20)));
 
index 422e389e38017f4fe4d27312921080c1dd1c7880..d38bca1e3b3ea9265ad1c410c3d6704e5d08bcf9 100644 (file)
@@ -454,6 +454,34 @@ fn half_if_even(x: &isize) -> Option<isize> {
     }
 }
 
+#[test]
+fn test_try_reduce() {
+    let v: Vec<usize> = vec![1, 2, 3, 4, 5];
+    let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y));
+    assert_eq!(sum, Some(Some(15)));
+
+    let v: Vec<usize> = vec![1, 2, 3, 4, 5, usize::MAX];
+    let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y));
+    assert_eq!(sum, None);
+
+    let v: Vec<usize> = Vec::new();
+    let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y));
+    assert_eq!(sum, Some(None));
+
+    let v = vec!["1", "2", "3", "4", "5"];
+    let max = v.into_iter().try_reduce(|x, y| {
+        if x.parse::<usize>().ok()? > y.parse::<usize>().ok()? { Some(x) } else { Some(y) }
+    });
+    assert_eq!(max, Some(Some("5")));
+
+    let v = vec!["1", "2", "3", "4", "5"];
+    let max: Result<Option<_>, <usize as std::str::FromStr>::Err> =
+        v.into_iter().try_reduce(|x, y| {
+            if x.parse::<usize>()? > y.parse::<usize>()? { Ok(x) } else { Ok(y) }
+        });
+    assert_eq!(max, Ok(Some("5")));
+}
+
 #[test]
 fn test_iterator_len() {
     let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
index 00d0259321d13da0b5158bec8f8de17600235ced..9ab98ba88865a07c7913f2260b879eeb2a136011 100644 (file)
@@ -36,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(iter_intersperse)]
 #![feature(iter_is_partitioned)]
 #![feature(iter_order_by)]
+#![feature(iterator_try_reduce)]
 #![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 66f03c68cbe017de7bb7e40a73a0c55d63a41db2..281df8a1326d009ecc4042f1897357c004c11207 100644 (file)
@@ -2234,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 b43445f2eed5c13c9ba457ffa0b06fa88b3244c7..f71117483214297ba4c5cc4d8300a2cb14673845 100644 (file)
@@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.108", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.53" }
+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 12246b5173d394058c21dba7ef05acf70e110900..ce34e235f5d6a3ba3ea0cc247c48372c13ce586e 100644 (file)
@@ -1186,7 +1186,7 @@ fn index(&self, key: &Q) -> &V {
     /// assert_eq!(map1, map2);
     /// ```
     fn from(arr: [(K, V); N]) -> Self {
-        crate::array::IntoIter::new(arr).collect()
+        Self::from_iter(arr)
     }
 }
 
index 1fc1d39b1816e63cd3e48c19defd8b486169ffed..3f264ee6732f7d1de80dbb9e026c41ff41164646 100644 (file)
@@ -1022,7 +1022,7 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
     /// assert_eq!(set1, set2);
     /// ```
     fn from(arr: [T; N]) -> Self {
-        crate::array::IntoIter::new(arr).collect()
+        Self::from_iter(arr)
     }
 }
 
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..67846e78835706581d67db9adb889278312be023 100644 (file)
 // std may use features in a platform-specific way
 #![allow(unused_features)]
 #![feature(rustc_allow_const_fn_unstable)]
-#![cfg_attr(
-    test,
-    feature(internal_output_capture, print_internals, update_panic_count, thread_local_const_init)
-)]
+#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform)
 #![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 f47a30c9b5d7dc109b4d402f1c918378615aa373..8fcd8cdeb1042db43170e0d58a80622f05088c57 100644 (file)
@@ -606,8 +606,7 @@ mod prim_pointer {}
 ///     println!("array[{}] = {}", i, x);
 /// }
 ///
-/// // You can explicitly iterate an array by value using
-/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`:
+/// // You can explicitly iterate an array by value using `IntoIterator::into_iter`
 /// for item in IntoIterator::into_iter(array).enumerate() {
 ///     let (i, x): (usize, i32) = item;
 ///     println!("array[{}] = {}", i, x);
index 7686b61b67a892de9ae9bfa7d25ada0448c0efde..8a028d99306dbae16acad8f47732e4a563a8a692 100644 (file)
@@ -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]
@@ -472,10 +473,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 
 #[cfg(target_os = "macos")]
 pub unsafe fn environ() -> *mut *const *const c_char {
-    extern "C" {
-        fn _NSGetEnviron() -> *mut *const *const c_char;
-    }
-    _NSGetEnviron()
+    libc::_NSGetEnviron() as *mut *const *const c_char
 }
 
 #[cfg(not(target_os = "macos"))]
index 4da59577d78a19cfb61ba24c47c1b54e7cc37cc9..c03fe116320aa4378a38a4acd7d76fb12714847a 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> {
@@ -164,7 +178,6 @@ macro_rules! __thread_local_inner {
     (@key $t:ty, const $init:expr) => {{
         #[cfg_attr(not(windows), inline)] // see comments below
         unsafe fn __getit() -> $crate::option::Option<&'static $t> {
-            const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local();
             const INIT_EXPR: $t = $init;
 
             // wasm without atomics maps directly to `static mut`, and dtors
index 343d3ef8dc5388bf0a2a304b8bf2afe5404ffa93..64f6c7fa022fc7268392897dacbf9bb7ae47dd9b 100644 (file)
 #[doc(hidden)]
 pub use self::local::statik::Key as __StaticLocalKeyInner;
 
-// This is only used to make thread locals with `const { .. }` initialization
-// expressions unstable. If and/or when that syntax is stabilized with thread
-// locals this will simply be removed.
-#[doc(hidden)]
-#[unstable(feature = "thread_local_const_init", issue = "84223")]
-pub const fn require_unstable_const_init_thread_local() {}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Builder
 ////////////////////////////////////////////////////////////////////////////////
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 09ea84a083eb2c4770b0ebfe9452c654df7339b1..5f28ffeda8fee35b30f0fc783e3c2bcfdcd3639d 100644 (file)
@@ -2085,6 +2085,13 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         ] {
             tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
         }
+
+        // We don't build LLD on some platforms, so only add it if it exists
+        let lld_path = builder.lld_out(target).join("bin").join(exe("lld", target));
+        if lld_path.exists() {
+            tarball.add_file(lld_path, "bin", 0o755);
+        }
+
         tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755);
 
         // Copy the include directory as well; needed mostly to build
index 1667dfc3f8544ad3f2ac2bb0519d055a914e956d..82462f9758e5c08853d2f59aa434888db863089a 100644 (file)
@@ -1043,7 +1043,7 @@ fn lld_flags(&self, target: TargetSelection) -> impl Iterator<Item = String> {
             options[1] = Some(format!("-Clink-arg=-Wl,{}", threads));
         }
 
-        std::array::IntoIter::new(options).flatten()
+        IntoIterator::into_iter(options).flatten()
     }
 
     /// Returns if this target should statically link the C runtime, if specified
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 fac55b978886cca41cd0020d5ee699450a624a82..fa238a8b3bc6591a55ed18b9403675440464b024 100644 (file)
@@ -454,7 +454,7 @@ operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
 reg_operand := dir_spec "(" reg_spec ")" operand_expr
 operand := reg_operand / "const" const_expr / "sym" path
 clobber_abi := "clobber_abi(" <abi> *["," <abi>] [","] ")"
-option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
+option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" / "may_unwind"
 options := "options(" option *["," option] [","] ")"
 asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," clobber_abi) *("," options) [","] ")"
 ```
@@ -829,6 +829,7 @@ Currently the following options are defined:
 - `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked.
 - `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
 - `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`.
+- `may_unwind`: The `asm` block may unwind the stack and be part of the stack unwinding process (This option is only supported by the LLVM backend right now).
 - `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. This is primarily useful when including raw assembly code from an external file using `include_str!`.
 
 The compiler performs some additional checks on options:
index 8647db5a45dc8277fbf12465c72a865b4f734a50..48a341ffe083710770023c465dfe4b5d03a2b40c 100644 (file)
@@ -90,10 +90,20 @@ There are a number of supported commands:
   highlights for example. If you want to simply check for the presence of
   a given node or attribute, use an empty string (`""`) as a `PATTERN`.
 
-* `@count PATH XPATH COUNT' checks for the occurrence of the given XPath
+* `@count PATH XPATH COUNT` checks for the occurrence of the given XPath
   in the specified file. The number of occurrences must match the given
   count.
 
+* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
+  A snapshot test captures a subtree of the DOM, at the location
+  determined by the XPath, and compares it to a pre-recorded value
+  in a file. The file's name is the test's name with the `.rs` extension
+  replaced with `.NAME.html`, where NAME is the snapshot's name.
+
+  htmldocck supports the `--bless` option to accept the current subtree
+  as expected, saving it to the file determined by the snapshot's name.
+  compiletest's `--bless` flag is forwarded to htmldocck.
+
 * `@has-dir PATH` checks for the existence of the given directory.
 
 All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
@@ -137,6 +147,10 @@ except NameError:
 
 channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
 
+# Initialized in main
+rust_test_path = None
+bless = None
+
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
 
@@ -387,6 +401,32 @@ def get_tree_count(tree, path):
     return len(tree.findall(path))
 
 
+def check_snapshot(snapshot_name, tree):
+    assert rust_test_path.endswith('.rs')
+    snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
+    try:
+        with open(snapshot_path, 'r') as snapshot_file:
+            expected_str = snapshot_file.read()
+    except FileNotFoundError:
+        if bless:
+            expected_str = None
+        else:
+            raise FailedCheck('No saved snapshot value')
+
+    actual_str = ET.tostring(tree).decode('utf-8')
+
+    if expected_str != actual_str:
+        if bless:
+            with open(snapshot_path, 'w') as snapshot_file:
+                snapshot_file.write(actual_str)
+        else:
+            print('--- expected ---\n')
+            print(expected_str)
+            print('\n\n--- actual ---\n')
+            print(actual_str)
+            print()
+            raise FailedCheck('Actual snapshot value is different than expected')
+
 def stderr(*args):
     if sys.version_info.major < 3:
         file = codecs.getwriter('utf-8')(sys.stderr)
@@ -448,6 +488,28 @@ def check_command(c, cache):
                 ret = expected == found
             else:
                 raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
+
+        elif c.cmd == 'snapshot':  # snapshot test
+            if len(c.args) == 3:  # @snapshot <snapshot-name> <html-path> <xpath>
+                [snapshot_name, html_path, pattern] = c.args
+                tree = cache.get_tree(html_path)
+                xpath = normalize_xpath(pattern)
+                subtrees = tree.findall(xpath)
+                if len(subtrees) == 1:
+                    [subtree] = subtrees
+                    try:
+                        check_snapshot(snapshot_name, subtree)
+                        ret = True
+                    except FailedCheck as err:
+                        cerr = str(err)
+                        ret = False
+                elif len(subtrees) == 0:
+                    raise FailedCheck('XPATH did not match')
+                else:
+                    raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees)))
+            else:
+                raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
+
         elif c.cmd == 'has-dir':  # has-dir test
             if len(c.args) == 1:  # @has-dir <path> = has-dir test
                 try:
@@ -458,11 +520,13 @@ def check_command(c, cache):
                     ret = False
             else:
                 raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
+
         elif c.cmd == 'valid-html':
             raise InvalidCheck('Unimplemented @valid-html')
 
         elif c.cmd == 'valid-links':
             raise InvalidCheck('Unimplemented @valid-links')
+
         else:
             raise InvalidCheck('Unrecognized @{}'.format(c.cmd))
 
@@ -483,11 +547,19 @@ def check(target, commands):
 
 
 if __name__ == '__main__':
-    if len(sys.argv) != 3:
-        stderr('Usage: {} <doc dir> <template>'.format(sys.argv[0]))
+    if len(sys.argv) not in [3, 4]:
+        stderr('Usage: {} <doc dir> <template> [--bless]'.format(sys.argv[0]))
         raise SystemExit(1)
 
-    check(sys.argv[1], get_commands(sys.argv[2]))
+    rust_test_path = sys.argv[2]
+    if len(sys.argv) > 3 and sys.argv[3] == '--bless':
+        bless = True
+    else:
+        # We only support `--bless` at the end of the arguments.
+        # This assert is to prevent silent failures.
+        assert '--bless' not in sys.argv
+        bless = False
+    check(sys.argv[1], get_commands(rust_test_path))
     if ERR_COUNT:
         stderr("\nEncountered {} errors".format(ERR_COUNT))
         raise SystemExit(1)
index 04fe1dccce44bfa8ce56da0cb9e4c4916f187ed8..7b66ff7d4113674a20e8e3da3cef6d2aad27c799 100644 (file)
@@ -100,9 +100,12 @@ fn generate_for_trait(
                 // Instead, we generate `impl !Send for Foo<T>`, which better
                 // expresses the fact that `Foo<T>` never implements `Send`,
                 // regardless of the choice of `T`.
-                let params = (tcx.generics_of(item_def_id), ty::GenericPredicates::default())
-                    .clean(self.cx)
-                    .params;
+                let raw_generics = clean_ty_generics(
+                    self.cx,
+                    tcx.generics_of(item_def_id),
+                    ty::GenericPredicates::default(),
+                );
+                let params = raw_generics.params;
 
                 Generics { params, where_predicates: Vec::new() }
             }
@@ -449,12 +452,14 @@ fn param_env_to_generics(
                         _ => false,
                     }
             })
-            .map(|p| p.fold_with(&mut replacer).into_ok());
+            .map(|p| p.fold_with(&mut replacer));
 
-        let mut generic_params =
-            (tcx.generics_of(item_def_id), tcx.explicit_predicates_of(item_def_id))
-                .clean(self.cx)
-                .params;
+        let raw_generics = clean_ty_generics(
+            self.cx,
+            tcx.generics_of(item_def_id),
+            tcx.explicit_predicates_of(item_def_id),
+        );
+        let mut generic_params = raw_generics.params;
 
         debug!("param_env_to_generics({:?}): generic_params={:?}", item_def_id, generic_params);
 
@@ -714,11 +719,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        Ok((match *r {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        (match *r {
             ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
             _ => None,
         })
-        .unwrap_or_else(|| r.super_fold_with(self).into_ok()))
+        .unwrap_or_else(|| r.super_fold_with(self))
     }
 }
index f44589f60675f5dbe8bb38c358121be812d540d1..80e3bb5c6624f99f611f09646545cddc9e7703c1 100644 (file)
@@ -107,11 +107,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                     kind: box ImplItem(Impl {
                         unsafety: hir::Unsafety::Normal,
-                        generics: (
+                        generics: clean_ty_generics(
+                            self.cx,
                             self.cx.tcx.generics_of(impl_def_id),
                             self.cx.tcx.explicit_predicates_of(impl_def_id),
-                        )
-                            .clean(self.cx),
+                        ),
                         // FIXME(eddyb) compute both `trait_` and `for_` from
                         // the post-inference `trait_ref`, as it's more accurate.
                         trait_: Some(trait_ref.clean(self.cx)),
index d4bf93bb40931178d5236796ed61fdefefa3d316..39544fa843de8665677c318c2a9e4ec035c9b44c 100644 (file)
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use crate::clean::{
-    self, utils, Attributes, AttributesExt, ImplKind, ItemId, NestedAttributesExt, Type,
+    self, clean_fn_decl_from_did_and_sig, clean_ty_generics, utils, Attributes, AttributesExt,
+    Clean, ImplKind, ItemId, NestedAttributesExt, Type, Visibility,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
 
-use super::{Clean, Visibility};
-
 type Attrs<'hir> = rustc_middle::ty::Attributes<'hir>;
 
 /// Attempt to inline a definition into this AST.
         .collect();
 
     let predicates = cx.tcx.predicates_of(did);
-    let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
     let is_auto = cx.tcx.trait_is_auto(did);
@@ -230,7 +229,9 @@ fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Functi
     let predicates = cx.tcx.predicates_of(did);
     let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
         // NOTE: generics need to be cleaned before the decl!
-        ((cx.tcx.generics_of(did), predicates).clean(cx), (did, sig).clean(cx))
+        let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+        let decl = clean_fn_decl_from_did_and_sig(cx, did, sig);
+        (generics, decl)
     });
     clean::Function {
         decl,
@@ -243,7 +244,7 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
     let predicates = cx.tcx.explicit_predicates_of(did);
 
     clean::Enum {
-        generics: (cx.tcx.generics_of(did), predicates).clean(cx),
+        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
         variants_stripped: false,
         variants: cx.tcx.adt_def(did).variants.iter().map(|v| v.clean(cx)).collect(),
     }
@@ -255,7 +256,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
 
     clean::Struct {
         struct_type: variant.ctor_kind,
-        generics: (cx.tcx.generics_of(did), predicates).clean(cx),
+        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
         fields: variant.fields.iter().map(|x| x.clean(cx)).collect(),
         fields_stripped: false,
     }
@@ -265,7 +266,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
     let predicates = cx.tcx.explicit_predicates_of(did);
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
-    let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
     let fields = variant.fields.iter().map(|x| x.clean(cx)).collect();
     clean::Union { generics, fields, fields_stripped: false }
 }
@@ -276,7 +277,7 @@ fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef {
 
     clean::Typedef {
         type_,
-        generics: (cx.tcx.generics_of(did), predicates).clean(cx),
+        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
         item_type: None,
     }
 }
@@ -359,13 +360,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,
     };
 
@@ -443,7 +441,9 @@ fn merge_attrs(
                     }
                 })
                 .collect::<Vec<_>>(),
-            clean::enter_impl_trait(cx, |cx| (tcx.generics_of(did), predicates).clean(cx)),
+            clean::enter_impl_trait(cx, |cx| {
+                clean_ty_generics(cx, tcx.generics_of(did), predicates)
+            }),
         ),
     };
     let polarity = tcx.impl_polarity(did);
index 4e1dabd05bb48373844d8add75862f764a6111fe..f11fa0295c52220c9f7d9546973245dfff3d6d12 100644 (file)
@@ -31,6 +31,7 @@
 
 use std::assert_matches::assert_matches;
 use std::collections::hash_map::Entry;
+use std::collections::BTreeMap;
 use std::default::Default;
 use std::hash::Hash;
 use std::{mem, vec};
 impl Clean<Item> for DocModule<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let mut items: Vec<Item> = vec![];
-        items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
+        items.extend(
+            self.foreigns
+                .iter()
+                .map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)),
+        );
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
-        items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
+        items.extend(
+            self.items
+                .iter()
+                .flat_map(|(item, renamed)| clean_maybe_renamed_item(cx, item, *renamed)),
+        );
 
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
@@ -102,11 +111,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
                     _ => bug!("clean: parenthesized `GenericBound::LangItemTrait`"),
                 };
 
+                let trait_ = clean_trait_ref_with_bindings(cx, trait_ref, &bindings);
                 GenericBound::TraitBound(
-                    PolyTrait {
-                        trait_: (trait_ref, &bindings[..]).clean(cx),
-                        generic_params: vec![],
-                    },
+                    PolyTrait { trait_, generic_params: vec![] },
                     hir::TraitBoundModifier::None,
                 )
             }
@@ -117,64 +124,60 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
     }
 }
 
-impl Clean<Path> for (ty::TraitRef<'_>, &[TypeBinding]) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Path {
-        let (trait_ref, bounds) = *self;
-        let kind = cx.tcx.def_kind(trait_ref.def_id).into();
-        if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
-            span_bug!(
-                cx.tcx.def_span(trait_ref.def_id),
-                "`TraitRef` had unexpected kind {:?}",
-                kind
-            );
-        }
-        inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-        let path = external_path(cx, trait_ref.def_id, true, bounds.to_vec(), trait_ref.substs);
+fn clean_trait_ref_with_bindings(
+    cx: &mut DocContext<'_>,
+    trait_ref: ty::TraitRef<'_>,
+    bindings: &[TypeBinding],
+) -> Path {
+    let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+    if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
+        span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
+    }
+    inline::record_extern_fqn(cx, trait_ref.def_id, kind);
+    let path = external_path(cx, trait_ref.def_id, true, bindings.to_vec(), trait_ref.substs);
 
-        debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
+    debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
 
-        path
-    }
+    path
 }
 
 impl Clean<Path> for ty::TraitRef<'tcx> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
-        (*self, &[][..]).clean(cx)
+        clean_trait_ref_with_bindings(cx, *self, &[])
     }
 }
 
-impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
-        let (poly_trait_ref, bounds) = *self;
-        let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
-
-        // collect any late bound regions
-        let late_bound_regions: Vec<_> = cx
-            .tcx
-            .collect_referenced_late_bound_regions(&poly_trait_ref)
-            .into_iter()
-            .filter_map(|br| match br {
-                ty::BrNamed(_, name) => Some(GenericParamDef {
-                    name,
-                    kind: GenericParamDefKind::Lifetime { outlives: vec![] },
-                }),
-                _ => None,
-            })
-            .collect();
+fn clean_poly_trait_ref_with_bindings(
+    cx: &mut DocContext<'_>,
+    poly_trait_ref: ty::PolyTraitRef<'_>,
+    bindings: &[TypeBinding],
+) -> GenericBound {
+    let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
+
+    // collect any late bound regions
+    let late_bound_regions: Vec<_> = cx
+        .tcx
+        .collect_referenced_late_bound_regions(&poly_trait_ref)
+        .into_iter()
+        .filter_map(|br| match br {
+            ty::BrNamed(_, name) => Some(GenericParamDef {
+                name,
+                kind: GenericParamDefKind::Lifetime { outlives: vec![] },
+            }),
+            _ => None,
+        })
+        .collect();
 
-        GenericBound::TraitBound(
-            PolyTrait {
-                trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx),
-                generic_params: late_bound_regions,
-            },
-            hir::TraitBoundModifier::None,
-        )
-    }
+    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+    GenericBound::TraitBound(
+        PolyTrait { trait_, generic_params: late_bound_regions },
+        hir::TraitBoundModifier::None,
+    )
 }
 
 impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
-        (*self, &[][..]).clean(cx)
+        clean_poly_trait_ref_with_bindings(cx, *self, &[])
     }
 }
 
@@ -528,170 +531,164 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
     }
 }
 
-impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
-        use self::WherePredicate as WP;
-        use std::collections::BTreeMap;
-
-        let (gens, preds) = *self;
-
-        // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
-        // since `Clean for ty::Predicate` would consume them.
-        let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
-
-        // Bounds in the type_params and lifetimes fields are repeated in the
-        // predicates field (see rustc_typeck::collect::ty_generics), so remove
-        // them.
-        let stripped_params = gens
-            .params
-            .iter()
-            .filter_map(|param| match param.kind {
-                ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
-                ty::GenericParamDefKind::Type { synthetic, .. } => {
-                    if param.name == kw::SelfUpper {
-                        assert_eq!(param.index, 0);
-                        return None;
-                    }
-                    if synthetic {
-                        impl_trait.insert(param.index.into(), vec![]);
-                        return None;
-                    }
-                    Some(param.clean(cx))
+fn clean_ty_generics(
+    cx: &mut DocContext<'_>,
+    gens: &ty::Generics,
+    preds: ty::GenericPredicates<'tcx>,
+) -> Generics {
+    // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
+    // since `Clean for ty::Predicate` would consume them.
+    let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
+
+    // Bounds in the type_params and lifetimes fields are repeated in the
+    // predicates field (see rustc_typeck::collect::ty_generics), so remove
+    // them.
+    let stripped_params = gens
+        .params
+        .iter()
+        .filter_map(|param| match param.kind {
+            ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
+            ty::GenericParamDefKind::Type { synthetic, .. } => {
+                if param.name == kw::SelfUpper {
+                    assert_eq!(param.index, 0);
+                    return None;
                 }
-                ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
-            })
-            .collect::<Vec<GenericParamDef>>();
-
-        // param index -> [(DefId of trait, associated type name, type)]
-        let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, Symbol, Ty<'tcx>)>>::default();
-
-        let where_predicates = preds
-            .predicates
-            .iter()
-            .flat_map(|(p, _)| {
-                let mut projection = None;
-                let param_idx = (|| {
-                    let bound_p = p.kind();
-                    match bound_p.skip_binder() {
-                        ty::PredicateKind::Trait(pred) => {
-                            if let ty::Param(param) = pred.self_ty().kind() {
-                                return Some(param.index);
-                            }
-                        }
-                        ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
-                            if let ty::Param(param) = ty.kind() {
-                                return Some(param.index);
-                            }
+                if synthetic {
+                    impl_trait.insert(param.index.into(), vec![]);
+                    return None;
+                }
+                Some(param.clean(cx))
+            }
+            ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
+        })
+        .collect::<Vec<GenericParamDef>>();
+
+    // param index -> [(DefId of trait, associated type name, type)]
+    let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, Symbol, Ty<'tcx>)>>::default();
+
+    let where_predicates = preds
+        .predicates
+        .iter()
+        .flat_map(|(p, _)| {
+            let mut projection = None;
+            let param_idx = (|| {
+                let bound_p = p.kind();
+                match bound_p.skip_binder() {
+                    ty::PredicateKind::Trait(pred) => {
+                        if let ty::Param(param) = pred.self_ty().kind() {
+                            return Some(param.index);
                         }
-                        ty::PredicateKind::Projection(p) => {
-                            if let ty::Param(param) = p.projection_ty.self_ty().kind() {
-                                projection = Some(bound_p.rebind(p));
-                                return Some(param.index);
-                            }
+                    }
+                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+                        if let ty::Param(param) = ty.kind() {
+                            return Some(param.index);
                         }
-                        _ => (),
                     }
-
-                    None
-                })();
-
-                if let Some(param_idx) = param_idx {
-                    if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
-                        let p = p.clean(cx)?;
-
-                        b.extend(
-                            p.get_bounds()
-                                .into_iter()
-                                .flatten()
-                                .cloned()
-                                .filter(|b| !b.is_sized_bound(cx)),
-                        );
-
-                        let proj = projection
-                            .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
-                        if let Some(((_, trait_did, name), rhs)) =
-                            proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
-                        {
-                            impl_trait_proj
-                                .entry(param_idx)
-                                .or_default()
-                                .push((trait_did, name, rhs));
+                    ty::PredicateKind::Projection(p) => {
+                        if let ty::Param(param) = p.projection_ty.self_ty().kind() {
+                            projection = Some(bound_p.rebind(p));
+                            return Some(param.index);
                         }
-
-                        return None;
                     }
+                    _ => (),
                 }
 
-                Some(p)
-            })
-            .collect::<Vec<_>>();
-
-        for (param, mut bounds) in impl_trait {
-            // Move trait bounds to the front.
-            bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
-
-            if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
-                if let Some(proj) = impl_trait_proj.remove(&idx) {
-                    for (trait_did, name, rhs) in proj {
-                        let rhs = rhs.clean(cx);
-                        simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
+                None
+            })();
+
+            if let Some(param_idx) = param_idx {
+                if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
+                    let p = p.clean(cx)?;
+
+                    b.extend(
+                        p.get_bounds()
+                            .into_iter()
+                            .flatten()
+                            .cloned()
+                            .filter(|b| !b.is_sized_bound(cx)),
+                    );
+
+                    let proj = projection
+                        .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
+                    if let Some(((_, trait_did, name), rhs)) =
+                        proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
+                    {
+                        impl_trait_proj.entry(param_idx).or_default().push((trait_did, name, rhs));
                     }
+
+                    return None;
                 }
-            } else {
-                unreachable!();
             }
 
-            cx.impl_trait_bounds.insert(param, bounds);
-        }
+            Some(p)
+        })
+        .collect::<Vec<_>>();
 
-        // Now that `cx.impl_trait_bounds` is populated, we can process
-        // remaining predicates which could contain `impl Trait`.
-        let mut where_predicates =
-            where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
-
-        // Type parameters have a Sized bound by default unless removed with
-        // ?Sized. Scan through the predicates and mark any type parameter with
-        // a Sized bound, removing the bounds as we find them.
-        //
-        // Note that associated types also have a sized bound by default, but we
-        // don't actually know the set of associated types right here so that's
-        // handled in cleaning associated types
-        let mut sized_params = FxHashSet::default();
-        where_predicates.retain(|pred| match *pred {
-            WP::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
-                if bounds.iter().any(|b| b.is_sized_bound(cx)) {
-                    sized_params.insert(*g);
-                    false
-                } else {
-                    true
+    for (param, mut bounds) in impl_trait {
+        // Move trait bounds to the front.
+        bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
+
+        if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
+            if let Some(proj) = impl_trait_proj.remove(&idx) {
+                for (trait_did, name, rhs) in proj {
+                    let rhs = rhs.clean(cx);
+                    simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
                 }
             }
-            _ => true,
-        });
+        } else {
+            unreachable!();
+        }
 
-        // Run through the type parameters again and insert a ?Sized
-        // unbound for any we didn't find to be Sized.
-        for tp in &stripped_params {
-            if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
-                && !sized_params.contains(&tp.name)
-            {
-                where_predicates.push(WP::BoundPredicate {
-                    ty: Type::Generic(tp.name),
-                    bounds: vec![GenericBound::maybe_sized(cx)],
-                    bound_params: Vec::new(),
-                })
+        cx.impl_trait_bounds.insert(param, bounds);
+    }
+
+    // Now that `cx.impl_trait_bounds` is populated, we can process
+    // remaining predicates which could contain `impl Trait`.
+    let mut where_predicates =
+        where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
+
+    // Type parameters have a Sized bound by default unless removed with
+    // ?Sized. Scan through the predicates and mark any type parameter with
+    // a Sized bound, removing the bounds as we find them.
+    //
+    // Note that associated types also have a sized bound by default, but we
+    // don't actually know the set of associated types right here so that's
+    // handled in cleaning associated types
+    let mut sized_params = FxHashSet::default();
+    where_predicates.retain(|pred| match *pred {
+        WherePredicate::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
+            if bounds.iter().any(|b| b.is_sized_bound(cx)) {
+                sized_params.insert(*g);
+                false
+            } else {
+                true
             }
         }
+        _ => true,
+    });
 
-        // It would be nice to collect all of the bounds on a type and recombine
-        // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
-        // and instead see `where T: Foo + Bar + Sized + 'a`
-
-        Generics {
-            params: stripped_params,
-            where_predicates: simplify::where_clauses(cx, where_predicates),
+    // Run through the type parameters again and insert a ?Sized
+    // unbound for any we didn't find to be Sized.
+    for tp in &stripped_params {
+        if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
+            && !sized_params.contains(&tp.name)
+        {
+            where_predicates.push(WherePredicate::BoundPredicate {
+                ty: Type::Generic(tp.name),
+                bounds: vec![GenericBound::maybe_sized(cx)],
+                bound_params: Vec::new(),
+            })
         }
     }
+
+    // It would be nice to collect all of the bounds on a type and recombine
+    // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
+    // and instead see `where T: Foo + Bar + Sized + 'a`
+
+    Generics {
+        params: stripped_params,
+        where_predicates: simplify::where_clauses(cx, where_predicates),
+    }
 }
 
 fn clean_fn_or_proc_macro(
@@ -741,7 +738,7 @@ fn clean_fn_or_proc_macro(
             ProcMacroItem(ProcMacro { kind, helpers })
         }
         None => {
-            let mut func = (sig, generics, body_id).clean(cx);
+            let mut func = clean_function(cx, sig, generics, body_id);
             let def_id = item.def_id.to_def_id();
             func.header.constness =
                 if cx.tcx.is_const_fn(def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() {
@@ -749,58 +746,95 @@ fn clean_fn_or_proc_macro(
                 } else {
                     hir::Constness::NotConst
                 };
+            clean_fn_decl_legacy_const_generics(&mut func, attrs);
             FunctionItem(func)
         }
     }
 }
 
-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| {
-            // NOTE: generics must be cleaned before args
-            let generics = self.1.clean(cx);
-            let args = (self.0.decl.inputs, self.2).clean(cx);
-            let decl = clean_fn_decl_with_args(cx, self.0.decl, args);
-            (generics, decl)
-        });
-        Function { decl, generics, header: self.0.header }
+/// 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<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
-        Arguments {
-            values: self
-                .0
-                .iter()
-                .enumerate()
-                .map(|(i, ty)| {
-                    let mut name = self.1.get(i).map_or(kw::Empty, |ident| ident.name);
-                    if name.is_empty() {
-                        name = kw::Underscore;
-                    }
-                    Argument { name, type_: ty.clean(cx) }
-                })
-                .collect(),
-        }
+fn clean_function(
+    cx: &mut DocContext<'_>,
+    sig: &hir::FnSig<'_>,
+    generics: &hir::Generics<'_>,
+    body_id: hir::BodyId,
+) -> Function {
+    let (generics, decl) = enter_impl_trait(cx, |cx| {
+        // NOTE: generics must be cleaned before args
+        let generics = generics.clean(cx);
+        let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id);
+        let decl = clean_fn_decl_with_args(cx, sig.decl, args);
+        (generics, decl)
+    });
+    Function { decl, generics, header: sig.header }
+}
+
+fn clean_args_from_types_and_names(
+    cx: &mut DocContext<'_>,
+    types: &[hir::Ty<'_>],
+    names: &[Ident],
+) -> Arguments {
+    Arguments {
+        values: types
+            .iter()
+            .enumerate()
+            .map(|(i, ty)| {
+                let mut name = names.get(i).map_or(kw::Empty, |ident| ident.name);
+                if name.is_empty() {
+                    name = kw::Underscore;
+                }
+                Argument { name, type_: ty.clean(cx), is_const: false }
+            })
+            .collect(),
     }
 }
 
-impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
-        let body = cx.tcx.hir().body(self.1);
+fn clean_args_from_types_and_body_id(
+    cx: &mut DocContext<'_>,
+    types: &[hir::Ty<'_>],
+    body_id: hir::BodyId,
+) -> Arguments {
+    let body = cx.tcx.hir().body(body_id);
 
-        Arguments {
-            values: self
-                .0
-                .iter()
-                .enumerate()
-                .map(|(i, ty)| Argument {
-                    name: name_from_pat(body.params[i].pat),
-                    type_: ty.clean(cx),
-                })
-                .collect(),
-        }
+    Arguments {
+        values: types
+            .iter()
+            .enumerate()
+            .map(|(i, ty)| Argument {
+                name: name_from_pat(body.params[i].pat),
+                type_: ty.clean(cx),
+                is_const: false,
+            })
+            .collect(),
     }
 }
 
@@ -812,26 +846,28 @@ fn clean_fn_decl_with_args(
     FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic }
 }
 
-impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
-        let (did, sig) = *self;
-        let mut names = if did.is_local() { &[] } else { cx.tcx.fn_arg_names(did) }.iter();
-
-        FnDecl {
-            output: Return(sig.skip_binder().output().clean(cx)),
-            c_variadic: sig.skip_binder().c_variadic,
-            inputs: Arguments {
-                values: sig
-                    .skip_binder()
-                    .inputs()
-                    .iter()
-                    .map(|t| Argument {
-                        type_: t.clean(cx),
-                        name: names.next().map_or(kw::Empty, |i| i.name),
-                    })
-                    .collect(),
-            },
-        }
+fn clean_fn_decl_from_did_and_sig(
+    cx: &mut DocContext<'_>,
+    did: DefId,
+    sig: ty::PolyFnSig<'_>,
+) -> FnDecl {
+    let mut names = if did.is_local() { &[] } else { cx.tcx.fn_arg_names(did) }.iter();
+
+    FnDecl {
+        output: Return(sig.skip_binder().output().clean(cx)),
+        c_variadic: sig.skip_binder().c_variadic,
+        inputs: Arguments {
+            values: sig
+                .skip_binder()
+                .inputs()
+                .iter()
+                .map(|t| Argument {
+                    type_: t.clean(cx),
+                    name: names.next().map_or(kw::Empty, |i| i.name),
+                    is_const: false,
+                })
+                .collect(),
+        },
     }
 }
 
@@ -879,7 +915,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx.tcx, e)))
                 }
                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                    let mut m = (sig, &self.generics, body).clean(cx);
+                    let mut m = clean_function(cx, sig, &self.generics, body);
                     if m.header.constness == hir::Constness::Const
                         && is_unstable_const_fn(cx.tcx, local_did).is_some()
                     {
@@ -891,7 +927,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     let (generics, decl) = enter_impl_trait(cx, |cx| {
                         // NOTE: generics must be cleaned before args
                         let generics = self.generics.clean(cx);
-                        let args = (sig.decl.inputs, names).clean(cx);
+                        let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names);
                         let decl = clean_fn_decl_with_args(cx, sig.decl, args);
                         (generics, decl)
                     });
@@ -926,7 +962,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     AssocConstItem(ty.clean(cx), Some(print_const_expr(cx.tcx, expr)))
                 }
                 hir::ImplItemKind::Fn(ref sig, body) => {
-                    let mut m = (sig, &self.generics, body).clean(cx);
+                    let mut m = clean_function(cx, sig, &self.generics, body);
                     if m.header.constness == hir::Constness::Const
                         && is_unstable_const_fn(cx.tcx, local_did).is_some()
                     {
@@ -950,7 +986,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 --
@@ -980,11 +1016,13 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                 AssocConstItem(ty.clean(cx), default)
             }
             ty::AssocKind::Fn => {
-                let generics =
-                    (tcx.generics_of(self.def_id), tcx.explicit_predicates_of(self.def_id))
-                        .clean(cx);
+                let generics = clean_ty_generics(
+                    cx,
+                    tcx.generics_of(self.def_id),
+                    tcx.explicit_predicates_of(self.def_id),
+                );
                 let sig = tcx.fn_sig(self.def_id);
-                let mut decl = (self.def_id, sig).clean(cx);
+                let mut decl = clean_fn_decl_from_did_and_sig(cx, self.def_id, sig);
 
                 if self.fn_has_self_parameter {
                     let self_ty = match self.container {
@@ -1053,7 +1091,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                 if let ty::TraitContainer(_) = self.container {
                     let bounds = tcx.explicit_item_bounds(self.def_id);
                     let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
-                    let generics = (tcx.generics_of(self.def_id), predicates).clean(cx);
+                    let generics = clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates);
                     let mut bounds = generics
                         .where_predicates
                         .iter()
@@ -1189,9 +1227,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;
     };
@@ -1338,25 +1375,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
         }
     }
@@ -1389,10 +1416,11 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 let ty = cx.tcx.lift(*self).expect("FnPtr lift failed");
                 let sig = ty.fn_sig(cx.tcx);
                 let def_id = DefId::local(CRATE_DEF_INDEX);
+                let decl = clean_fn_decl_from_did_and_sig(cx, def_id, sig);
                 BareFunction(box BareFunctionDecl {
                     unsafety: sig.unsafety(),
                     generic_params: Vec::new(),
-                    decl: (def_id, sig).clean(cx),
+                    decl,
                     abi: sig.abi(),
                 })
             }
@@ -1498,7 +1526,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                             }
                         }
 
-                        let bounds: Vec<_> = bounds
+                        let bindings: Vec<_> = bounds
                             .iter()
                             .filter_map(|bound| {
                                 if let ty::PredicateKind::Projection(proj) =
@@ -1526,7 +1554,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                             })
                             .collect();
 
-                        Some((trait_ref, &bounds[..]).clean(cx))
+                        Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, &bindings))
                     })
                     .collect::<Vec<_>>();
                 bounds.extend(regions);
@@ -1698,7 +1726,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
             // NOTE: generics must be cleaned before args
             let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
-            let args = (self.decl.inputs, self.param_names).clean(cx);
+            let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
             let decl = clean_fn_decl_with_args(cx, self.decl, args);
             (generic_params, decl)
         });
@@ -1706,94 +1734,93 @@ fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
     }
 }
 
-impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
-        use hir::ItemKind;
-
-        let (item, renamed) = self;
-        let def_id = item.def_id.to_def_id();
-        let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
-        cx.with_param_env(def_id, |cx| {
-            let kind = match item.kind {
-                ItemKind::Static(ty, mutability, body_id) => {
-                    StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) })
-                }
-                ItemKind::Const(ty, body_id) => ConstantItem(Constant {
-                    type_: ty.clean(cx),
-                    kind: ConstantKind::Local { body: body_id, def_id },
-                }),
-                ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
-                    bounds: ty.bounds.iter().map(|x| x.clean(cx)).collect(),
-                    generics: ty.generics.clean(cx),
-                }),
-                ItemKind::TyAlias(hir_ty, ref generics) => {
-                    let rustdoc_ty = hir_ty.clean(cx);
-                    let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
-                    TypedefItem(
-                        Typedef {
-                            type_: rustdoc_ty,
-                            generics: generics.clean(cx),
-                            item_type: Some(ty),
-                        },
-                        false,
-                    )
-                }
-                ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
-                    variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
-                    generics: generics.clean(cx),
-                    variants_stripped: false,
-                }),
-                ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
+fn clean_maybe_renamed_item(
+    cx: &mut DocContext<'_>,
+    item: &hir::Item<'_>,
+    renamed: Option<Symbol>,
+) -> Vec<Item> {
+    use hir::ItemKind;
+
+    let def_id = item.def_id.to_def_id();
+    let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
+    cx.with_param_env(def_id, |cx| {
+        let kind = match item.kind {
+            ItemKind::Static(ty, mutability, body_id) => {
+                StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) })
+            }
+            ItemKind::Const(ty, body_id) => ConstantItem(Constant {
+                type_: ty.clean(cx),
+                kind: ConstantKind::Local { body: body_id, def_id },
+            }),
+            ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
+                bounds: ty.bounds.iter().map(|x| x.clean(cx)).collect(),
+                generics: ty.generics.clean(cx),
+            }),
+            ItemKind::TyAlias(hir_ty, ref generics) => {
+                let rustdoc_ty = hir_ty.clean(cx);
+                let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
+                TypedefItem(
+                    Typedef {
+                        type_: rustdoc_ty,
+                        generics: generics.clean(cx),
+                        item_type: Some(ty),
+                    },
+                    false,
+                )
+            }
+            ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
+                variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
+                generics: generics.clean(cx),
+                variants_stripped: false,
+            }),
+            ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
+                generics: generics.clean(cx),
+                bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
+            }),
+            ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
+                generics: generics.clean(cx),
+                fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
+                fields_stripped: false,
+            }),
+            ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
+                struct_type: CtorKind::from_hir(variant_data),
+                generics: generics.clean(cx),
+                fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
+                fields_stripped: false,
+            }),
+            ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
+            // proc macros can have a name set by attributes
+            ItemKind::Fn(ref sig, ref generics, body_id) => {
+                clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
+            }
+            ItemKind::Macro(ref macro_def) => {
+                let ty_vis = cx.tcx.visibility(def_id).clean(cx);
+                MacroItem(Macro {
+                    source: display_macro_source(cx, name, macro_def, def_id, ty_vis),
+                })
+            }
+            ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
+                let items =
+                    item_ids.iter().map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)).collect();
+                TraitItem(Trait {
+                    unsafety,
+                    items,
                     generics: generics.clean(cx),
                     bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
-                }),
-                ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
-                    generics: generics.clean(cx),
-                    fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
-                    fields_stripped: false,
-                }),
-                ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
-                    struct_type: CtorKind::from_hir(variant_data),
-                    generics: generics.clean(cx),
-                    fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
-                    fields_stripped: false,
-                }),
-                ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
-                // proc macros can have a name set by attributes
-                ItemKind::Fn(ref sig, ref generics, body_id) => {
-                    clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
-                }
-                ItemKind::Macro(ref macro_def) => {
-                    let ty_vis = cx.tcx.visibility(def_id).clean(cx);
-                    MacroItem(Macro {
-                        source: display_macro_source(cx, name, macro_def, def_id, ty_vis),
-                    })
-                }
-                ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
-                    let items = item_ids
-                        .iter()
-                        .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
-                        .collect();
-                    TraitItem(Trait {
-                        unsafety,
-                        items,
-                        generics: generics.clean(cx),
-                        bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
-                        is_auto: is_auto.clean(cx),
-                    })
-                }
-                ItemKind::ExternCrate(orig_name) => {
-                    return clean_extern_crate(item, name, orig_name, cx);
-                }
-                ItemKind::Use(path, kind) => {
-                    return clean_use_statement(item, name, path, kind, cx);
-                }
-                _ => unreachable!("not yet converted"),
-            };
+                    is_auto: is_auto.clean(cx),
+                })
+            }
+            ItemKind::ExternCrate(orig_name) => {
+                return clean_extern_crate(item, name, orig_name, cx);
+            }
+            ItemKind::Use(path, kind) => {
+                return clean_use_statement(item, name, path, kind, cx);
+            }
+            _ => unreachable!("not yet converted"),
+        };
 
-            vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
-        })
-    }
+        vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
+    })
 }
 
 impl Clean<Item> for hir::Variant<'_> {
@@ -2007,50 +2034,51 @@ fn clean_use_statement(
     vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)]
 }
 
-impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
-        let (item, renamed) = self;
-        let def_id = item.def_id.to_def_id();
-        cx.with_param_env(def_id, |cx| {
-            let kind = match item.kind {
-                hir::ForeignItemKind::Fn(decl, names, ref generics) => {
-                    let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
-                    let (generics, decl) = enter_impl_trait(cx, |cx| {
-                        // NOTE: generics must be cleaned before args
-                        let generics = generics.clean(cx);
-                        let args = (decl.inputs, names).clean(cx);
-                        let decl = clean_fn_decl_with_args(cx, decl, args);
-                        (generics, decl)
-                    });
-                    ForeignFunctionItem(Function {
-                        decl,
-                        generics,
-                        header: hir::FnHeader {
-                            unsafety: if abi == Abi::RustIntrinsic {
-                                intrinsic_operation_unsafety(item.ident.name)
-                            } else {
-                                hir::Unsafety::Unsafe
-                            },
-                            abi,
-                            constness: hir::Constness::NotConst,
-                            asyncness: hir::IsAsync::NotAsync,
+fn clean_maybe_renamed_foreign_item(
+    cx: &mut DocContext<'_>,
+    item: &hir::ForeignItem<'_>,
+    renamed: Option<Symbol>,
+) -> Item {
+    let def_id = item.def_id.to_def_id();
+    cx.with_param_env(def_id, |cx| {
+        let kind = match item.kind {
+            hir::ForeignItemKind::Fn(decl, names, ref generics) => {
+                let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
+                let (generics, decl) = enter_impl_trait(cx, |cx| {
+                    // NOTE: generics must be cleaned before args
+                    let generics = generics.clean(cx);
+                    let args = clean_args_from_types_and_names(cx, decl.inputs, names);
+                    let decl = clean_fn_decl_with_args(cx, decl, args);
+                    (generics, decl)
+                });
+                ForeignFunctionItem(Function {
+                    decl,
+                    generics,
+                    header: hir::FnHeader {
+                        unsafety: if abi == Abi::RustIntrinsic {
+                            intrinsic_operation_unsafety(item.ident.name)
+                        } else {
+                            hir::Unsafety::Unsafe
                         },
-                    })
-                }
-                hir::ForeignItemKind::Static(ref ty, mutability) => {
-                    ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
-                }
-                hir::ForeignItemKind::Type => ForeignTypeItem,
-            };
+                        abi,
+                        constness: hir::Constness::NotConst,
+                        asyncness: hir::IsAsync::NotAsync,
+                    },
+                })
+            }
+            hir::ForeignItemKind::Static(ref ty, mutability) => {
+                ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
+            }
+            hir::ForeignItemKind::Type => ForeignTypeItem,
+        };
 
-            Item::from_hir_id_and_parts(
-                item.hir_id(),
-                Some(renamed.unwrap_or(item.ident.name)),
-                kind,
-                cx,
-            )
-        })
-    }
+        Item::from_hir_id_and_parts(
+            item.hir_id(),
+            Some(renamed.unwrap_or(item.ident.name)),
+            kind,
+            cx,
+        )
+    })
 }
 
 impl Clean<TypeBinding> for hir::TypeBinding<'_> {
index 37acf68defd259204b53bc550d8730abc3639f61..1fe4aa9023ea310193eb6f2494b2d8f47b64122e 100644 (file)
@@ -376,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> {
@@ -602,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,
         }
     }
@@ -1207,10 +1207,6 @@ impl GenericBound {
 crate struct Lifetime(pub Symbol);
 
 impl Lifetime {
-    crate fn get_ref(&self) -> SymbolStr {
-        self.0.as_str()
-    }
-
     crate fn statik() -> Lifetime {
         Lifetime(kw::StaticLifetime)
     }
@@ -1248,17 +1244,6 @@ impl GenericParamDefKind {
     crate fn is_type(&self) -> bool {
         matches!(self, GenericParamDefKind::Type { .. })
     }
-
-    // FIXME(eddyb) this either returns the default of a type parameter, or the
-    // type of a `const` parameter. It seems that the intention is to *visit*
-    // any embedded types, but `get_type` seems to be the wrong name for that.
-    crate fn get_type(&self) -> Option<Type> {
-        match self {
-            GenericParamDefKind::Type { default, .. } => default.as_deref().cloned(),
-            GenericParamDefKind::Const { ty, .. } => Some((&**ty).clone()),
-            GenericParamDefKind::Lifetime { .. } => None,
-        }
-    }
 }
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -1283,10 +1268,6 @@ impl GenericParamDef {
         self.kind.is_type()
     }
 
-    crate fn get_type(&self) -> Option<Type> {
-        self.kind.get_type()
-    }
-
     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
         match self.kind {
             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
@@ -1353,6 +1334,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)]
@@ -1468,6 +1452,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),
index 38f53d7e0b28656b6f0deb3df34f3809823f5bed..19b309d6a30c8ea10514b5abb950ebd9610d8fae 100644 (file)
@@ -395,9 +395,7 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
     let (did, kind) = match res {
         // These should be added to the cache using `record_extern_fqn`.
         Res::Def(
-            kind
-            @
-            (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
+            kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
             | Union | Mod | ForeignTy | Const | Static | Macro(..) | TraitAlias),
             i,
         ) => (i, kind.into()),
index 34742fac0e4b7f1155a3290dc92c4eaf96873004..a3cbb5756fefc38fa878f0ed481a6f7e95535e87 100644 (file)
@@ -346,7 +346,7 @@ impl clean::Generics {
 
 impl clean::Lifetime {
     crate fn print(&self) -> impl fmt::Display + '_ {
-        self.get_ref()
+        self.0.as_str()
     }
 }
 
@@ -1177,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));
@@ -1349,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 d12667c9e5c777c205c8f690ab4c212450fc5754..2f7214e958ea7d2169b64afb03fad5928c0060d1 100644 (file)
@@ -347,19 +347,19 @@ fn insert_ty(
             let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
             for bound in bounds.iter() {
                 if let GenericBound::TraitBound(poly_trait, _) = bound {
-                    for x in poly_trait.generic_params.iter() {
-                        if !x.is_type() {
-                            continue;
-                        }
-                        if let Some(ty) = x.get_type() {
-                            get_real_types(
-                                generics,
-                                &ty,
-                                tcx,
-                                recurse + 1,
-                                &mut ty_generics,
-                                cache,
-                            );
+                    for param_def in poly_trait.generic_params.iter() {
+                        match &param_def.kind {
+                            clean::GenericParamDefKind::Type { default: Some(ty), .. } => {
+                                get_real_types(
+                                    generics,
+                                    ty,
+                                    tcx,
+                                    recurse + 1,
+                                    &mut ty_generics,
+                                    cache,
+                                )
+                            }
+                            _ => {}
                         }
                     }
                 }
index 08022d526fefb71c5f87af68a7a3d8d6334d8915..166e084012724e18999eb920770880617556c5ad 100644 (file)
@@ -804,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,
@@ -861,6 +861,7 @@ fn render_assoc_item(
     link: AssocItemLink<'_>,
     parent: ItemType,
     cx: &Context<'_>,
+    render_mode: RenderMode,
 ) {
     fn method(
         w: &mut Buffer,
@@ -871,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 {
@@ -893,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());
@@ -945,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,
@@ -1235,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();
 
@@ -1415,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(
@@ -1424,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>");
@@ -1459,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(
@@ -1638,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);
@@ -1683,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\">");
 
index d3738cfa3e7815af2c3935b4e9b2407f021ba7f1..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 {
@@ -1427,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),
     )
 }
 
@@ -1769,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 13d8e6318a4fe107f10e3582d50204930ab1ab66..3c6f083419aefbf038ffd52e86c843b964c0fb4e 100644 (file)
@@ -7,6 +7,12 @@
     <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" {# -#}
index 6ba56fe01a93505a7306cf628a98c89ad27cbdb9..b6311abb5c3e821f053aa79b1832fa3012bf716e 100644 (file)
@@ -18,7 +18,6 @@
 #![feature(type_ascription)]
 #![feature(iter_intersperse)]
 #![recursion_limit = "256"]
-#![feature(unwrap_infallible)]
 #![warn(rustc::internal)]
 
 #[macro_use]
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..2b9078f4afae82f60c5ac0fdb4af42d269e2f2f3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f9b03d0e2d7378f8dd5697ceb72b310060f7598f
+Subproject commit 2b9078f4afae82f60c5ac0fdb4af42d269e2f2f3
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);
+}
diff --git a/src/test/codegen/asm-may_unwind.rs b/src/test/codegen/asm-may_unwind.rs
new file mode 100644 (file)
index 0000000..85cae8b
--- /dev/null
@@ -0,0 +1,25 @@
+// min-llvm-version: 13.0.0
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm, asm_unwind)]
+
+#[no_mangle]
+pub extern "C" fn panicky() {}
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!();
+    }
+}
+
+// CHECK-LABEL: @may_unwind
+#[no_mangle]
+pub unsafe fn may_unwind() {
+    let _m = Foo;
+    // CHECK: invoke void asm sideeffect alignstack inteldialect unwind ""
+    asm!("", options(may_unwind));
+}
index 29b5e3ca244bf02eff41180eaf5e305d0832ac21..bebaa7754dd5a55dd061beac22bbdb5a63b8661e 100644 (file)
@@ -1,5 +1,4 @@
 #![crate_type = "lib"]
-#![feature(thread_local_const_init)]
 
 use std::cell::Cell;
 
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 f14368e39902dc6b41d9e46b02688e639cf0688b..5ac30d949fa4e4c5aff0611d88ca4fca41a6e892 100644 (file)
@@ -6,7 +6,6 @@
 // ignore-android does not use #[thread_local]
 
 #![crate_type = "lib"]
-#![feature(thread_local_const_init)]
 
 extern crate thread_local_aux as aux;
 
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 aa9ddf485b5aa606ef146b62d5267aece6e371a6..d04e2a0429d5c3c42be3202eb878751b51d53a5a 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=4
+// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
 
 // must not optimize as it does not follow the pattern of
 // left and right hand side being the same variant
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 32d1da390c547728e3f0efb5f32f8db16e492af6..c80bce2d140b9228df0a755509d450404fbf6d0b 100644 (file)
@@ -1,6 +1,6 @@
 // pp-exact
 
-fn main() { }
+fn main() {}
 
 #[cfg(FALSE)]
 fn syntax() {
@@ -117,7 +117,7 @@ fn syntax() {
     let _ = #[attr] foo!(#! [attr]);
     let _ = #[attr] foo![];
     let _ = #[attr] foo![#! [attr]];
-    let _ = #[attr] foo! { };
+    let _ = #[attr] foo! {};
     let _ = #[attr] foo! { #! [attr] };
     let _ = #[attr] Foo{bar: baz,};
     let _ = #[attr] Foo{..foo};
@@ -135,7 +135,7 @@ fn syntax() {
         foo!();
 
         #[attr]
-        foo! { }
+        foo! {}
 
         #[attr]
         foo![];
@@ -170,6 +170,6 @@ fn syntax() {
     {
 
         #[attr]
-        foo! { }
+        foo! {}
     }
 }
index 4ce6d2fbf17b9265cb18d151e5710494c0b5c471..0eb403c6bc843aeb4703cdf708a0e442200caad8 100644 (file)
@@ -29,4 +29,4 @@ enum Enum {
     Qwerty,
 }
 
-fn main() { }
+fn main() {}
index 61644e7df09ae5f64304666f7ed1c82b3d637906..c3c47cff5eda9a600dfcff80fab4aa10956d0502 100644 (file)
@@ -2,8 +2,8 @@
 
 // pp-exact
 
-auto trait MyTrait { }
+auto trait MyTrait {}
 
-unsafe auto trait UnsafeMyTrait { }
+unsafe auto trait UnsafeMyTrait {}
 
-pub fn main() { }
+pub fn main() {}
index b7c42e39557c9cd89f665dd692e6d13a297fedf5..e53d51e34cefa8d3942eb09f8c52c7d0d1319f3b 100644 (file)
@@ -1,9 +1,8 @@
 // compile-flags: --crate-type=lib
 
 // pp-exact
-fn f() {
-} /*
-  The next line should not be indented.
+fn f() {} /*
+          The next line should not be indented.
 
-  That one. It shouldn't have been indented.
-  */
+          That one. It shouldn't have been indented.
+          */
index ef5189fa13ee1c6a62880572eb39ea32eaa7027e..1eba1e6bdec3f4f0507d606b975d9628ff4b71b0 100644 (file)
@@ -3,14 +3,14 @@
 
 // pp-exact
 
-fn call_it(f: Box<FnMut(String) -> String>) { }
+fn call_it(f: Box<FnMut(String) -> String>) {}
 
-fn call_this<F>(f: F) where F: Fn(&str) + Send { }
+fn call_this<F>(f: F) where F: Fn(&str) + Send {}
 
-fn call_that<F>(f: F) where F: for<'a> Fn(&'a isize, &'a isize) -> isize { }
+fn call_that<F>(f: F) where F: for<'a> Fn(&'a isize, &'a isize) -> isize {}
 
-fn call_extern(f: fn() -> isize) { }
+fn call_extern(f: fn() -> isize) {}
 
-fn call_abid_extern(f: extern "C" fn() -> isize) { }
+fn call_abid_extern(f: extern "C" fn() -> isize) {}
 
-pub fn main() { }
+pub fn main() {}
index 601ca7bb6de1cd3e6836cf1cd6da5854d9328ba2..734f9fa123eea2c420947d12f3c162b92f7aa5a4 100644 (file)
@@ -7,4 +7,4 @@
 fn id<F>(f: F) -> isize where F: Fn() -> isize { f() }
 
 fn wsucc(_n: isize) -> isize { id(|| { 1 }) - 0 }
-fn main() { }
+fn main() {}
index a3e8178aeb3ded4cd2a98ef3d8b7c1ed2ee679b5..fc646c2956c4f74b8e25c920cac036c7b91a9988 100644 (file)
@@ -2,7 +2,7 @@
 
 // Check that the visibility is printed on an enum variant.
 
-fn main() { }
+fn main() {}
 
 #[cfg(FALSE)]
 enum Foo { pub V, }
index 4f7d5e7e71e176d161d26f1f7dbdd24fd686154b..8df74e8e1f9c871247264f335b576916915b616e 100644 (file)
@@ -1,3 +1,3 @@
 // pp-exact
 
-fn main() { }
+fn main() {}
index 852b9f316ce0fca5bf0662b3136f406d01abd30e..3f7129afde26d3c5f0530da24e950b745cee84a4 100644 (file)
@@ -1,3 +1,3 @@
 // pp-exact:example2.pp
 
-fn main() { }
+fn main() {}
index 852b9f316ce0fca5bf0662b3136f406d01abd30e..3f7129afde26d3c5f0530da24e950b745cee84a4 100644 (file)
@@ -1,3 +1,3 @@
 // pp-exact:example2.pp
 
-fn main() { }
+fn main() {}
index 1579ea41cfdf1b62ad4fb4f735505e39efff1c67..8385c5fa8c91a75d30224568e3f1852754ef2899 100644 (file)
@@ -10,4 +10,4 @@ extern crate std;
 // pp-exact:expanded-and-path-remap-80832.pp
 // compile-flags: --remap-path-prefix {{src-base}}=the/src
 
-fn main() { }
+fn main() {}
index 142d852cd6a132326deaadea46423c39079acf47..b932e83aaf10fd7f0a5e0bbc56abb1659771cab3 100644 (file)
@@ -1,7 +1,7 @@
 // pp-exact
 
-// Check that `fn f() -> () { }` does not print as `fn f() { }`.
+// Check that `fn f() -> () {}` does not print as `fn f() {}`.
 
-fn f() -> () { }
+fn f() -> () {}
 
-fn main() { }
+fn main() {}
index 842138e28c3531f51baa001980e3c07bd7123492..f012763c3f606f61cc04615f1c953c7dbd9c680e 100644 (file)
@@ -1,5 +1,5 @@
 // pp-exact
 
-fn from_foreign_fn(_x: fn()) { }
-fn from_stack_closure<F>(_x: F) where F: Fn() { }
-fn main() { }
+fn from_foreign_fn(_x: fn()) {}
+fn from_stack_closure<F>(_x: F) where F: Fn() {}
+fn main() {}
index d499be424603badfa5f9fd4c4a70dd6ae7432661..59e477cfa8ecba76fa24692ccdad2ad0331802ec 100644 (file)
@@ -12,4 +12,4 @@
     ap.arg::<usize>()
 }
 
-fn main() { }
+fn main() {}
index 652604fc7f34b2808e6af7db558ab27189ab332e..7b90b0becacbaf38e3b1dc2e8b4ae624489564f6 100644 (file)
@@ -4,34 +4,34 @@
 fn simple_attr() {
 
     #[attr]
-    if true { }
+    if true {}
 
     #[allow_warnings]
-    if true { }
+    if true {}
 }
 
 #[cfg(FALSE)]
 fn if_else_chain() {
 
     #[first_attr]
-    if true { } else if false { } else { }
+    if true {} else if false {} else {}
 }
 
 #[cfg(FALSE)]
 fn if_let() {
 
     #[attr]
-    if let Some(_) = Some(true) { }
+    if let Some(_) = Some(true) {}
 }
 
 #[cfg(FALSE)]
 fn let_attr_if() {
-    let _ = #[attr] if let _ = 0 { };
-    let _ = #[attr] if true { };
+    let _ = #[attr] if let _ = 0 {};
+    let _ = #[attr] if true {};
 
-    let _ = #[attr] if let _ = 0 { } else { };
-    let _ = #[attr] if true { } else { };
+    let _ = #[attr] if let _ = 0 {} else {};
+    let _ = #[attr] if true {} else {};
 }
 
 
-fn main() { }
+fn main() {}
index ca1fef83cffc5fcfa249e8496d39d6c79fd71456..3c88f5cb8a41c13012e883c78fb847d49687b77b 100644 (file)
@@ -6,4 +6,4 @@
 #[path = "issue-12590-b.rs"]
 mod issue_12590_b;
 
-fn main() { }
+fn main() {}
index dd0b8899b2d9d5ee57d4a8aa2bbf3c00199be497..07b3f5653d36b076eddccde7dd4afd0189fbcb91 100644 (file)
@@ -13,7 +13,7 @@ extern crate std;
 #[path = "issue-12590-b.rs"]
 mod issue_12590_b {
 
-    fn b() { }
-    fn main() { }
+    fn b() {}
+    fn main() {}
 }
-fn main() { }
+fn main() {}
index 2cc444edda3d7f1d0900add319b5dbe7703ffe98..0ec05f9a8051ba6e1f87471c91c1b5b8466756b6 100644 (file)
@@ -7,4 +7,4 @@
 #[path = "issue-12590-b.rs"]
 mod issue_12590_b;
 
-fn main() { }
+fn main() {}
index b42791113056e336c354142ab33814b1466f4993..0d2702804d12db379962dbf2ccea1cde7c33d5d5 100644 (file)
@@ -4,8 +4,8 @@
 fn main() {
     match true {
         true if true => (),
-        false if false => unsafe { },
-        true => { }
+        false if false => unsafe {},
+        true => {}
         false => (),
     }
 }
index 02951395e70b440491cab26889ef5c1301bda97c..607cbebee170c124737f0034f58ca2ad7f0a1fce 100644 (file)
@@ -5,4 +5,4 @@
 // pretty-compare-only
 // pp-exact
 
-fn main() { b! { } c }
+fn main() { b! {} c }
index 031a4825959329f11360f13940057b1c8ebcac31..ed7879001d5598df74797deeb9d6ac73db3a5b01 100644 (file)
@@ -1,6 +1,6 @@
 // pp-exact
 
-fn main() { }
+fn main() {}
 
 struct C {
     field: u8,
index bfef51202dbe1f81db412b1c9c0632e900b47c6f..34eae849be45eab5f215752a5884023699a23ae5 100644 (file)
@@ -1,5 +1,5 @@
 // pp-exact
 
-fn f1<'a, 'b, 'c>(_x: &'a u32, _y: &'b u32, _z: &'c u32) where 'c: 'a + 'b { }
+fn f1<'a, 'b, 'c>(_x: &'a u32, _y: &'b u32, _z: &'c u32) where 'c: 'a + 'b {}
 
-fn main() { }
+fn main() {}
index d3865d93a30d8ca0949c0808a39f0aeded46aa11..b88ae703950baec310a26f0deeee62a05372c0f1 100644 (file)
@@ -4,4 +4,4 @@
 
 pub(crate) macro mac { ($arg : expr) => { $arg + $arg } }
 
-fn main() { }
+fn main() {}
index 3b13f2530dd9276f2009948de758835e9c6bd63c..fb66e4a7758420962926977cb859dcfc997243b5 100644 (file)
@@ -1,19 +1,19 @@
 // pp-exact
 
-macro_rules! brace { () => { } ; }
+macro_rules! brace { () => {} ; }
 
-macro_rules! bracket[() => { } ;];
+macro_rules! bracket[() => {} ;];
 
-macro_rules! paren(() => { } ;);
+macro_rules! paren(() => {} ;);
 
 macro_rules! matcher_brackets {
-    (paren) => { } ; (bracket) => { } ; (brace) => { } ;
+    (paren) => {} ; (bracket) => {} ; (brace) => {} ;
 }
 
 macro_rules! all_fragments {
     ($b : block, $e : expr, $i : ident, $it : item, $l : lifetime, $lit :
      literal, $m : meta, $p : pat, $pth : path, $s : stmt, $tt : tt, $ty : ty,
-     $vis : vis) => { } ;
+     $vis : vis) => {} ;
 }
 
-fn main() { }
+fn main() {}
index 0a3f2a10c8549ab24fa354baaad7361acc9865d0..f46c0e3f1bc629fe38753079d6e1672d5c282066 100644 (file)
@@ -2,7 +2,7 @@
 
 // pp-exact
 
-fn main() { }
+fn main() {}
 
 #[cfg(FALSE)]
 extern "C" {
index 3072e416cbeefdb71067c8dd42f8d898ea2163c2..f1970de6feb4b14581aa65c4f7fc4a55195e41b8 100644 (file)
@@ -2,9 +2,9 @@
 
 
 trait Tr {
-    fn dummy(&self) { }
+    fn dummy(&self) {}
 }
-impl Tr for isize { }
+impl Tr for isize {}
 
 fn foo<'a>(x: Box<Tr + Sync + 'a>) -> Box<Tr + Sync + 'a> { x }
 
index e06885e03882bc6d5d99a79b76c1d3b8b51a9b4e..67a5d1dd8ec664db2d54205a7fa1d3a8202e2312 100644 (file)
@@ -8,9 +8,9 @@ pub trait Tr {
 }
 
 trait Tu {
-    fn dummy() { }
+    fn dummy() {}
 }
 
 fn foo<T: m::Tr>() { <T as m::Tr>::Ts::dummy(); }
 
-fn main() { }
+fn main() {}
index e4a3acade871be7e443fb85e71d3da1dba43233b..12204c8cd30ed825e454c8f314aa04a468ea1250 100644 (file)
@@ -4,7 +4,7 @@
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 
-fn main() { }
+fn main() {}
 
 fn _0() {
 
@@ -35,7 +35,7 @@ fn _2() {
 fn _3() {
 
     #[rustc_dummy]
-    match () { _ => { } }
+    match () { _ => {} }
 }
 
 fn _4() {
@@ -117,13 +117,13 @@ fn _9() {
     stmt_mac!();
 
     #[rustc_dummy]
-    stmt_mac! { };
+    stmt_mac! {};
 
     #[rustc_dummy]
     stmt_mac![];
 
     #[rustc_dummy]
-    stmt_mac! { }
+    stmt_mac! {}
 
     let _ = ();
 }
@@ -133,7 +133,7 @@ macro_rules! expr_mac { () => { () } }
 fn _10() {
     let _ = #[rustc_dummy] expr_mac!();
     let _ = #[rustc_dummy] expr_mac![];
-    let _ = #[rustc_dummy] expr_mac! { };
+    let _ = #[rustc_dummy] expr_mac! {};
 }
 
 fn _11() {
@@ -235,7 +235,7 @@ fn _11() {
     || #[rustc_dummy] return;
     let _ = #[rustc_dummy] expr_mac!();
     let _ = #[rustc_dummy] expr_mac![];
-    let _ = #[rustc_dummy] expr_mac! { };
+    let _ = #[rustc_dummy] expr_mac! {};
     let _ = #[rustc_dummy] Foo{data: (),};
     let _ = #[rustc_dummy] Foo{..s};
     let _ = #[rustc_dummy] Foo{data: (), ..s};
@@ -258,6 +258,6 @@ fn _12() {
     }
 }
 
-fn foo() { }
-fn foo3(_: i32, _: (), _: ()) { }
-fn qux(_: i32) { }
+fn foo() {}
+fn foo3(_: i32, _: (), _: ()) {}
+fn qux(_: i32) {}
index 28ed4fccaf26be8bd328bfb3803a227fdbfdf078..d53f6e4b52850b8a6d0b9317f64b5bc6c8c5ed24 100644 (file)
@@ -5,4 +5,4 @@ enum foo {
     baz,
 }
 
-fn main() { }
+fn main() {}
index bb4fb1459bd64597037bb9afad15ac31bb73bec0..6cb0e4136b62cc2eddfe3f8ca44303010823d62c 100644 (file)
@@ -4,4 +4,4 @@ trait Foo {
     #![allow(bar)]
 }
 
-fn main() { }
+fn main() {}
index df1a7946afb119c3cf89fac4bcbd8322d907ce90..310506eabca17a2250833a99b89b7ee10d8af02d 100644 (file)
@@ -4,6 +4,6 @@
 
 struct Test;
 
-impl !Send for Test { }
+impl !Send for Test {}
 
-pub fn main() { }
+pub fn main() {}
index b2f2d610c31228c2de294f5726420c417f58b976..c4ae7606946badce71e41784f8afd4ca3b6ef754 100644 (file)
@@ -5,11 +5,11 @@ unsafe trait UnsafeTrait {
 }
 
 unsafe impl UnsafeTrait for isize {
-    fn foo(&self) { }
+    fn foo(&self) {}
 }
 
 pub unsafe trait PubUnsafeTrait {
     fn foo(&self);
 }
 
-fn main() { }
+fn main() {}
index 3d6e431a11a9afae97be44dee12fc259286bb190..5614a81b0eb410f0d7afe97ed090e244a296428f 100644 (file)
@@ -2,4 +2,4 @@
 
 fn f<'a, 'b, T>(t: T) -> isize where T: 'a, 'a: 'b, T: Eq { 0 }
 
-fn main() { }
+fn main() {}
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 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!()
+    }
+}
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>.
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 6bf09b9d24bdeb4cb57e8663e0aef261595eeaa7..9465c8a35c886f83e6681b4eb70c963b68ee47f3 100644 (file)
@@ -96,6 +96,6 @@ pub fn uses_cfg_target_feature() {
 // @has doc_cfg/fn.multiple_attrs.html \
 //  '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
 //  'This is supported on x and y and z only.'
-#[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 1869cc6758ced9470592d823cceeb021f51610d1..c3340af33d5a72c11506bfbe9ffb822e747d7675 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 7f0fcceca421a876e270b6b0f2438527112d47dc..fd0b1b97c6ef2653db8e707bf4e67dab2ff0b0a5 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 7c3b90839eeb9bebacbf54e7f40dd0886443f195..a412a23fda835e65f3296a9938485f7935a92d23 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 
 // @has prim_methods/index.html
 // @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
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 081df89a139dd193e11819e61b9086666d4f64ea..e02be9cabd26842386307979b1d6c140f3aff4b7 100644 (file)
@@ -1,4 +1,4 @@
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![crate_name = "foo"]
 
 // @has foo/index.html
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/mixing-doc-comments-and-attrs.S1_top-doc.html b/src/test/rustdoc/mixing-doc-comments-and-attrs.S1_top-doc.html
new file mode 100644 (file)
index 0000000..69d647a
--- /dev/null
@@ -0,0 +1,4 @@
+<div class="docblock"><p>Hello world!
+Goodbye!
+Hello again!</p>
+</div>
\ No newline at end of file
diff --git a/src/test/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html b/src/test/rustdoc/mixing-doc-comments-and-attrs.S2_top-doc.html
new file mode 100644 (file)
index 0000000..8ff114b
--- /dev/null
@@ -0,0 +1,4 @@
+<div class="docblock"><p>Hello world!</p>
+<p>Goodbye!
+Hello again!</p>
+</div>
\ No newline at end of file
index c26d3a319878dea6568405928bdd85afcd1c550a..1aedd4d107c21ef3d972678088ef5a042a0c624f 100644 (file)
@@ -1,10 +1,7 @@
 #![crate_name = "foo"]
 
 // @has 'foo/struct.S1.html'
-// @count - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p' \
-//     1
-// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[1]' \
-//     'Hello world! Goodbye! Hello again!'
+// @snapshot S1_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
 
 #[doc = "Hello world!\n\n"]
 /// Goodbye!
@@ -12,12 +9,7 @@
 pub struct S1;
 
 // @has 'foo/struct.S2.html'
-// @count - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p' \
-//     2
-// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[1]' \
-//     'Hello world!'
-// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[2]' \
-//     'Goodbye! Hello again!'
+// @snapshot S2_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
 
 /// Hello world!
 ///
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 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");
index 21bcc4a9c7badd4ddbc01351734661187eb6d68a..867e0433eae1bece783672fd52c8dcf4c2ebac31 100644 (file)
@@ -36,41 +36,41 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    |
    |                    generic outputs
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
   --> $DIR/bad-options.rs:28:25
    |
 LL | global_asm!("", options(nomem));
-   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `readonly`
   --> $DIR/bad-options.rs:30:25
    |
 LL | global_asm!("", options(readonly));
-   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `noreturn`
   --> $DIR/bad-options.rs:32:25
    |
 LL | global_asm!("", options(noreturn));
-   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `pure`
   --> $DIR/bad-options.rs:34:25
    |
 LL | global_asm!("", options(pure));
-   |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nostack`
   --> $DIR/bad-options.rs:36:25
    |
 LL | global_asm!("", options(nostack));
-   |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `preserves_flags`
   --> $DIR/bad-options.rs:38:25
    |
 LL | global_asm!("", options(preserves_flags));
-   |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
 error: invalid ABI for `clobber_abi`
   --> $DIR/bad-options.rs:20:18
diff --git a/src/test/ui/asm/aarch64/may_unwind.rs b/src/test/ui/asm/aarch64/may_unwind.rs
new file mode 100644 (file)
index 0000000..94cc7d7
--- /dev/null
@@ -0,0 +1,37 @@
+// min-llvm-version: 13.0.0
+// only-aarch64
+// run-pass
+// needs-asm-support
+
+#![feature(asm, asm_sym, asm_unwind)]
+
+use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
+
+struct Foo<'a>(&'a mut bool);
+
+impl Drop for Foo<'_> {
+    fn drop(&mut self) {
+        *self.0 = false;
+    }
+}
+
+extern "C" fn panicky() {
+    resume_unwind(Box::new(()));
+}
+
+fn main() {
+    let flag = &mut true;
+    catch_unwind(AssertUnwindSafe(|| {
+        let _foo = Foo(flag);
+        unsafe {
+            asm!(
+                "bl {}",
+                sym panicky,
+                clobber_abi("C"),
+                options(may_unwind)
+            );
+        }
+    }))
+    .expect_err("expected a panic");
+    assert_eq!(*flag, false);
+}
index 3d88cef5c7d71771c022f20c0b68a3915f354159..a143c3b2b28180ea94aa8d112035957ec4cfbcc4 100644 (file)
@@ -64,11 +64,11 @@ error: argument to `sym` must be a path expression
 LL |         asm!("{}", sym foo + bar);
    |                        ^^^^^^^^^
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:31:26
    |
 LL |         asm!("", options(foo));
-   |                          ^^^ expected one of 9 possible tokens
+   |                          ^^^ expected one of 10 possible tokens
 
 error: expected one of `)` or `,`, found `foo`
   --> $DIR/parse-error.rs:33:32
@@ -76,11 +76,11 @@ error: expected one of `)` or `,`, found `foo`
 LL |         asm!("", options(nomem foo));
    |                                ^^^ expected one of `)` or `,`
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:35:33
    |
 LL |         asm!("", options(nomem, foo));
-   |                                 ^^^ expected one of 9 possible tokens
+   |                                 ^^^ expected one of 10 possible tokens
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:37:31
@@ -260,23 +260,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `FOO`
   --> $DIR/parse-error.rs:100:25
    |
 LL | global_asm!("", options(FOO));
-   |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:102:25
    |
 LL | global_asm!("", options(nomem FOO));
-   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:104:25
    |
 LL | global_asm!("", options(nomem, FOO));
-   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:106:30
diff --git a/src/test/ui/asm/may_unwind.rs b/src/test/ui/asm/may_unwind.rs
new file mode 100644 (file)
index 0000000..436e8b9
--- /dev/null
@@ -0,0 +1,9 @@
+// min-llvm-version: 13.0.0
+// run-pass
+// needs-asm-support
+
+#![feature(asm, asm_unwind)]
+
+fn main() {
+    unsafe { asm!("", options(may_unwind)) };
+}
index e2351840eef211612b880b82ec4c538f50e3cfeb..a63c42aac27377d543b3385867ea922774c2036b 100644 (file)
@@ -45,41 +45,41 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                    |             clobber_abi
    |                    generic outputs
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
   --> $DIR/bad-options.rs:31:25
    |
 LL | global_asm!("", options(nomem));
-   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `readonly`
   --> $DIR/bad-options.rs:33:25
    |
 LL | global_asm!("", options(readonly));
-   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `noreturn`
   --> $DIR/bad-options.rs:35:25
    |
 LL | global_asm!("", options(noreturn));
-   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `pure`
   --> $DIR/bad-options.rs:37:25
    |
 LL | global_asm!("", options(pure));
-   |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nostack`
   --> $DIR/bad-options.rs:39:25
    |
 LL | global_asm!("", options(nostack));
-   |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `preserves_flags`
   --> $DIR/bad-options.rs:41:25
    |
 LL | global_asm!("", options(preserves_flags));
-   |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
 error: invalid ABI for `clobber_abi`
   --> $DIR/bad-options.rs:20:18
diff --git a/src/test/ui/asm/x86_64/may_unwind.rs b/src/test/ui/asm/x86_64/may_unwind.rs
new file mode 100644 (file)
index 0000000..5ac4dd9
--- /dev/null
@@ -0,0 +1,37 @@
+// min-llvm-version: 13.0.0
+// only-x86_64
+// run-pass
+// needs-asm-support
+
+#![feature(asm, asm_sym, asm_unwind)]
+
+use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
+
+struct Foo<'a>(&'a mut bool);
+
+impl Drop for Foo<'_> {
+    fn drop(&mut self) {
+        *self.0 = false;
+    }
+}
+
+extern "C" fn panicky() {
+    resume_unwind(Box::new(()));
+}
+
+fn main() {
+    let flag = &mut true;
+    catch_unwind(AssertUnwindSafe(|| {
+        let _foo = Foo(flag);
+        unsafe {
+            asm!(
+                "call {}",
+                sym panicky,
+                clobber_abi("C"),
+                options(may_unwind)
+            );
+        }
+    }))
+    .expect_err("expected a panic");
+    assert_eq!(*flag, false);
+}
index 018df9826c6ee8ebc5d935353945516fb25e2eab..4f16c15af381c5b8ffa789f2ee64d06045b20f53 100644 (file)
@@ -64,11 +64,11 @@ error: argument to `sym` must be a path expression
 LL |         asm!("{}", sym foo + bar);
    |                        ^^^^^^^^^
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:31:26
    |
 LL |         asm!("", options(foo));
-   |                          ^^^ expected one of 9 possible tokens
+   |                          ^^^ expected one of 10 possible tokens
 
 error: expected one of `)` or `,`, found `foo`
   --> $DIR/parse-error.rs:33:32
@@ -76,11 +76,11 @@ error: expected one of `)` or `,`, found `foo`
 LL |         asm!("", options(nomem foo));
    |                                ^^^ expected one of `)` or `,`
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:35:33
    |
 LL |         asm!("", options(nomem, foo));
-   |                                 ^^^ expected one of 9 possible tokens
+   |                                 ^^^ expected one of 10 possible tokens
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:37:31
@@ -266,23 +266,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `FOO`
   --> $DIR/parse-error.rs:102:25
    |
 LL | global_asm!("", options(FOO));
-   |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:104:25
    |
 LL | global_asm!("", options(nomem FOO));
-   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:106:25
    |
 LL | global_asm!("", options(nomem, FOO));
-   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:108:30
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
+
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 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 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 395d9e21b3848a1b953baf4ef1a5429f1a003242..6f980e606645149fadfca22d1dfee4dd4061544d 100644 (file)
@@ -1,3 +1,3 @@
-async fn f(mut x : u8) { }
-async fn g((mut x, y, mut z) : (u8, u8, u8)) { }
-async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) { }
+async fn f(mut x : u8) {}
+async fn g((mut x, y, mut z) : (u8, u8, u8)) {}
+async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) {}
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 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`.
index d466157f04e0cd3c1f955fb69e7e2b02ed0ed5db..2718b65108cdd24c9d4a940e5928ead26ceddf85 100644 (file)
@@ -8,7 +8,7 @@ LL | #![u=||{static d=||1;}]
    |      ^^^^^^^^^^^^^^^^^
 
 error: unexpected token: `{
-           impl std::ops::Neg for i8 { }
+           impl std::ops::Neg for i8 {}
        }`
   --> $DIR/issue-90873.rs:7:6
    |
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/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 1bceb8cbb94ddcc3b8e8ac179d353e43000dcb0d..9f65b8f25baaf85781800339386494aea82e6cb8 100644 (file)
@@ -11,9 +11,9 @@ use ::std::prelude::rust_2015::*;
 #[macro_use]
 extern crate std;
 
-trait Foo<const KIND : bool = true> { }
+trait Foo<const KIND : bool = true> {}
 
-fn foo<const SIZE : usize = 5>() { }
+fn foo<const SIZE : usize = 5>() {}
 
 struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize =
              FROM>;
index 0dfd804be41b48a0c44c0cae1a396c1d0c9b249f..18010413b9394528e0ef615a33b48fa5cfb2b1e3 100644 (file)
@@ -4,7 +4,7 @@ error: overly complex generic constant
 LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
    |                                   ^^^^-------^^
    |                                       |
-   |                                       dereferencing is not supported in generic constants
+   |                                       borrowing is not supported in generic constants
    |
    = help: consider moving this anonymous constant into a `const` function
    = note: this operation may be supported in the future
index b79bc262d2bac1877a3ee9af2dfea10e5ab12189..18f33acaabbba19fbcc73a699924d4c26b0cad2b 100644 (file)
@@ -1,4 +1,3 @@
-// run-pass
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
@@ -22,8 +21,11 @@ fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
 }
 
 fn main() {
-    // Test that we can correctly infer `T` which requires evaluating
-    // `{ N + 1 }` which has substs containing an inference var
+    // FIXME(generic_const_exprs): We can't correctly infer `T` which requires
+    // evaluating `{ N + 1 }` which has substs containing an inference var
     let mut _q = Default::default();
+    //~^ ERROR type annotations needed
+
     _q = foo::<_, 2>(_q);
+    //~^ ERROR type annotations needed
 }
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr
new file mode 100644 (file)
index 0000000..e59f1ac
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0282]: type annotations needed
+  --> $DIR/const_eval_resolve_canonical.rs:26:9
+   |
+LL |     let mut _q = Default::default();
+   |         ^^^^^^ consider giving `_q` a type
+
+error[E0283]: type annotations needed
+  --> $DIR/const_eval_resolve_canonical.rs:29:10
+   |
+LL |     _q = foo::<_, 2>(_q);
+   |          ^^^^^^^^^^^ cannot infer type
+   |
+note: multiple `impl`s satisfying `(): Foo<{ N + 1 }>` found
+  --> $DIR/const_eval_resolve_canonical.rs:8:1
+   |
+LL | impl Foo<0> for () {
+   | ^^^^^^^^^^^^^^^^^^
+...
+LL | impl Foo<3> for () {
+   | ^^^^^^^^^^^^^^^^^^
+note: required by a bound in `foo`
+  --> $DIR/const_eval_resolve_canonical.rs:18:9
+   |
+LL | fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
+   |    --- required by a bound in this
+LL | where
+LL |     (): Foo<{ N + 1 }>,
+   |         ^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/issues/issue-83249.rs b/src/test/ui/const-generics/issues/issue-83249.rs
new file mode 100644 (file)
index 0000000..65148c5
--- /dev/null
@@ -0,0 +1,23 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+trait Foo {
+    const N: usize;
+}
+
+impl Foo for u8 {
+    const N: usize = 1;
+}
+
+fn foo<T: Foo>(_: [u8; T::N]) -> T {
+    todo!()
+}
+
+pub fn bar() {
+    let _: u8 = foo([0; 1]);
+
+    let _ = foo([0; 1]);
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83249.stderr b/src/test/ui/const-generics/issues/issue-83249.stderr
new file mode 100644 (file)
index 0000000..402b3aa
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-83249.rs:19:13
+   |
+LL |     let _ = foo([0; 1]);
+   |         -   ^^^ cannot infer type for type parameter `T` declared on the function `foo`
+   |         |
+   |         consider giving this pattern a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/issues/issue-83288.rs b/src/test/ui/const-generics/issues/issue-83288.rs
new file mode 100644 (file)
index 0000000..a24596d
--- /dev/null
@@ -0,0 +1,69 @@
+// build-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+use std::{marker::PhantomData, ops::Mul};
+
+pub enum Nil {}
+pub struct Cons<T, L> {
+    _phantom: PhantomData<(T, L)>,
+}
+
+pub trait Indices<const N: usize> {
+    const RANK: usize;
+    const NUM_ELEMS: usize;
+}
+
+impl<const N: usize> Indices<N> for Nil {
+    const RANK: usize = 0;
+    const NUM_ELEMS: usize = 1;
+}
+
+impl<T, I: Indices<N>, const N: usize> Indices<N> for Cons<T, I> {
+    const RANK: usize = I::RANK + 1;
+    const NUM_ELEMS: usize = I::NUM_ELEMS * N;
+}
+
+pub trait Concat<J> {
+    type Output;
+}
+
+impl<J> Concat<J> for Nil {
+    type Output = J;
+}
+
+impl<T, I, J> Concat<J> for Cons<T, I>
+where
+    I: Concat<J>,
+{
+    type Output = Cons<T, <I as Concat<J>>::Output>;
+}
+
+pub struct Tensor<I: Indices<N>, const N: usize>
+where
+    [u8; I::NUM_ELEMS]: Sized,
+{
+    pub data: [u8; I::NUM_ELEMS],
+    _phantom: PhantomData<I>,
+}
+
+impl<I: Indices<N>, J: Indices<N>, const N: usize> Mul<Tensor<J, N>> for Tensor<I, N>
+where
+    I: Concat<J>,
+    <I as Concat<J>>::Output: Indices<N>,
+    [u8; I::NUM_ELEMS]: Sized,
+    [u8; J::NUM_ELEMS]: Sized,
+    [u8; <I as Concat<J>>::Output::NUM_ELEMS]: Sized,
+{
+    type Output = Tensor<<I as Concat<J>>::Output, N>;
+
+    fn mul(self, _rhs: Tensor<J, N>) -> Self::Output {
+        Tensor {
+            data: [0u8; <I as Concat<J>>::Output::NUM_ELEMS],
+            _phantom: PhantomData,
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-87470.rs b/src/test/ui/const-generics/issues/issue-87470.rs
new file mode 100644 (file)
index 0000000..d60181a
--- /dev/null
@@ -0,0 +1,24 @@
+// build-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait TraitWithConst {
+    const SOME_CONST: usize;
+}
+
+pub trait OtherTrait: TraitWithConst {
+    fn some_fn(self) -> [u8 ; <Self as TraitWithConst>::SOME_CONST];
+}
+
+impl TraitWithConst for f32 {
+    const SOME_CONST: usize = 32;
+}
+
+impl OtherTrait for f32 {
+    fn some_fn(self) -> [u8 ; <Self as TraitWithConst>::SOME_CONST] {
+        [0; 32]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-87964.rs b/src/test/ui/const-generics/issues/issue-87964.rs
new file mode 100644 (file)
index 0000000..116686a
--- /dev/null
@@ -0,0 +1,29 @@
+// build-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Target {
+    const LENGTH: usize;
+}
+
+
+pub struct Container<T: Target>
+where
+    [(); T::LENGTH]: Sized,
+{
+    _target: T,
+}
+
+impl<T: Target> Container<T>
+where
+    [(); T::LENGTH]: Sized,
+{
+    pub fn start(
+        _target: T,
+    ) -> Container<T> {
+        Container { _target }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-89146.rs b/src/test/ui/const-generics/issues/issue-89146.rs
new file mode 100644 (file)
index 0000000..e3540f4
--- /dev/null
@@ -0,0 +1,26 @@
+// build-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+pub trait Foo {
+    const SIZE: usize;
+
+    fn to_bytes(&self) -> [u8; Self::SIZE];
+}
+
+pub fn bar<G: Foo>(a: &G) -> u8
+where
+    [(); G::SIZE]: Sized,
+{
+    deeper_bar(a)
+}
+
+fn deeper_bar<G: Foo>(a: &G) -> u8
+where
+    [(); G::SIZE]: Sized,
+{
+    a.to_bytes()[0]
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-89320.rs b/src/test/ui/const-generics/issues/issue-89320.rs
new file mode 100644 (file)
index 0000000..afa5c8f
--- /dev/null
@@ -0,0 +1,19 @@
+// build-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Enumerable {
+    const N: usize;
+}
+
+#[derive(Clone)]
+pub struct SymmetricGroup<S>
+where
+    S: Enumerable,
+    [(); S::N]: Sized,
+{
+    _phantom: std::marker::PhantomData<S>,
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-90455.rs b/src/test/ui/const-generics/issues/issue-90455.rs
new file mode 100644 (file)
index 0000000..a580410
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(generic_const_exprs, adt_const_params)]
+#![allow(incomplete_features)]
+
+struct FieldElement<const N: &'static str> {
+    n: [u64; num_limbs(N)],
+    //~^ ERROR unconstrained generic constant
+}
+const fn num_limbs(_: &str) -> usize {
+    0
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-90455.stderr b/src/test/ui/const-generics/issues/issue-90455.stderr
new file mode 100644 (file)
index 0000000..724d7f4
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/issue-90455.rs:5:8
+   |
+LL |     n: [u64; num_limbs(N)],
+   |        ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); num_limbs(N)]:`
+
+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
-
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 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 08fc82e91f62379a681bcb41f0e4e357d25c1833..08f293d2ebb06150d38ab7e6561fdc8e672b6d87 100644 (file)
@@ -1,3 +1,16 @@
 #![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive`
+//~^ ERROR `derive` attribute cannot be used at crate level
+
+#![test]//~ ERROR cannot determine resolution for the attribute macro `test`
+//~^ ERROR `test` attribute cannot be used at crate level
+
+#![test_case]//~ ERROR cannot determine resolution for the attribute macro `test_case`
+//~^ ERROR `test_case` attribute cannot be used at crate level
+
+#![bench]//~ ERROR cannot determine resolution for the attribute macro `bench`
+//~^ ERROR `bench` attribute cannot be used at crate level
+
+#![global_allocator]//~ ERROR cannot determine resolution for the attribute macro `global_allocator`
+//~^ ERROR `global_allocator` attribute cannot be used at crate level
 
 fn main() {}
index 0716764b4270460e1e616364b8d8eaa7ebb8058b..9cc0a29b0651db9c487e9005183318d70775b98e 100644 (file)
@@ -6,5 +6,92 @@ LL | #![derive(Copy)]
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to previous error
+error: cannot determine resolution for the attribute macro `test`
+  --> $DIR/issue-36617.rs:4:4
+   |
+LL | #![test]
+   |    ^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the attribute macro `test_case`
+  --> $DIR/issue-36617.rs:7:4
+   |
+LL | #![test_case]
+   |    ^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the attribute macro `bench`
+  --> $DIR/issue-36617.rs:10:4
+   |
+LL | #![bench]
+   |    ^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the attribute macro `global_allocator`
+  --> $DIR/issue-36617.rs:13:4
+   |
+LL | #![global_allocator]
+   |    ^^^^^^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: `derive` attribute cannot be used at crate level
+  --> $DIR/issue-36617.rs:1:1
+   |
+LL | #![derive(Copy)]
+   | ^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[derive(Copy)]
+   | ~~~~~~~~~~~~~~~
+
+error: `test` attribute cannot be used at crate level
+  --> $DIR/issue-36617.rs:4:1
+   |
+LL | #![test]
+   | ^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[test]
+   | ~~~~~~~
+
+error: `test_case` attribute cannot be used at crate level
+  --> $DIR/issue-36617.rs:7:1
+   |
+LL | #![test_case]
+   | ^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[test_case]
+   | ~~~~~~~~~~~~
+
+error: `bench` attribute cannot be used at crate level
+  --> $DIR/issue-36617.rs:10:1
+   |
+LL | #![bench]
+   | ^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[bench]
+   | ~~~~~~~~
+
+error: `global_allocator` attribute cannot be used at crate level
+  --> $DIR/issue-36617.rs:13:1
+   |
+LL | #![global_allocator]
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[global_allocator]
+   | ~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
 
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 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/feature-gates/feature-gate-asm_unwind.rs b/src/test/ui/feature-gates/feature-gate-asm_unwind.rs
new file mode 100644 (file)
index 0000000..c9957ff
--- /dev/null
@@ -0,0 +1,10 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("", options(may_unwind));
+        //~^ ERROR the `may_unwind` option is unstable
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_unwind.stderr b/src/test/ui/feature-gates/feature-gate-asm_unwind.stderr
new file mode 100644 (file)
index 0000000..6b5bf28
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: the `may_unwind` option is unstable
+  --> $DIR/feature-gate-asm_unwind.rs:7:9
+   |
+LL |         asm!("", options(may_unwind));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_unwind)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index 31eee88d1fac6949195b23feec4aa7cdfbf410da..796325b79af66cf6b60c4ba6c9ed09029baf2609 100644 (file)
@@ -6,5 +6,5 @@
 
 #![bench                   = "4100"]
 //~^ ERROR cannot determine resolution for the attribute macro `bench`
-
+//~^^ ERROR `bench` attribute cannot be used at crate level
 fn main() {}
index d0305c5160f7e97241d65bde153a3afd689ff1b6..6b33221194221263fd467ce61739a55ad0d048c4 100644 (file)
@@ -6,5 +6,16 @@ LL | #![bench                   = "4100"]
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to previous error
+error: `bench` attribute cannot be used at crate level
+  --> $DIR/issue-43106-gating-of-bench.rs:7:1
+   |
+LL | #![bench                   = "4100"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[bench                   = "4100"]
+   |
+
+error: aborting due to 2 previous errors
 
index 9e2e2d4137d258ca3aa4c20044f66164b342f0da..f94ec7d47041b38141d798b4e5864abe42056a85 100644 (file)
@@ -129,36 +129,66 @@ error: `macro_export` attribute cannot be used at crate level
    |
 LL | #![macro_export]
    | ^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[macro_export]
+   |
 
 error: `rustc_main` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1
    |
 LL | #![rustc_main]
    | ^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[rustc_main]
+   | ~~~~~~~~~~~~~
 
 error: `start` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
    |
 LL | #![start]
    | ^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[start]
+   |
 
 error: `repr` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:18:1
    |
 LL | #![repr()]
    | ^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[repr()]
+   |
 
 error: `path` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:20:1
    |
 LL | #![path = "3800"]
    | ^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[path = "3800"]
+   |
 
 error: `automatically_derived` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:22:1
    |
 LL | #![automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[automatically_derived]
+   |
 
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:17
index ee3fe712e36e5b944056ace8f272e449553cb13c..39835c9268eef89324b9af59ca0f8aae0547e605 100644 (file)
@@ -3,5 +3,5 @@
 #![allow(soft_unstable)]
 #![test                    = "4200"]
 //~^ ERROR cannot determine resolution for the attribute macro `test`
-
+//~^^ ERROR `test` attribute cannot be used at crate level
 fn main() {}
index 335af5e7905f22079f7963ec6979a43f8bdc9af4..300a9966dd880910dc9253d59e5a9cc725011996 100644 (file)
@@ -6,5 +6,16 @@ LL | #![test                    = "4200"]
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to previous error
+error: `test` attribute cannot be used at crate level
+  --> $DIR/issue-43106-gating-of-test.rs:4:1
+   |
+LL | #![test                    = "4200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[test                    = "4200"]
+   |
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gates/thread-local-const-init.rs b/src/test/ui/feature-gates/thread-local-const-init.rs
deleted file mode 100644 (file)
index 6584ffa..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-thread_local!(static X: u32 = const { 0 });
-//~^ ERROR: use of unstable library feature 'thread_local_const_init'
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/thread-local-const-init.stderr b/src/test/ui/feature-gates/thread-local-const-init.stderr
deleted file mode 100644 (file)
index f805068..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: use of unstable library feature 'thread_local_const_init'
-  --> $DIR/thread-local-const-init.rs:1:1
-   |
-LL | thread_local!(static X: u32 = const { 0 });
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #84223 <https://github.com/rust-lang/rust/issues/84223> for more information
-   = help: add `#![feature(thread_local_const_init)]` to the crate attributes to enable
-   = note: this error originates in the macro `$crate::__thread_local_inner` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
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`.
diff --git a/src/test/ui/generator/issue-91477.rs b/src/test/ui/generator/issue-91477.rs
new file mode 100644 (file)
index 0000000..6c027fe
--- /dev/null
@@ -0,0 +1,7 @@
+#![feature(generators)]
+
+fn foo() -> impl Sized {
+    yield 1; //~ ERROR E0627
+}
+
+fn main() {}
diff --git a/src/test/ui/generator/issue-91477.stderr b/src/test/ui/generator/issue-91477.stderr
new file mode 100644 (file)
index 0000000..4597dc1
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0627]: yield expression outside of generator literal
+  --> $DIR/issue-91477.rs:4:5
+   |
+LL |     yield 1;
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0627`.
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 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 ffb9f9eed41fb92a1f20c322c893dff491fbf900..51c21043db8888d616bf8ff6302f620cfdde49f8 100644 (file)
@@ -15,7 +15,7 @@ fn bar /* 0#0 */() {
     y /* 0#1 */ + x /* 0#0 */
 }
 
-fn y /* 0#0 */() { }
+fn y /* 0#0 */() {}
 
 /*
 Expansions:
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 1ed2d330b5123e4517869adc3a10f09f1beb2128..ef2a5d634a678a00a21d49fd3880740b161067b1 100644 (file)
@@ -2,3 +2,4 @@
 
 #![allow(soft_unstable)]
 #![test] //~ ERROR cannot determine resolution for the attribute macro `test`
+//~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level
index 8ed4d015f3216658d06911f3b06c294cb73b8b2e..33cb53f202a30d36ec655c578beb046d1ffd6607 100644 (file)
@@ -6,5 +6,16 @@ LL | #![test]
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to previous error
+error: `test` attribute cannot be used at crate level
+  --> $DIR/issue-28134.rs:4:1
+   |
+LL | #![test]
+   | ^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[test]
+   | ~~~~~~~
+
+error: aborting due to 2 previous errors
 
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 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 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 e53a543f3a0bab6185fccc25417b7ebfa5c26e76..cdf1f0dfc536108e9f2fbd0df1b5d5876bbf82a1 100644 (file)
@@ -10,6 +10,10 @@ note: required because of the requirements on the impl of `IntoNullable` for `<C
 LL | impl<T: NotNull> IntoNullable for T {
    |                  ^^^^^^^^^^^^     ^
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting the associated type
+   |
+LL |     Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull,
+   |                                                                       +++++++++++++++++++++++++++++++++++++++
 
 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 deb63872f6968c44f976912a544c357c1f3ae266..10597caf5b2dc09759e2a3430a26f592b7938e68 100644 (file)
@@ -1,8 +1,17 @@
 #[derive(Clone, Copy)]
 //~^ ERROR the trait `Copy` may not be implemented for this type
-struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
 //~^ ERROR cannot find type `NotDefined` in this scope
 //~| ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR `i32` is not an iterator
+
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
 //~| ERROR `i32` is not an iterator
 
 fn main() {}
index 15f38c892679bcd75a87805b461c63a42b9cc576..0bb1f9ae03500236017838440ae4aa0125dd5801 100644 (file)
@@ -1,20 +1,61 @@
-error[E0412]: cannot find type `NotDefined` in this scope
+error[E0412]: cannot find type `N` in this scope
   --> $DIR/issue-50480.rs:3:12
    |
-LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |            ^^^^^^^^^^ not found in this scope
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           -^ not found in this scope
+   |           |
+   |           help: you might be missing a type parameter: `<N>`
 
 error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:15
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |               ^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `N` in this scope
   --> $DIR/issue-50480.rs:3:12
    |
-LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |            ^^^^^^^^^^ not found in this scope
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           -^ not found in this scope
+   |           |
+   |           help: you might be missing a type parameter: `<N>`
+
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:15
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           -   ^^^^^^^^^^ not found in this scope
+   |           |
+   |           help: you might be missing a type parameter: `<NotDefined>`
+
+error[E0412]: cannot find type `N` in this scope
+  --> $DIR/issue-50480.rs:12:18
+   |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |            -     ^
+   |            |
+   |            similarly named type parameter `T` defined here
+   |
+help: a type parameter with a similar name exists
+   |
+LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                  ~
+help: you might be missing a type parameter
+   |
+LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |             +++
+
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:12:21
+   |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                     ^^^^^^^^^^ not found in this scope
 
 error[E0277]: `i32` is not an iterator
-  --> $DIR/issue-50480.rs:3:24
+  --> $DIR/issue-50480.rs:3:27
    |
-LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
@@ -25,14 +66,36 @@ error[E0204]: the trait `Copy` may not be implemented for this type
 LL | #[derive(Clone, Copy)]
    |                 ^^^^
 LL |
-LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                                                 --------  ------ this field does not implement `Copy`
-   |                                                 |
-   |                                                 this field does not implement `Copy`
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                                    --------  ------ this field does not implement `Copy`
+   |                                                    |
+   |                                                    this field does not implement `Copy`
+   |
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `i32` is not an iterator
+  --> $DIR/issue-50480.rs:12:33
+   |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `i32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/issue-50480.rs:10:17
+   |
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^
+LL |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                                          --------  ------ this field does not implement `Copy`
+   |                                                          |
+   |                                                          this field does not implement `Copy`
    |
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 4 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0204, E0277, E0412.
 For more information about an error, try `rustc --explain E0204`.
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();
+}
index 785d64ec8ea2210d5b995dd35da93d1eb807dab5..55c7ac128ffdecaa49b1d9f5d5b4b5843ab43008 100644 (file)
@@ -1,10 +1,10 @@
 // Regression test of #36638.
 
 struct Foo<Self>(Self);
-//~^ ERROR expected identifier, found keyword `Self`
-//~^^ ERROR E0392
+//~^ ERROR unexpected keyword `Self` in generic parameters
+//~| ERROR recursive type `Foo` has infinite size
 
 trait Bar<Self> {}
-//~^ ERROR expected identifier, found keyword `Self`
+//~^ ERROR unexpected keyword `Self` in generic parameters
 
 fn main() {}
index cc3df2e36f7f54ad413701d8bf281fad81f7a360..fd101b32b4c9c0c2e30c12fea48376c30de10de4 100644 (file)
@@ -1,24 +1,33 @@
-error: expected identifier, found keyword `Self`
+error: unexpected keyword `Self` in generic parameters
   --> $DIR/keyword-self-as-type-param.rs:3:12
    |
 LL | struct Foo<Self>(Self);
-   |            ^^^^ expected identifier, found keyword
+   |            ^^^^
+   |
+   = note: you cannot use `Self` as a generic parameter because it is reserved for associated items
 
-error: expected identifier, found keyword `Self`
+error: unexpected keyword `Self` in generic parameters
   --> $DIR/keyword-self-as-type-param.rs:7:11
    |
 LL | trait Bar<Self> {}
-   |           ^^^^ expected identifier, found keyword
+   |           ^^^^
+   |
+   = note: you cannot use `Self` as a generic parameter because it is reserved for associated items
 
-error[E0392]: parameter `Self` is never used
-  --> $DIR/keyword-self-as-type-param.rs:3:12
+error[E0072]: recursive type `Foo` has infinite size
+  --> $DIR/keyword-self-as-type-param.rs:3:1
    |
 LL | struct Foo<Self>(Self);
-   |            ^^^^ unused parameter
+   | ^^^^^^^^^^^^^^^^^----^^
+   | |                |
+   | |                recursive without indirection
+   | recursive type has infinite size
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
    |
-   = help: consider removing `Self`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `Self` to be a const parameter, use `const Self: usize` instead
+LL | struct Foo<Self>(Box<Self>);
+   |                  ++++    +
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0392`.
+For more information about this error, try `rustc --explain E0072`.
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 e18d725faefea722f2073e3230fb8fc935bcccf6..a208689523401ad3f5a6947174a518dbc3e86532 100644 (file)
@@ -11,9 +11,8 @@ LL |     a: &'b str,
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
    |
-LL | #[derive(Eq, PartialEq)]
-   |          -- lifetime `'b` is missing in item created through this procedural macro
 LL | struct Test {
+   |            - help: consider introducing lifetime `'b` here: `<'b>`
 LL |     a: &'b str,
    |         ^^ undeclared lifetime
    |
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 ce8c118dab2426de9ad8c22488234ad297bbe8e9..c5f477cc4500ee9de04640c8ccfe41668266b561 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Zfuture-incompat-test -Zemit-future-incompat-report
+// compile-flags: -Zfuture-incompat-test
 // check-pass
 
 // The `-Zfuture-incompat-test flag causes any normal warning to be included
index 68a076c93be614b0071e64e011bbee894f410401..4f81ee8b7e6bb59422b2849ace99552762492020 100644 (file)
@@ -11,4 +11,4 @@ extern crate std;
 
 macro_rules! foo { () => { break 'x ; } }
 
-pub fn main() { loop { } }
+pub fn main() { loop {} }
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 a5987a25551d224940e8ba08507eec32e042b564..a06487be3d601bfcc8f06ef6ace38bae47b19594 100644 (file)
@@ -2,7 +2,9 @@ error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:3:28
    |
 LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
-   |                            ^ not allowed after `pat` fragments
+   |                     ------ ^ not allowed after `pat` fragments
+   |                     |
+   |                     help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
    = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
 
@@ -10,7 +12,9 @@ error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32
    |
 LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
-   |                                ^ not allowed after `pat` fragments
+   |                       ------   ^ not allowed after `pat` fragments
+   |                       |
+   |                       help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
    = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
 
@@ -18,7 +22,9 @@ error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragmen
   --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36
    |
 LL |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
-   |                                    ^ not allowed after `pat` fragments
+   |                          --------  ^ not allowed after `pat` fragments
+   |                          |
+   |                          help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
    |
    = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
 
index 8aebe98515f4d3653cbd47248e3eb03eb8b1643f..c3754dde080a39e3fe1acaebf653752226c791ec 100644 (file)
@@ -2,7 +2,9 @@ error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat2021-pattern-followed-by-or.rs:4:28
    |
 LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
-   |                            ^ not allowed after `pat` fragments
+   |                     ------ ^ not allowed after `pat` fragments
+   |                     |
+   |                     help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
    = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
 
@@ -10,7 +12,9 @@ error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat2021-pattern-followed-by-or.rs:7:28
    |
 LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
-   |                            ^ not allowed after `pat` fragments
+   |                     ------ ^ not allowed after `pat` fragments
+   |                     |
+   |                     help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
    = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
 
@@ -18,7 +22,9 @@ error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragmen
   --> $DIR/macro-pat2021-pattern-followed-by-or.rs:9:35
    |
 LL |     ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => {
-   |                                   ^ not allowed after `pat` fragments
+   |                          -------- ^ not allowed after `pat` fragments
+   |                          |
+   |                          help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
    |
    = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
 
index 0ccdf6e5f2e74782688b98a08aa22b040bb04454..84fffe44d6a55a4d6a5b88ba0f7da7ebd6a1f9ac 100644 (file)
@@ -16,7 +16,7 @@
         struct S;
     }
 
-    n!(a $nt_item b); //~ ERROR no rules expected the token `enum E { }`
+    n!(a $nt_item b); //~ ERROR no rules expected the token `enum E {}`
 }
 
 simple_nonterminal!(a, 'a, (x, y, z)); // OK
index 155a94251312c7951a7c5febb1d78ac7ff04cbd3..585f2355321f5fac9da3a9ad0933e5d365519e25 100644 (file)
@@ -1,4 +1,4 @@
-error: no rules expected the token `enum E { }`
+error: no rules expected the token `enum E {}`
   --> $DIR/nonterminal-matching.rs:19:10
    |
 LL |     macro n(a $nt_item b) {
index 3e2bc5bc82d4206f76e9246e0d5c51cec6b8da5c..b8f2d88ab4957e9fb246700d708eab9f34528959 100644 (file)
@@ -994,8 +994,8 @@ error[E0308]: mismatched types
 LL |     foo::<f64>(x_usize);
    |                ^^^^^^^ expected `f64`, found `usize`
    |
-help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer,
-   |                                              rounded if necessary
+help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
+   |
 LL |     foo::<f64>(x_usize as f64);
    |                        ++++++
 
@@ -1005,8 +1005,8 @@ error[E0308]: mismatched types
 LL |     foo::<f64>(x_u64);
    |                ^^^^^ expected `f64`, found `u64`
    |
-help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer,
-   |                                              rounded if necessary
+help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
+   |
 LL |     foo::<f64>(x_u64 as f64);
    |                      ++++++
 
@@ -1115,8 +1115,8 @@ error[E0308]: mismatched types
 LL |     foo::<f32>(x_usize);
    |                ^^^^^^^ expected `f32`, found `usize`
    |
-help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer,
-   |                                              rounded if necessary
+help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
+   |
 LL |     foo::<f32>(x_usize as f32);
    |                        ++++++
 
@@ -1126,8 +1126,8 @@ error[E0308]: mismatched types
 LL |     foo::<f32>(x_u64);
    |                ^^^^^ expected `f32`, found `u64`
    |
-help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer,
-   |                                              rounded if necessary
+help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
+   |
 LL |     foo::<f32>(x_u64 as f32);
    |                      ++++++
 
@@ -1137,8 +1137,8 @@ error[E0308]: mismatched types
 LL |     foo::<f32>(x_u32);
    |                ^^^^^ expected `f32`, found `u32`
    |
-help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer,
-   |                                              rounded if necessary
+help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
+   |
 LL |     foo::<f32>(x_u32 as f32);
    |                      ++++++
 
index 7aedb09928b6491edbee6154fe3cd01eb1ce90e6..36549cbc554bfdd1a6b504989006afbb6c51750f 100644 (file)
@@ -1,10 +1,19 @@
 // build-pass
 // ignore-pass
 // no-system-llvm
-// revisions: all inline
-//          compile-flags: --crate-type=lib -Cdebuginfo=1 -Copt-level=2
+// 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
 
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`.
index eae169b162f4d6a9f3329316c16086901256c3f4..091862de30f7f032462c0e2d1f45c42080ceb0b5 100644 (file)
@@ -14,7 +14,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:49:20: 49:21 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -140,7 +140,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:61:28: 61:29 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar { }) ;
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "second_make_stmt",
@@ -201,7 +201,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:64:57: 64:58 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -257,7 +257,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
index fbefa3923ee22c1e2dcf88667b5d9b9844f4bae8..fc69a13ddb9b417f7dae9d356f1394d5c6e0e648 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-ATTR INPUT (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >> > () { }
+PRINT-ATTR INPUT (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >> > () {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
index edb9fbab342e21120623b83001530368056075f3..f9b2305c7359bb07bbcc0a85a2923527f2e0d7ee 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -124,7 +124,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-stmt-expr.rs:53:28: 53:29 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar { }) ;
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "second_make_stmt",
@@ -185,7 +185,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-stmt-expr.rs:56:57: 56:58 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -241,7 +241,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
index c5b84b0367c8fbdf1c5c501a2811a574e1a54988..1b17d60476a8445765dcbc0ec725e68f41a83444 100644 (file)
@@ -83,7 +83,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { }
+PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive {}
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -99,7 +99,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { }
+PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute {}
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
index 8dd2a5ac7866f29392ad5ef2abd28a26c71ef177..5f76a4484e1a425ffde371c0947dba4345b5b9e3 100644 (file)
@@ -15,7 +15,7 @@ pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream {
 
     let input = input.to_string();
 
-    assert_eq!(input, "fn foo() { }");
+    assert_eq!(input, "fn foo() {}");
 
     r#"
         fn foo() -> &'static str { "Hello, world!" }
index d89aaac59f6bd85d34b4d21d5d5fe0a8a08b2212..3787b8eeccc40b5151d895783db34c97fd1a77a3 100644 (file)
@@ -10,6 +10,6 @@
 #[proc_macro_attribute]
 pub fn foo(attr: TokenStream, item: TokenStream) -> TokenStream {
     drop(attr);
-    assert_eq!(item.to_string(), "fn foo() { }");
+    assert_eq!(item.to_string(), "fn foo() {}");
     "fn foo(&self);".parse().unwrap()
 }
index 714417deee5872b53b6b7025a4bf652a700e683f..3b7811748edfac37f58939cebc8c78a79a379705 100644 (file)
@@ -6,6 +6,7 @@
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro;
+use std::iter::FromIterator;
 use std::str::FromStr;
 use proc_macro::*;
 
@@ -23,7 +24,7 @@ pub fn custom_quote(input: TokenStream) -> TokenStream {
             let set_span_method = TokenStream::from_str("ident.set_span").unwrap();
             let set_span_arg = TokenStream::from(TokenTree::Group(Group::new(Delimiter::Parenthesis, quoted_span)));
             let suffix = TokenStream::from_str(";proc_macro::TokenStream::from(proc_macro::TokenTree::Ident(ident))").unwrap();
-            let full_stream: TokenStream = std::array::IntoIter::new([prefix, set_span_method, set_span_arg, suffix]).collect();
+            let full_stream = TokenStream::from_iter([prefix, set_span_method, set_span_arg, suffix]);
             full_stream
         }
         _ => unreachable!()
index 08ead5aaeee8489f02212c7d105593180cdc4d08..debbad57a86994f644431d00ced7a18e8cdaa068 100644 (file)
@@ -3,7 +3,7 @@ PRINT-ATTR INPUT (DISPLAY): impl Foo <
  {
      #! [rustc_dummy(cursed_inner)] #! [allow(unused)] struct Inner
      { field : [u8 ; { #! [rustc_dummy(another_cursed_inner)] 1 }] } 0
- }] > { #! [rustc_dummy(evaluated_attr)] fn bar() { } }
+ }] > { #! [rustc_dummy(evaluated_attr)] fn bar() {} }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "impl",
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 3ac1adf92c24f7dffe9447512f8cccdd161bce1f..dffbbf1494b9ae9d5ed9c1a04209e1f3369e0d74 100644 (file)
@@ -1,5 +1,5 @@
-Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo { }
-Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo { }
-Derive Third: #[derive(Fifth)] pub struct Foo { }
-Derive Fourth: #[derive(Fifth)] pub struct Foo { }
-Derive Fifth: pub struct Foo { }
+Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {}
+Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {}
+Derive Third: #[derive(Fifth)] pub struct Foo {}
+Derive Fourth: #[derive(Fifth)] pub struct Foo {}
+Derive Fifth: pub struct Foo {}
index e37a483cb87bc0335194cbc6968e6671d558360a..686d53e8876608a322b87badfbd6f4cd5b0b580f 100644 (file)
@@ -202,7 +202,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #8 bytes(430..483),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { { } } ; 0 }, }
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "enum",
index 9b7865be6220ea075a6ceb7d80bced193c59a5aa..eaa8882d6a6cb6d60365cba92c941b67791ce09c 100644 (file)
@@ -269,7 +269,7 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:20:30: 20:36 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): fn foo() { }
+PRINT-ATTR INPUT (DISPLAY): fn foo() {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
@@ -552,7 +552,7 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:27:30: 27:40 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): mod inline_mod { }
+PRINT-ATTR INPUT (DISPLAY): mod inline_mod {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "mod",
@@ -933,7 +933,7 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:82:42: 82:47 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): fn weird_extern() { }
+PRINT-ATTR INPUT (DISPLAY): fn weird_extern() {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
index 866608e4d8e1d0a1aa5be7855fed1b6ec311c14c..44baa37577cfa25facbf015750f4abe8520638ae 100644 (file)
@@ -53,7 +53,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: #4 bytes(432..433),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): struct A { }
+PRINT-DERIVE INPUT (DISPLAY): struct A {}
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
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
 
index ea03653c52f833f6e785daf8107093f34c477e32..0fda6654ff37051f9a4c3c18d72256ee430fb547 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-ATTR INPUT (DISPLAY): fn main() { & | _ : u8 | { } ; mul_2! (1 + 1) ; }
+PRINT-ATTR INPUT (DISPLAY): fn main() { & | _ : u8 | {} ; mul_2! (1 + 1) ; }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
index 81b2b219c436815f7f3299b6bfd18a5d3c8a1df8..fdd178a52292f5d27df6d410295c6b3e54e5b5f4 100644 (file)
@@ -8,8 +8,8 @@ struct Foo < #[cfg(FALSE)] A, B >
          #[cfg(FALSE)] struct Bar ; #[cfg(not(FALSE))] struct Inner ;
          #[cfg(FALSE)] let a = 25 ; match true
          {
-             #[cfg(FALSE)] true => { },
-             #[cfg_attr(not(FALSE), allow(warnings))] false => { }, _ => { }
+             #[cfg(FALSE)] true => {},
+             #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {}
          } ; #[print_helper(should_be_removed)] fn removed_fn()
          { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn
          kept_fn() { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum
@@ -1278,7 +1278,7 @@ PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_hel
     [u8 ;
      {
          #[cfg(not(FALSE))] struct Inner ; match true
-         { #[allow(warnings)] false => { }, _ => { } } ; #[print_helper(c)]
+         { #[allow(warnings)] false => {}, _ => {} } ; #[print_helper(c)]
          #[cfg(not(FALSE))] fn kept_fn()
          { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum
          { Foo(#[cfg(not(FALSE))] i32, u8) } struct
index 6f880a120217002560b131b202a6b9068f006997..3c001e9954b5e440eed0175e791d2761e01cc2ad 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-ATTR INPUT (DISPLAY): #[doc = r" A doc comment"] struct Foo { }
+PRINT-ATTR INPUT (DISPLAY): #[doc = r" A doc comment"] struct Foo {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -40,7 +40,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/issue-81007-item-attrs.rs:22:16: 22:18 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[doc = r" Another comment comment"] struct Bar { }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[doc = r" Another comment comment"] struct Bar {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
index 8292617fc1675687a360a71b3ee0fff04a7ba3f1..68f30c23a8d284c57cea13612137d995dbcdb154 100644 (file)
@@ -11,7 +11,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#6),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct { }
+PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -46,7 +46,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#15),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct { }
+PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
index 709b2a2169e08d8f9033ba28e706f17f06756acc..c08e5308138c966deb834cceb151ad98e058099f 100644 (file)
@@ -64,7 +64,7 @@ macro inner /* 0#4 */ { () => { print_bang! { struct S; } } }
 struct S /* 0#5 */;
 // OK, not a duplicate definition of `S`
 
-fn main /* 0#0 */() { }
+fn main /* 0#0 */() {}
 
 /*
 Expansions:
index d60f400af2bb9c06839d35949056310cdf262a81..b90057cd6d5201819b7a03a231e5427ad18b385a 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + { }
+PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
index dc35df1159f883dc8a8feca4a3616b716c71df42..9bf5622173458b22660df683ba00d4fdf65ecd7d 100644 (file)
@@ -445,7 +445,7 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/weird-braces.rs:20:30: 20:42 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > { }
+PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "impl",
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 dad3641f0f5af87b125456ded6023cceaf40434e..aaf3993538acf1c7fecd52ab8d6ba76c76a0e79e 100644 (file)
@@ -13,7 +13,6 @@ extern crate std;
 // [pretty]compile-flags: -Zunpretty=everybody_loops
 // [pretty]check-pass
 #[repr("C")]
-struct A {
-}
+struct A {}
 
-fn main() { loop { } }
+fn main() { loop {} }
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);
+}
index aeee43b01cc021d62666b1e60c94b746b04f587d..6052ea95d0f85fe37666e2688ad1082b5f0ecb44 100644 (file)
@@ -7,4 +7,4 @@ extern crate std;
 // build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z unpretty=expanded
 
-fn main() { if let 0 = 1 { } }
+fn main() { if let 0 = 1 {} }
index 2a172c8458d71462493c1cb4a7b26d03c3e231b2..8800d3e66f9e42909fba8c00c93f17eafbb6d944 100644 (file)
@@ -18,14 +18,14 @@ pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream {
 }
 
 checker!(attr_extern, r#"extern "C" { fn ffi(#[a1] arg1 : i32, #[a2] ...) ; }"#);
-checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1 : i32, #[a1] mut args : ...) { }"#);
+checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1 : i32, #[a1] mut args : ...) {}"#);
 checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...) ;");
 checker!(attr_free, "fn free(#[a1] arg1 : u8) { let lam = | #[a2] W(x), #[a3] y | () ; }");
-checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1 : u8) { }");
-checker!(attr_inherent_2, "fn inherent2(#[a1] & self, #[a2] arg1 : u8) { }");
-checker!(attr_inherent_3, "fn inherent3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) { }");
-checker!(attr_inherent_4, "fn inherent4 < 'a > (#[a1] self : Box < Self >, #[a2] arg1 : u8) { }");
-checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) { }");
+checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1 : u8) {}");
+checker!(attr_inherent_2, "fn inherent2(#[a1] & self, #[a2] arg1 : u8) {}");
+checker!(attr_inherent_3, "fn inherent3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) {}");
+checker!(attr_inherent_4, "fn inherent4 < 'a > (#[a1] self : Box < Self >, #[a2] arg1 : u8) {}");
+checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) {}");
 checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1 : u8) ;");
 checker!(attr_trait_2, "fn trait2(#[a1] & self, #[a2] arg1 : u8) ;");
 checker!(attr_trait_3, "fn trait3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) ;");
@@ -35,9 +35,9 @@ pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream {
 checker!(rename_params, r#"impl Foo
 {
     fn hello(#[angery(true)] a : i32, #[a2] b : i32, #[what = "how"] c : u32)
-    { } fn
+    {} fn
     hello2(#[a1] #[a2] a : i32, #[what = "how"] b : i32, #[angery(true)] c :
-           u32) { } fn
+           u32) {} fn
     hello_self(#[a1] #[a2] & self, #[a1] #[a2] a : i32, #[what = "how"] b :
-               i32, #[angery(true)] c : u32) { }
+               i32, #[angery(true)] c : u32) {}
 }"#);
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 840c12e16e1c8dfbb692f3647d0a9eecb21861cd..935bfa001bfc6135d16ccc49525c55da0a55ea2f 100644 (file)
@@ -1,5 +1,6 @@
 #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
 //~^ ERROR cannot determine resolution for the attribute macro `derive`
+//~^^ ERROR `derive` attribute cannot be used at crate level
 struct DerivedOn;
 
 fn main() {}
index 9ef81c5150a45011bb71c8aee941f02185523450..e3ae37e368937997a54090390628b6dbdab97723 100644 (file)
@@ -6,5 +6,16 @@ LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to previous error
+error: `derive` attribute cannot be used at crate level
+  --> $DIR/issue-43927-non-ADT-derive.rs:1:1
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
 
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
    |
diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.rs b/src/test/ui/suggestions/derive-macro-missing-bounds.rs
new file mode 100644 (file)
index 0000000..56c218f
--- /dev/null
@@ -0,0 +1,89 @@
+mod a {
+    use std::fmt::{Debug, Formatter, Result};
+    struct Inner<T>(T);
+
+    impl Debug for Inner<()> {
+        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+            todo!()
+        }
+    }
+
+    #[derive(Debug)]
+    struct Outer<T>(Inner<T>); //~ ERROR `a::Inner<T>` doesn't implement `Debug`
+}
+
+mod b {
+    use std::fmt::{Debug, Formatter, Result};
+    struct Inner<T>(T);
+
+    impl<T: Debug> Debug for Inner<T> {
+        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+            todo!()
+        }
+    }
+
+    #[derive(Debug)]
+    struct Outer<T>(Inner<T>);
+}
+
+mod c {
+    use std::fmt::{Debug, Formatter, Result};
+    struct Inner<T>(T);
+    trait Trait {}
+
+    impl<T: Debug + Trait> Debug for Inner<T> {
+        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+            todo!()
+        }
+    }
+
+    #[derive(Debug)]
+    struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: c::Trait` is not satisfied
+}
+
+mod d {
+    use std::fmt::{Debug, Formatter, Result};
+    struct Inner<T>(T);
+    trait Trait {}
+
+    impl<T> Debug for Inner<T> where T: Debug, T: Trait {
+        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+            todo!()
+        }
+    }
+
+    #[derive(Debug)]
+    struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: d::Trait` is not satisfied
+}
+
+mod e {
+    use std::fmt::{Debug, Formatter, Result};
+    struct Inner<T>(T);
+    trait Trait {}
+
+    impl<T> Debug for Inner<T> where T: Debug + Trait {
+        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+            todo!()
+        }
+    }
+
+    #[derive(Debug)]
+    struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: e::Trait` is not satisfied
+}
+
+mod f {
+    use std::fmt::{Debug, Formatter, Result};
+    struct Inner<T>(T);
+    trait Trait {}
+
+    impl<T: Debug> Debug for Inner<T> where T: Trait {
+        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+            todo!()
+        }
+    }
+
+    #[derive(Debug)]
+    struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: f::Trait` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr
new file mode 100644 (file)
index 0000000..7a4f7e2
--- /dev/null
@@ -0,0 +1,107 @@
+error[E0277]: `a::Inner<T>` doesn't implement `Debug`
+  --> $DIR/derive-macro-missing-bounds.rs:12:21
+   |
+LL |     #[derive(Debug)]
+   |              ----- in this derive macro expansion
+LL |     struct Outer<T>(Inner<T>);
+   |                     ^^^^^^^^ `a::Inner<T>` cannot be formatted using `{:?}`
+   |
+   = help: the trait `Debug` is not implemented for `a::Inner<T>`
+   = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>`
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
+   |
+LL |     struct Outer<T>(Inner<T>) where a::Inner<T>: Debug;
+   |                               ++++++++++++++++++++++++
+
+error[E0277]: the trait bound `T: c::Trait` is not satisfied
+  --> $DIR/derive-macro-missing-bounds.rs:41:21
+   |
+LL |     #[derive(Debug)]
+   |              ----- in this derive macro expansion
+LL |     struct Outer<T>(Inner<T>);
+   |                     ^^^^^^^^ the trait `c::Trait` is not implemented for `T`
+   |
+note: required because of the requirements on the impl of `Debug` for `c::Inner<T>`
+  --> $DIR/derive-macro-missing-bounds.rs:34:28
+   |
+LL |     impl<T: Debug + Trait> Debug for Inner<T> {
+   |                            ^^^^^     ^^^^^^^^
+   = note: 1 redundant requirement hidden
+   = note: required because of the requirements on the impl of `Debug` for `&c::Inner<T>`
+   = note: required for the cast to the object type `dyn Debug`
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+LL |     struct Outer<T: c::Trait>(Inner<T>);
+   |                   ++++++++++
+
+error[E0277]: the trait bound `T: d::Trait` is not satisfied
+  --> $DIR/derive-macro-missing-bounds.rs:56:21
+   |
+LL |     #[derive(Debug)]
+   |              ----- in this derive macro expansion
+LL |     struct Outer<T>(Inner<T>);
+   |                     ^^^^^^^^ the trait `d::Trait` is not implemented for `T`
+   |
+note: required because of the requirements on the impl of `Debug` for `d::Inner<T>`
+  --> $DIR/derive-macro-missing-bounds.rs:49:13
+   |
+LL |     impl<T> Debug for Inner<T> where T: Debug, T: Trait {
+   |             ^^^^^     ^^^^^^^^
+   = note: 1 redundant requirement hidden
+   = note: required because of the requirements on the impl of `Debug` for `&d::Inner<T>`
+   = note: required for the cast to the object type `dyn Debug`
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+LL |     struct Outer<T: d::Trait>(Inner<T>);
+   |                   ++++++++++
+
+error[E0277]: the trait bound `T: e::Trait` is not satisfied
+  --> $DIR/derive-macro-missing-bounds.rs:71:21
+   |
+LL |     #[derive(Debug)]
+   |              ----- in this derive macro expansion
+LL |     struct Outer<T>(Inner<T>);
+   |                     ^^^^^^^^ the trait `e::Trait` is not implemented for `T`
+   |
+note: required because of the requirements on the impl of `Debug` for `e::Inner<T>`
+  --> $DIR/derive-macro-missing-bounds.rs:64:13
+   |
+LL |     impl<T> Debug for Inner<T> where T: Debug + Trait {
+   |             ^^^^^     ^^^^^^^^
+   = note: 1 redundant requirement hidden
+   = note: required because of the requirements on the impl of `Debug` for `&e::Inner<T>`
+   = note: required for the cast to the object type `dyn Debug`
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+LL |     struct Outer<T: e::Trait>(Inner<T>);
+   |                   ++++++++++
+
+error[E0277]: the trait bound `T: f::Trait` is not satisfied
+  --> $DIR/derive-macro-missing-bounds.rs:86:21
+   |
+LL |     #[derive(Debug)]
+   |              ----- in this derive macro expansion
+LL |     struct Outer<T>(Inner<T>);
+   |                     ^^^^^^^^ the trait `f::Trait` is not implemented for `T`
+   |
+note: required because of the requirements on the impl of `Debug` for `f::Inner<T>`
+  --> $DIR/derive-macro-missing-bounds.rs:79:20
+   |
+LL |     impl<T: Debug> Debug for Inner<T> where T: Trait {
+   |                    ^^^^^     ^^^^^^^^
+   = note: 1 redundant requirement hidden
+   = note: required because of the requirements on the impl of `Debug` for `&f::Inner<T>`
+   = note: required for the cast to the object type `dyn Debug`
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+LL |     struct Outer<T: f::Trait>(Inner<T>);
+   |                   ++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
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
+
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`.
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/typeck/issue-91450-inner-ty-error.rs b/src/test/ui/typeck/issue-91450-inner-ty-error.rs
new file mode 100644 (file)
index 0000000..0b942d6
--- /dev/null
@@ -0,0 +1,7 @@
+// Regression test for #91450.
+// This test ensures that the compiler does not suggest `Foo<[type error]>` in diagnostic messages.
+
+fn foo() -> Option<_> {} //~ ERROR: [E0308]
+//~^ ERROR: the type placeholder `_` is not allowed
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91450-inner-ty-error.stderr b/src/test/ui/typeck/issue-91450-inner-ty-error.stderr
new file mode 100644 (file)
index 0000000..314fe56
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-91450-inner-ty-error.rs:4:13
+   |
+LL | fn foo() -> Option<_> {}
+   |    ---      ^^^^^^^^^ expected enum `Option`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+   = note:   expected enum `Option<_>`
+           found unit type `()`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/issue-91450-inner-ty-error.rs:4:20
+   |
+LL | fn foo() -> Option<_> {}
+   |                    ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0121, E0308.
+For more information about an error, try `rustc --explain E0121`.
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 7f08ace4f1305de7f3b1b0e2f765911957226bd4..294967c53f0c70d598fc54ca189313c86c576ea7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7f08ace4f1305de7f3b1b0e2f765911957226bd4
+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 7142df98c3f10fde54afa98e822067dd468532f2..48e459e016592b49b1a467b87f365f7ca4628d95 100644 (file)
@@ -13,7 +13,6 @@
     remove_blocks, strip_pat_refs,
 };
 use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash};
-use core::array;
 use core::iter::{once, ExactSizeIterator};
 use if_chain::if_chain;
 use rustc_ast::ast::{Attribute, LitKind};
@@ -1306,7 +1305,7 @@ fn check_match_like_matches<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)
         return find_matches_sugg(
             cx,
             let_expr,
-            array::IntoIter::new([(&[][..], Some(let_pat), if_then, None), (&[][..], None, if_else, None)]),
+            IntoIterator::into_iter([(&[][..], Some(let_pat), if_then, None), (&[][..], None, if_else, None)]),
             expr,
             true,
         );
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 f7711b6fe947654b6de39254a0f3cc87f3f80717..0eba6633ee19b36650bd3ee15b863fa43dba4661 100644 (file)
@@ -15,7 +15,7 @@
     Mutability,
 };
 use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt};
-use rustc_mir_dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
+use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis, ResultsCursor};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::sym;
@@ -499,11 +499,9 @@ fn terminator_effect(
 
     fn call_return_effect(
         &self,
-        _in_out: &mut impl GenKill<Self::Idx>,
+        _trans: &mut impl GenKill<Self::Idx>,
         _block: mir::BasicBlock,
-        _func: &mir::Operand<'tcx>,
-        _args: &[mir::Operand<'tcx>],
-        _return_place: mir::Place<'tcx>,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         // Nothing to do when a call returns successfully
     }
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 3c85b9076dd1af977591fc0fcbdcd6d54a3fbf01..3ccd4a1cc599a9a867d10964e11c5b5e640d0fc4 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);
 
@@ -1800,6 +1802,7 @@ fn make_compile_args(
                 // patterns still match the raw compiler output.
                 if self.props.error_patterns.is_empty() {
                     rustc.args(&["--error-format", "json"]);
+                    rustc.args(&["--json", "future-incompat"]);
                 }
                 rustc.arg("-Zui-testing");
                 rustc.arg("-Zdeduplicate-diagnostics=no");
@@ -1807,11 +1810,11 @@ fn make_compile_args(
             Ui => {
                 if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) {
                     rustc.args(&["--error-format", "json"]);
+                    rustc.args(&["--json", "future-incompat"]);
                 }
                 rustc.arg("-Ccodegen-units=1");
                 rustc.arg("-Zui-testing");
                 rustc.arg("-Zdeduplicate-diagnostics=no");
-                rustc.arg("-Zemit-future-incompat-report");
             }
             MirOpt => {
                 rustc.args(&[
@@ -2217,12 +2220,12 @@ fn run_rustdoc_test(&self) {
             self.check_rustdoc_test_option(proc_res);
         } else {
             let root = self.config.find_rust_src_root().unwrap();
-            let res = self.cmd2procres(
-                Command::new(&self.config.docck_python)
-                    .arg(root.join("src/etc/htmldocck.py"))
-                    .arg(&out_dir)
-                    .arg(&self.testpaths.file),
-            );
+            let mut cmd = Command::new(&self.config.docck_python);
+            cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
+            if self.config.bless {
+                cmd.arg("--bless");
+            }
+            let res = self.cmd2procres(&mut cmd);
             if !res.status.success() {
                 self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| {
                     this.compare_to_default_rustdoc(&out_dir)
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 acc91f861e474df3f36879b9e71277246cc04495..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,
 }
@@ -3173,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;