]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #87354 - Wind-River:2021_master, r=kennytm
authorYuki Okushi <jtitor@2k36.org>
Tue, 27 Jul 2021 10:52:42 +0000 (19:52 +0900)
committerGitHub <noreply@github.com>
Tue, 27 Jul 2021 10:52:42 +0000 (19:52 +0900)
Update VxWork's UNIX support

1. VxWorks does not provide glibc
2. VxWorks does provide `sigemptyset` and `sigaddset`

Note: these changes are concurrent to [this PR](https://github.com/rust-lang/libc/pull/2295) in libc.

567 files changed:
.mailmap
Cargo.lock
Cargo.toml
RELEASES.md
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_data_structures/src/profiling.rs
compiler/rustc_data_structures/src/sorted_map/index_map.rs
compiler/rustc_data_structures/src/sorted_map/tests.rs
compiler/rustc_data_structures/src/vec_map.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_feature/src/accepted.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_hir/src/arena.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint_defs/src/lib.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/hir/map/collector.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/hir/mod.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/limits.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/assoc.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/vtable.rs
compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
compiler/rustc_mir/src/borrow_check/type_check/mod.rs
compiler/rustc_mir/src/interpret/memory.rs
compiler/rustc_mir/src/lib.rs
compiler/rustc_mir/src/monomorphize/collector.rs
compiler/rustc_mir/src/transform/check_consts/check.rs [new file with mode: 0644]
compiler/rustc_mir/src/transform/check_consts/mod.rs
compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs
compiler/rustc_mir/src/transform/check_consts/validation.rs [deleted file]
compiler/rustc_mir/src/transform/mod.rs
compiler/rustc_mir/src/transform/separate_const_switch.rs [new file with mode: 0644]
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/pattern/check_match.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/diagnostic_items.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_query_impl/src/keys.rs
compiler/rustc_query_system/src/dep_graph/graph.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/spec/freebsd_base.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/lib.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
compiler/rustc_typeck/src/hir_wf_check.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/mod.rs
config.toml.example
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/map/tests.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/btree/set/tests.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/vec_deque/drain.rs
library/alloc/src/collections/vec_deque/into_iter.rs
library/alloc/src/collections/vec_deque/macros.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/collections/vec_deque/pair_slices.rs
library/alloc/src/lib.rs
library/alloc/src/vec/mod.rs
library/alloc/tests/str.rs
library/core/src/alloc/global.rs
library/core/src/array/iter.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/macros/mod.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/str/pattern.rs
library/std/src/collections/hash/map.rs
library/std/src/collections/hash/map/tests.rs
library/std/src/collections/hash/set.rs
library/std/src/collections/hash/set/tests.rs
library/std/src/env.rs
library/std/src/io/buffered/bufwriter.rs
library/std/src/io/buffered/mod.rs
library/std/src/os/unix/mod.rs
library/std/src/os/unix/net/stream.rs
library/std/src/os/unix/ucred.rs
library/std/src/sys/unix/thread.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/flags.rs
src/bootstrap/job.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/doc/rustc/src/platform-support.md
src/doc/unstable-book/src/compiler-flags/force-warn.md [new file with mode: 0644]
src/doc/unstable-book/src/compiler-flags/force-warns.md [deleted file]
src/doc/unstable-book/src/compiler-flags/move-size-limit.md [new file with mode: 0644]
src/etc/pre-commit.sh [changed mode: 0755->0644]
src/librustdoc/clean/types.rs
src/librustdoc/config.rs
src/librustdoc/doctest.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/markdown/tests.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/html/static/js/main.js
src/librustdoc/html/static/js/storage.js
src/librustdoc/html/templates/page.html
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/visit_ast.rs
src/test/codegen/pgo-instrumentation.rs
src/test/debuginfo/pretty-std.rs
src/test/mir-opt/separate_const_switch.identity.ConstProp.diff [new file with mode: 0644]
src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff [new file with mode: 0644]
src/test/mir-opt/separate_const_switch.rs [new file with mode: 0644]
src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff [new file with mode: 0644]
src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff [new file with mode: 0644]
src/test/pretty/block-comment-wchar.pp
src/test/pretty/block-comment-wchar.rs
src/test/run-make-fulldeps/pgo-branch-weights/Makefile
src/test/run-make-fulldeps/pgo-gen-lto/Makefile
src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
src/test/run-make-fulldeps/pgo-gen/Makefile
src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile
src/test/run-make-fulldeps/pgo-use/Makefile
src/test/run-make-fulldeps/pretty-expanded/Makefile
src/test/run-make-fulldeps/pretty-print-to-file/Makefile
src/test/run-make/unstable-flag-required/Makefile
src/test/run-make/unstable-flag-required/force-warn.stderr [new file with mode: 0644]
src/test/run-make/unstable-flag-required/force-warns.stderr [deleted file]
src/test/rustdoc-gui/default-settings.goml [new file with mode: 0644]
src/test/rustdoc-gui/font-weight.goml
src/test/rustdoc-gui/implementors.goml
src/test/rustdoc-gui/item-summary-table.goml [new file with mode: 0644]
src/test/rustdoc-gui/module-items-font.goml [new file with mode: 0644]
src/test/rustdoc-gui/src/Cargo.lock [deleted file]
src/test/rustdoc-gui/src/Cargo.toml [deleted file]
src/test/rustdoc-gui/src/implementors/Cargo.toml [deleted file]
src/test/rustdoc-gui/src/implementors/lib.rs [deleted file]
src/test/rustdoc-gui/src/lib2/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/Cargo.toml
src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/implementors/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/lib.rs
src/test/rustdoc-gui/src/settings/.cargo/config.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/settings/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/src/test_docs/Cargo.lock [new file with mode: 0644]
src/test/rustdoc/assoc-consts.rs
src/test/rustdoc/assoc-types.rs
src/test/rustdoc/async-fn.rs
src/test/rustdoc/blanket-reexport-item.rs
src/test/rustdoc/const-display.rs
src/test/rustdoc/const-generics/add-impl.rs
src/test/rustdoc/const-generics/const-generics-docs.rs
src/test/rustdoc/const-generics/const-impl.rs
src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
src/test/rustdoc/const.rs
src/test/rustdoc/default-theme.rs [new file with mode: 0644]
src/test/rustdoc/duplicate_impls/issue-33054.rs
src/test/rustdoc/extern-impl-trait.rs
src/test/rustdoc/extern-impl.rs
src/test/rustdoc/extern-method.rs
src/test/rustdoc/generic-impl.rs
src/test/rustdoc/higher-ranked-trait-bounds.rs
src/test/rustdoc/impl-disambiguation.rs
src/test/rustdoc/impl-parts.rs
src/test/rustdoc/inline_cross/impl_trait.rs
src/test/rustdoc/inline_cross/issue-31948-1.rs
src/test/rustdoc/inline_cross/issue-31948-2.rs
src/test/rustdoc/inline_cross/issue-31948.rs
src/test/rustdoc/inline_cross/issue-32881.rs
src/test/rustdoc/inline_cross/issue-33113.rs
src/test/rustdoc/inline_cross/trait-vis.rs
src/test/rustdoc/inline_local/trait-vis.rs
src/test/rustdoc/issue-19190.rs
src/test/rustdoc/issue-25001.rs
src/test/rustdoc/issue-27362.rs
src/test/rustdoc/issue-29503.rs
src/test/rustdoc/issue-33592.rs
src/test/rustdoc/issue-35169-2.rs
src/test/rustdoc/issue-35169.rs
src/test/rustdoc/issue-46727.rs
src/test/rustdoc/issue-50159.rs
src/test/rustdoc/issue-51236.rs
src/test/rustdoc/issue-53689.rs
src/test/rustdoc/issue-54705.rs
src/test/rustdoc/issue-55321.rs
src/test/rustdoc/issue-56822.rs
src/test/rustdoc/issue-60726.rs
src/test/rustdoc/issue-75588.rs
src/test/rustdoc/issue-80233-normalize-auto-trait.rs
src/test/rustdoc/issue-82465-asref-for-and-of-local.rs
src/test/rustdoc/negative-impl.rs
src/test/rustdoc/primitive-generic-impl.rs
src/test/rustdoc/recursive-deref.rs
src/test/rustdoc/sidebar-links-to-foreign-impl.rs
src/test/rustdoc/sized_trait.rs
src/test/rustdoc/src-links-auto-impls.rs
src/test/rustdoc/synthetic_auto/basic.rs
src/test/rustdoc/synthetic_auto/complex.rs
src/test/rustdoc/synthetic_auto/crate-local.rs
src/test/rustdoc/synthetic_auto/lifetimes.rs
src/test/rustdoc/synthetic_auto/manual.rs
src/test/rustdoc/synthetic_auto/negative.rs
src/test/rustdoc/synthetic_auto/nested.rs
src/test/rustdoc/synthetic_auto/no-redundancy.rs
src/test/rustdoc/synthetic_auto/overflow.rs
src/test/rustdoc/synthetic_auto/project.rs
src/test/rustdoc/synthetic_auto/self-referential.rs
src/test/rustdoc/synthetic_auto/static-region.rs
src/test/rustdoc/toggle-item-contents.rs
src/test/rustdoc/toggle-method.rs
src/test/rustdoc/toggle-trait-fn.rs
src/test/rustdoc/trait-impl.rs
src/test/rustdoc/traits-in-bodies.rs
src/test/rustdoc/typedef.rs
src/test/rustdoc/visibility.rs
src/test/rustdoc/where.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
src/test/ui/associated-item/issue-48027.stderr
src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
src/test/ui/associated-types/hr-associated-type-projection-1.rs
src/test/ui/associated-types/hr-associated-type-projection-1.stderr
src/test/ui/associated-types/issue-87261.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-87261.stderr [new file with mode: 0644]
src/test/ui/async-await/issue-86507.rs [new file with mode: 0644]
src/test/ui/async-await/issue-86507.stderr [new file with mode: 0644]
src/test/ui/async-await/large_moves.attribute.stderr [new file with mode: 0644]
src/test/ui/async-await/large_moves.option.stderr [new file with mode: 0644]
src/test/ui/async-await/large_moves.rs
src/test/ui/async-await/large_moves.stderr [deleted file]
src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
src/test/ui/bastion-of-the-turbofish.rs
src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
src/test/ui/borrowck/borrowck-assign-to-subfield.rs
src/test/ui/borrowck/issue-85765.rs
src/test/ui/borrowck/issue-85765.stderr
src/test/ui/closures/2229_closure_analysis/issue-87378.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/issue-87378.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs [new file with mode: 0644]
src/test/ui/closures/issue-41366.stderr
src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
src/test/ui/const-generics/auxiliary/impl-const.rs [deleted file]
src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr
src/test/ui/const-generics/defaults/cec-concrete-default.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/cec-concrete-default.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/cec-generic-default.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/cec-generic-default.stderr [new file with mode: 0644]
src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr [deleted file]
src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr [deleted file]
src/test/ui/const-generics/issue-61522-array-len-succ.rs [deleted file]
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr [deleted file]
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs [deleted file]
src/test/ui/const-generics/issue-67375.full.stderr [deleted file]
src/test/ui/const-generics/issue-67375.min.stderr [deleted file]
src/test/ui/const-generics/issue-67375.rs [deleted file]
src/test/ui/const-generics/issue-67945-1.full.stderr [deleted file]
src/test/ui/const-generics/issue-67945-1.min.stderr [deleted file]
src/test/ui/const-generics/issue-67945-1.rs [deleted file]
src/test/ui/const-generics/issue-67945-2.full.stderr [deleted file]
src/test/ui/const-generics/issue-67945-2.min.stderr [deleted file]
src/test/ui/const-generics/issue-67945-2.rs [deleted file]
src/test/ui/const-generics/issue-67945-3.full.stderr [deleted file]
src/test/ui/const-generics/issue-67945-3.min.stderr [deleted file]
src/test/ui/const-generics/issue-67945-3.rs [deleted file]
src/test/ui/const-generics/issue-68104-print-stack-overflow.rs [deleted file]
src/test/ui/const-generics/issue-70180-1-stalled_on.rs [deleted file]
src/test/ui/const-generics/issue-70180-2-stalled_on.rs [deleted file]
src/test/ui/const-generics/issue-71202.rs [deleted file]
src/test/ui/const-generics/issue-71986.rs [deleted file]
src/test/ui/const-generics/issue-73899.rs [deleted file]
src/test/ui/const-generics/issue-74906.rs [deleted file]
src/test/ui/const-generics/issue-75763.rs [deleted file]
src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs [deleted file]
src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr [deleted file]
src/test/ui/const-generics/issue-80561-incorrect-param-env.rs [deleted file]
src/test/ui/const-generics/issue-86820.rs [deleted file]
src/test/ui/const-generics/issue-86820.stderr [deleted file]
src/test/ui/const-generics/issues/auxiliary/impl-const.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-1.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-1.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-1.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-2.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-2.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-2.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-3.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-3.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67945-3.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-71202.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-71986.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-73899.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-74906.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-75763.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86820.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86820.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-87076.rs [new file with mode: 0644]
src/test/ui/crate-loading/missing-std.rs
src/test/ui/crate-loading/missing-std.stderr
src/test/ui/dep-graph/dep-graph-struct-signature.stderr
src/test/ui/dep-graph/dep-graph-type-alias.stderr
src/test/ui/drop/dynamic-drop.rs
src/test/ui/error-codes/E0038.stderr
src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
src/test/ui/generic-associated-types/gat-in-trait-path.stderr
src/test/ui/generic-associated-types/issue-67510-pass.stderr
src/test/ui/generic-associated-types/issue-81487.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/trait-objects.stderr
src/test/ui/impl-trait/auto-trait-leak.rs
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/issue-86465.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-86465.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54600.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54600.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54840.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-54840.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58504.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58504.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58956.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-58956.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-70971.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-70971.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-79099.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-79099.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-84919.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-84919.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86201.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86201.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86642.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-86642.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-87295.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-87295.stderr [new file with mode: 0644]
src/test/ui/issues/issue-18611.stderr
src/test/ui/issues/issue-18959.stderr
src/test/ui/issues/issue-19380.stderr
src/test/ui/issues/issue-20413.stderr
src/test/ui/issues/issue-37131.stderr
src/test/ui/issues/issue-43623.stderr
src/test/ui/issues/issue-49851/compiler-builtins-error.stderr
src/test/ui/issues/issue-60283.stderr
src/test/ui/issues/issue-86756.rs [new file with mode: 0644]
src/test/ui/issues/issue-86756.stderr [new file with mode: 0644]
src/test/ui/issues/issue-87199.rs [new file with mode: 0644]
src/test/ui/issues/issue-87199.stderr [new file with mode: 0644]
src/test/ui/lint/cli-lint-override.force_warn_deny.stderr
src/test/ui/lint/cli-lint-override.rs
src/test/ui/lint/cli-unknown-force-warn.rs
src/test/ui/lint/cli-unknown-force-warn.stderr
src/test/ui/lint/dead-code/self-assign.rs
src/test/ui/lint/dead-code/write-only-field.rs [deleted file]
src/test/ui/lint/dead-code/write-only-field.stderr [deleted file]
src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs
src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr
src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs
src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr
src/test/ui/lint/force-warn/force-allowed-warning.rs
src/test/ui/lint/force-warn/force-allowed-warning.stderr
src/test/ui/lint/force-warn/force-deny-by-default-lint.rs
src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr
src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs
src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr
src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs
src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr
src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs
src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr
src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs
src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr
src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs
src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr
src/test/ui/lint/force-warn/force-warn-group.rs
src/test/ui/lint/force-warn/force-warn-group.stderr
src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs [deleted file]
src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr [deleted file]
src/test/ui/lint/inert-attr-macro.rs [new file with mode: 0644]
src/test/ui/lint/inert-attr-macro.stderr [new file with mode: 0644]
src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr
src/test/ui/parser/issue-87197-missing-semicolon.fixed [new file with mode: 0644]
src/test/ui/parser/issue-87197-missing-semicolon.rs [new file with mode: 0644]
src/test/ui/parser/issue-87197-missing-semicolon.stderr [new file with mode: 0644]
src/test/ui/parser/macros-no-semicolon.rs
src/test/ui/parser/macros-no-semicolon.stderr
src/test/ui/pattern/bindings-after-at/bind-by-copy.rs
src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs
src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs
src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr
src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
src/test/ui/pattern/bindings-after-at/box-patterns.rs
src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs
src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs
src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
src/test/ui/pattern/bindings-after-at/feature-gate-bindings_after_at.rs [deleted file]
src/test/ui/pattern/bindings-after-at/feature-gate-bindings_after_at.stderr [deleted file]
src/test/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs
src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs
src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr
src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs
src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr
src/test/ui/pattern/bindings-after-at/nested-patterns.rs
src/test/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs
src/test/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs
src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs
src/test/ui/pattern/bindings-after-at/or-patterns.rs
src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.rs
src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr
src/test/ui/pattern/bindings-after-at/slice-patterns.rs
src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs
src/test/ui/repr/repr-no-niche.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr
src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
src/test/ui/traits/vtable/vtable-diamond.rs [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-diamond.stderr [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-multi-level.rs [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-multi-level.stderr [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-multiple.rs [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-multiple.stderr [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-vacant.rs [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-vacant.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
src/test/ui/type-alias-impl-trait/issue-60371.rs
src/test/ui/type-alias-impl-trait/issue-60371.stderr
src/test/ui/type-alias-impl-trait/issue-74761-2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-74761-2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
src/test/ui/typeck/issue-83693.rs [new file with mode: 0644]
src/test/ui/typeck/issue-83693.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-84768.rs [new file with mode: 0644]
src/test/ui/typeck/issue-84768.stderr [new file with mode: 0644]
src/test/ui/union/union-unsafe.rs
src/test/ui/union/union-unsafe.thir.stderr
src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
src/test/ui/wf/wf-in-fn-arg.stderr
src/test/ui/wf/wf-in-fn-type-arg.stderr
src/test/ui/wf/wf-in-fn-type-ret.stderr
src/test/ui/wf/wf-in-obj-type-trait.stderr
src/test/ui/wf/wf-trait-default-fn-arg.stderr
src/test/ui/wf/wf-trait-fn-arg.stderr
src/tools/cargo
src/tools/clippy/clippy_lints/src/missing_doc.rs
src/tools/clippy/tests/ui/future_not_send.stderr
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs
src/tools/html-checker/main.rs
src/tools/rls
src/tools/rust-analyzer
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/tidy/src/deps.rs
src/version
triagebot.toml

index d6b7ab51a48c66d18c6d61ac0ee09ae0ef3d4878..56ac5296774ddfdcd40a1e82b8b8bddd596cc38b 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -175,6 +175,7 @@ Lennart Kudling <github@kudling.de>
 Léo Lanteri Thauvin <leseulartichaut@gmail.com>
 Léo Lanteri Thauvin <leseulartichaut@gmail.com> <38361244+LeSeulArtichaut@users.noreply.github.com>
 Léo Testard <leo.testard@gmail.com>
+Lily Ballard <lily@ballards.net> <kevin@sb.org>
 Lindsey Kuper <lindsey@composition.al> <lindsey@rockstargirl.org>
 Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com>
 Luke Metz <luke.metz@students.olin.edu>
@@ -215,7 +216,7 @@ Neil Pankey <npankey@gmail.com> <neil@wire.im>
 Nick Platt <platt.nicholas@gmail.com>
 Nicole Mazzuca <npmazzuca@gmail.com>
 Nif Ward <nif.ward@gmail.com>
-Nika Layzell <michael@thelayzells.com>
+Nika Layzell <nika@thelayzells.com> <michael@thelayzells.com>
 Oliver Middleton <olliemail27@gmail.com> <ollie27@users.noreply.github.com>
 Oliver Scherer <oliver.schneider@kit.edu> <git-spam-no-reply9815368754983@oli-obk.de>
 Oliver Scherer <oliver.schneider@kit.edu> <git-spam9815368754983@oli-obk.de>
index 5441542d84e0327e289c0d30aafab75fe8541e22..553d9d05e57bad99604d1f5894f179d0b84668ce 100644 (file)
@@ -73,7 +73,7 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -82,7 +82,7 @@ version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -111,7 +111,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
  "hermit-abi",
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -186,7 +186,7 @@ dependencies = [
  "serde_json",
  "time",
  "toml",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -243,9 +243,9 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
 
 [[package]]
 name = "bytes"
-version = "0.5.6"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
 
 [[package]]
 name = "bytesize"
@@ -310,7 +310,7 @@ dependencies = [
  "unicode-xid",
  "url 2.2.2",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -339,7 +339,7 @@ name = "cargo-credential-wincred"
 version = "0.1.0"
 dependencies = [
  "cargo-credential",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -398,12 +398,12 @@ dependencies = [
  "jobserver",
  "libc",
  "log",
- "miow 0.3.7",
+ "miow",
  "same-file",
  "shell-escape",
  "tempfile",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -521,7 +521,7 @@ dependencies = [
  "num-integer",
  "num-traits",
  "time",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -623,7 +623,7 @@ checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
 dependencies = [
  "atty",
  "lazy_static",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -664,7 +664,7 @@ dependencies = [
  "glob",
  "lazy_static",
  "libc",
- "miow 0.3.7",
+ "miow",
  "regex",
  "rustfix 0.6.0",
  "serde",
@@ -673,7 +673,7 @@ dependencies = [
  "tracing-subscriber",
  "unified-diff",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -688,7 +688,7 @@ dependencies = [
  "lazy_static",
  "libc",
  "log",
- "miow 0.3.7",
+ "miow",
  "regex",
  "rustfix 0.5.1",
  "serde",
@@ -696,7 +696,7 @@ dependencies = [
  "serde_json",
  "tempfile",
  "tester",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -831,7 +831,7 @@ dependencies = [
  "commoncrypto",
  "hex 0.3.2",
  "openssl",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -866,7 +866,7 @@ dependencies = [
  "openssl-sys",
  "schannel",
  "socket2",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -882,7 +882,7 @@ dependencies = [
  "openssl-sys",
  "pkg-config",
  "vcpkg",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -980,7 +980,7 @@ checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
 dependencies = [
  "libc",
  "redox_users",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -991,7 +991,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
 dependencies = [
  "libc",
  "redox_users",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -1148,7 +1148,7 @@ dependencies = [
  "cfg-if 1.0.0",
  "libc",
  "redox_syscall",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -1229,22 +1229,6 @@ version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d79238883cf0307100b90aba4a755d8051a3182305dfe7f649a1e9dc0517006f"
 
-[[package]]
-name = "fuchsia-zircon"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
-dependencies = [
- "bitflags",
- "fuchsia-zircon-sys",
-]
-
-[[package]]
-name = "fuchsia-zircon-sys"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
-
 [[package]]
 name = "futf"
 version = "0.1.4"
@@ -1351,7 +1335,7 @@ dependencies = [
  "futures-sink",
  "futures-task",
  "memchr",
- "pin-project-lite 0.2.4",
+ "pin-project-lite",
  "pin-utils",
  "proc-macro-hack",
  "proc-macro-nested",
@@ -1572,7 +1556,7 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -1694,7 +1678,7 @@ dependencies = [
  "remove_dir_all",
  "tar",
  "walkdir",
- "winapi 0.3.9",
+ "winapi",
  "xz2",
 ]
 
@@ -1704,15 +1688,6 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
 
-[[package]]
-name = "iovec"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "itertools"
 version = "0.8.2"
@@ -1789,9 +1764,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-client-transports"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15b6c6ad01c7354d60de493148c30ac8a82b759e22ae678c8705e9b8e0c566a4"
+checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a"
 dependencies = [
  "derive_more",
  "futures 0.3.12",
@@ -1808,11 +1783,13 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07569945133257ff557eb37b015497104cea61a2c9edaf126c1cbd6e8332397f"
+checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb"
 dependencies = [
  "futures 0.3.12",
+ "futures-executor",
+ "futures-util",
  "log",
  "serde",
  "serde_derive",
@@ -1821,9 +1798,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core-client"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ac9d56dc729912796637c30f475bbf834594607b27740dfea6e5fa7ba40d1f1"
+checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0"
 dependencies = [
  "futures 0.3.12",
  "jsonrpc-client-transports",
@@ -1831,9 +1808,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-derive"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b68ba7e76e5c7796cfa4d2a30e83986550c34404c6d40551c902ca6f7bd4a137"
+checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -1843,9 +1820,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-ipc-server"
-version = "17.0.1"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c4cd89e5ea7e7f0884e828fc35bb83591a371b92439675eae28efa66c24a97"
+checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845"
 dependencies = [
  "futures 0.3.12",
  "jsonrpc-core",
@@ -1858,9 +1835,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-pubsub"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c48dbebce7a9c88ab272a4db7d6478aa4c6d9596e6c086366e89efc4e9ed89e"
+checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011"
 dependencies = [
  "futures 0.3.12",
  "jsonrpc-core",
@@ -1873,9 +1850,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-server-utils"
-version = "17.0.0"
+version = "18.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4207cce738bf713a82525065b750a008f28351324f438f56b33d698ada95bb4"
+checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4"
 dependencies = [
  "bytes",
  "futures 0.3.12",
@@ -1884,20 +1861,11 @@ dependencies = [
  "lazy_static",
  "log",
  "tokio",
+ "tokio-stream",
  "tokio-util",
  "unicase",
 ]
 
-[[package]]
-name = "kernel32-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
-
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -2018,9 +1986,9 @@ dependencies = [
 
 [[package]]
 name = "lsp-codec"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d33c83e320715a1e7e0466a53db2238becb2e5c446deff5506abc81aeacc5ec4"
+checksum = "aa939d0b62476a5a19fb7fcb423a5c6ce8c7e09b851d37531e2fe3e0e6d9d257"
 dependencies = [
  "bytes",
  "serde_json",
@@ -2240,56 +2208,15 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.6.22"
+version = "0.7.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
+checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
 dependencies = [
- "cfg-if 0.1.10",
- "fuchsia-zircon",
- "fuchsia-zircon-sys",
- "iovec",
- "kernel32-sys",
  "libc",
  "log",
- "miow 0.2.2",
- "net2",
- "slab",
- "winapi 0.2.8",
-]
-
-[[package]]
-name = "mio-named-pipes"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
-dependencies = [
- "log",
- "mio",
- "miow 0.3.7",
- "winapi 0.3.9",
-]
-
-[[package]]
-name = "mio-uds"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
-dependencies = [
- "iovec",
- "libc",
- "mio",
-]
-
-[[package]]
-name = "miow"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
-dependencies = [
- "kernel32-sys",
- "net2",
- "winapi 0.2.8",
- "ws2_32-sys",
+ "miow",
+ "ntapi",
+ "winapi",
 ]
 
 [[package]]
@@ -2298,7 +2225,7 @@ version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2320,23 +2247,21 @@ dependencies = [
  "smallvec",
 ]
 
-[[package]]
-name = "net2"
-version = "0.2.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "winapi 0.3.9",
-]
-
 [[package]]
 name = "new_debug_unreachable"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
 
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "num-integer"
 version = "0.1.43"
@@ -2412,7 +2337,7 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2422,7 +2347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
 dependencies = [
  "bstr",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2480,7 +2405,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2518,18 +2443,16 @@ dependencies = [
 
 [[package]]
 name = "parity-tokio-ipc"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd7f6c69d7687501b2205fe51ade1d7b8797bb3aa141fe5bf13dd78c0483bc89"
+checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6"
 dependencies = [
  "futures 0.3.12",
  "libc",
  "log",
- "mio-named-pipes",
- "miow 0.3.7",
  "rand 0.7.3",
  "tokio",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2554,7 +2477,7 @@ dependencies = [
  "libc",
  "redox_syscall",
  "smallvec",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -2675,12 +2598,6 @@ dependencies = [
  "siphasher",
 ]
 
-[[package]]
-name = "pin-project-lite"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
-
 [[package]]
 name = "pin-project-lite"
 version = "0.2.4"
@@ -3095,7 +3012,7 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3140,6 +3057,7 @@ dependencies = [
  "serde_json",
  "tempfile",
  "tokio",
+ "tokio-stream",
  "tokio-util",
  "toml",
  "url 2.2.2",
@@ -3303,7 +3221,7 @@ dependencies = [
  "stacker",
  "tempfile",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3323,7 +3241,7 @@ dependencies = [
  "termize",
  "tracing",
  "unicode-width",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3576,7 +3494,7 @@ dependencies = [
  "smallvec",
  "syn",
  "url 2.2.2",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3778,7 +3696,7 @@ dependencies = [
  "stacker",
  "tempfile",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3811,7 +3729,7 @@ dependencies = [
  "tracing",
  "tracing-subscriber",
  "tracing-tree",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3833,7 +3751,7 @@ dependencies = [
  "termize",
  "tracing",
  "unicode-width",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -3989,7 +3907,7 @@ dependencies = [
  "smallvec",
  "tempfile",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4077,7 +3995,7 @@ dependencies = [
  "smallvec",
  "snap",
  "tracing",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4637,7 +4555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
 dependencies = [
  "lazy_static",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4880,7 +4798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
 dependencies = [
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -4899,7 +4817,7 @@ dependencies = [
  "cfg-if 0.1.10",
  "libc",
  "psm",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5066,7 +4984,7 @@ dependencies = [
  "rand 0.8.3",
  "redox_syscall",
  "remove_dir_all",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5102,7 +5020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
 dependencies = [
  "dirs",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5113,7 +5031,7 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
 dependencies = [
  "dirs-next",
  "rustversion",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5132,7 +5050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295"
 dependencies = [
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5243,7 +5161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
 dependencies = [
  "libc",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5254,49 +5172,44 @@ checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
 
 [[package]]
 name = "tokio"
-version = "0.2.24"
+version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48"
+checksum = "c2602b8af3767c285202012822834005f596c811042315fa7e9f5b12b2a43207"
 dependencies = [
+ "autocfg",
  "bytes",
- "futures-core",
- "iovec",
- "lazy_static",
  "libc",
  "memchr",
  "mio",
- "mio-named-pipes",
- "mio-uds",
  "num_cpus",
- "pin-project-lite 0.1.11",
+ "once_cell",
+ "pin-project-lite",
  "signal-hook-registry",
- "slab",
- "tokio-macros",
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
-name = "tokio-macros"
-version = "0.2.6"
+name = "tokio-stream"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
+checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
 ]
 
 [[package]]
 name = "tokio-util"
-version = "0.3.1"
+version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
+checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592"
 dependencies = [
  "bytes",
  "futures-core",
  "futures-sink",
  "log",
- "pin-project-lite 0.1.11",
+ "pin-project-lite",
  "tokio",
 ]
 
@@ -5322,7 +5235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
 dependencies = [
  "cfg-if 1.0.0",
- "pin-project-lite 0.2.4",
+ "pin-project-lite",
  "tracing-attributes",
  "tracing-core",
 ]
@@ -5619,7 +5532,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
 dependencies = [
  "same-file",
- "winapi 0.3.9",
+ "winapi",
  "winapi-util",
 ]
 
@@ -5634,12 +5547,6 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
-[[package]]
-name = "winapi"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
-
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -5650,12 +5557,6 @@ dependencies = [
  "winapi-x86_64-pc-windows-gnu",
 ]
 
-[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
-
 [[package]]
 name = "winapi-i686-pc-windows-gnu"
 version = "0.4.0"
@@ -5668,7 +5569,7 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
 
 [[package]]
@@ -5677,16 +5578,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
-
 [[package]]
 name = "xattr"
 version = "0.2.2"
@@ -5749,5 +5640,5 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
 dependencies = [
- "winapi 0.3.9",
+ "winapi",
 ]
index 4c00a7dc99ea9ddecee65ef54d11e621f01b1900..dedfe45aca49bd807af07a9b573d245375e98bbd 100644 (file)
@@ -40,6 +40,7 @@ members = [
 exclude = [
   "build",
   "compiler/rustc_codegen_cranelift",
+  "src/test/rustdoc-gui",
   # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
   "obj",
   # The `x` binary is a thin wrapper that calls `x.py`, which initializes
index 35e5627e61ff86f95f9547751ea938b656ccd1a5..19fe97deacca691d621f0bd071c560f7a6de6613 100644 (file)
@@ -1,3 +1,127 @@
+Version 1.54.0 (2021-07-29)
+============================
+
+Language
+-----------------------
+
+- [You can now use macros for values in built-in attribute macros.][83366]
+  While a seemingly minor addition on its own, this enables a lot of
+  powerful functionality when combined correctly. Most notably you can
+  now include external documentation in your crate by writing the following.
+  ```rust
+  #![doc = include_str!("README.md")]
+  ```
+  You can also use this to include auto-generated modules:
+  ```rust
+  #[path = concat!(env!("OUT_DIR"), "/generated.rs")]
+  mod generated;
+  ```
+
+- [You can now cast between unsized slice types (and types which contain
+  unsized slices) in `const fn`.][85078]
+- [You can now use multiple generic lifetimes with `impl Trait` where the
+   lifetimes don't explicitly outlive another.][84701] In code this means
+   that you can now have `impl Trait<'a, 'b>` where as before you could
+   only have `impl Trait<'a, 'b> where 'b: 'a`.
+
+Compiler
+-----------------------
+
+- [Rustc will now search for custom JSON targets in
+  `/lib/rustlib/<target-triple>/target.json` where `/` is the "sysroot"
+  directory.][83800] You can find your sysroot directory by running
+  `rustc --print sysroot`.
+- [Added `wasm` as a `target_family` for WebAssembly platforms.][84072]
+- [You can now use `#[target_feature]` on safe functions when targeting
+  WebAssembly platforms.][84988]
+- [Improved debugger output for enums on Windows MSVC platforms.][85292]
+- [Added tier 3\* support for `bpfel-unknown-none`
+   and `bpfeb-unknown-none`.][79608]
+
+\* Refer to Rust's [platform support page][platform-support-doc] for more
+   information on Rust's tiered platform support.
+
+Libraries
+-----------------------
+
+- [`panic::panic_any` will now `#[track_caller]`.][85745]
+- [Added `OutOfMemory` as a variant of `io::ErrorKind`.][84744]
+- [ `proc_macro::Literal` now implements `FromStr`.][84717]
+- [The implementations of vendor intrinsics in core::arch have been
+   significantly refactored.][83278] The main user-visible changes are
+   a 50% reduction in the size of libcore.rlib and stricter validation
+   of constant operands passed to intrinsics. The latter is technically
+   a breaking change, but allows Rust to more closely match the C vendor
+   intrinsics API.
+
+Stabilized APIs
+---------------
+
+- [`BTreeMap::into_keys`]
+- [`BTreeMap::into_values`]
+- [`HashMap::into_keys`]
+- [`HashMap::into_values`]
+- [`arch::wasm32`]
+- [`VecDeque::binary_search`]
+- [`VecDeque::binary_search_by`]
+- [`VecDeque::binary_search_by_key`]
+- [`VecDeque::partition_point`]
+
+Cargo
+-----
+
+- [Added the `--prune <spec>` option to `cargo-tree` to remove a package from
+  the dependency graph.][cargo/9520]
+- [Added the `--depth` option to `cargo-tree` to print only to a certain depth
+  in the tree ][cargo/9499]
+- [Added the `no-proc-macro` value to `cargo-tree --edges` to hide procedural
+  macro dependencies.][cargo/9488]
+- [A new environment variable named `CARGO_TARGET_TMPDIR` is available.][cargo/9375]
+  This variable points to a directory that integration tests and benches
+  can use as a "scratchpad" for testing filesystem operations.
+
+Compatibility Notes
+-------------------
+- [Mixing Option and Result via `?` is no longer permitted in closures for inferred types.][86831]
+- [Previously unsound code is no longer permitted where different constructors in branches
+  could require different lifetimes.][85574]
+- As previously mentioned the [`std::arch` instrinsics now uses stricter const checking][83278]
+  than before and may reject some previously accepted code.
+- [`i128` multiplication on Cortex M0+ platforms currently unconditionally causes overflow
+   when compiled with `codegen-units = 1`.][86063]
+
+[85574]: https://github.com/rust-lang/rust/issues/85574
+[86831]: https://github.com/rust-lang/rust/issues/86831
+[86063]: https://github.com/rust-lang/rust/issues/86063
+[86831]: https://github.com/rust-lang/rust/issues/86831
+[79608]: https://github.com/rust-lang/rust/pull/79608
+[84988]: https://github.com/rust-lang/rust/pull/84988
+[84701]: https://github.com/rust-lang/rust/pull/84701
+[84072]: https://github.com/rust-lang/rust/pull/84072
+[85745]: https://github.com/rust-lang/rust/pull/85745
+[84744]: https://github.com/rust-lang/rust/pull/84744
+[85078]: https://github.com/rust-lang/rust/pull/85078
+[84717]: https://github.com/rust-lang/rust/pull/84717
+[83800]: https://github.com/rust-lang/rust/pull/83800
+[83366]: https://github.com/rust-lang/rust/pull/83366
+[83278]: https://github.com/rust-lang/rust/pull/83278
+[85292]: https://github.com/rust-lang/rust/pull/85292
+[cargo/9520]: https://github.com/rust-lang/cargo/pull/9520
+[cargo/9499]: https://github.com/rust-lang/cargo/pull/9499
+[cargo/9488]: https://github.com/rust-lang/cargo/pull/9488
+[cargo/9375]: https://github.com/rust-lang/cargo/pull/9375
+[`BTreeMap::into_keys`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.into_keys
+[`BTreeMap::into_values`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.into_values
+[`HashMap::into_keys`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.into_keys
+[`HashMap::into_values`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.into_values
+[`arch::wasm32`]: https://doc.rust-lang.org/core/arch/wasm32/index.html
+[`VecDeque::binary_search`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.binary_search
+[`VecDeque::binary_search_by`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.binary_search_by
+
+[`VecDeque::binary_search_by_key`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.binary_search_by_key
+
+[`VecDeque::partition_point`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.partition_point
+
 Version 1.53.0 (2021-06-17)
 ============================
 
@@ -44,7 +168,7 @@ Libraries
 - [`leading_zeros`, and `trailing_zeros` are now available on all
   `NonZero` integer types.][84082]
 - [`{f32, f64}::from_str` now parse and print special values
-  (`NaN`, `-0`) according to IEEE RFC 754.][78618]
+  (`NaN`, `-0`) according to IEEE 754.][78618]
 - [You can now index into slices using `(Bound<usize>, Bound<usize>)`.][77704]
 - [Add the `BITS` associated constant to all numeric types.][82565]
 
@@ -1749,7 +1873,7 @@ Language
 - [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
   that you can create an enum that has the exact layout and ABI of the type
   it contains.
-- [You can now use outer attribute procedural macros on inline modules.][64273]  
+- [You can now use outer attribute procedural macros on inline modules.][64273]
 - [There are some *syntax-only* changes:][67131]
    - `default` is syntactically allowed before items in `trait` definitions.
    - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
index 9f9d41c3f3d9e8f816d7ad0a99eae3c4abfc2dd9..0fddb0ee4cc8c8f29c0d424acc4e14c3b2987a2c 100644 (file)
@@ -82,15 +82,11 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
         self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
             AssocCtxt::Trait => {
                 let hir_item = lctx.lower_trait_item(item);
-                let id = hir_item.trait_item_id();
-                lctx.trait_items.insert(id, hir_item);
-                lctx.modules.entry(lctx.current_module).or_default().trait_items.insert(id);
+                lctx.insert_trait_item(hir_item);
             }
             AssocCtxt::Impl => {
                 let hir_item = lctx.lower_impl_item(item);
-                let id = hir_item.impl_item_id();
-                lctx.impl_items.insert(id, hir_item);
-                lctx.modules.entry(lctx.current_module).or_default().impl_items.insert(id);
+                lctx.insert_impl_item(hir_item);
             }
         });
 
@@ -101,9 +97,7 @@ fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
         self.lctx.allocate_hir_id_counter(item.id);
         self.lctx.with_hir_id_owner(item.id, |lctx| {
             let hir_item = lctx.lower_foreign_item(item);
-            let id = hir_item.foreign_item_id();
-            lctx.foreign_items.insert(id, hir_item);
-            lctx.modules.entry(lctx.current_module).or_default().foreign_items.insert(id);
+            lctx.insert_foreign_item(hir_item);
         });
 
         visit::walk_foreign_item(self, item);
@@ -123,7 +117,7 @@ fn with_parent_item_lifetime_defs<T>(
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
 
-        let parent_generics = match self.items.get(&parent_hir_id).unwrap().kind {
+        let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind {
             hir::ItemKind::Impl(hir::Impl { ref generics, .. })
             | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
             _ => &[],
@@ -224,7 +218,7 @@ pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
                 let hir_id = self.lower_node_id(i.id);
                 self.lower_attrs(hir_id, &i.attrs);
                 let body = P(self.lower_mac_args(body));
-                self.exported_macros.push(hir::MacroDef {
+                self.insert_macro_def(hir::MacroDef {
                     ident,
                     vis,
                     def_id: hir_id.expect_owner(),
@@ -1373,50 +1367,34 @@ pub(super) fn lower_generics_mut(
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> GenericsCtor<'hir> {
         // Collect `?Trait` bounds in where clause and move them to parameter definitions.
-        // FIXME: this could probably be done with less rightward drift. It also looks like two
-        // control paths where `report_error` is called are the only paths that advance to after the
-        // match statement, so the error reporting could probably just be moved there.
         let mut add_bounds: NodeMap<Vec<_>> = Default::default();
         for pred in &generics.where_clause.predicates {
             if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
                 'next_bound: for bound in &bound_pred.bounds {
                     if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
-                        let report_error = |this: &mut Self| {
-                            this.diagnostic().span_err(
-                                bound_pred.bounded_ty.span,
-                                "`?Trait` bounds are only permitted at the \
-                                 point where a type parameter is declared",
-                            );
-                        };
                         // Check if the where clause type is a plain type parameter.
-                        match bound_pred.bounded_ty.kind {
-                            TyKind::Path(None, ref path)
-                                if path.segments.len() == 1
-                                    && bound_pred.bound_generic_params.is_empty() =>
+                        match self
+                            .resolver
+                            .get_partial_res(bound_pred.bounded_ty.id)
+                            .map(|d| (d.base_res(), d.unresolved_segments()))
+                        {
+                            Some((Res::Def(DefKind::TyParam, def_id), 0))
+                                if bound_pred.bound_generic_params.is_empty() =>
                             {
-                                if let Some(Res::Def(DefKind::TyParam, def_id)) = self
-                                    .resolver
-                                    .get_partial_res(bound_pred.bounded_ty.id)
-                                    .map(|d| d.base_res())
-                                {
-                                    if let Some(def_id) = def_id.as_local() {
-                                        for param in &generics.params {
-                                            if let GenericParamKind::Type { .. } = param.kind {
-                                                if def_id == self.resolver.local_def_id(param.id) {
-                                                    add_bounds
-                                                        .entry(param.id)
-                                                        .or_default()
-                                                        .push(bound.clone());
-                                                    continue 'next_bound;
-                                                }
-                                            }
-                                        }
+                                for param in &generics.params {
+                                    if def_id == self.resolver.local_def_id(param.id).to_def_id() {
+                                        add_bounds.entry(param.id).or_default().push(bound.clone());
+                                        continue 'next_bound;
                                     }
                                 }
-                                report_error(self)
                             }
-                            _ => report_error(self),
+                            _ => {}
                         }
+                        self.diagnostic().span_err(
+                            bound_pred.bounded_ty.span,
+                            "`?Trait` bounds are only permitted at the \
+                                 point where a type parameter is declared",
+                        );
                     }
                 }
             }
index d4caba924160088c892f4e487b172ef809bd3a51..57bf7be40566e16fbbc3ad8942926e6cfd4c6015 100644 (file)
@@ -101,13 +101,8 @@ struct LoweringContext<'a, 'hir: 'a> {
     arena: &'hir Arena<'hir>,
 
     /// The items being lowered are collected here.
-    items: BTreeMap<hir::ItemId, hir::Item<'hir>>,
-
-    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
-    impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
-    foreign_items: BTreeMap<hir::ForeignItemId, hir::ForeignItem<'hir>>,
+    owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
     bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
-    exported_macros: Vec<hir::MacroDef<'hir>>,
     non_exported_macro_attrs: Vec<ast::Attribute>,
 
     trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
@@ -330,15 +325,11 @@ pub fn lower_crate<'a, 'hir>(
         resolver,
         nt_to_tokenstream,
         arena,
-        items: BTreeMap::new(),
-        trait_items: BTreeMap::new(),
-        impl_items: BTreeMap::new(),
-        foreign_items: BTreeMap::new(),
+        owners: IndexVec::default(),
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
         modules: BTreeMap::new(),
         attrs: BTreeMap::default(),
-        exported_macros: Vec::new(),
         non_exported_macro_attrs: Vec::new(),
         catch_scopes: Vec::new(),
         loop_scopes: Vec::new(),
@@ -521,8 +512,11 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
         visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
 
-        let module = self.lower_mod(&c.items, c.span);
+        let module = self.arena.alloc(self.lower_mod(&c.items, c.span));
         self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
+        self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
+        self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
+
         let body_ids = body_ids(&self.bodies);
         let proc_macros =
             c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
@@ -557,13 +551,8 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         }
 
         let krate = hir::Crate {
-            item: module,
-            exported_macros: self.arena.alloc_from_iter(self.exported_macros),
             non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
-            items: self.items,
-            trait_items: self.trait_items,
-            impl_items: self.impl_items,
-            foreign_items: self.foreign_items,
+            owners: self.owners,
             bodies: self.bodies,
             body_ids,
             trait_impls: self.trait_impls,
@@ -576,12 +565,48 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
     }
 
     fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
-        let id = hir::ItemId { def_id: item.def_id };
-        self.items.insert(id, item);
+        let id = item.item_id();
+        let item = self.arena.alloc(item);
+        self.owners.ensure_contains_elem(id.def_id, || None);
+        self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
         self.modules.entry(self.current_module).or_default().items.insert(id);
         id
     }
 
+    fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId {
+        let id = item.foreign_item_id();
+        let item = self.arena.alloc(item);
+        self.owners.ensure_contains_elem(id.def_id, || None);
+        self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
+        self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
+        id
+    }
+
+    fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId {
+        let id = item.impl_item_id();
+        let item = self.arena.alloc(item);
+        self.owners.ensure_contains_elem(id.def_id, || None);
+        self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
+        self.modules.entry(self.current_module).or_default().impl_items.insert(id);
+        id
+    }
+
+    fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId {
+        let id = item.trait_item_id();
+        let item = self.arena.alloc(item);
+        self.owners.ensure_contains_elem(id.def_id, || None);
+        self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
+        self.modules.entry(self.current_module).or_default().trait_items.insert(id);
+        id
+    }
+
+    fn insert_macro_def(&mut self, item: hir::MacroDef<'hir>) {
+        let def_id = item.def_id;
+        let item = self.arena.alloc(item);
+        self.owners.ensure_contains_elem(def_id, || None);
+        self.owners[def_id] = Some(hir::OwnerNode::MacroDef(item));
+    }
+
     fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
         // Set up the counter if needed.
         self.item_local_id_counters.entry(owner).or_insert(0);
index 26da18b571cc0d205fec2f4f592d0cee31b9b4d1..6cde7d2bbd22a0b03f1bf532f501417bca5cebfa 100644 (file)
@@ -4,7 +4,7 @@
 //!
 //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
 
-#![feature(bindings_after_at)]
+#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(iter_is_partitioned)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
index 16151e9dca5e039bc832b83246e3afb2ed19642d..041d52aa20abd6cef4d45258c71f4109f262c82e 100644 (file)
@@ -7,23 +7,26 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(allow_internal_unstable)]
 #![feature(array_windows)]
+#![feature(associated_type_bounds)]
+#![feature(auto_traits)]
+#![feature(bool_to_option)]
+#![feature(const_panic)]
 #![feature(control_flow_enum)]
+#![feature(core_intrinsics)]
+#![feature(extend_one)]
+#![feature(hash_raw_entry)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_map_while)]
+#![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
-#![feature(auto_traits)]
+#![feature(min_type_alias_impl_trait)]
+#![feature(new_uninit)]
 #![feature(nll)]
-#![feature(allow_internal_unstable)]
-#![feature(hash_raw_entry)]
-#![feature(core_intrinsics)]
+#![feature(once_cell)]
 #![feature(test)]
-#![feature(associated_type_bounds)]
 #![feature(thread_id_value)]
-#![feature(extend_one)]
-#![feature(const_panic)]
-#![feature(new_uninit)]
-#![feature(once_cell)]
-#![feature(maybe_uninit_uninit_array)]
 #![allow(rustc::default_hash_types)]
 #![deny(unaligned_references)]
 
index 51f851dc9469fe10dc0a07fea8d21e20c8a71b4a..ef101c56ab578716525fb042b72eb0b056988728 100644 (file)
 use std::sync::Arc;
 use std::time::{Duration, Instant};
 
-use measureme::{EventId, EventIdBuilder, Profiler, SerializableString, StringId};
+pub use measureme::EventId;
+use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
 use parking_lot::RwLock;
 
 bitflags::bitflags! {
     struct EventFilter: u32 {
-        const GENERIC_ACTIVITIES = 1 << 0;
-        const QUERY_PROVIDERS    = 1 << 1;
-        const QUERY_CACHE_HITS   = 1 << 2;
-        const QUERY_BLOCKED      = 1 << 3;
-        const INCR_CACHE_LOADS   = 1 << 4;
+        const GENERIC_ACTIVITIES  = 1 << 0;
+        const QUERY_PROVIDERS     = 1 << 1;
+        const QUERY_CACHE_HITS    = 1 << 2;
+        const QUERY_BLOCKED       = 1 << 3;
+        const INCR_CACHE_LOADS    = 1 << 4;
 
-        const QUERY_KEYS         = 1 << 5;
-        const FUNCTION_ARGS      = 1 << 6;
-        const LLVM               = 1 << 7;
+        const QUERY_KEYS          = 1 << 5;
+        const FUNCTION_ARGS       = 1 << 6;
+        const LLVM                = 1 << 7;
+        const INCR_RESULT_HASHING = 1 << 8;
 
         const DEFAULT = Self::GENERIC_ACTIVITIES.bits |
                         Self::QUERY_PROVIDERS.bits |
                         Self::QUERY_BLOCKED.bits |
-                        Self::INCR_CACHE_LOADS.bits;
+                        Self::INCR_CACHE_LOADS.bits |
+                        Self::INCR_RESULT_HASHING.bits;
 
         const ARGS = Self::QUERY_KEYS.bits | Self::FUNCTION_ARGS.bits;
     }
 }
 
-// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs
+// keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs
 const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("none", EventFilter::empty()),
     ("all", EventFilter::all()),
@@ -132,6 +135,7 @@ struct EventFilter: u32 {
     ("function-args", EventFilter::FUNCTION_ARGS),
     ("args", EventFilter::ARGS),
     ("llvm", EventFilter::LLVM),
+    ("incr-result-hashing", EventFilter::INCR_RESULT_HASHING),
 ];
 
 /// Something that uniquely identifies a query invocation.
@@ -248,6 +252,15 @@ pub fn generic_activity(&self, event_label: &'static str) -> TimingGuard<'_> {
         })
     }
 
+    /// Start profiling with some event filter for a given event. Profiling continues until the
+    /// TimingGuard returned from this call is dropped.
+    #[inline(always)]
+    pub fn generic_activity_with_event_id(&self, event_id: EventId) -> TimingGuard<'_> {
+        self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
+            TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
+        })
+    }
+
     /// Start profiling a generic activity. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
@@ -337,6 +350,19 @@ pub fn incr_cache_loading(&self) -> TimingGuard<'_> {
         })
     }
 
+    /// Start profiling how long it takes to hash query results for incremental compilation.
+    /// Profiling continues until the TimingGuard returned from this call is dropped.
+    #[inline(always)]
+    pub fn incr_result_hashing(&self) -> TimingGuard<'_> {
+        self.exec(EventFilter::INCR_RESULT_HASHING, |profiler| {
+            TimingGuard::start(
+                profiler,
+                profiler.incremental_result_hashing_event_kind,
+                EventId::INVALID,
+            )
+        })
+    }
+
     #[inline(always)]
     fn instant_query_event(
         &self,
@@ -364,6 +390,14 @@ pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) {
         }
     }
 
+    /// Gets a `StringId` for the given string. This method makes sure that
+    /// any strings going through it will only be allocated once in the
+    /// profiling data.
+    /// Returns `None` if the self-profiling is not enabled.
+    pub fn get_or_alloc_cached_string(&self, s: &str) -> Option<StringId> {
+        self.profiler.as_ref().map(|p| p.get_or_alloc_cached_string(s))
+    }
+
     #[inline]
     pub fn enabled(&self) -> bool {
         self.profiler.is_some()
@@ -388,6 +422,7 @@ pub struct SelfProfiler {
     query_event_kind: StringId,
     generic_activity_event_kind: StringId,
     incremental_load_result_event_kind: StringId,
+    incremental_result_hashing_event_kind: StringId,
     query_blocked_event_kind: StringId,
     query_cache_hit_event_kind: StringId,
 }
@@ -408,6 +443,8 @@ pub fn new(
         let query_event_kind = profiler.alloc_string("Query");
         let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
         let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
+        let incremental_result_hashing_event_kind =
+            profiler.alloc_string("IncrementalResultHashing");
         let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
         let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit");
 
@@ -451,6 +488,7 @@ pub fn new(
             query_event_kind,
             generic_activity_event_kind,
             incremental_load_result_event_kind,
+            incremental_result_hashing_event_kind,
             query_blocked_event_kind,
             query_cache_hit_event_kind,
         })
index 65689ab769c1a1a55701d4aa5eba64f12833136f..e92db9ea128057f4c82556a55ff27d3d728aafb0 100644 (file)
@@ -1,6 +1,5 @@
 //! A variant of `SortedMap` that preserves insertion order.
 
-use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::iter::FromIterator;
 
@@ -76,11 +75,7 @@ pub fn get(&self, idx: I) -> Option<&(K, V)> {
     ///
     /// If there are multiple items that are equivalent to `key`, they will be yielded in
     /// insertion order.
-    pub fn get_by_key<Q: 'a>(&'a self, key: &Q) -> impl 'a + Iterator<Item = &'a V>
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
+    pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator<Item = &'a V> {
         self.get_by_key_enumerated(key).map(|(_, v)| v)
     }
 
@@ -89,35 +84,12 @@ pub fn get_by_key<Q: 'a>(&'a self, key: &Q) -> impl 'a + Iterator<Item = &'a V>
     ///
     /// If there are multiple items that are equivalent to `key`, they will be yielded in
     /// insertion order.
-    pub fn get_by_key_enumerated<Q>(&self, key: &Q) -> impl '_ + Iterator<Item = (I, &V)>
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        match self.binary_search_idx(key) {
-            Err(_) => self.idxs_to_items_enumerated(&[]),
-
-            Ok(idx) => {
-                let start = self.idx_sorted_by_item_key[..idx]
-                    .partition_point(|&i| self.items[i].0.borrow() != key);
-                let end = idx
-                    + self.idx_sorted_by_item_key[idx..]
-                        .partition_point(|&i| self.items[i].0.borrow() == key);
-                self.idxs_to_items_enumerated(&self.idx_sorted_by_item_key[start..end])
-            }
-        }
-    }
-
-    fn binary_search_idx<Q>(&self, key: &Q) -> Result<usize, usize>
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        self.idx_sorted_by_item_key.binary_search_by(|&idx| self.items[idx].0.borrow().cmp(key))
-    }
-
-    fn idxs_to_items_enumerated(&'a self, idxs: &'a [I]) -> impl 'a + Iterator<Item = (I, &'a V)> {
-        idxs.iter().map(move |&idx| (idx, &self.items[idx].1))
+    pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator<Item = (I, &V)> {
+        let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key);
+        self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| {
+            let (k, v) = &self.items[i];
+            (k == &key).then_some((i, v))
+        })
     }
 }
 
index 7d91e1fdcef6a3f1db929218752e9a8cfa316416..1e977d709f1cdae35699717160e0c29b97c973da 100644 (file)
@@ -14,11 +14,11 @@ fn test_sorted_index_multi_map() {
     }
 
     // `get_by_key` works.
-    assert_eq!(set.get_by_key(&3).copied().collect::<Vec<_>>(), vec![0]);
-    assert!(set.get_by_key(&4).next().is_none());
+    assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
+    assert!(set.get_by_key(4).next().is_none());
 
     // `get_by_key` returns items in insertion order.
-    let twos: Vec<_> = set.get_by_key_enumerated(&2).collect();
+    let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
     let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
     let values: Vec<usize> = twos.iter().map(|(_, &v)| v).collect();
 
index 1786fa340cc8bb9831039ef8b839f997009c8ce8..cc7ec9432faed31803376bbc5113cebd642229ca 100644 (file)
@@ -1,6 +1,7 @@
 use std::borrow::Borrow;
+use std::fmt::Debug;
 use std::iter::FromIterator;
-use std::slice::{Iter, IterMut};
+use std::slice::Iter;
 use std::vec::IntoIter;
 
 use crate::stable_hasher::{HashStable, StableHasher};
@@ -12,7 +13,8 @@
 
 impl<K, V> VecMap<K, V>
 where
-    K: PartialEq,
+    K: Debug + PartialEq,
+    V: Debug,
 {
     pub fn new() -> Self {
         VecMap(Default::default())
@@ -37,14 +39,31 @@ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
         self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
     }
 
-    /// Returns the value corresponding to the supplied predicate filter.
+    /// Returns the any value corresponding to the supplied predicate filter.
     ///
     /// The supplied predicate will be applied to each (key, value) pair and it will return a
     /// reference to the values where the predicate returns `true`.
-    pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
+    pub fn any_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
         self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
     }
 
+    /// Returns the value corresponding to the supplied predicate filter. It crashes if there's
+    /// more than one matching element.
+    ///
+    /// The supplied predicate will be applied to each (key, value) pair and it will return a
+    /// reference to the value where the predicate returns `true`.
+    pub fn get_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
+        let mut filter = self.0.iter().filter(|kv| predicate(kv));
+        let (_, value) = filter.next()?;
+        // This should return just one element, otherwise it's a bug
+        assert!(
+            filter.next().is_none(),
+            "Collection {:?} should have just one matching element",
+            self
+        );
+        Some(value)
+    }
+
     /// Returns `true` if the map contains a value for the specified key.
     ///
     /// The key may be any borrowed form of the map's key type,
@@ -67,9 +86,13 @@ pub fn iter(&self) -> Iter<'_, (K, V)> {
         self.into_iter()
     }
 
-    pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
+    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
         self.into_iter()
     }
+
+    pub fn retain(&mut self, f: impl Fn(&(K, V)) -> bool) {
+        self.0.retain(f)
+    }
 }
 
 impl<K, V> Default for VecMap<K, V> {
@@ -108,12 +131,12 @@ fn into_iter(self) -> Self::IntoIter {
 }
 
 impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
-    type Item = &'a mut (K, V);
-    type IntoIter = IterMut<'a, (K, V)>;
+    type Item = (&'a K, &'a mut V);
+    type IntoIter = impl Iterator<Item = Self::Item>;
 
     #[inline]
     fn into_iter(self) -> Self::IntoIter {
-        self.0.iter_mut()
+        self.0.iter_mut().map(|(k, v)| (&*k, v))
     }
 }
 
@@ -127,7 +150,7 @@ fn into_iter(self) -> Self::IntoIter {
     }
 }
 
-impl<K: PartialEq, V> Extend<(K, V)> for VecMap<K, V> {
+impl<K: PartialEq + Debug, V: Debug> Extend<(K, V)> for VecMap<K, V> {
     fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
         for (k, v) in iter {
             self.insert(k, v);
index 8c6aef80635cf596c26137255496d728139ef303..b454737fb8077db26141b7af2738028004327eaa 100644 (file)
@@ -1,6 +1,7 @@
 use crate::expand::{self, AstFragment, Invocation};
 use crate::module::DirOwnership;
 
+use rustc_ast::attr::MarkedAttrs;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream};
@@ -928,6 +929,7 @@ pub struct ExpansionData {
     pub prior_type_ascription: Option<(Span, bool)>,
     /// Some parent node that is close to this macro call
     pub lint_node_id: NodeId,
+    pub is_trailing_mac: bool,
 }
 
 type OnExternModLoaded<'a> =
@@ -951,6 +953,10 @@ pub struct ExtCtxt<'a> {
     ///
     /// `Ident` is the module name.
     pub(super) extern_mod_loaded: OnExternModLoaded<'a>,
+    /// When we 'expand' an inert attribute, we leave it
+    /// in the AST, but insert it here so that we know
+    /// not to expand it again.
+    pub(super) expanded_inert_attrs: MarkedAttrs,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -974,9 +980,11 @@ pub fn new(
                 dir_ownership: DirOwnership::Owned { relative: None },
                 prior_type_ascription: None,
                 lint_node_id: ast::CRATE_NODE_ID,
+                is_trailing_mac: false,
             },
             force_mode: false,
             expansions: FxHashMap::default(),
+            expanded_inert_attrs: MarkedAttrs::new(),
         }
     }
 
index dcd871c9d205056d64e0ec6af3d82005542a0d27..09beda33483745b0c85d7b120a1265dde17a76e3 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs};
+use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs, MacCall};
 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
 use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
 use rustc_ast_pretty::pprust;
@@ -26,7 +26,7 @@
     AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
 };
 use rustc_parse::validate_attr;
-use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
+use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
 use rustc_session::Limit;
@@ -754,7 +754,7 @@ fn expand_invoc(
                     }
                 }
                 SyntaxExtensionKind::NonMacroAttr { mark_used } => {
-                    self.cx.sess.mark_attr_known(&attr);
+                    self.cx.expanded_inert_attrs.mark(&attr);
                     if *mark_used {
                         self.cx.sess.mark_attr_used(&attr);
                     }
@@ -1040,7 +1040,7 @@ fn take_first_attr(
         item.visit_attrs(|attrs| {
             attr = attrs
                 .iter()
-                .position(|a| !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a))
+                .position(|a| !self.cx.expanded_inert_attrs.is_marked(a) && !is_builtin_attr(a))
                 .map(|attr_pos| {
                     let attr = attrs.remove(attr_pos);
                     let following_derives = attrs[attr_pos..]
@@ -1070,7 +1070,7 @@ fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
 
     // Detect use of feature-gated or invalid attributes on macro invocations
     // since they will not be detected after macro expansion.
-    fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
+    fn check_attributes(&mut self, attrs: &[ast::Attribute], call: &MacCall) {
         let features = self.cx.ecfg.features.unwrap();
         let mut attrs = attrs.iter().peekable();
         let mut span: Option<Span> = None;
@@ -1085,14 +1085,31 @@ fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
                 continue;
             }
 
-            if attr.doc_str().is_some() {
+            if attr.is_doc_comment() {
                 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
                     &UNUSED_DOC_COMMENTS,
                     current_span,
-                    ast::CRATE_NODE_ID,
+                    self.cx.current_expansion.lint_node_id,
                     "unused doc comment",
                     BuiltinLintDiagnostics::UnusedDocComment(attr.span),
                 );
+            } else if rustc_attr::is_builtin_attr(attr) {
+                let attr_name = attr.ident().unwrap().name;
+                // `#[cfg]` and `#[cfg_attr]` are special - they are
+                // eagerly evaluated.
+                if attr_name != sym::cfg && attr_name != sym::cfg_attr {
+                    self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
+                        &UNUSED_ATTRIBUTES,
+                        attr.span,
+                        self.cx.current_expansion.lint_node_id,
+                        &format!("unused attribute `{}`", attr_name),
+                        BuiltinLintDiagnostics::UnusedBuiltinAttribute {
+                            attr_name,
+                            macro_name: pprust::path_to_string(&call.path),
+                            invoc_span: call.path.span,
+                        },
+                    );
+                }
             }
         }
     }
@@ -1152,7 +1169,7 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
             }
 
             if let ast::ExprKind::MacCall(mac) = expr.kind {
-                self.check_attributes(&expr.attrs);
+                self.check_attributes(&expr.attrs, &mac);
                 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
             } else {
                 assign_id!(self, &mut expr.id, || {
@@ -1253,7 +1270,7 @@ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
             }
 
             if let ast::ExprKind::MacCall(mac) = expr.kind {
-                self.check_attributes(&expr.attrs);
+                self.check_attributes(&expr.attrs, &mac);
                 self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
                     .make_opt_expr()
                     .map(|expr| expr.into_inner())
@@ -1296,7 +1313,7 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
 
         if let StmtKind::MacCall(mac) = stmt.kind {
             let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner();
-            self.check_attributes(&attrs);
+            self.check_attributes(&attrs, &mac);
             let mut placeholder =
                 self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
 
@@ -1311,14 +1328,30 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
             return placeholder;
         }
 
+        // The only way that we can end up with a `MacCall` expression statement,
+        // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the
+        // traiing expression in a block (e.g. `fn foo() { my_macro!() }`).
+        // Record this information, so that we can report a more specific
+        // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
+        // See #78991 for an investigation of treating macros in this position
+        // as statements, rather than expressions, during parsing.
+        if let StmtKind::Expr(expr) = &stmt.kind {
+            if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) {
+                self.cx.current_expansion.is_trailing_mac = true;
+            }
+        }
+
         // The placeholder expander gives ids to statements, so we avoid folding the id here.
         // We don't use `assign_id!` - it will be called when we visit statement's contents
         // (e.g. an expression, item, or local)
         let ast::Stmt { id, kind, span } = stmt;
-        noop_flat_map_stmt_kind(kind, self)
+        let res = noop_flat_map_stmt_kind(kind, self)
             .into_iter()
             .map(|kind| ast::Stmt { id, kind, span })
-            .collect()
+            .collect();
+
+        self.cx.current_expansion.is_trailing_mac = false;
+        res
     }
 
     fn visit_block(&mut self, block: &mut P<Block>) {
@@ -1344,9 +1377,9 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         let span = item.span;
 
         match item.kind {
-            ast::ItemKind::MacCall(..) => {
+            ast::ItemKind::MacCall(ref mac) => {
+                self.check_attributes(&attrs, &mac);
                 item.attrs = attrs;
-                self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
                     ItemKind::MacCall(mac) => {
                         self.collect_bang(mac, span, AstFragmentKind::Items).make_items()
@@ -1455,8 +1488,8 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
 
         match item.kind {
-            ast::AssocItemKind::MacCall(..) => {
-                self.check_attributes(&item.attrs);
+            ast::AssocItemKind::MacCall(ref mac) => {
+                self.check_attributes(&item.attrs, &mac);
                 item.and_then(|item| match item.kind {
                     ast::AssocItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
@@ -1480,8 +1513,8 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
 
         match item.kind {
-            ast::AssocItemKind::MacCall(..) => {
-                self.check_attributes(&item.attrs);
+            ast::AssocItemKind::MacCall(ref mac) => {
+                self.check_attributes(&item.attrs, &mac);
                 item.and_then(|item| match item.kind {
                     ast::AssocItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
@@ -1526,8 +1559,8 @@ fn flat_map_foreign_item(
         }
 
         match foreign_item.kind {
-            ast::ForeignItemKind::MacCall(..) => {
-                self.check_attributes(&foreign_item.attrs);
+            ast::ForeignItemKind::MacCall(ref mac) => {
+                self.check_attributes(&foreign_item.attrs, &mac);
                 foreign_item.and_then(|item| match item.kind {
                     ast::ForeignItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
index 7f985af364d7dbf34369be8461e25bb690d69a91..b97593b92b35523d635aab358e5e60a6e507af99 100644 (file)
@@ -43,6 +43,7 @@
     /// The ident of the macro we're parsing
     macro_ident: Ident,
     lint_node_id: NodeId,
+    is_trailing_mac: bool,
     arm_span: Span,
 }
 
@@ -116,8 +117,14 @@ fn emit_frag_parse_err(
 
 impl<'a> ParserAnyMacro<'a> {
     crate fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
-        let ParserAnyMacro { site_span, macro_ident, ref mut parser, lint_node_id, arm_span } =
-            *self;
+        let ParserAnyMacro {
+            site_span,
+            macro_ident,
+            ref mut parser,
+            lint_node_id,
+            arm_span,
+            is_trailing_mac,
+        } = *self;
         let snapshot = &mut parser.clone();
         let fragment = match parse_ast_fragment(parser, kind) {
             Ok(f) => f,
@@ -131,11 +138,12 @@ impl<'a> ParserAnyMacro<'a> {
         // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
         // but `m!()` is allowed in expression positions (cf. issue #34706).
         if kind == AstFragmentKind::Expr && parser.token == token::Semi {
-            parser.sess.buffer_lint(
+            parser.sess.buffer_lint_with_diagnostic(
                 SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
                 parser.token.span,
                 lint_node_id,
                 "trailing semicolon in macro used in expression position",
+                BuiltinLintDiagnostics::TrailingMacro(is_trailing_mac, macro_ident),
             );
             parser.bump();
         }
@@ -301,6 +309,7 @@ fn generic_extension<'cx>(
                     site_span: sp,
                     macro_ident: name,
                     lint_node_id: cx.current_expansion.lint_node_id,
+                    is_trailing_mac: cx.current_expansion.is_trailing_mac,
                     arm_span,
                 });
             }
index 95504723e7b248b9250368a8f4136dde95d87f27..c593009ce674a9ef85d50fda3da867d3ad1ba372 100644 (file)
@@ -287,6 +287,9 @@ macro_rules! declare_features {
     (accepted, const_fn_unsize, "1.54.0", Some(64992), None),
     /// Allows `impl Trait` with multiple unrelated lifetimes.
     (accepted, member_constraints, "1.54.0", Some(61997), None),
+    /// Allows bindings in the subpattern of a binding pattern.
+    /// For example, you can write `x @ Some(y)`.
+    (accepted, bindings_after_at, "1.54.0", Some(65490), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
index a3e40daf6bf6dccaaf22787394abd7b157a5f6e5..952fe3f9f818808f2f047ce2045c0fdd5ffb2feb 100644 (file)
@@ -526,10 +526,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using `&mut` in constant functions.
     (active, const_mut_refs, "1.41.0", Some(57349), None),
 
-    /// Allows bindings in the subpattern of a binding pattern.
-    /// For example, you can write `x @ Some(y)`.
-    (active, bindings_after_at, "1.41.0", Some(65490), None),
-
     /// Allows `impl const Trait for T` syntax.
     (active, const_trait_impl, "1.42.0", Some(67792), None),
 
index b1c725ecd85c857db40b883d631ac7b529263add..36d035cdfd3ae34bd53566d79b0ccad199852d04 100644 (file)
@@ -603,6 +603,7 @@ macro_rules! experimental {
     rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)),
     rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)),
     rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)),
+    rustc_attr!(TEST, rustc_dump_vtable, AssumedUsed, template!(Word)),
     rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)),
     gated!(
         omit_gdb_pretty_printer_section, AssumedUsed, template!(Word),
index b05ca381b8ab6e9263be40f01a2e17fa2258073c..c4cff79f6c525c5509821b620c4948b43334e08d 100644 (file)
@@ -29,11 +29,14 @@ macro_rules! arena_types {
             [] fn_decl: rustc_hir::FnDecl<$tcx>,
             [] foreign_item: rustc_hir::ForeignItem<$tcx>,
             [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
+            [] impl_item: rustc_hir::ImplItem<$tcx>,
             [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+            [] item: rustc_hir::Item<$tcx>,
             [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
             [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
             [] local: rustc_hir::Local<$tcx>,
             [few] macro_def: rustc_hir::MacroDef<$tcx>,
+            [few] mod_: rustc_hir::Mod<$tcx>,
             [] param: rustc_hir::Param<$tcx>,
             [] pat: rustc_hir::Pat<$tcx>,
             [] path: rustc_hir::Path<$tcx>,
@@ -42,6 +45,7 @@ macro_rules! arena_types {
             [] qpath: rustc_hir::QPath<$tcx>,
             [] stmt: rustc_hir::Stmt<$tcx>,
             [] field_def: rustc_hir::FieldDef<$tcx>,
+            [] trait_item: rustc_hir::TraitItem<$tcx>,
             [] trait_item_ref: rustc_hir::TraitItemRef,
             [] ty: rustc_hir::Ty<$tcx>,
             [] type_binding: rustc_hir::TypeBinding<$tcx>,
index 6aff2fdbd1f220e6964f2340cc371bfb5ff1bea2..389d1e5899f70b77defab04752e6d6739754a3ed 100644 (file)
@@ -1,6 +1,6 @@
 // ignore-tidy-filelength
 use crate::def::{CtorKind, DefKind, Res};
-use crate::def_id::DefId;
+use crate::def_id::{DefId, CRATE_DEF_ID};
 crate use crate::hir_id::{HirId, ItemLocalId};
 use crate::{itemlikevisit, LangItem};
 
@@ -12,6 +12,7 @@
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
+use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -627,22 +628,10 @@ pub struct ModuleItems {
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 #[derive(Debug)]
 pub struct Crate<'hir> {
-    pub item: Mod<'hir>,
-    pub exported_macros: &'hir [MacroDef<'hir>],
     // Attributes from non-exported macros, kept only for collecting the library feature list.
     pub non_exported_macro_attrs: &'hir [Attribute],
 
-    // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates
-    // over the ids in increasing order. In principle it should not
-    // matter what order we visit things in, but in *practice* it
-    // does, because it can affect the order in which errors are
-    // detected, which in turn can make UI tests yield
-    // slightly different results.
-    pub items: BTreeMap<ItemId, Item<'hir>>,
-
-    pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
-    pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
-    pub foreign_items: BTreeMap<ForeignItemId, ForeignItem<'hir>>,
+    pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
     pub bodies: BTreeMap<BodyId, Body<'hir>>,
     pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
 
@@ -668,20 +657,24 @@ pub struct Crate<'hir> {
 }
 
 impl Crate<'hir> {
-    pub fn item(&self, id: ItemId) -> &Item<'hir> {
-        &self.items[&id]
+    pub fn module(&self) -> &'hir Mod<'hir> {
+        if let Some(OwnerNode::Crate(m)) = self.owners[CRATE_DEF_ID] { m } else { panic!() }
     }
 
-    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem<'hir> {
-        &self.trait_items[&id]
+    pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
+        self.owners[id.def_id].as_ref().unwrap().expect_item()
     }
 
-    pub fn impl_item(&self, id: ImplItemId) -> &ImplItem<'hir> {
-        &self.impl_items[&id]
+    pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        self.owners[id.def_id].as_ref().unwrap().expect_trait_item()
     }
 
-    pub fn foreign_item(&self, id: ForeignItemId) -> &ForeignItem<'hir> {
-        &self.foreign_items[&id]
+    pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.owners[id.def_id].as_ref().unwrap().expect_impl_item()
+    }
+
+    pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        self.owners[id.def_id].as_ref().unwrap().expect_foreign_item()
     }
 
     pub fn body(&self, id: BodyId) -> &Body<'hir> {
@@ -702,20 +695,14 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
     where
         V: itemlikevisit::ItemLikeVisitor<'hir>,
     {
-        for item in self.items.values() {
-            visitor.visit_item(item);
-        }
-
-        for trait_item in self.trait_items.values() {
-            visitor.visit_trait_item(trait_item);
-        }
-
-        for impl_item in self.impl_items.values() {
-            visitor.visit_impl_item(impl_item);
-        }
-
-        for foreign_item in self.foreign_items.values() {
-            visitor.visit_foreign_item(foreign_item);
+        for owner in self.owners.iter().filter_map(Option::as_ref) {
+            match owner {
+                OwnerNode::Item(item) => visitor.visit_item(item),
+                OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
+                OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
+                OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
+                OwnerNode::MacroDef(_) | OwnerNode::Crate(_) => {}
+            }
         }
     }
 
@@ -724,28 +711,27 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
     where
         V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
     {
-        parallel!(
-            {
-                par_for_each_in(&self.items, |(_, item)| {
-                    visitor.visit_item(item);
-                });
-            },
-            {
-                par_for_each_in(&self.trait_items, |(_, trait_item)| {
-                    visitor.visit_trait_item(trait_item);
-                });
-            },
-            {
-                par_for_each_in(&self.impl_items, |(_, impl_item)| {
-                    visitor.visit_impl_item(impl_item);
-                });
-            },
-            {
-                par_for_each_in(&self.foreign_items, |(_, foreign_item)| {
-                    visitor.visit_foreign_item(foreign_item);
-                });
-            }
-        );
+        par_for_each_in(&self.owners.raw, |owner| match owner {
+            Some(OwnerNode::Item(item)) => visitor.visit_item(item),
+            Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
+            Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
+            Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
+            Some(OwnerNode::MacroDef(_)) | Some(OwnerNode::Crate(_)) | None => {}
+        })
+    }
+
+    pub fn items<'hir>(&'hir self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir {
+        self.owners.iter().filter_map(|owner| match owner {
+            Some(OwnerNode::Item(item)) => Some(*item),
+            _ => None,
+        })
+    }
+
+    pub fn exported_macros<'hir>(&'hir self) -> impl Iterator<Item = &'hir MacroDef<'hir>> + 'hir {
+        self.owners.iter().filter_map(|owner| match owner {
+            Some(OwnerNode::MacroDef(macro_def)) => Some(*macro_def),
+            _ => None,
+        })
     }
 }
 
@@ -1422,6 +1408,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// These are usually found nested inside types (e.g., array lengths)
 /// or expressions (e.g., repeat counts), and also used to define
 /// explicit discriminant values for enum variants.
+///
+/// You can check if this anon const is a default in a const param
+/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_hir_id(..)`
 #[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
 pub struct AnonConst {
     pub hir_id: HirId,
@@ -2953,6 +2942,163 @@ pub struct TraitCandidate {
     pub import_ids: SmallVec<[LocalDefId; 1]>,
 }
 
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
+pub enum OwnerNode<'hir> {
+    Item(&'hir Item<'hir>),
+    ForeignItem(&'hir ForeignItem<'hir>),
+    TraitItem(&'hir TraitItem<'hir>),
+    ImplItem(&'hir ImplItem<'hir>),
+    MacroDef(&'hir MacroDef<'hir>),
+    Crate(&'hir Mod<'hir>),
+}
+
+impl<'hir> OwnerNode<'hir> {
+    pub fn ident(&self) -> Option<Ident> {
+        match self {
+            OwnerNode::Item(Item { ident, .. })
+            | OwnerNode::ForeignItem(ForeignItem { ident, .. })
+            | OwnerNode::ImplItem(ImplItem { ident, .. })
+            | OwnerNode::TraitItem(TraitItem { ident, .. })
+            | OwnerNode::MacroDef(MacroDef { ident, .. }) => Some(*ident),
+            OwnerNode::Crate(..) => None,
+        }
+    }
+
+    pub fn span(&self) -> Span {
+        match self {
+            OwnerNode::Item(Item { span, .. })
+            | OwnerNode::ForeignItem(ForeignItem { span, .. })
+            | OwnerNode::ImplItem(ImplItem { span, .. })
+            | OwnerNode::TraitItem(TraitItem { span, .. })
+            | OwnerNode::MacroDef(MacroDef { span, .. })
+            | OwnerNode::Crate(Mod { inner: span, .. }) => *span,
+        }
+    }
+
+    pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
+        match self {
+            OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
+            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
+            OwnerNode::ForeignItem(ForeignItem {
+                kind: ForeignItemKind::Fn(fn_decl, _, _),
+                ..
+            }) => Some(fn_decl),
+            _ => None,
+        }
+    }
+
+    pub fn body_id(&self) -> Option<BodyId> {
+        match self {
+            OwnerNode::TraitItem(TraitItem {
+                kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
+                ..
+            })
+            | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
+            | OwnerNode::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
+            _ => None,
+        }
+    }
+
+    pub fn generics(&self) -> Option<&'hir Generics<'hir>> {
+        match self {
+            OwnerNode::TraitItem(TraitItem { generics, .. })
+            | OwnerNode::ImplItem(ImplItem { generics, .. }) => Some(generics),
+            OwnerNode::Item(item) => item.kind.generics(),
+            _ => None,
+        }
+    }
+
+    pub fn def_id(self) -> LocalDefId {
+        match self {
+            OwnerNode::Item(Item { def_id, .. })
+            | OwnerNode::TraitItem(TraitItem { def_id, .. })
+            | OwnerNode::ImplItem(ImplItem { def_id, .. })
+            | OwnerNode::ForeignItem(ForeignItem { def_id, .. })
+            | OwnerNode::MacroDef(MacroDef { def_id, .. }) => *def_id,
+            OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
+        }
+    }
+
+    pub fn expect_item(self) -> &'hir Item<'hir> {
+        match self {
+            OwnerNode::Item(n) => n,
+            _ => panic!(),
+        }
+    }
+
+    pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> {
+        match self {
+            OwnerNode::ForeignItem(n) => n,
+            _ => panic!(),
+        }
+    }
+
+    pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> {
+        match self {
+            OwnerNode::ImplItem(n) => n,
+            _ => panic!(),
+        }
+    }
+
+    pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> {
+        match self {
+            OwnerNode::TraitItem(n) => n,
+            _ => panic!(),
+        }
+    }
+
+    pub fn expect_macro_def(self) -> &'hir MacroDef<'hir> {
+        match self {
+            OwnerNode::MacroDef(n) => n,
+            _ => panic!(),
+        }
+    }
+}
+
+impl<'hir> Into<OwnerNode<'hir>> for &'hir Item<'hir> {
+    fn into(self) -> OwnerNode<'hir> {
+        OwnerNode::Item(self)
+    }
+}
+
+impl<'hir> Into<OwnerNode<'hir>> for &'hir ForeignItem<'hir> {
+    fn into(self) -> OwnerNode<'hir> {
+        OwnerNode::ForeignItem(self)
+    }
+}
+
+impl<'hir> Into<OwnerNode<'hir>> for &'hir ImplItem<'hir> {
+    fn into(self) -> OwnerNode<'hir> {
+        OwnerNode::ImplItem(self)
+    }
+}
+
+impl<'hir> Into<OwnerNode<'hir>> for &'hir TraitItem<'hir> {
+    fn into(self) -> OwnerNode<'hir> {
+        OwnerNode::TraitItem(self)
+    }
+}
+
+impl<'hir> Into<OwnerNode<'hir>> for &'hir MacroDef<'hir> {
+    fn into(self) -> OwnerNode<'hir> {
+        OwnerNode::MacroDef(self)
+    }
+}
+
+impl<'hir> Into<Node<'hir>> for OwnerNode<'hir> {
+    fn into(self) -> Node<'hir> {
+        match self {
+            OwnerNode::Item(n) => Node::Item(n),
+            OwnerNode::ForeignItem(n) => Node::ForeignItem(n),
+            OwnerNode::ImplItem(n) => Node::ImplItem(n),
+            OwnerNode::TraitItem(n) => Node::TraitItem(n),
+            OwnerNode::MacroDef(n) => Node::MacroDef(n),
+            OwnerNode::Crate(n) => Node::Crate(n),
+        }
+    }
+}
+
 #[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum Node<'hir> {
     Param(&'hir Param<'hir>),
@@ -3081,6 +3227,18 @@ pub fn constness(&self) -> Constness {
             _ => Constness::NotConst,
         }
     }
+
+    pub fn as_owner(self) -> Option<OwnerNode<'hir>> {
+        match self {
+            Node::Item(i) => Some(OwnerNode::Item(i)),
+            Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)),
+            Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
+            Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
+            Node::MacroDef(i) => Some(OwnerNode::MacroDef(i)),
+            Node::Crate(i) => Some(OwnerNode::Crate(i)),
+            _ => None,
+        }
+    }
 }
 
 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
index c08f1f53218d625c6062bbe39caf7a89186a1490..711b62c4a314259a61e1803c252adbedd084c55b 100644 (file)
@@ -478,8 +478,9 @@ fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
 
 /// Walks the contents of a crate. See also `Crate::visit_all_items`.
 pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
-    visitor.visit_mod(&krate.item, krate.item.inner, CRATE_HIR_ID);
-    walk_list!(visitor, visit_macro_def, krate.exported_macros);
+    let top_mod = krate.module();
+    visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
+    walk_list!(visitor, visit_macro_def, krate.exported_macros());
     for (&id, attrs) in krate.attrs.iter() {
         for a in *attrs {
             visitor.visit_attribute(id, a)
index 5c1739b1ab9b63a02be65fa50170dd7baf04bebc..4177c2f8d525e9081eb0096f3c298b8e48fd6c24 100644 (file)
@@ -169,7 +169,7 @@ pub fn print_crate<'a>(
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
 
-    s.print_mod(&krate.item, s.attrs(hir::CRATE_HIR_ID));
+    s.print_mod(&krate.module(), s.attrs(hir::CRATE_HIR_ID));
     s.print_remaining_comments();
     s.s.eof()
 }
index ac953f4305c31d3622c9b512715e2d727c925fb3..448dd6623482cf67f6fbddc93c5921a64b4d4d87 100644 (file)
@@ -102,20 +102,11 @@ pub fn canonicalize_user_type_annotation<V>(&self, value: V) -> Canonicalized<'t
         )
     }
 
-    /// A hacky variant of `canonicalize_query` that does not
-    /// canonicalize `'static`. Unfortunately, the existing leak
-    /// check treats `'static` differently in some cases (see also
-    /// #33684), so if we are performing an operation that may need to
-    /// prove "leak-check" related things, we leave `'static`
-    /// alone.
-    ///
-    /// `'static` is also special cased when winnowing candidates when
-    /// selecting implementation candidates, so we also have to leave `'static`
-    /// alone for queries that do selection.
-    //
-    // FIXME(#48536): once the above issues are resolved, we can remove this
-    // and just use `canonicalize_query`.
-    pub fn canonicalize_hr_query_hack<V>(
+    /// A variant of `canonicalize_query` that does not
+    /// canonicalize `'static`. This is useful when
+    /// the query implementation can perform more efficient
+    /// handling of `'static` regions (e.g. trait evaluation).
+    pub fn canonicalize_query_keep_static<V>(
         &self,
         value: V,
         query_state: &mut OriginalQueryValues<'tcx>,
index 426db95aca16e8dab5657c489d3172b378d12bc2..f885c0a4b87bd1f6c42312128203d18381cb6227 100644 (file)
@@ -995,7 +995,7 @@ fn cmp_fn_sig(
         let get_lifetimes = |sig| {
             use rustc_hir::def::Namespace;
             let mut s = String::new();
-            let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
+            let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
                 .name_all_regions(sig)
                 .unwrap();
             let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();
index b3d7876c6e81922c91e25ea4ea10bd911b2cdd40..4af1bdf97a773f7e9796b857d02ce31ff6f24b32 100644 (file)
@@ -47,16 +47,18 @@ pub struct TypeFreshener<'a, 'tcx> {
     const_freshen_count: u32,
     ty_freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
     const_freshen_map: FxHashMap<ty::InferConst<'tcx>, &'tcx ty::Const<'tcx>>,
+    keep_static: bool,
 }
 
 impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> TypeFreshener<'a, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, keep_static: bool) -> TypeFreshener<'a, 'tcx> {
         TypeFreshener {
             infcx,
             ty_freshen_count: 0,
             const_freshen_count: 0,
             ty_freshen_map: Default::default(),
             const_freshen_map: Default::default(),
+            keep_static,
         }
     }
 
@@ -124,8 +126,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 r
             }
 
-            ty::ReStatic
-            | ty::ReEarlyBound(..)
+            ty::ReEarlyBound(..)
             | ty::ReFree(_)
             | ty::ReVar(_)
             | ty::RePlaceholder(..)
@@ -134,6 +135,13 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 // replace all free regions with 'erased
                 self.tcx().lifetimes.re_erased
             }
+            ty::ReStatic => {
+                if self.keep_static {
+                    r
+                } else {
+                    self.tcx().lifetimes.re_erased
+                }
+            }
         }
     }
 
index ab34cda8cc18f514edec1adcd522ea453b05d3cd..869fd225d5114766625630418f73d2b61023dd1c 100644 (file)
@@ -638,6 +638,7 @@ fn collect_errors(
             let sub = var_data.normalize(self.tcx(), verify.region);
 
             let verify_kind_ty = verify.kind.to_ty(self.tcx());
+            let verify_kind_ty = var_data.normalize(self.tcx(), verify_kind_ty);
             if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
                 continue;
             }
index f39431f2494b1868f53c19f58ff893eb0c93a614..d3bfb2b2e4428090a07ea433f4f8de16598929ba 100644 (file)
@@ -646,7 +646,12 @@ pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool {
     }
 
     pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
-        freshen::TypeFreshener::new(self)
+        freshen::TypeFreshener::new(self, false)
+    }
+
+    /// Like `freshener`, but does not replace `'static` regions.
+    pub fn freshener_keep_static<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
+        freshen::TypeFreshener::new(self, true)
     }
 
     pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumeric {
index 1cde4802a40b00e67a6beca539603033dca99f91..ce1445f8a47466609116d60603fdce9b95c9e02e 100644 (file)
@@ -14,17 +14,17 @@ pub fn anonymize_predicate<'tcx>(
     tcx.reuse_or_mk_predicate(pred, new)
 }
 
-struct PredicateSet<'tcx> {
+pub struct PredicateSet<'tcx> {
     tcx: TyCtxt<'tcx>,
     set: FxHashSet<ty::Predicate<'tcx>>,
 }
 
 impl PredicateSet<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
         Self { tcx, set: Default::default() }
     }
 
-    fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
+    pub fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
         // We have to be careful here because we want
         //
         //    for<'a> Foo<&'a i32>
index b1e4e3ba395217fefa8917c70aaa31836f42b998..de0d5fb0097f91bfed87d54016651b9382661145 100644 (file)
@@ -735,6 +735,7 @@ macro_rules! tracked {
     tracked!(merge_functions, Some(MergeFunctions::Disabled));
     tracked!(mir_emit_retag, true);
     tracked!(mir_opt_level, Some(4));
+    tracked!(move_size_limit, Some(4096));
     tracked!(mutable_noalias, Some(true));
     tracked!(new_llvm_pass_manager, Some(true));
     tracked!(no_generate_arange_section, true);
index ccdbccae156c34cb2d2f5e6e066c8ee57dc652f4..b3c64b76820f11e3b55aa4da2437d1c8d3444a0d 100644 (file)
@@ -568,9 +568,9 @@ fn exit_lint_attrs(&mut self, _: &LateContext<'_>, _attrs: &[ast::Attribute]) {
     }
 
     fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) {
-        self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate");
+        self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.module().inner, "the", "crate");
 
-        for macro_def in krate.exported_macros {
+        for macro_def in krate.exported_macros() {
             // Non exported macros should be skipped, since `missing_docs` only
             // applies to externally visible items.
             if !cx.access_levels.is_exported(macro_def.hir_id()) {
index c16d46efb886321932d9c69ca94c126e425dcc61..ad8a41a56cc16287799824e5ea34ed0bb6dad769 100644 (file)
@@ -370,7 +370,7 @@ pub fn check_lint_name_cmdline(
                 match level {
                     Level::Allow => "-A",
                     Level::Warn => "-W",
-                    Level::ForceWarn => "--force-warns",
+                    Level::ForceWarn => "--force-warn",
                     Level::Deny => "-D",
                     Level::Forbid => "-F",
                 },
@@ -734,6 +734,22 @@ fn lookup_with_diagnostics(
                         Applicability::MachineApplicable,
                     );
                 }
+                BuiltinLintDiagnostics::UnusedBuiltinAttribute {
+                    attr_name,
+                    macro_name,
+                    invoc_span
+                } => {
+                    db.span_note(
+                        invoc_span,
+                        &format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`")
+                    );
+                }
+                BuiltinLintDiagnostics::TrailingMacro(is_trailing, name) => {
+                    if is_trailing {
+                        db.note("macro invocations at the end of a block are treated as expressions");
+                        db.note(&format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`"));
+                    }
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
index 069fa41fa886ab175b09186fbbabe2a70e3e401d..4f223afcc27a0055613882dde239db97172d66f6 100644 (file)
@@ -33,11 +33,11 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
     let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
-    builder.levels.id_to_set.reserve(krate.exported_macros.len() + 1);
+    builder.levels.id_to_set.reserve(krate.owners.len() + 1);
 
     let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true);
     builder.levels.register_id(hir::CRATE_HIR_ID);
-    for macro_def in krate.exported_macros {
+    for macro_def in krate.exported_macros() {
         builder.levels.register_id(macro_def.hir_id());
     }
     intravisit::walk_crate(&mut builder, krate);
index c9478016140b7ad3349d2362dbb8399657d7f544..1786f1e70343a5d97e724022c8b2cdecd10865af 100644 (file)
@@ -32,6 +32,7 @@
 #![feature(box_syntax)]
 #![feature(box_patterns)]
 #![feature(crate_visibility_modifier)]
+#![feature(format_args_capture)]
 #![feature(iter_order_by)]
 #![feature(iter_zip)]
 #![feature(never_type)]
index 4d85bf6b499d950ca010bc312b95781738615ea8..6c38b8f5bc0a14c84fd5fe14939fc5461f312b41 100644 (file)
@@ -64,7 +64,7 @@ pub fn as_str(self) -> &'static str {
         match self {
             Level::Allow => "allow",
             Level::Warn => "warn",
-            Level::ForceWarn => "force-warns",
+            Level::ForceWarn => "force-warn",
             Level::Deny => "deny",
             Level::Forbid => "forbid",
         }
@@ -296,12 +296,14 @@ pub enum BuiltinLintDiagnostics {
     DeprecatedMacro(Option<Symbol>, Span),
     MissingAbi(Span, Abi),
     UnusedDocComment(Span),
+    UnusedBuiltinAttribute { attr_name: Symbol, macro_name: String, invoc_span: Span },
     PatternsInFnsWithoutBody(Span, Ident),
     LegacyDeriveHelpers(Span),
     ExternDepSpec(String, ExternDepSpec),
     ProcMacroBackCompat(String),
     OrPatternsBackCompat(Span, String),
     ReservedPrefix(Span),
+    TrailingMacro(bool, Ident),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
index 028104fd6b5057a1bef7d6f13fae94eb9dcc586b..4936b22c7b983010e15e699bda1f5ed370ba793e 100644 (file)
@@ -1080,7 +1080,10 @@ impl CrateError {
                                 locator.triple
                             ));
                         }
-                        if missing_core && std::env::var("RUSTUP_HOME").is_ok() {
+                        // NOTE: this suggests using rustup, even though the user may not have it installed.
+                        // That's because they could choose to install it; or this may give them a hint which
+                        // target they need to install from their distro.
+                        if missing_core {
                             err.help(&format!(
                                 "consider downloading the target with `rustup target add {}`",
                                 locator.triple
@@ -1097,7 +1100,7 @@ impl CrateError {
                                 current_crate
                             ));
                         }
-                        if sess.is_nightly_build() && std::env::var("CARGO").is_ok() {
+                        if sess.is_nightly_build() {
                             err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
                         }
                     } else if Some(crate_name)
index a4913a32e81efbc7cdfa5276fff142f6e3249df2..45a4762c700e41d6c83fbd2582516eccb3850d99 100644 (file)
@@ -439,7 +439,7 @@ fn lazy<T: ?Sized + LazyMeta>(
 
     fn encode_info_for_items(&mut self) {
         let krate = self.tcx.hir().krate();
-        self.encode_info_for_mod(CRATE_DEF_ID, &krate.item);
+        self.encode_info_for_mod(CRATE_DEF_ID, krate.module());
 
         // Proc-macro crates only export proc-macro items, which are looked
         // up using `proc_macro_data`
@@ -448,7 +448,7 @@ fn encode_info_for_items(&mut self) {
         }
 
         krate.visit_all_item_likes(&mut self.as_deep_visitor());
-        for macro_def in krate.exported_macros {
+        for macro_def in krate.exported_macros() {
             self.visit_macro_def(macro_def);
         }
     }
index 8ffd98326f1c86ce022a72a9747820a1442b22f8..0eb0c3eca4e3f226c0b2883a4a90d73f11c13887 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::def_id::CRATE_DEF_INDEX;
+use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_hir::definitions;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::*;
@@ -75,46 +75,20 @@ pub(super) fn root(
         arena: &'hir Arena<'hir>,
         krate: &'hir Crate<'hir>,
         definitions: &'a definitions::Definitions,
-        mut hcx: StableHashingContext<'a>,
+        hcx: StableHashingContext<'a>,
     ) -> NodeCollector<'a, 'hir> {
-        let hash = {
-            let Crate {
-                ref item,
-                // These fields are handled separately:
-                exported_macros: _,
-                non_exported_macro_attrs: _,
-                items: _,
-                trait_items: _,
-                impl_items: _,
-                foreign_items: _,
-                bodies: _,
-                trait_impls: _,
-                body_ids: _,
-                modules: _,
-                proc_macros: _,
-                trait_map: _,
-                attrs: _,
-            } = *krate;
-
-            hash_body(&mut hcx, item)
-        };
-
         let mut collector = NodeCollector {
             arena,
             krate,
             source_map: sess.source_map(),
             parent_node: hir::CRATE_HIR_ID,
-            current_dep_node_owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
+            current_dep_node_owner: CRATE_DEF_ID,
             definitions,
             hcx,
             map: IndexVec::from_fn_n(|_| None, definitions.def_index_count()),
             parenting: FxHashMap::default(),
         };
-        collector.insert_entry(
-            hir::CRATE_HIR_ID,
-            Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) },
-            hash,
-        );
+        collector.insert_owner(CRATE_DEF_ID, OwnerNode::Crate(krate.module()));
 
         collector
     }
@@ -128,53 +102,20 @@ pub(super) fn finalize_and_compute_crate_hash(mut self) -> IndexedHir<'hir> {
         IndexedHir { map: self.map, parenting: self.parenting }
     }
 
-    fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) {
-        let i = id.local_id.as_u32() as usize;
-
-        let arena = self.arena;
+    fn insert_owner(&mut self, owner: LocalDefId, node: OwnerNode<'hir>) {
+        let hash = hash_body(&mut self.hcx, node);
 
-        let data = &mut self.map[id.owner];
-
-        if i == 0 {
-            debug_assert!(data.is_none());
-            *data = Some(arena.alloc(OwnerNodes {
-                hash,
-                nodes: IndexVec::new(),
-                bodies: FxHashMap::default(),
-            }));
-
-            let dk_parent = self.definitions.def_key(id.owner).parent;
-            if let Some(dk_parent) = dk_parent {
-                let dk_parent = LocalDefId { local_def_index: dk_parent };
-                let dk_parent = self.definitions.local_def_id_to_hir_id(dk_parent);
-                if dk_parent.owner != entry.parent.owner {
-                    panic!(
-                        "Different parents for {:?} => dk_parent={:?} actual={:?}",
-                        id.owner, dk_parent, entry.parent,
-                    )
-                }
+        let mut nodes = IndexVec::new();
+        nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: node.into() }));
 
-                debug_assert_eq!(self.parenting.get(&id.owner), Some(&entry.parent));
-            }
-        } else {
-            debug_assert_eq!(entry.parent.owner, id.owner);
-        }
-
-        let data = data.as_mut().unwrap();
-
-        insert_vec_map(
-            &mut data.nodes,
-            id.local_id,
-            ParentedNode { parent: entry.parent.local_id, node: entry.node },
-        );
+        debug_assert!(self.map[owner].is_none());
+        self.map[owner] =
+            Some(self.arena.alloc(OwnerNodes { hash, nodes, bodies: FxHashMap::default() }));
     }
 
     fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
-        self.insert_with_hash(span, hir_id, node, Fingerprint::ZERO)
-    }
-
-    fn insert_with_hash(&mut self, span: Span, hir_id: HirId, node: Node<'hir>, hash: Fingerprint) {
-        let entry = Entry { parent: self.parent_node, node };
+        debug_assert_eq!(self.current_dep_node_owner, hir_id.owner);
+        debug_assert_ne!(hir_id.local_id.as_u32(), 0);
 
         // Make sure that the DepNode of some node coincides with the HirId
         // owner of that node.
@@ -201,7 +142,14 @@ fn insert_with_hash(&mut self, span: Span, hir_id: HirId, node: Node<'hir>, hash
             }
         }
 
-        self.insert_entry(hir_id, entry, hash);
+        let nodes = self.map[hir_id.owner].as_mut().unwrap();
+
+        debug_assert_eq!(self.parent_node.owner, self.current_dep_node_owner);
+        insert_vec_map(
+            &mut nodes.nodes,
+            hir_id.local_id,
+            ParentedNode { parent: self.parent_node.local_id, node: node },
+        );
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
@@ -211,21 +159,15 @@ fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
         self.parent_node = parent_node;
     }
 
-    fn with_dep_node_owner<
-        T: for<'b> HashStable<StableHashingContext<'b>>,
-        F: FnOnce(&mut Self, Fingerprint),
-    >(
-        &mut self,
-        dep_node_owner: LocalDefId,
-        item_like: &T,
-        f: F,
-    ) {
+    fn with_dep_node_owner(&mut self, dep_node_owner: LocalDefId, f: impl FnOnce(&mut Self)) {
         let prev_owner = self.current_dep_node_owner;
-        let hash = hash_body(&mut self.hcx, item_like);
+        let prev_parent = self.parent_node;
 
         self.current_dep_node_owner = dep_node_owner;
-        f(self, hash);
+        self.parent_node = HirId::make_owner(dep_node_owner);
+        f(self);
         self.current_dep_node_owner = prev_owner;
+        self.parent_node = prev_parent;
     }
 
     fn insert_nested(&mut self, item: LocalDefId) {
@@ -291,28 +233,22 @@ fn visit_param(&mut self, param: &'hir Param<'hir>) {
 
     fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug!("visit_item: {:?}", i);
-        self.with_dep_node_owner(i.def_id, i, |this, hash| {
-            let hir_id = i.hir_id();
-            this.insert_with_hash(i.span, hir_id, Node::Item(i), hash);
-            this.with_parent(hir_id, |this| {
-                if let ItemKind::Struct(ref struct_def, _) = i.kind {
-                    // If this is a tuple or unit-like struct, register the constructor.
-                    if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
-                        this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
-                    }
+        self.insert_owner(i.def_id, OwnerNode::Item(i));
+        self.with_dep_node_owner(i.def_id, |this| {
+            if let ItemKind::Struct(ref struct_def, _) = i.kind {
+                // If this is a tuple or unit-like struct, register the constructor.
+                if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+                    this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
                 }
-                intravisit::walk_item(this, i);
-            });
+            }
+            intravisit::walk_item(this, i);
         });
     }
 
     fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
-        self.with_dep_node_owner(fi.def_id, fi, |this, hash| {
-            this.insert_with_hash(fi.span, fi.hir_id(), Node::ForeignItem(fi), hash);
-
-            this.with_parent(fi.hir_id(), |this| {
-                intravisit::walk_foreign_item(this, fi);
-            });
+        self.insert_owner(fi.def_id, OwnerNode::ForeignItem(fi));
+        self.with_dep_node_owner(fi.def_id, |this| {
+            intravisit::walk_foreign_item(this, fi);
         });
     }
 
@@ -322,26 +258,22 @@ fn visit_generic_param(&mut self, param: &'hir GenericParam<'hir>) {
     }
 
     fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
-        self.with_parent(param, |this| intravisit::walk_const_param_default(this, ct))
+        self.with_parent(param, |this| {
+            intravisit::walk_const_param_default(this, ct);
+        })
     }
 
     fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
-        self.with_dep_node_owner(ti.def_id, ti, |this, hash| {
-            this.insert_with_hash(ti.span, ti.hir_id(), Node::TraitItem(ti), hash);
-
-            this.with_parent(ti.hir_id(), |this| {
-                intravisit::walk_trait_item(this, ti);
-            });
+        self.insert_owner(ti.def_id, OwnerNode::TraitItem(ti));
+        self.with_dep_node_owner(ti.def_id, |this| {
+            intravisit::walk_trait_item(this, ti);
         });
     }
 
     fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
-        self.with_dep_node_owner(ii.def_id, ii, |this, hash| {
-            this.insert_with_hash(ii.span, ii.hir_id(), Node::ImplItem(ii), hash);
-
-            this.with_parent(ii.hir_id(), |this| {
-                intravisit::walk_impl_item(this, ii);
-            });
+        self.insert_owner(ii.def_id, OwnerNode::ImplItem(ii));
+        self.with_dep_node_owner(ii.def_id, |this| {
+            intravisit::walk_impl_item(this, ii);
         });
     }
 
@@ -433,7 +365,9 @@ fn visit_block(&mut self, block: &'hir Block<'hir>) {
 
     fn visit_local(&mut self, l: &'hir Local<'hir>) {
         self.insert(l.span, l.hir_id, Node::Local(l));
-        self.with_parent(l.hir_id, |this| intravisit::walk_local(this, l))
+        self.with_parent(l.hir_id, |this| {
+            intravisit::walk_local(this, l);
+        })
     }
 
     fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
@@ -460,16 +394,9 @@ fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
         let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| {
             self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index })
         });
+        self.insert_owner(macro_def.def_id, OwnerNode::MacroDef(macro_def));
         self.with_parent(parent, |this| {
             this.insert_nested(macro_def.def_id);
-            this.with_dep_node_owner(macro_def.def_id, macro_def, |this, hash| {
-                this.insert_with_hash(
-                    macro_def.span,
-                    macro_def.hir_id(),
-                    Node::MacroDef(macro_def),
-                    hash,
-                );
-            })
         });
     }
 
index ae53f1ac3bb49aad914d0da0e5e5804e592720e6..1a3d875c5ba6b0d03767932070a2d6ceddb19659 100644 (file)
@@ -1,6 +1,6 @@
 use self::collector::NodeCollector;
 
-use crate::hir::{AttributeMap, IndexedHir};
+use crate::hir::{AttributeMap, IndexedHir, Owner};
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -29,7 +29,10 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
         Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
         | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
         | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
-        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) => Some(fn_decl),
+        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. })
+        | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
+            Some(fn_decl)
+        }
         _ => None,
     }
 }
@@ -118,13 +121,13 @@ pub struct ParentOwnerIterator<'map, 'hir> {
 }
 
 impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
-    type Item = (HirId, Node<'hir>);
+    type Item = (HirId, OwnerNode<'hir>);
 
     fn next(&mut self) -> Option<Self::Item> {
         if self.current_id.local_id.index() != 0 {
             self.current_id.local_id = ItemLocalId::new(0);
-            if let Some(node) = self.map.find(self.current_id) {
-                return Some((self.current_id, node));
+            if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
+                return Some((self.current_id, node.node));
             }
         }
         if self.current_id == CRATE_HIR_ID {
@@ -141,8 +144,8 @@ fn next(&mut self) -> Option<Self::Item> {
             self.current_id = HirId::make_owner(parent_id);
 
             // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
-            if let Some(node) = self.map.find(self.current_id) {
-                return Some((self.current_id, node));
+            if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
+                return Some((self.current_id, node.node));
             }
         }
     }
@@ -310,7 +313,7 @@ pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
     pub fn find(&self, id: HirId) -> Option<Node<'hir>> {
         if id.local_id == ItemLocalId::from_u32(0) {
             let owner = self.tcx.hir_owner(id.owner)?;
-            Some(owner.node)
+            Some(owner.node.into())
         } else {
             let owner = self.tcx.hir_owner_nodes(id.owner)?;
             let node = owner.nodes[id.local_id].as_ref()?;
@@ -328,10 +331,12 @@ pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
     }
 
     pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
-        self.get_if_local(id).and_then(|node| match &node {
-            Node::ImplItem(impl_item) => Some(&impl_item.generics),
-            Node::TraitItem(trait_item) => Some(&trait_item.generics),
-            Node::Item(Item {
+        let id = id.as_local()?;
+        let node = self.tcx.hir_owner(id)?;
+        match node.node {
+            OwnerNode::ImplItem(impl_item) => Some(&impl_item.generics),
+            OwnerNode::TraitItem(trait_item) => Some(&trait_item.generics),
+            OwnerNode::Item(Item {
                 kind:
                     ItemKind::Fn(_, generics, _)
                     | ItemKind::TyAlias(_, generics)
@@ -344,35 +349,23 @@ pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
                 ..
             }) => Some(generics),
             _ => None,
-        })
+        }
     }
 
     pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
-        match self.find(id.hir_id()).unwrap() {
-            Node::Item(item) => item,
-            _ => bug!(),
-        }
+        self.tcx.hir_owner(id.def_id).unwrap().node.expect_item()
     }
 
     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        match self.find(id.hir_id()).unwrap() {
-            Node::TraitItem(item) => item,
-            _ => bug!(),
-        }
+        self.tcx.hir_owner(id.def_id).unwrap().node.expect_trait_item()
     }
 
     pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        match self.find(id.hir_id()).unwrap() {
-            Node::ImplItem(item) => item,
-            _ => bug!(),
-        }
+        self.tcx.hir_owner(id.def_id).unwrap().node.expect_impl_item()
     }
 
     pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        match self.find(id.hir_id()).unwrap() {
-            Node::ForeignItem(item) => item,
-            _ => bug!(),
-        }
+        self.tcx.hir_owner(id.def_id).unwrap().node.expect_foreign_item()
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
@@ -516,10 +509,12 @@ pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
     }
 
     pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
-        let hir_id = self.local_def_id_to_hir_id(module);
-        match self.get(hir_id) {
-            Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
-            Node::Crate(item) => (&item, item.inner, hir_id),
+        let hir_id = HirId::make_owner(module);
+        match self.tcx.hir_owner(module).map(|o| o.node) {
+            Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => {
+                (m, span, hir_id)
+            }
+            Some(OwnerNode::Crate(item)) => (item, item.inner, hir_id),
             node => panic!("not a module: {:?}", node),
         }
     }
@@ -551,8 +546,8 @@ pub fn visit_exported_macros_in_krate<V>(&self, visitor: &mut V)
     where
         V: Visitor<'hir>,
     {
-        for id in self.krate().exported_macros {
-            visitor.visit_macro_def(self.expect_macro_def(id.hir_id()));
+        for macro_def in self.krate().exported_macros() {
+            visitor.visit_macro_def(macro_def);
         }
     }
 
@@ -656,24 +651,20 @@ pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
     /// in the HIR which is recorded by the map and is an item, either an item
     /// in a module, trait, or impl.
     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
-        for (hir_id, node) in self.parent_owner_iter(hir_id) {
-            if let Node::Crate(_)
-            | Node::Item(_)
-            | Node::ForeignItem(_)
-            | Node::TraitItem(_)
-            | Node::ImplItem(_) = node
-            {
-                return hir_id;
-            }
+        if let Some((hir_id, _node)) = self.parent_owner_iter(hir_id).next() {
+            // A MacroDef does not have children.
+            debug_assert!(!matches!(_node, OwnerNode::MacroDef(_)));
+            hir_id
+        } else {
+            CRATE_HIR_ID
         }
-        CRATE_HIR_ID
     }
 
     /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
     /// module parent is in this map.
     pub(super) fn get_module_parent_node(&self, hir_id: HirId) -> HirId {
         for (hir_id, node) in self.parent_owner_iter(hir_id) {
-            if let Node::Item(&Item { kind: ItemKind::Mod(_), .. }) = node {
+            if let OwnerNode::Item(&Item { kind: ItemKind::Mod(_), .. }) = node {
                 return hir_id;
             }
         }
@@ -746,8 +737,9 @@ pub fn get_parent_did(&self, id: HirId) -> LocalDefId {
 
     pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
         let parent = self.get_parent_item(hir_id);
-        if let Some(node) = self.find(parent) {
-            if let Node::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node {
+        if let Some(node) = self.tcx.hir_owner(self.local_def_id(parent)) {
+            if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node.node
+            {
                 return *abi;
             }
         }
@@ -755,22 +747,22 @@ pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
     }
 
     pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
-        match self.find(id) {
-            Some(Node::Item(item)) => item,
+        match self.tcx.hir_owner(id.expect_owner()) {
+            Some(Owner { node: OwnerNode::Item(item) }) => item,
             _ => bug!("expected item, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
-        match self.find(id) {
-            Some(Node::ImplItem(item)) => item,
+        match self.tcx.hir_owner(id.expect_owner()) {
+            Some(Owner { node: OwnerNode::ImplItem(item) }) => item,
             _ => bug!("expected impl item, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
-        match self.find(id) {
-            Some(Node::TraitItem(item)) => item,
+        match self.tcx.hir_owner(id.expect_owner()) {
+            Some(Owner { node: OwnerNode::TraitItem(item) }) => item,
             _ => bug!("expected trait item, found {}", self.node_to_string(id)),
         }
     }
@@ -783,15 +775,15 @@ pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> {
     }
 
     pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
-        match self.find(id) {
-            Some(Node::ForeignItem(item)) => item,
+        match self.tcx.hir_owner(id.expect_owner()) {
+            Some(Owner { node: OwnerNode::ForeignItem(item) }) => item,
             _ => bug!("expected foreign item, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_macro_def(&self, id: HirId) -> &'hir MacroDef<'hir> {
-        match self.find(id) {
-            Some(Node::MacroDef(macro_def)) => macro_def,
+        match self.tcx.hir_owner(id.expect_owner()) {
+            Some(Owner { node: OwnerNode::MacroDef(macro_def) }) => macro_def,
             _ => bug!("expected macro def, found {}", self.node_to_string(id)),
         }
     }
@@ -916,6 +908,19 @@ pub fn res_span(&self, res: Res) -> Option<Span> {
     pub fn node_to_string(&self, id: HirId) -> String {
         hir_id_to_string(self, id)
     }
+
+    /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
+    /// called with the HirId for the `{ ... }` anon const
+    pub fn opt_const_param_default_param_hir_id(&self, anon_const: HirId) -> Option<HirId> {
+        match self.get(self.get_parent_node(anon_const)) {
+            Node::GenericParam(GenericParam {
+                hir_id: param_id,
+                kind: GenericParamKind::Const { .. },
+                ..
+            }) => Some(*param_id),
+            _ => None,
+        }
+    }
 }
 
 impl<'hir> intravisit::Map<'hir> for Map<'hir> {
index 3026bf8274d2e2eb60717de5f7b146b4fdd2e4da..158499bc0aef787661ac8e3164344293597f62c4 100644 (file)
@@ -33,9 +33,12 @@ pub struct IndexedHir<'hir> {
 
 /// Top-level HIR node for current owner. This only contains the node for which
 /// `HirId::local_id == 0`, and excludes bodies.
+///
+/// This struct exists to encapsulate all access to the hir_owner query in this module, and to
+/// implement HashStable without hashing bodies.
 #[derive(Copy, Clone, Debug)]
 pub struct Owner<'tcx> {
-    node: Node<'tcx>,
+    node: OwnerNode<'tcx>,
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
@@ -140,7 +143,8 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
     providers.hir_owner = |tcx, id| {
         let owner = tcx.index_hir(()).map[id].as_ref()?;
-        let node = owner.nodes[ItemLocalId::new(0)].as_ref()?.node;
+        let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
+        let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
         Some(Owner { node })
     };
     providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].as_deref();
index 848e60fe1342ebcd8c1448d5c08eb5a28a2b00c0..6ad68877235dc7d6453c65be964d44e5b278f05a 100644 (file)
@@ -288,7 +288,7 @@ fn struct_lint_level_impl(
                     Level::Deny => "-D",
                     Level::Forbid => "-F",
                     Level::Allow => "-A",
-                    Level::ForceWarn => "--force-warns",
+                    Level::ForceWarn => "--force-warn",
                 };
                 let hyphen_case_lint_name = name.replace("_", "-");
                 if lint_flag_val.as_str() == name {
index c4bfd0ebb2fde61996d0e3f365ed89e0f027cf16..7ea4902f4bc3922fec77fbab16246ac9616c9715 100644 (file)
 pub fn provide(providers: &mut ty::query::Providers) {
     providers.limits = |tcx, ()| Limits {
         recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
-        move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0),
+        move_size_limit: get_limit(
+            tcx.hir().krate_attrs(),
+            tcx.sess,
+            sym::move_size_limit,
+            tcx.sess.opts.debugging_opts.move_size_limit.unwrap_or(0),
+        ),
         type_length_limit: get_limit(
             tcx.hir().krate_attrs(),
             tcx.sess,
index cb99ae19ee72ea65a262fb052ec4341ffedabb2e..0908b6a1763d50c32129019ce2e63435908dadd5 100644 (file)
     /// span) for an *existing* error. Therefore, it is best-effort, and may never handle
     /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
     /// because the `ty::Ty`-based wfcheck is always run.
-    query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, hir::HirId)) -> Option<traits::ObligationCause<'tcx>> {
+    query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
         eval_always
         no_hash
         desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }
index f951e43fbfa3538c163e24eb35447cef734d62f1..a4a2e824637570b96200cb42163fe7a60a764292 100644 (file)
@@ -16,7 +16,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Constness;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
@@ -327,17 +327,39 @@ pub enum ObligationCauseCode<'tcx> {
     /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
     OpaqueType,
 
-    /// Well-formed checking. If a `HirId` is provided,
-    /// it is used to perform HIR-based wf checking if an error
-    /// occurs, in order to generate a more precise error message.
+    /// Well-formed checking. If a `WellFormedLoc` is provided,
+    /// then it will be used to eprform HIR-based wf checking
+    /// after an error occurs, in order to generate a more precise error span.
     /// This is purely for diagnostic purposes - it is always
-    /// correct to use `MiscObligation` instead
-    WellFormed(Option<hir::HirId>),
+    /// correct to use `MiscObligation` instead, or to specify
+    /// `WellFormed(None)`
+    WellFormed(Option<WellFormedLoc>),
 
     /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
     MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId),
 }
 
+/// The 'location' at which we try to perform HIR-based wf checking.
+/// This information is used to obtain an `hir::Ty`, which
+/// we can walk in order to obtain precise spans for any
+/// 'nested' types (e.g. `Foo` in `Option<Foo>`).
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum WellFormedLoc {
+    /// Use the type of the provided definition.
+    Ty(LocalDefId),
+    /// Use the type of the parameter of the provided function.
+    /// We cannot use `hir::Param`, since the function may
+    /// not have a body (e.g. a trait method definition)
+    Param {
+        /// The function to lookup the parameter in
+        function: LocalDefId,
+        /// The index of the parameter to use.
+        /// Parameters are indexed from 0, with the return type
+        /// being the last 'parameter'
+        param_idx: u16,
+    },
+}
+
 impl ObligationCauseCode<'_> {
     // Return the base obligation, ignoring derived obligations.
     pub fn peel_derives(&self) -> &Self {
index d005f63ed4383b4365d9790cd715a8746000547c..2d177551664f6fa43aa22b08674b1a415a6ac65a 100644 (file)
@@ -124,7 +124,7 @@ pub fn filter_by_name_unhygienic(
         &self,
         name: Symbol,
     ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
-        self.items.get_by_key(&name).copied()
+        self.items.get_by_key(name).copied()
     }
 
     /// Returns an iterator over all associated items with the given name.
index b84058011066f3acaf71b717598a2eddb38e0dc2..4ce49032398bc7877cc2438953c63fec117cfcfc 100644 (file)
@@ -1682,7 +1682,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 // This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
-CloneLiftImpls! { for<'tcx> { Constness, } }
+CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
 
 pub mod tls {
     use super::{ptr_eq, GlobalCtxt, TyCtxt};
index 96aae3bd70cd21710ac81b3f93b30b01ee674cc0..f1c7c1ea852a285e08c3f12dbbf24aedcc47e0e9 100644 (file)
@@ -628,6 +628,7 @@ fn suggest_constraint(
                             assoc_substs,
                             ty,
                             msg,
+                            false,
                         ) {
                             return true;
                         }
@@ -646,6 +647,7 @@ fn suggest_constraint(
                             assoc_substs,
                             ty,
                             msg,
+                            false,
                         );
                     }
                 }
@@ -771,13 +773,24 @@ fn suggest_constraining_opaque_associated_type(
     ) -> bool {
         let assoc = self.associated_item(proj_ty.item_def_id);
         if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
-            self.constrain_associated_type_structured_suggestion(
+            let opaque_local_def_id = def_id.expect_local();
+            let opaque_hir_id = self.hir().local_def_id_to_hir_id(opaque_local_def_id);
+            let opaque_hir_ty = match &self.hir().expect_item(opaque_hir_id).kind {
+                hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
+                _ => bug!("The HirId comes from a `ty::Opaque`"),
+            };
+
+            let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
+
+            self.constrain_generic_bound_associated_type_structured_suggestion(
                 db,
-                self.def_span(def_id),
-                &assoc,
-                proj_ty.trait_ref_and_own_substs(self).1,
+                &trait_ref,
+                opaque_hir_ty.bounds,
+                assoc,
+                assoc_substs,
                 ty,
-                &msg,
+                msg,
+                true,
             )
         } else {
             false
@@ -899,6 +912,11 @@ trait defining them",
 
     /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
     /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
+    ///
+    /// `is_bound_surely_present` indicates whether we know the bound we're looking for is
+    /// inside `bounds`. If that's the case then we can consider `bounds` containing only one
+    /// trait bound as the one we're looking for. This can help in cases where the associated
+    /// type is defined on a supertrait of the one present in the bounds.
     fn constrain_generic_bound_associated_type_structured_suggestion(
         self,
         db: &mut DiagnosticBuilder<'_>,
@@ -908,23 +926,30 @@ fn constrain_generic_bound_associated_type_structured_suggestion(
         assoc_substs: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
         msg: &str,
+        is_bound_surely_present: bool,
     ) -> bool {
         // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
-        bounds.iter().any(|bound| match bound {
-            hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => {
-                // Relate the type param against `T` in `<A as T>::Foo`.
-                ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id)
-                    && self.constrain_associated_type_structured_suggestion(
-                        db,
-                        ptr.span,
-                        assoc,
-                        assoc_substs,
-                        ty,
-                        msg,
-                    )
-            }
-            _ => false,
-        })
+
+        let trait_bounds = bounds.iter().filter_map(|bound| match bound {
+            hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
+            _ => None,
+        });
+
+        let matching_trait_bounds = trait_bounds
+            .clone()
+            .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
+            .collect::<Vec<_>>();
+
+        let span = match &matching_trait_bounds[..] {
+            &[ptr] => ptr.span,
+            &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
+                &[ptr] => ptr.span,
+                _ => return false,
+            },
+            _ => return false,
+        };
+
+        self.constrain_associated_type_structured_suggestion(db, span, assoc, assoc_substs, ty, msg)
     }
 
     /// Given a span corresponding to a bound, provide a structured suggestion to set an
index 6dfbd28f7763b7db91a00610dc21d5ef151eb3b3..dc94124e62ab6a031d22990bfeeb87dc9a8aac40 100644 (file)
@@ -1776,13 +1776,73 @@ pub fn pretty_print_region(mut self, region: ty::Region<'_>) -> Result<Self, fmt
     }
 }
 
+/// Folds through bound vars and placeholders, naming them
+struct RegionFolder<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    current_index: ty::DebruijnIndex,
+    region_map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+    name: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
+}
+
+impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: ty::Binder<'tcx, T>,
+    ) -> 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>) -> 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);
+            }
+            _ => {}
+        }
+        t
+    }
+
+    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)),
+            ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
+                // If this is an anonymous placeholder, don't rename. Otherwise, in some
+                // async fns, we get a `for<'r> Send` bound
+                match kind {
+                    ty::BrAnon(_) | ty::BrEnv => r,
+                    _ => {
+                        // Index doesn't matter, since this is just for naming and these never get bound
+                        let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
+                        self.region_map.entry(br).or_insert_with(|| name(br))
+                    }
+                }
+            }
+            _ => return r,
+        };
+        if let ty::ReLateBound(debruijn1, br) = *region {
+            assert_eq!(debruijn1, ty::INNERMOST);
+            self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+        } else {
+            region
+        }
+    }
+}
+
 // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
 // `region_index` and `used_region_names`.
 impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
     pub fn name_all_regions<T>(
         mut self,
         value: &ty::Binder<'tcx, T>,
-    ) -> Result<(Self, (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)), fmt::Error>
+    ) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
     where
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
@@ -1805,16 +1865,16 @@ fn name_by_region_index(index: usize) -> Symbol {
 
         let mut empty = true;
         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
-            write!(
-                cx,
-                "{}",
-                if empty {
-                    empty = false;
-                    start
-                } else {
-                    cont
-                }
-            )
+            let w = if empty {
+                empty = false;
+                start
+            } else {
+                cont
+            };
+            let _ = write!(cx, "{}", w);
+        };
+        let do_continue = |cx: &mut Self, cont: Symbol| {
+            let _ = write!(cx, "{}", cont);
         };
 
         define_scoped_cx!(self);
@@ -1824,18 +1884,18 @@ fn name_by_region_index(index: usize) -> Symbol {
         // aren't named. Eventually, we might just want this as the default, but
         // this is not *quite* right and changes the ordering of some output
         // anyways.
-        let new_value = if self.tcx().sess.verbose() {
+        let (new_value, map) = if self.tcx().sess.verbose() {
             // anon index + 1 (BrEnv takes 0) -> name
             let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
             let bound_vars = value.bound_vars();
             for var in bound_vars {
                 match var {
                     ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
-                        let _ = start_or_continue(&mut self, "for<", ", ");
-                        let _ = write!(self, "{}", name);
+                        start_or_continue(&mut self, "for<", ", ");
+                        do_continue(&mut self, name);
                     }
                     ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
-                        let _ = start_or_continue(&mut self, "for<", ", ");
+                        start_or_continue(&mut self, "for<", ", ");
                         let name = loop {
                             let name = name_by_region_index(region_index);
                             region_index += 1;
@@ -1843,11 +1903,11 @@ fn name_by_region_index(index: usize) -> Symbol {
                                 break name;
                             }
                         };
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         region_map.insert(i + 1, name);
                     }
                     ty::BoundVariableKind::Region(ty::BrEnv) => {
-                        let _ = start_or_continue(&mut self, "for<", ", ");
+                        start_or_continue(&mut self, "for<", ", ");
                         let name = loop {
                             let name = name_by_region_index(region_index);
                             region_index += 1;
@@ -1855,13 +1915,13 @@ fn name_by_region_index(index: usize) -> Symbol {
                                 break name;
                             }
                         };
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         region_map.insert(0, name);
                     }
                     _ => continue,
                 }
             }
-            start_or_continue(&mut self, "", "> ")?;
+            start_or_continue(&mut self, "", "> ");
 
             self.tcx.replace_late_bound_regions(value.clone(), |br| {
                 let kind = match br.kind {
@@ -1881,11 +1941,12 @@ fn name_by_region_index(index: usize) -> Symbol {
                 ))
             })
         } else {
-            let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| {
-                let _ = start_or_continue(&mut self, "for<", ", ");
+            let tcx = self.tcx;
+            let mut name = |br: ty::BoundRegion| {
+                start_or_continue(&mut self, "for<", ", ");
                 let kind = match br.kind {
                     ty::BrNamed(_, name) => {
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         br.kind
                     }
                     ty::BrAnon(_) | ty::BrEnv => {
@@ -1896,22 +1957,27 @@ fn name_by_region_index(index: usize) -> Symbol {
                                 break name;
                             }
                         };
-                        let _ = write!(self, "{}", name);
+                        do_continue(&mut self, name);
                         ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
                     }
                 };
-                self.tcx.mk_region(ty::ReLateBound(
-                    ty::INNERMOST,
-                    ty::BoundRegion { var: br.var, kind },
-                ))
-            });
-            start_or_continue(&mut self, "", "> ")?;
-            new_value
+                tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
+            };
+            let mut folder = RegionFolder {
+                tcx,
+                current_index: ty::INNERMOST,
+                name: &mut name,
+                region_map: BTreeMap::new(),
+            };
+            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)
         };
 
         self.binder_depth += 1;
         self.region_index = region_index;
-        Ok((self, new_value))
+        Ok((self, new_value, map))
     }
 
     pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
@@ -1919,8 +1985,8 @@ pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fm
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
         let old_region_index = self.region_index;
-        let (new, new_value) = self.name_all_regions(value)?;
-        let mut inner = new_value.0.print(new)?;
+        let (new, new_value, _) = self.name_all_regions(value)?;
+        let mut inner = new_value.print(new)?;
         inner.region_index = old_region_index;
         inner.binder_depth -= 1;
         Ok(inner)
@@ -1935,8 +2001,8 @@ pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
         T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
     {
         let old_region_index = self.region_index;
-        let (new, new_value) = self.name_all_regions(value)?;
-        let mut inner = f(&new_value.0, new)?;
+        let (new, new_value, _) = self.name_all_regions(value)?;
+        let mut inner = f(&new_value, new)?;
         inner.region_index = old_region_index;
         inner.binder_depth -= 1;
         Ok(inner)
@@ -1960,6 +2026,12 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
                 debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r);
                 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
                     self.used_region_names.insert(name);
+                } else if let ty::RePlaceholder(ty::PlaceholderRegion {
+                    name: ty::BrNamed(_, name),
+                    ..
+                }) = *r
+                {
+                    self.used_region_names.insert(name);
                 }
                 r.super_visit_with(self)
             }
@@ -2235,7 +2307,7 @@ pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPat
 fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
     // Iterate all local crate items no matter where they are defined.
     let hir = tcx.hir();
-    for item in hir.krate().items.values() {
+    for item in hir.krate().items() {
         if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) {
             continue;
         }
index 78109fc7b5713beeeb494c7e5d56ef4ad77e96bc..5904f133e78c34d9a7ddde04178b7bde97dce484 100644 (file)
@@ -1,17 +1,39 @@
 use std::convert::TryFrom;
+use std::fmt;
 
 use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, ScalarMaybeUninit};
-use crate::ty::fold::TypeFoldable;
-use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt};
+use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
 use rustc_ast::Mutability;
 
-#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
+#[derive(Clone, Copy, PartialEq, HashStable)]
 pub enum VtblEntry<'tcx> {
+    /// destructor of this type (used in vtable header)
     MetadataDropInPlace,
+    /// layout size of this type (used in vtable header)
     MetadataSize,
+    /// layout align of this type (used in vtable header)
     MetadataAlign,
+    /// non-dispatchable associated function that is excluded from trait object
     Vacant,
-    Method(DefId, SubstsRef<'tcx>),
+    /// dispatchable associated function
+    Method(Instance<'tcx>),
+    /// pointer to a separate supertrait vtable, can be used by trait upcasting coercion
+    TraitVPtr(PolyTraitRef<'tcx>),
+}
+
+impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // We want to call `Display` on `Instance` and `PolyTraitRef`,
+        // so we implement this manually.
+        match self {
+            VtblEntry::MetadataDropInPlace => write!(f, "MetadataDropInPlace"),
+            VtblEntry::MetadataSize => write!(f, "MetadataSize"),
+            VtblEntry::MetadataAlign => write!(f, "MetadataAlign"),
+            VtblEntry::Vacant => write!(f, "Vacant"),
+            VtblEntry::Method(instance) => write!(f, "Method({})", instance),
+            VtblEntry::TraitVPtr(trait_ref) => write!(f, "TraitVPtr({})", trait_ref),
+        }
+    }
 }
 
 pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] =
@@ -36,11 +58,6 @@ pub fn vtable_allocation(
         }
         drop(vtables_cache);
 
-        // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
-        assert!(
-            !ty.needs_subst() && !poly_trait_ref.map_or(false, |trait_ref| trait_ref.needs_subst())
-        );
-        let param_env = ty::ParamEnv::reveal_all();
         let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
             let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
             let trait_ref = tcx.erase_regions(trait_ref);
@@ -50,8 +67,9 @@ pub fn vtable_allocation(
             COMMON_VTABLE_ENTRIES
         };
 
-        let layout =
-            tcx.layout_of(param_env.and(ty)).expect("failed to build vtable representation");
+        let layout = tcx
+            .layout_of(ty::ParamEnv::reveal_all().and(ty))
+            .expect("failed to build vtable representation");
         assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
         let size = layout.size.bytes();
         let align = layout.align.abi.bytes();
@@ -79,19 +97,21 @@ pub fn vtable_allocation(
                 VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
                 VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
                 VtblEntry::Vacant => continue,
-                VtblEntry::Method(def_id, substs) => {
-                    // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
-                    assert!(!substs.needs_subst());
-
+                VtblEntry::Method(instance) => {
                     // Prepare the fn ptr we write into the vtable.
-                    let instance =
-                        ty::Instance::resolve_for_vtable(tcx, param_env, *def_id, substs)
-                            .expect("resolution failed during building vtable representation")
-                            .polymorphize(tcx);
+                    let instance = instance.polymorphize(tcx);
                     let fn_alloc_id = tcx.create_fn_alloc(instance);
                     let fn_ptr = Pointer::from(fn_alloc_id);
                     ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
                 }
+                VtblEntry::TraitVPtr(trait_ref) => {
+                    let super_trait_ref = trait_ref.map_bound(|trait_ref| {
+                        ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
+                    });
+                    let supertrait_alloc_id = self.vtable_allocation(ty, Some(super_trait_ref));
+                    let vptr = Pointer::from(supertrait_alloc_id);
+                    ScalarMaybeUninit::from_pointer(vptr, &tcx)
+                }
             };
             vtable
                 .write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar)
index 671d947d1b1321f2ac7d1797e53e9914794520d3..336f48bde55ecff4441a177c6684acf53c9c21cd 100644 (file)
@@ -905,6 +905,8 @@ fn suggest_ampmut<'tcx>(
                         Some(c) if c.is_whitespace() => true,
                         // e.g. `&mut(x)`
                         Some('(') => true,
+                        // e.g. `&mut{x}`
+                        Some('{') => true,
                         // e.g. `&mutablevar`
                         _ => false,
                     }
@@ -912,9 +914,7 @@ fn suggest_ampmut<'tcx>(
                     false
                 }
             };
-            if let (true, Some(ws_pos)) =
-                (src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() }))
-            {
+            if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace)) {
                 let lt_name = &src[1..ws_pos];
                 let ty = src[ws_pos..].trim_start();
                 if !is_mutbl(ty) {
@@ -940,9 +940,7 @@ fn suggest_ampmut<'tcx>(
     };
 
     if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span) {
-        if let (true, Some(ws_pos)) =
-            (src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() }))
-        {
+        if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace)) {
             let lt_name = &src[1..ws_pos];
             let ty = &src[ws_pos..];
             return (highlight_span, format!("&{} mut{}", lt_name, ty));
index aa3ff98f7ff9f7439683a81da5ae9e6ae3cee89a..3fb06cd2f5f441e1e93234fb9302d4c49d48fb63 100644 (file)
@@ -26,7 +26,7 @@
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
+use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
 use rustc_middle::ty::{
     self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
     ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
@@ -60,7 +60,6 @@
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
     },
     region_infer::{ClosureRegionRequirementsExt, TypeTest},
-    renumber,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
     Upvar,
@@ -180,7 +179,54 @@ pub(crate) fn type_check<'mir, 'tcx>(
             liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
 
             translate_outlives_facts(&mut cx);
-            cx.opaque_type_values
+            let mut opaque_type_values = cx.opaque_type_values;
+
+            for (_, revealed_ty) in &mut opaque_type_values {
+                *revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty);
+                if revealed_ty.has_infer_types_or_consts() {
+                    infcx.tcx.sess.delay_span_bug(
+                        body.span,
+                        &format!("could not resolve {:#?}", revealed_ty.kind()),
+                    );
+                    *revealed_ty = infcx.tcx.ty_error();
+                }
+            }
+
+            opaque_type_values.retain(|(opaque_type_key, resolved_ty)| {
+                let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
+                    *def_id == opaque_type_key.def_id
+                } else {
+                    false
+                };
+
+                if concrete_is_opaque {
+                    // We're using an opaque `impl Trait` type without
+                    // 'revealing' it. For example, code like this:
+                    //
+                    // type Foo = impl Debug;
+                    // fn foo1() -> Foo { ... }
+                    // fn foo2() -> Foo { foo1() }
+                    //
+                    // In `foo2`, we're not revealing the type of `Foo` - we're
+                    // just treating it as the opaque type.
+                    //
+                    // When this occurs, we do *not* want to try to equate
+                    // the concrete type with the underlying defining type
+                    // of the opaque type - this will always fail, since
+                    // the defining type of an opaque type is always
+                    // some other type (e.g. not itself)
+                    // Essentially, none of the normal obligations apply here -
+                    // we're just passing around some unknown opaque type,
+                    // without actually looking at the underlying type it
+                    // gets 'revealed' into
+                    debug!(
+                        "eq_opaque_type_and_type: non-defining use of {:?}",
+                        opaque_type_key.def_id,
+                    );
+                }
+                !concrete_is_opaque
+            });
+            opaque_type_values
         },
     );
 
@@ -1239,14 +1285,10 @@ fn eq_opaque_type_and_type(
             return Ok(());
         }
 
-        let infcx = self.infcx;
-        let tcx = infcx.tcx;
         let param_env = self.param_env;
         let body = self.body;
         let mir_def_id = body.source.def_id().expect_local();
 
-        // the "concrete opaque types" maps
-        let concrete_opaque_types = &tcx.typeck(mir_def_id).concrete_opaque_types;
         let mut opaque_type_values = VecMap::new();
 
         debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id);
@@ -1296,88 +1338,8 @@ fn eq_opaque_type_and_type(
                             .eq(output_ty, revealed_ty)?,
                     );
 
-                    // For each opaque type `Foo<T>` inferred by this value, we want to equate
-                    // the inference variable `?T` with the revealed type that was computed
-                    // earlier by type check.
                     for &(opaque_type_key, opaque_decl) in &opaque_type_map {
-                        let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
-                        let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
-                            *def_id == opaque_type_key.def_id
-                        } else {
-                            false
-                        };
-
-                        // The revealed type computed by the earlier phase of type check.
-                        // In our example, this would be `(U, u32)`. Note that this references
-                        // the type parameter `U` from the definition of `Foo`.
-                        let concrete_ty = match concrete_opaque_types
-                            .get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
-                        {
-                            None => {
-                                if !concrete_is_opaque {
-                                    tcx.sess.delay_span_bug(
-                                        body.span,
-                                        &format!(
-                                            "Non-defining use of {:?} with revealed type",
-                                            opaque_type_key.def_id,
-                                        ),
-                                    );
-                                }
-                                continue;
-                            }
-                            Some(concrete_ty) => concrete_ty,
-                        };
-                        debug!("concrete_ty = {:?}", concrete_ty);
-
-                        // Apply the substitution, in this case `[U -> T]`, so that the
-                        // concrete type becomes `Foo<(T, u32)>`
-                        let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
-
-                        // "Renumber" this, meaning that we replace all the regions
-                        // with fresh inference variables. Not relevant to our example.
-                        let renumbered_opaque_defn_ty =
-                            renumber::renumber_regions(infcx, subst_opaque_defn_ty);
-
-                        debug!(
-                            "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
-                            concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
-                        );
-
-                        if !concrete_is_opaque {
-                            // Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
-                            // in our example) with the renumbered version that we took from
-                            // the type check results (`Foo<(T, u32)>`).
-                            obligations.add(
-                                infcx
-                                    .at(&ObligationCause::dummy(), param_env)
-                                    .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
-                            );
-                            opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty);
-                        } else {
-                            // We're using an opaque `impl Trait` type without
-                            // 'revealing' it. For example, code like this:
-                            //
-                            // type Foo = impl Debug;
-                            // fn foo1() -> Foo { ... }
-                            // fn foo2() -> Foo { foo1() }
-                            //
-                            // In `foo2`, we're not revealing the type of `Foo` - we're
-                            // just treating it as the opaque type.
-                            //
-                            // When this occurs, we do *not* want to try to equate
-                            // the concrete type with the underlying defining type
-                            // of the opaque type - this will always fail, since
-                            // the defining type of an opaque type is always
-                            // some other type (e.g. not itself)
-                            // Essentially, none of the normal obligations apply here -
-                            // we're just passing around some unknown opaque type,
-                            // without actually looking at the underlying type it
-                            // gets 'revealed' into
-                            debug!(
-                                "eq_opaque_type_and_type: non-defining use of {:?}",
-                                opaque_type_key.def_id,
-                            );
-                        }
+                        opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty);
                     }
 
                     debug!("eq_opaque_type_and_type: equated");
@@ -1405,7 +1367,7 @@ fn eq_opaque_type_and_type(
                     locations,
                     ConstraintCategory::OpaqueType,
                     CustomTypeOp::new(
-                        |_cx| {
+                        |infcx| {
                             infcx.constrain_opaque_type(
                                 opaque_type_key,
                                 &opaque_decl,
index 6dcd944a1c3f22cc7645704784c76d9b1184a771..0396806f822fbd862bb676264303f204780f4aeb 100644 (file)
@@ -1142,7 +1142,11 @@ pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M::
             Err(ptr) => ptr.into(),
             Ok(bits) => {
                 let addr = u64::try_from(bits).unwrap();
-                M::ptr_from_addr(&self, addr)
+                let ptr = M::ptr_from_addr(&self, addr);
+                if addr == 0 {
+                    assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId");
+                }
+                ptr
             }
         }
     }
index a58ded9cfd3a4b77f682fe61775aa5fdabf88cdb..6c14410a4cc70180b98c59615bdac79d03bc9f88 100644 (file)
@@ -8,7 +8,7 @@
 #![feature(in_band_lifetimes)]
 #![feature(array_windows)]
 #![feature(assert_matches)]
-#![feature(bindings_after_at)]
+#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
index 2ce7cf71116bbf9125ff8ba57777fcfcb093b2c6..95c4237f38396b58c9e5c12c9f8eba2b40f67b56 100644 (file)
@@ -1116,13 +1116,13 @@ fn create_mono_items_for_vtable_methods<'tcx>(
                     | VtblEntry::MetadataSize
                     | VtblEntry::MetadataAlign
                     | VtblEntry::Vacant => None,
-                    VtblEntry::Method(def_id, substs) => ty::Instance::resolve_for_vtable(
-                        tcx,
-                        ty::ParamEnv::reveal_all(),
-                        *def_id,
-                        substs,
-                    )
-                    .filter(|instance| should_codegen_locally(tcx, instance)),
+                    VtblEntry::TraitVPtr(_) => {
+                        // all super trait items already covered, so skip them.
+                        None
+                    }
+                    VtblEntry::Method(instance) => {
+                        Some(*instance).filter(|instance| should_codegen_locally(tcx, instance))
+                    }
                 })
                 .map(|item| create_fn_mono_item(tcx, item, source));
             output.extend(methods);
diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs
new file mode 100644 (file)
index 0000000..cff386f
--- /dev/null
@@ -0,0 +1,1104 @@
+//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
+
+use rustc_errors::{Applicability, Diagnostic, ErrorReported};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir, HirId, LangItem};
+use rustc_index::bit_set::BitSet;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
+use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::*;
+use rustc_middle::ty::cast::CastTy;
+use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
+use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
+use rustc_span::{sym, Span, Symbol};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
+
+use std::mem;
+use std::ops::Deref;
+
+use super::ops::{self, NonConstOp, Status};
+use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
+use super::resolver::FlowSensitiveAnalysis;
+use super::{is_lang_panic_fn, ConstCx, Qualif};
+use crate::const_eval::is_unstable_const_fn;
+use crate::dataflow::impls::MaybeMutBorrowedLocals;
+use crate::dataflow::{self, Analysis};
+
+// We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated
+// through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals`
+// kills locals upon `StorageDead` because a local will never be used after a `StorageDead`.
+type IndirectlyMutableResults<'mir, 'tcx> =
+    dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
+
+type QualifResults<'mir, 'tcx, Q> =
+    dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
+
+#[derive(Default)]
+pub struct Qualifs<'mir, 'tcx> {
+    has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
+    needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
+    indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
+}
+
+impl Qualifs<'mir, 'tcx> {
+    pub fn indirectly_mutable(
+        &mut self,
+        ccx: &'mir ConstCx<'mir, 'tcx>,
+        local: Local,
+        location: Location,
+    ) -> bool {
+        let indirectly_mutable = self.indirectly_mutable.get_or_insert_with(|| {
+            let ConstCx { tcx, body, param_env, .. } = *ccx;
+
+            // We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
+            // allowed in a const.
+            //
+            // FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
+            // without breaking stable code?
+            MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
+                .unsound_ignore_borrow_on_drop()
+                .into_engine(tcx, &body)
+                .pass_name("const_qualification")
+                .iterate_to_fixpoint()
+                .into_results_cursor(&body)
+        });
+
+        indirectly_mutable.seek_before_primary_effect(location);
+        indirectly_mutable.get().contains(local)
+    }
+
+    /// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
+    ///
+    /// Only updates the cursor if absolutely necessary
+    pub fn needs_drop(
+        &mut self,
+        ccx: &'mir ConstCx<'mir, 'tcx>,
+        local: Local,
+        location: Location,
+    ) -> bool {
+        let ty = ccx.body.local_decls[local].ty;
+        if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
+            return false;
+        }
+
+        let needs_drop = self.needs_drop.get_or_insert_with(|| {
+            let ConstCx { tcx, body, .. } = *ccx;
+
+            FlowSensitiveAnalysis::new(NeedsDrop, ccx)
+                .into_engine(tcx, &body)
+                .iterate_to_fixpoint()
+                .into_results_cursor(&body)
+        });
+
+        needs_drop.seek_before_primary_effect(location);
+        needs_drop.get().contains(local) || self.indirectly_mutable(ccx, local, location)
+    }
+
+    /// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
+    ///
+    /// Only updates the cursor if absolutely necessary.
+    pub fn has_mut_interior(
+        &mut self,
+        ccx: &'mir ConstCx<'mir, 'tcx>,
+        local: Local,
+        location: Location,
+    ) -> bool {
+        let ty = ccx.body.local_decls[local].ty;
+        if !HasMutInterior::in_any_value_of_ty(ccx, ty) {
+            return false;
+        }
+
+        let has_mut_interior = self.has_mut_interior.get_or_insert_with(|| {
+            let ConstCx { tcx, body, .. } = *ccx;
+
+            FlowSensitiveAnalysis::new(HasMutInterior, ccx)
+                .into_engine(tcx, &body)
+                .iterate_to_fixpoint()
+                .into_results_cursor(&body)
+        });
+
+        has_mut_interior.seek_before_primary_effect(location);
+        has_mut_interior.get().contains(local) || self.indirectly_mutable(ccx, local, location)
+    }
+
+    fn in_return_place(
+        &mut self,
+        ccx: &'mir ConstCx<'mir, 'tcx>,
+        error_occured: Option<ErrorReported>,
+    ) -> ConstQualifs {
+        // Find the `Return` terminator if one exists.
+        //
+        // If no `Return` terminator exists, this MIR is divergent. Just return the conservative
+        // qualifs for the return type.
+        let return_block = ccx
+            .body
+            .basic_blocks()
+            .iter_enumerated()
+            .find(|(_, block)| match block.terminator().kind {
+                TerminatorKind::Return => true,
+                _ => false,
+            })
+            .map(|(bb, _)| bb);
+
+        let return_block = match return_block {
+            None => return qualifs::in_any_value_of_ty(ccx, ccx.body.return_ty(), error_occured),
+            Some(bb) => bb,
+        };
+
+        let return_loc = ccx.body.terminator_loc(return_block);
+
+        let custom_eq = match ccx.const_kind() {
+            // We don't care whether a `const fn` returns a value that is not structurally
+            // matchable. Functions calls are opaque and always use type-based qualification, so
+            // this value should never be used.
+            hir::ConstContext::ConstFn => true,
+
+            // If we know that all values of the return type are structurally matchable, there's no
+            // need to run dataflow.
+            _ if !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => false,
+
+            hir::ConstContext::Const | hir::ConstContext::Static(_) => {
+                let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
+                    .into_engine(ccx.tcx, &ccx.body)
+                    .iterate_to_fixpoint()
+                    .into_results_cursor(&ccx.body);
+
+                cursor.seek_after_primary_effect(return_loc);
+                cursor.contains(RETURN_PLACE)
+            }
+        };
+
+        ConstQualifs {
+            needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
+            has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
+            custom_eq,
+            error_occured,
+        }
+    }
+}
+
+pub struct Checker<'mir, 'tcx> {
+    ccx: &'mir ConstCx<'mir, 'tcx>,
+    qualifs: Qualifs<'mir, 'tcx>,
+
+    /// The span of the current statement.
+    span: Span,
+
+    /// A set that stores for each local whether it has a `StorageDead` for it somewhere.
+    local_has_storage_dead: Option<BitSet<Local>>,
+
+    error_emitted: Option<ErrorReported>,
+    secondary_errors: Vec<Diagnostic>,
+}
+
+impl Deref for Checker<'mir, 'tcx> {
+    type Target = ConstCx<'mir, 'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.ccx
+    }
+}
+
+impl Checker<'mir, 'tcx> {
+    pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
+        Checker {
+            span: ccx.body.span,
+            ccx,
+            qualifs: Default::default(),
+            local_has_storage_dead: None,
+            error_emitted: None,
+            secondary_errors: Vec::new(),
+        }
+    }
+
+    pub fn check_body(&mut self) {
+        let ConstCx { tcx, body, .. } = *self.ccx;
+        let def_id = self.ccx.def_id();
+
+        // `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
+        // no need to emit duplicate errors here.
+        if is_async_fn(self.ccx) || body.generator.is_some() {
+            tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`");
+            return;
+        }
+
+        // The local type and predicate checks are not free and only relevant for `const fn`s.
+        if self.const_kind() == hir::ConstContext::ConstFn {
+            // Prevent const trait methods from being annotated as `stable`.
+            // FIXME: Do this as part of stability checking.
+            if self.is_const_stable_const_fn() {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
+                    self.ccx
+                        .tcx
+                        .sess
+                        .struct_span_err(self.span, "trait methods cannot be stable const fn")
+                        .emit();
+                }
+            }
+
+            self.check_item_predicates();
+
+            for (idx, local) in body.local_decls.iter_enumerated() {
+                // Handle the return place below.
+                if idx == RETURN_PLACE || local.internal {
+                    continue;
+                }
+
+                self.span = local.source_info.span;
+                self.check_local_or_return_ty(local.ty, idx);
+            }
+
+            // impl trait is gone in MIR, so check the return type of a const fn by its signature
+            // instead of the type of the return place.
+            self.span = body.local_decls[RETURN_PLACE].source_info.span;
+            let return_ty = tcx.fn_sig(def_id).output();
+            self.check_local_or_return_ty(return_ty.skip_binder(), RETURN_PLACE);
+        }
+
+        self.visit_body(&body);
+
+        // Ensure that the end result is `Sync` in a non-thread local `static`.
+        let should_check_for_sync = self.const_kind()
+            == hir::ConstContext::Static(hir::Mutability::Not)
+            && !tcx.is_thread_local_static(def_id.to_def_id());
+
+        if should_check_for_sync {
+            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+            check_return_ty_is_sync(tcx, &body, hir_id);
+        }
+
+        // If we got through const-checking without emitting any "primary" errors, emit any
+        // "secondary" errors if they occurred.
+        let secondary_errors = mem::take(&mut self.secondary_errors);
+        if self.error_emitted.is_none() {
+            for error in secondary_errors {
+                self.tcx.sess.diagnostic().emit_diagnostic(&error);
+            }
+        } else {
+            assert!(self.tcx.sess.has_errors());
+        }
+    }
+
+    fn local_has_storage_dead(&mut self, local: Local) -> bool {
+        let ccx = self.ccx;
+        self.local_has_storage_dead
+            .get_or_insert_with(|| {
+                struct StorageDeads {
+                    locals: BitSet<Local>,
+                }
+                impl Visitor<'tcx> for StorageDeads {
+                    fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) {
+                        if let StatementKind::StorageDead(l) = stmt.kind {
+                            self.locals.insert(l);
+                        }
+                    }
+                }
+                let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) };
+                v.visit_body(ccx.body);
+                v.locals
+            })
+            .contains(local)
+    }
+
+    pub fn qualifs_in_return_place(&mut self) -> ConstQualifs {
+        self.qualifs.in_return_place(self.ccx, self.error_emitted)
+    }
+
+    /// Emits an error if an expression cannot be evaluated in the current context.
+    pub fn check_op(&mut self, op: impl NonConstOp) {
+        self.check_op_spanned(op, self.span);
+    }
+
+    /// Emits an error at the given `span` if an expression cannot be evaluated in the current
+    /// context.
+    pub fn check_op_spanned<O: NonConstOp>(&mut self, op: O, span: Span) {
+        let gate = match op.status_in_item(self.ccx) {
+            Status::Allowed => return,
+
+            Status::Unstable(gate) if self.tcx.features().enabled(gate) => {
+                let unstable_in_stable = self.ccx.is_const_stable_const_fn()
+                    && !super::rustc_allow_const_fn_unstable(
+                        self.tcx,
+                        self.def_id().to_def_id(),
+                        gate,
+                    );
+                if unstable_in_stable {
+                    emit_unstable_in_stable_error(self.ccx, span, gate);
+                }
+
+                return;
+            }
+
+            Status::Unstable(gate) => Some(gate),
+            Status::Forbidden => None,
+        };
+
+        if self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
+            self.tcx.sess.miri_unleashed_feature(span, gate);
+            return;
+        }
+
+        let mut err = op.build_error(self.ccx, span);
+        assert!(err.is_error());
+
+        match op.importance() {
+            ops::DiagnosticImportance::Primary => {
+                self.error_emitted = Some(ErrorReported);
+                err.emit();
+            }
+
+            ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),
+        }
+    }
+
+    fn check_static(&mut self, def_id: DefId, span: Span) {
+        if self.tcx.is_thread_local_static(def_id) {
+            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
+        }
+        self.check_op_spanned(ops::StaticAccess, span)
+    }
+
+    fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
+        let kind = self.body.local_kind(local);
+
+        for ty in ty.walk() {
+            let ty = match ty.unpack() {
+                GenericArgKind::Type(ty) => ty,
+
+                // No constraints on lifetimes or constants, except potentially
+                // constants' types, but `walk` will get to them as well.
+                GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue,
+            };
+
+            match *ty.kind() {
+                ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)),
+                ty::Opaque(..) => self.check_op(ops::ty::ImplTrait),
+                ty::FnPtr(..) => self.check_op(ops::ty::FnPtr(kind)),
+
+                ty::Dynamic(preds, _) => {
+                    for pred in preds.iter() {
+                        match pred.skip_binder() {
+                            ty::ExistentialPredicate::AutoTrait(_)
+                            | ty::ExistentialPredicate::Projection(_) => {
+                                self.check_op(ops::ty::TraitBound(kind))
+                            }
+                            ty::ExistentialPredicate::Trait(trait_ref) => {
+                                if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() {
+                                    self.check_op(ops::ty::TraitBound(kind))
+                                }
+                            }
+                        }
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+
+    fn check_item_predicates(&mut self) {
+        let ConstCx { tcx, .. } = *self.ccx;
+
+        let mut current = self.def_id().to_def_id();
+        loop {
+            let predicates = tcx.predicates_of(current);
+            for (predicate, _) in predicates.predicates {
+                match predicate.kind().skip_binder() {
+                    ty::PredicateKind::RegionOutlives(_)
+                    | ty::PredicateKind::TypeOutlives(_)
+                    | ty::PredicateKind::WellFormed(_)
+                    | ty::PredicateKind::Projection(_)
+                    | ty::PredicateKind::ConstEvaluatable(..)
+                    | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
+                    ty::PredicateKind::ObjectSafe(_) => {
+                        bug!("object safe predicate on function: {:#?}", predicate)
+                    }
+                    ty::PredicateKind::ClosureKind(..) => {
+                        bug!("closure kind predicate on function: {:#?}", predicate)
+                    }
+                    ty::PredicateKind::Subtype(_) => {
+                        bug!("subtype predicate on function: {:#?}", predicate)
+                    }
+                    ty::PredicateKind::Trait(pred, _constness) => {
+                        if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
+                            continue;
+                        }
+                        match pred.self_ty().kind() {
+                            ty::Param(p) => {
+                                let generics = tcx.generics_of(current);
+                                let def = generics.type_param(p, tcx);
+                                let span = tcx.def_span(def.def_id);
+
+                                // These are part of the function signature, so treat them like
+                                // arguments when determining importance.
+                                let kind = LocalKind::Arg;
+
+                                self.check_op_spanned(ops::ty::TraitBound(kind), span);
+                            }
+                            // other kinds of bounds are either tautologies
+                            // or cause errors in other passes
+                            _ => continue,
+                        }
+                    }
+                }
+            }
+            match predicates.parent {
+                Some(parent) => current = parent,
+                None => break,
+            }
+        }
+    }
+
+    fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
+        match self.const_kind() {
+            // In a const fn all borrows are transient or point to the places given via
+            // references in the arguments (so we already checked them with
+            // TransientMutBorrow/MutBorrow as appropriate).
+            // The borrow checker guarantees that no new non-transient borrows are created.
+            // NOTE: Once we have heap allocations during CTFE we need to figure out
+            // how to prevent `const fn` to create long-lived allocations that point
+            // to mutable memory.
+            hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
+            _ => {
+                // Locals with StorageDead do not live beyond the evaluation and can
+                // thus safely be borrowed without being able to be leaked to the final
+                // value of the constant.
+                if self.local_has_storage_dead(local) {
+                    self.check_op(ops::TransientMutBorrow(kind));
+                } else {
+                    self.check_op(ops::MutBorrow(kind));
+                }
+            }
+        }
+    }
+}
+
+impl Visitor<'tcx> for Checker<'mir, 'tcx> {
+    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) {
+        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
+
+        // We don't const-check basic blocks on the cleanup path since we never unwind during
+        // const-eval: a panic causes an immediate compile error. In other words, cleanup blocks
+        // are unreachable during const-eval.
+        //
+        // We can't be more conservative (e.g., by const-checking cleanup blocks anyways) because
+        // locals that would never be dropped during normal execution are sometimes dropped during
+        // unwinding, which means backwards-incompatible live-drop errors.
+        if block.is_cleanup {
+            return;
+        }
+
+        self.super_basic_block_data(bb, block);
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
+
+        // Special-case reborrows to be more like a copy of a reference.
+        match *rvalue {
+            Rvalue::Ref(_, kind, place) => {
+                if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
+                    let ctx = match kind {
+                        BorrowKind::Shared => {
+                            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
+                        }
+                        BorrowKind::Shallow => {
+                            PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
+                        }
+                        BorrowKind::Unique => {
+                            PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
+                        }
+                        BorrowKind::Mut { .. } => {
+                            PlaceContext::MutatingUse(MutatingUseContext::Borrow)
+                        }
+                    };
+                    self.visit_local(&reborrowed_place_ref.local, ctx, location);
+                    self.visit_projection(reborrowed_place_ref, ctx, location);
+                    return;
+                }
+            }
+            Rvalue::AddressOf(mutbl, place) => {
+                if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
+                    let ctx = match mutbl {
+                        Mutability::Not => {
+                            PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
+                        }
+                        Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
+                    };
+                    self.visit_local(&reborrowed_place_ref.local, ctx, location);
+                    self.visit_projection(reborrowed_place_ref, ctx, location);
+                    return;
+                }
+            }
+            _ => {}
+        }
+
+        self.super_rvalue(rvalue, location);
+
+        match *rvalue {
+            Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess),
+
+            Rvalue::Use(_)
+            | Rvalue::Repeat(..)
+            | Rvalue::Discriminant(..)
+            | Rvalue::Len(_)
+            | Rvalue::Aggregate(..) => {}
+
+            Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place)
+            | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => {
+                let ty = place.ty(self.body, self.tcx).ty;
+                let is_allowed = match ty.kind() {
+                    // Inside a `static mut`, `&mut [...]` is allowed.
+                    ty::Array(..) | ty::Slice(_)
+                        if self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut) =>
+                    {
+                        true
+                    }
+
+                    // FIXME(ecstaticmorse): We could allow `&mut []` inside a const context given
+                    // that this is merely a ZST and it is already eligible for promotion.
+                    // This may require an RFC?
+                    /*
+                    ty::Array(_, len) if len.try_eval_usize(cx.tcx, cx.param_env) == Some(0)
+                        => true,
+                    */
+                    _ => false,
+                };
+
+                if !is_allowed {
+                    if let BorrowKind::Mut { .. } = kind {
+                        self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
+                    } else {
+                        self.check_op(ops::CellBorrow);
+                    }
+                }
+            }
+
+            Rvalue::AddressOf(Mutability::Mut, ref place) => {
+                self.check_mut_borrow(place.local, hir::BorrowKind::Raw)
+            }
+
+            Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, ref place)
+            | Rvalue::AddressOf(Mutability::Not, ref place) => {
+                let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
+                    &self.ccx,
+                    &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
+                    place.as_ref(),
+                );
+
+                if borrowed_place_has_mut_interior {
+                    match self.const_kind() {
+                        // In a const fn all borrows are transient or point to the places given via
+                        // references in the arguments (so we already checked them with
+                        // TransientCellBorrow/CellBorrow as appropriate).
+                        // The borrow checker guarantees that no new non-transient borrows are created.
+                        // NOTE: Once we have heap allocations during CTFE we need to figure out
+                        // how to prevent `const fn` to create long-lived allocations that point
+                        // to (interior) mutable memory.
+                        hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow),
+                        _ => {
+                            // Locals with StorageDead are definitely not part of the final constant value, and
+                            // it is thus inherently safe to permit such locals to have their
+                            // address taken as we can't end up with a reference to them in the
+                            // final value.
+                            // Note: This is only sound if every local that has a `StorageDead` has a
+                            // `StorageDead` in every control flow path leading to a `return` terminator.
+                            if self.local_has_storage_dead(place.local) {
+                                self.check_op(ops::TransientCellBorrow);
+                            } else {
+                                self.check_op(ops::CellBorrow);
+                            }
+                        }
+                    }
+                }
+            }
+
+            Rvalue::Cast(
+                CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
+                _,
+                _,
+            ) => {}
+
+            Rvalue::Cast(
+                CastKind::Pointer(
+                    PointerCast::UnsafeFnPointer
+                    | PointerCast::ClosureFnPointer(_)
+                    | PointerCast::ReifyFnPointer,
+                ),
+                _,
+                _,
+            ) => self.check_op(ops::FnPtrCast),
+
+            Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
+                // Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
+                // in the type of any local, which also excludes casts).
+            }
+
+            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
+                let operand_ty = operand.ty(self.body, self.tcx);
+                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
+                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+
+                if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
+                    self.check_op(ops::RawPtrToIntCast);
+                }
+            }
+
+            Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
+            Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
+
+            Rvalue::UnaryOp(_, ref operand) => {
+                let ty = operand.ty(self.body, self.tcx);
+                if is_int_bool_or_char(ty) {
+                    // Int, bool, and char operations are fine.
+                } else if ty.is_floating_point() {
+                    self.check_op(ops::FloatingPointOp);
+                } else {
+                    span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
+                }
+            }
+
+            Rvalue::BinaryOp(op, box (ref lhs, ref rhs))
+            | Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
+                let lhs_ty = lhs.ty(self.body, self.tcx);
+                let rhs_ty = rhs.ty(self.body, self.tcx);
+
+                if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) {
+                    // Int, bool, and char operations are fine.
+                } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
+                    assert_eq!(lhs_ty, rhs_ty);
+                    assert!(
+                        op == BinOp::Eq
+                            || op == BinOp::Ne
+                            || op == BinOp::Le
+                            || op == BinOp::Lt
+                            || op == BinOp::Ge
+                            || op == BinOp::Gt
+                            || op == BinOp::Offset
+                    );
+
+                    self.check_op(ops::RawPtrComparison);
+                } else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() {
+                    self.check_op(ops::FloatingPointOp);
+                } else {
+                    span_bug!(
+                        self.span,
+                        "non-primitive type in `Rvalue::BinaryOp`: {:?} âš¬ {:?}",
+                        lhs_ty,
+                        rhs_ty
+                    );
+                }
+            }
+        }
+    }
+
+    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        self.super_operand(op, location);
+        if let Operand::Constant(c) = op {
+            if let Some(def_id) = c.check_static_ptr(self.tcx) {
+                self.check_static(def_id, self.span);
+            }
+        }
+    }
+    fn visit_projection_elem(
+        &mut self,
+        place_local: Local,
+        proj_base: &[PlaceElem<'tcx>],
+        elem: PlaceElem<'tcx>,
+        context: PlaceContext,
+        location: Location,
+    ) {
+        trace!(
+            "visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
+            context={:?} location={:?}",
+            place_local,
+            proj_base,
+            elem,
+            context,
+            location,
+        );
+
+        self.super_projection_elem(place_local, proj_base, elem, context, location);
+
+        match elem {
+            ProjectionElem::Deref => {
+                let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
+                if let ty::RawPtr(_) = base_ty.kind() {
+                    if proj_base.is_empty() {
+                        let decl = &self.body.local_decls[place_local];
+                        if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
+                            let span = decl.source_info.span;
+                            self.check_static(def_id, span);
+                            return;
+                        }
+                    }
+                    self.check_op(ops::RawPtrDeref);
+                }
+
+                if context.is_mutating_use() {
+                    self.check_op(ops::MutDeref);
+                }
+            }
+
+            ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Downcast(..)
+            | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Field(..)
+            | ProjectionElem::Index(_) => {
+                let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
+                if base_ty.is_union() {
+                    self.check_op(ops::UnionAccess);
+                }
+            }
+        }
+    }
+
+    fn visit_source_info(&mut self, source_info: &SourceInfo) {
+        trace!("visit_source_info: source_info={:?}", source_info);
+        self.span = source_info.span;
+    }
+
+    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
+        trace!("visit_statement: statement={:?} location={:?}", statement, location);
+
+        self.super_statement(statement, location);
+
+        match statement.kind {
+            StatementKind::LlvmInlineAsm { .. } => {
+                self.check_op(ops::InlineAsm);
+            }
+
+            StatementKind::Assign(..)
+            | StatementKind::SetDiscriminant { .. }
+            | StatementKind::FakeRead(..)
+            | StatementKind::StorageLive(_)
+            | StatementKind::StorageDead(_)
+            | StatementKind::Retag { .. }
+            | StatementKind::AscribeUserType(..)
+            | StatementKind::Coverage(..)
+            | StatementKind::CopyNonOverlapping(..)
+            | StatementKind::Nop => {}
+        }
+    }
+
+    #[instrument(level = "debug", skip(self))]
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+        use rustc_target::spec::abi::Abi::RustIntrinsic;
+
+        self.super_terminator(terminator, location);
+
+        match &terminator.kind {
+            TerminatorKind::Call { func, args, .. } => {
+                let ConstCx { tcx, body, param_env, .. } = *self.ccx;
+                let caller = self.def_id().to_def_id();
+
+                let fn_ty = func.ty(body, tcx);
+
+                let (mut callee, substs) = match *fn_ty.kind() {
+                    ty::FnDef(def_id, substs) => (def_id, substs),
+
+                    ty::FnPtr(_) => {
+                        self.check_op(ops::FnCallIndirect);
+                        return;
+                    }
+                    _ => {
+                        span_bug!(terminator.source_info.span, "invalid callee of type {:?}", fn_ty)
+                    }
+                };
+
+                // Attempting to call a trait method?
+                if let Some(trait_id) = tcx.trait_of_item(callee) {
+                    trace!("attempting to call a trait method");
+                    if !self.tcx.features().const_trait_impl {
+                        self.check_op(ops::FnCallNonConst);
+                        return;
+                    }
+
+                    let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
+                    let obligation = Obligation::new(
+                        ObligationCause::dummy(),
+                        param_env,
+                        Binder::dummy(TraitPredicate { trait_ref }),
+                    );
+
+                    let implsrc = tcx.infer_ctxt().enter(|infcx| {
+                        let mut selcx = SelectionContext::new(&infcx);
+                        selcx.select(&obligation).unwrap()
+                    });
+
+                    // If the method is provided via a where-clause that does not use the `?const`
+                    // opt-out, the call is allowed.
+                    if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc {
+                        debug!(
+                            "const_trait_impl: provided {:?} via where-clause in {:?}",
+                            trait_ref, param_env
+                        );
+                        return;
+                    }
+
+                    // Resolve a trait method call to its concrete implementation, which may be in a
+                    // `const` trait impl.
+                    let instance = Instance::resolve(tcx, param_env, callee, substs);
+                    debug!("Resolving ({:?}) -> {:?}", callee, instance);
+                    if let Ok(Some(func)) = instance {
+                        if let InstanceDef::Item(def) = func.def {
+                            callee = def.did;
+                        }
+                    }
+                }
+
+                // At this point, we are calling a function, `callee`, whose `DefId` is known...
+                if is_lang_panic_fn(tcx, callee) {
+                    self.check_op(ops::Panic);
+
+                    // const-eval of the `begin_panic` fn assumes the argument is `&str`
+                    if Some(callee) == tcx.lang_items().begin_panic_fn() {
+                        match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+                            ty::Ref(_, ty, _) if ty.is_str() => (),
+                            _ => self.check_op(ops::PanicNonStr),
+                        }
+                    }
+
+                    return;
+                }
+
+                // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
+                let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
+                if is_async_block {
+                    let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block);
+                    self.check_op(ops::Generator(kind));
+                    return;
+                }
+
+                let is_intrinsic = tcx.fn_sig(callee).abi() == RustIntrinsic;
+
+                // HACK: This is to "unstabilize" the `transmute` intrinsic
+                // within const fns. `transmute` is allowed in all other const contexts.
+                // This won't really scale to more intrinsics or functions. Let's allow const
+                // transmutes in const fn before we add more hacks to this.
+                if is_intrinsic && tcx.item_name(callee) == sym::transmute {
+                    self.check_op(ops::Transmute);
+                    return;
+                }
+
+                if !tcx.is_const_fn_raw(callee) {
+                    let mut permitted = false;
+
+                    let callee_trait = tcx.trait_of_item(callee);
+                    if let Some(trait_id) = callee_trait {
+                        if tcx.has_attr(caller, sym::default_method_body_is_const) {
+                            // permit call to non-const fn when caller has default_method_body_is_const..
+                            if tcx.trait_of_item(caller) == callee_trait {
+                                // ..and caller and callee are in the same trait.
+                                permitted = true;
+                            }
+                        }
+                        if !permitted {
+                            // if trait's impls are all const, permit the call.
+                            let mut const_impls = true;
+                            tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| {
+                                if const_impls {
+                                    if let hir::Constness::NotConst = tcx.impl_constness(imp) {
+                                        const_impls = false;
+                                    }
+                                }
+                            });
+                            if const_impls {
+                                permitted = true;
+                            }
+                        }
+                    }
+
+                    if !permitted {
+                        self.check_op(ops::FnCallNonConst);
+                        return;
+                    }
+                }
+
+                // If the `const fn` we are trying to call is not const-stable, ensure that we have
+                // the proper feature gate enabled.
+                if let Some(gate) = is_unstable_const_fn(tcx, callee) {
+                    trace!(?gate, "calling unstable const fn");
+                    if self.span.allows_unstable(gate) {
+                        return;
+                    }
+
+                    // Calling an unstable function *always* requires that the corresponding gate
+                    // be enabled, even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`.
+                    if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
+                        self.check_op(ops::FnCallUnstable(callee, Some(gate)));
+                        return;
+                    }
+
+                    // If this crate is not using stability attributes, or the caller is not claiming to be a
+                    // stable `const fn`, that is all that is required.
+                    if !self.ccx.is_const_stable_const_fn() {
+                        trace!("crate not using stability attributes or caller not stably const");
+                        return;
+                    }
+
+                    // Otherwise, we are something const-stable calling a const-unstable fn.
+
+                    if super::rustc_allow_const_fn_unstable(tcx, caller, gate) {
+                        trace!("rustc_allow_const_fn_unstable gate active");
+                        return;
+                    }
+
+                    self.check_op(ops::FnCallUnstable(callee, Some(gate)));
+                    return;
+                }
+
+                // FIXME(ecstaticmorse); For compatibility, we consider `unstable` callees that
+                // have no `rustc_const_stable` attributes to be const-unstable as well. This
+                // should be fixed later.
+                let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none()
+                    && tcx.lookup_stability(callee).map_or(false, |s| s.level.is_unstable());
+                if callee_is_unstable_unmarked {
+                    trace!("callee_is_unstable_unmarked");
+                    // We do not use `const` modifiers for intrinsic "functions", as intrinsics are
+                    // `extern` funtions, and these have no way to get marked `const`. So instead we
+                    // use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
+                    if self.ccx.is_const_stable_const_fn() || is_intrinsic {
+                        self.check_op(ops::FnCallUnstable(callee, None));
+                        return;
+                    }
+                }
+                trace!("permitting call");
+            }
+
+            // Forbid all `Drop` terminators unless the place being dropped is a local with no
+            // projections that cannot be `NeedsDrop`.
+            TerminatorKind::Drop { place: dropped_place, .. }
+            | TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
+                // If we are checking live drops after drop-elaboration, don't emit duplicate
+                // errors here.
+                if super::post_drop_elaboration::checking_enabled(self.ccx) {
+                    return;
+                }
+
+                let mut err_span = self.span;
+
+                // Check to see if the type of this place can ever have a drop impl. If not, this
+                // `Drop` terminator is frivolous.
+                let ty_needs_drop =
+                    dropped_place.ty(self.body, self.tcx).ty.needs_drop(self.tcx, self.param_env);
+
+                if !ty_needs_drop {
+                    return;
+                }
+
+                let needs_drop = if let Some(local) = dropped_place.as_local() {
+                    // Use the span where the local was declared as the span of the drop error.
+                    err_span = self.body.local_decls[local].source_info.span;
+                    self.qualifs.needs_drop(self.ccx, local, location)
+                } else {
+                    true
+                };
+
+                if needs_drop {
+                    self.check_op_spanned(
+                        ops::LiveDrop { dropped_at: Some(terminator.source_info.span) },
+                        err_span,
+                    );
+                }
+            }
+
+            TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
+
+            TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
+                self.check_op(ops::Generator(hir::GeneratorKind::Gen))
+            }
+
+            TerminatorKind::Abort => {
+                // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
+                span_bug!(self.span, "`Abort` terminator outside of cleanup block")
+            }
+
+            TerminatorKind::Assert { .. }
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Return
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Unreachable => {}
+        }
+    }
+}
+
+fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) {
+    let ty = body.return_ty();
+    tcx.infer_ctxt().enter(|infcx| {
+        let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic);
+        let mut fulfillment_cx = traits::FulfillmentContext::new();
+        let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
+        fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
+        if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
+            infcx.report_fulfillment_errors(&err, None, false);
+        }
+    });
+}
+
+fn place_as_reborrow(
+    tcx: TyCtxt<'tcx>,
+    body: &Body<'tcx>,
+    place: Place<'tcx>,
+) -> Option<PlaceRef<'tcx>> {
+    match place.as_ref().last_projection() {
+        Some((place_base, ProjectionElem::Deref)) => {
+            // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
+            // that points to the allocation for the static. Don't treat these as reborrows.
+            if body.local_decls[place_base.local].is_ref_to_static() {
+                None
+            } else {
+                // Ensure the type being derefed is a reference and not a raw pointer.
+                // This is sufficient to prevent an access to a `static mut` from being marked as a
+                // reborrow, even if the check above were to disappear.
+                let inner_ty = place_base.ty(body, tcx).ty;
+
+                if let ty::Ref(..) = inner_ty.kind() {
+                    return Some(place_base);
+                } else {
+                    return None;
+                }
+            }
+        }
+        _ => None,
+    }
+}
+
+fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
+    ty.is_bool() || ty.is_integral() || ty.is_char()
+}
+
+fn is_async_fn(ccx: &ConstCx<'_, '_>) -> bool {
+    ccx.fn_sig().map_or(false, |sig| sig.header.asyncness == hir::IsAsync::Async)
+}
+
+fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) {
+    let attr_span = ccx.fn_sig().map_or(ccx.body.span, |sig| sig.span.shrink_to_lo());
+
+    ccx.tcx
+        .sess
+        .struct_span_err(
+            span,
+            &format!("const-stable function cannot use `#[feature({})]`", gate.as_str()),
+        )
+        .span_suggestion(
+            attr_span,
+            "if it is not part of the public API, make this function unstably const",
+            concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
+            Applicability::HasPlaceholders,
+        )
+        .span_suggestion(
+            attr_span,
+            "otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks",
+            format!("#[rustc_allow_const_fn_unstable({})]\n", gate),
+            Applicability::MaybeIncorrect,
+        )
+        .emit();
+}
index 19aee033a6923fb1cda51eef51fe67efb3999160..0ca086d74db7b318bee90f366bd3e54f3f7b8bc6 100644 (file)
 
 pub use self::qualifs::Qualif;
 
+pub mod check;
 mod ops;
 pub mod post_drop_elaboration;
 pub mod qualifs;
 mod resolver;
-pub mod validation;
 
 /// Information about the item currently being const-checked, as well as a reference to the global
 /// context.
index 057092b8ef574884b6970c370e4f5c3325fa1fc1..b08ce219034ce09eb5b38d2b4dd7fcea7b7b5959 100644 (file)
@@ -3,9 +3,9 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
+use super::check::Qualifs;
 use super::ops::{self, NonConstOp};
 use super::qualifs::{NeedsDrop, Qualif};
-use super::validation::Qualifs;
 use super::ConstCx;
 
 /// Returns `true` if we should use the more precise live drop checker that runs after drop
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
deleted file mode 100644 (file)
index cfc538e..0000000
+++ /dev/null
@@ -1,1104 +0,0 @@
-//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
-
-use rustc_errors::{Applicability, Diagnostic, ErrorReported};
-use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, HirId, LangItem};
-use rustc_index::bit_set::BitSet;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
-use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::*;
-use rustc_middle::ty::cast::CastTy;
-use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
-use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
-use rustc_span::{sym, Span, Symbol};
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
-
-use std::mem;
-use std::ops::Deref;
-
-use super::ops::{self, NonConstOp, Status};
-use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
-use super::resolver::FlowSensitiveAnalysis;
-use super::{is_lang_panic_fn, ConstCx, Qualif};
-use crate::const_eval::is_unstable_const_fn;
-use crate::dataflow::impls::MaybeMutBorrowedLocals;
-use crate::dataflow::{self, Analysis};
-
-// We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated
-// through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals`
-// kills locals upon `StorageDead` because a local will never be used after a `StorageDead`.
-type IndirectlyMutableResults<'mir, 'tcx> =
-    dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
-
-type QualifResults<'mir, 'tcx, Q> =
-    dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
-
-#[derive(Default)]
-pub struct Qualifs<'mir, 'tcx> {
-    has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
-    needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
-    indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
-}
-
-impl Qualifs<'mir, 'tcx> {
-    pub fn indirectly_mutable(
-        &mut self,
-        ccx: &'mir ConstCx<'mir, 'tcx>,
-        local: Local,
-        location: Location,
-    ) -> bool {
-        let indirectly_mutable = self.indirectly_mutable.get_or_insert_with(|| {
-            let ConstCx { tcx, body, param_env, .. } = *ccx;
-
-            // We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
-            // allowed in a const.
-            //
-            // FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
-            // without breaking stable code?
-            MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
-                .unsound_ignore_borrow_on_drop()
-                .into_engine(tcx, &body)
-                .pass_name("const_qualification")
-                .iterate_to_fixpoint()
-                .into_results_cursor(&body)
-        });
-
-        indirectly_mutable.seek_before_primary_effect(location);
-        indirectly_mutable.get().contains(local)
-    }
-
-    /// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
-    ///
-    /// Only updates the cursor if absolutely necessary
-    pub fn needs_drop(
-        &mut self,
-        ccx: &'mir ConstCx<'mir, 'tcx>,
-        local: Local,
-        location: Location,
-    ) -> bool {
-        let ty = ccx.body.local_decls[local].ty;
-        if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
-            return false;
-        }
-
-        let needs_drop = self.needs_drop.get_or_insert_with(|| {
-            let ConstCx { tcx, body, .. } = *ccx;
-
-            FlowSensitiveAnalysis::new(NeedsDrop, ccx)
-                .into_engine(tcx, &body)
-                .iterate_to_fixpoint()
-                .into_results_cursor(&body)
-        });
-
-        needs_drop.seek_before_primary_effect(location);
-        needs_drop.get().contains(local) || self.indirectly_mutable(ccx, local, location)
-    }
-
-    /// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
-    ///
-    /// Only updates the cursor if absolutely necessary.
-    pub fn has_mut_interior(
-        &mut self,
-        ccx: &'mir ConstCx<'mir, 'tcx>,
-        local: Local,
-        location: Location,
-    ) -> bool {
-        let ty = ccx.body.local_decls[local].ty;
-        if !HasMutInterior::in_any_value_of_ty(ccx, ty) {
-            return false;
-        }
-
-        let has_mut_interior = self.has_mut_interior.get_or_insert_with(|| {
-            let ConstCx { tcx, body, .. } = *ccx;
-
-            FlowSensitiveAnalysis::new(HasMutInterior, ccx)
-                .into_engine(tcx, &body)
-                .iterate_to_fixpoint()
-                .into_results_cursor(&body)
-        });
-
-        has_mut_interior.seek_before_primary_effect(location);
-        has_mut_interior.get().contains(local) || self.indirectly_mutable(ccx, local, location)
-    }
-
-    fn in_return_place(
-        &mut self,
-        ccx: &'mir ConstCx<'mir, 'tcx>,
-        error_occured: Option<ErrorReported>,
-    ) -> ConstQualifs {
-        // Find the `Return` terminator if one exists.
-        //
-        // If no `Return` terminator exists, this MIR is divergent. Just return the conservative
-        // qualifs for the return type.
-        let return_block = ccx
-            .body
-            .basic_blocks()
-            .iter_enumerated()
-            .find(|(_, block)| match block.terminator().kind {
-                TerminatorKind::Return => true,
-                _ => false,
-            })
-            .map(|(bb, _)| bb);
-
-        let return_block = match return_block {
-            None => return qualifs::in_any_value_of_ty(ccx, ccx.body.return_ty(), error_occured),
-            Some(bb) => bb,
-        };
-
-        let return_loc = ccx.body.terminator_loc(return_block);
-
-        let custom_eq = match ccx.const_kind() {
-            // We don't care whether a `const fn` returns a value that is not structurally
-            // matchable. Functions calls are opaque and always use type-based qualification, so
-            // this value should never be used.
-            hir::ConstContext::ConstFn => true,
-
-            // If we know that all values of the return type are structurally matchable, there's no
-            // need to run dataflow.
-            _ if !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => false,
-
-            hir::ConstContext::Const | hir::ConstContext::Static(_) => {
-                let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
-                    .into_engine(ccx.tcx, &ccx.body)
-                    .iterate_to_fixpoint()
-                    .into_results_cursor(&ccx.body);
-
-                cursor.seek_after_primary_effect(return_loc);
-                cursor.contains(RETURN_PLACE)
-            }
-        };
-
-        ConstQualifs {
-            needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
-            has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
-            custom_eq,
-            error_occured,
-        }
-    }
-}
-
-pub struct Validator<'mir, 'tcx> {
-    ccx: &'mir ConstCx<'mir, 'tcx>,
-    qualifs: Qualifs<'mir, 'tcx>,
-
-    /// The span of the current statement.
-    span: Span,
-
-    /// A set that stores for each local whether it has a `StorageDead` for it somewhere.
-    local_has_storage_dead: Option<BitSet<Local>>,
-
-    error_emitted: Option<ErrorReported>,
-    secondary_errors: Vec<Diagnostic>,
-}
-
-impl Deref for Validator<'mir, 'tcx> {
-    type Target = ConstCx<'mir, 'tcx>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.ccx
-    }
-}
-
-impl Validator<'mir, 'tcx> {
-    pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
-        Validator {
-            span: ccx.body.span,
-            ccx,
-            qualifs: Default::default(),
-            local_has_storage_dead: None,
-            error_emitted: None,
-            secondary_errors: Vec::new(),
-        }
-    }
-
-    pub fn check_body(&mut self) {
-        let ConstCx { tcx, body, .. } = *self.ccx;
-        let def_id = self.ccx.def_id();
-
-        // `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
-        // no need to emit duplicate errors here.
-        if is_async_fn(self.ccx) || body.generator.is_some() {
-            tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`");
-            return;
-        }
-
-        // The local type and predicate checks are not free and only relevant for `const fn`s.
-        if self.const_kind() == hir::ConstContext::ConstFn {
-            // Prevent const trait methods from being annotated as `stable`.
-            // FIXME: Do this as part of stability checking.
-            if self.is_const_stable_const_fn() {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
-                    self.ccx
-                        .tcx
-                        .sess
-                        .struct_span_err(self.span, "trait methods cannot be stable const fn")
-                        .emit();
-                }
-            }
-
-            self.check_item_predicates();
-
-            for (idx, local) in body.local_decls.iter_enumerated() {
-                // Handle the return place below.
-                if idx == RETURN_PLACE || local.internal {
-                    continue;
-                }
-
-                self.span = local.source_info.span;
-                self.check_local_or_return_ty(local.ty, idx);
-            }
-
-            // impl trait is gone in MIR, so check the return type of a const fn by its signature
-            // instead of the type of the return place.
-            self.span = body.local_decls[RETURN_PLACE].source_info.span;
-            let return_ty = tcx.fn_sig(def_id).output();
-            self.check_local_or_return_ty(return_ty.skip_binder(), RETURN_PLACE);
-        }
-
-        self.visit_body(&body);
-
-        // Ensure that the end result is `Sync` in a non-thread local `static`.
-        let should_check_for_sync = self.const_kind()
-            == hir::ConstContext::Static(hir::Mutability::Not)
-            && !tcx.is_thread_local_static(def_id.to_def_id());
-
-        if should_check_for_sync {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-            check_return_ty_is_sync(tcx, &body, hir_id);
-        }
-
-        // If we got through const-checking without emitting any "primary" errors, emit any
-        // "secondary" errors if they occurred.
-        let secondary_errors = mem::take(&mut self.secondary_errors);
-        if self.error_emitted.is_none() {
-            for error in secondary_errors {
-                self.tcx.sess.diagnostic().emit_diagnostic(&error);
-            }
-        } else {
-            assert!(self.tcx.sess.has_errors());
-        }
-    }
-
-    fn local_has_storage_dead(&mut self, local: Local) -> bool {
-        let ccx = self.ccx;
-        self.local_has_storage_dead
-            .get_or_insert_with(|| {
-                struct StorageDeads {
-                    locals: BitSet<Local>,
-                }
-                impl Visitor<'tcx> for StorageDeads {
-                    fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) {
-                        if let StatementKind::StorageDead(l) = stmt.kind {
-                            self.locals.insert(l);
-                        }
-                    }
-                }
-                let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) };
-                v.visit_body(ccx.body);
-                v.locals
-            })
-            .contains(local)
-    }
-
-    pub fn qualifs_in_return_place(&mut self) -> ConstQualifs {
-        self.qualifs.in_return_place(self.ccx, self.error_emitted)
-    }
-
-    /// Emits an error if an expression cannot be evaluated in the current context.
-    pub fn check_op(&mut self, op: impl NonConstOp) {
-        self.check_op_spanned(op, self.span);
-    }
-
-    /// Emits an error at the given `span` if an expression cannot be evaluated in the current
-    /// context.
-    pub fn check_op_spanned<O: NonConstOp>(&mut self, op: O, span: Span) {
-        let gate = match op.status_in_item(self.ccx) {
-            Status::Allowed => return,
-
-            Status::Unstable(gate) if self.tcx.features().enabled(gate) => {
-                let unstable_in_stable = self.ccx.is_const_stable_const_fn()
-                    && !super::rustc_allow_const_fn_unstable(
-                        self.tcx,
-                        self.def_id().to_def_id(),
-                        gate,
-                    );
-                if unstable_in_stable {
-                    emit_unstable_in_stable_error(self.ccx, span, gate);
-                }
-
-                return;
-            }
-
-            Status::Unstable(gate) => Some(gate),
-            Status::Forbidden => None,
-        };
-
-        if self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
-            self.tcx.sess.miri_unleashed_feature(span, gate);
-            return;
-        }
-
-        let mut err = op.build_error(self.ccx, span);
-        assert!(err.is_error());
-
-        match op.importance() {
-            ops::DiagnosticImportance::Primary => {
-                self.error_emitted = Some(ErrorReported);
-                err.emit();
-            }
-
-            ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),
-        }
-    }
-
-    fn check_static(&mut self, def_id: DefId, span: Span) {
-        if self.tcx.is_thread_local_static(def_id) {
-            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
-        }
-        self.check_op_spanned(ops::StaticAccess, span)
-    }
-
-    fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
-        let kind = self.body.local_kind(local);
-
-        for ty in ty.walk() {
-            let ty = match ty.unpack() {
-                GenericArgKind::Type(ty) => ty,
-
-                // No constraints on lifetimes or constants, except potentially
-                // constants' types, but `walk` will get to them as well.
-                GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue,
-            };
-
-            match *ty.kind() {
-                ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)),
-                ty::Opaque(..) => self.check_op(ops::ty::ImplTrait),
-                ty::FnPtr(..) => self.check_op(ops::ty::FnPtr(kind)),
-
-                ty::Dynamic(preds, _) => {
-                    for pred in preds.iter() {
-                        match pred.skip_binder() {
-                            ty::ExistentialPredicate::AutoTrait(_)
-                            | ty::ExistentialPredicate::Projection(_) => {
-                                self.check_op(ops::ty::TraitBound(kind))
-                            }
-                            ty::ExistentialPredicate::Trait(trait_ref) => {
-                                if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() {
-                                    self.check_op(ops::ty::TraitBound(kind))
-                                }
-                            }
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
-    }
-
-    fn check_item_predicates(&mut self) {
-        let ConstCx { tcx, .. } = *self.ccx;
-
-        let mut current = self.def_id().to_def_id();
-        loop {
-            let predicates = tcx.predicates_of(current);
-            for (predicate, _) in predicates.predicates {
-                match predicate.kind().skip_binder() {
-                    ty::PredicateKind::RegionOutlives(_)
-                    | ty::PredicateKind::TypeOutlives(_)
-                    | ty::PredicateKind::WellFormed(_)
-                    | ty::PredicateKind::Projection(_)
-                    | ty::PredicateKind::ConstEvaluatable(..)
-                    | ty::PredicateKind::ConstEquate(..)
-                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
-                    ty::PredicateKind::ObjectSafe(_) => {
-                        bug!("object safe predicate on function: {:#?}", predicate)
-                    }
-                    ty::PredicateKind::ClosureKind(..) => {
-                        bug!("closure kind predicate on function: {:#?}", predicate)
-                    }
-                    ty::PredicateKind::Subtype(_) => {
-                        bug!("subtype predicate on function: {:#?}", predicate)
-                    }
-                    ty::PredicateKind::Trait(pred, _constness) => {
-                        if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
-                            continue;
-                        }
-                        match pred.self_ty().kind() {
-                            ty::Param(p) => {
-                                let generics = tcx.generics_of(current);
-                                let def = generics.type_param(p, tcx);
-                                let span = tcx.def_span(def.def_id);
-
-                                // These are part of the function signature, so treat them like
-                                // arguments when determining importance.
-                                let kind = LocalKind::Arg;
-
-                                self.check_op_spanned(ops::ty::TraitBound(kind), span);
-                            }
-                            // other kinds of bounds are either tautologies
-                            // or cause errors in other passes
-                            _ => continue,
-                        }
-                    }
-                }
-            }
-            match predicates.parent {
-                Some(parent) => current = parent,
-                None => break,
-            }
-        }
-    }
-
-    fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
-        match self.const_kind() {
-            // In a const fn all borrows are transient or point to the places given via
-            // references in the arguments (so we already checked them with
-            // TransientMutBorrow/MutBorrow as appropriate).
-            // The borrow checker guarantees that no new non-transient borrows are created.
-            // NOTE: Once we have heap allocations during CTFE we need to figure out
-            // how to prevent `const fn` to create long-lived allocations that point
-            // to mutable memory.
-            hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
-            _ => {
-                // Locals with StorageDead do not live beyond the evaluation and can
-                // thus safely be borrowed without being able to be leaked to the final
-                // value of the constant.
-                if self.local_has_storage_dead(local) {
-                    self.check_op(ops::TransientMutBorrow(kind));
-                } else {
-                    self.check_op(ops::MutBorrow(kind));
-                }
-            }
-        }
-    }
-}
-
-impl Visitor<'tcx> for Validator<'mir, 'tcx> {
-    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) {
-        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
-
-        // We don't const-check basic blocks on the cleanup path since we never unwind during
-        // const-eval: a panic causes an immediate compile error. In other words, cleanup blocks
-        // are unreachable during const-eval.
-        //
-        // We can't be more conservative (e.g., by const-checking cleanup blocks anyways) because
-        // locals that would never be dropped during normal execution are sometimes dropped during
-        // unwinding, which means backwards-incompatible live-drop errors.
-        if block.is_cleanup {
-            return;
-        }
-
-        self.super_basic_block_data(bb, block);
-    }
-
-    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
-
-        // Special-case reborrows to be more like a copy of a reference.
-        match *rvalue {
-            Rvalue::Ref(_, kind, place) => {
-                if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
-                    let ctx = match kind {
-                        BorrowKind::Shared => {
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
-                        }
-                        BorrowKind::Shallow => {
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
-                        }
-                        BorrowKind::Unique => {
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
-                        }
-                        BorrowKind::Mut { .. } => {
-                            PlaceContext::MutatingUse(MutatingUseContext::Borrow)
-                        }
-                    };
-                    self.visit_local(&reborrowed_place_ref.local, ctx, location);
-                    self.visit_projection(reborrowed_place_ref, ctx, location);
-                    return;
-                }
-            }
-            Rvalue::AddressOf(mutbl, place) => {
-                if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
-                    let ctx = match mutbl {
-                        Mutability::Not => {
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
-                        }
-                        Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
-                    };
-                    self.visit_local(&reborrowed_place_ref.local, ctx, location);
-                    self.visit_projection(reborrowed_place_ref, ctx, location);
-                    return;
-                }
-            }
-            _ => {}
-        }
-
-        self.super_rvalue(rvalue, location);
-
-        match *rvalue {
-            Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess),
-
-            Rvalue::Use(_)
-            | Rvalue::Repeat(..)
-            | Rvalue::Discriminant(..)
-            | Rvalue::Len(_)
-            | Rvalue::Aggregate(..) => {}
-
-            Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place)
-            | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => {
-                let ty = place.ty(self.body, self.tcx).ty;
-                let is_allowed = match ty.kind() {
-                    // Inside a `static mut`, `&mut [...]` is allowed.
-                    ty::Array(..) | ty::Slice(_)
-                        if self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut) =>
-                    {
-                        true
-                    }
-
-                    // FIXME(ecstaticmorse): We could allow `&mut []` inside a const context given
-                    // that this is merely a ZST and it is already eligible for promotion.
-                    // This may require an RFC?
-                    /*
-                    ty::Array(_, len) if len.try_eval_usize(cx.tcx, cx.param_env) == Some(0)
-                        => true,
-                    */
-                    _ => false,
-                };
-
-                if !is_allowed {
-                    if let BorrowKind::Mut { .. } = kind {
-                        self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
-                    } else {
-                        self.check_op(ops::CellBorrow);
-                    }
-                }
-            }
-
-            Rvalue::AddressOf(Mutability::Mut, ref place) => {
-                self.check_mut_borrow(place.local, hir::BorrowKind::Raw)
-            }
-
-            Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, ref place)
-            | Rvalue::AddressOf(Mutability::Not, ref place) => {
-                let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
-                    &self.ccx,
-                    &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
-                    place.as_ref(),
-                );
-
-                if borrowed_place_has_mut_interior {
-                    match self.const_kind() {
-                        // In a const fn all borrows are transient or point to the places given via
-                        // references in the arguments (so we already checked them with
-                        // TransientCellBorrow/CellBorrow as appropriate).
-                        // The borrow checker guarantees that no new non-transient borrows are created.
-                        // NOTE: Once we have heap allocations during CTFE we need to figure out
-                        // how to prevent `const fn` to create long-lived allocations that point
-                        // to (interior) mutable memory.
-                        hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow),
-                        _ => {
-                            // Locals with StorageDead are definitely not part of the final constant value, and
-                            // it is thus inherently safe to permit such locals to have their
-                            // address taken as we can't end up with a reference to them in the
-                            // final value.
-                            // Note: This is only sound if every local that has a `StorageDead` has a
-                            // `StorageDead` in every control flow path leading to a `return` terminator.
-                            if self.local_has_storage_dead(place.local) {
-                                self.check_op(ops::TransientCellBorrow);
-                            } else {
-                                self.check_op(ops::CellBorrow);
-                            }
-                        }
-                    }
-                }
-            }
-
-            Rvalue::Cast(
-                CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
-                _,
-                _,
-            ) => {}
-
-            Rvalue::Cast(
-                CastKind::Pointer(
-                    PointerCast::UnsafeFnPointer
-                    | PointerCast::ClosureFnPointer(_)
-                    | PointerCast::ReifyFnPointer,
-                ),
-                _,
-                _,
-            ) => self.check_op(ops::FnPtrCast),
-
-            Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
-                // Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
-                // in the type of any local, which also excludes casts).
-            }
-
-            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
-                let operand_ty = operand.ty(self.body, self.tcx);
-                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
-                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-
-                if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
-                    self.check_op(ops::RawPtrToIntCast);
-                }
-            }
-
-            Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
-            Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
-
-            Rvalue::UnaryOp(_, ref operand) => {
-                let ty = operand.ty(self.body, self.tcx);
-                if is_int_bool_or_char(ty) {
-                    // Int, bool, and char operations are fine.
-                } else if ty.is_floating_point() {
-                    self.check_op(ops::FloatingPointOp);
-                } else {
-                    span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
-                }
-            }
-
-            Rvalue::BinaryOp(op, box (ref lhs, ref rhs))
-            | Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
-                let lhs_ty = lhs.ty(self.body, self.tcx);
-                let rhs_ty = rhs.ty(self.body, self.tcx);
-
-                if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) {
-                    // Int, bool, and char operations are fine.
-                } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
-                    assert_eq!(lhs_ty, rhs_ty);
-                    assert!(
-                        op == BinOp::Eq
-                            || op == BinOp::Ne
-                            || op == BinOp::Le
-                            || op == BinOp::Lt
-                            || op == BinOp::Ge
-                            || op == BinOp::Gt
-                            || op == BinOp::Offset
-                    );
-
-                    self.check_op(ops::RawPtrComparison);
-                } else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() {
-                    self.check_op(ops::FloatingPointOp);
-                } else {
-                    span_bug!(
-                        self.span,
-                        "non-primitive type in `Rvalue::BinaryOp`: {:?} âš¬ {:?}",
-                        lhs_ty,
-                        rhs_ty
-                    );
-                }
-            }
-        }
-    }
-
-    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
-        self.super_operand(op, location);
-        if let Operand::Constant(c) = op {
-            if let Some(def_id) = c.check_static_ptr(self.tcx) {
-                self.check_static(def_id, self.span);
-            }
-        }
-    }
-    fn visit_projection_elem(
-        &mut self,
-        place_local: Local,
-        proj_base: &[PlaceElem<'tcx>],
-        elem: PlaceElem<'tcx>,
-        context: PlaceContext,
-        location: Location,
-    ) {
-        trace!(
-            "visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
-            context={:?} location={:?}",
-            place_local,
-            proj_base,
-            elem,
-            context,
-            location,
-        );
-
-        self.super_projection_elem(place_local, proj_base, elem, context, location);
-
-        match elem {
-            ProjectionElem::Deref => {
-                let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
-                if let ty::RawPtr(_) = base_ty.kind() {
-                    if proj_base.is_empty() {
-                        let decl = &self.body.local_decls[place_local];
-                        if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
-                            let span = decl.source_info.span;
-                            self.check_static(def_id, span);
-                            return;
-                        }
-                    }
-                    self.check_op(ops::RawPtrDeref);
-                }
-
-                if context.is_mutating_use() {
-                    self.check_op(ops::MutDeref);
-                }
-            }
-
-            ProjectionElem::ConstantIndex { .. }
-            | ProjectionElem::Downcast(..)
-            | ProjectionElem::Subslice { .. }
-            | ProjectionElem::Field(..)
-            | ProjectionElem::Index(_) => {
-                let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
-                if base_ty.is_union() {
-                    self.check_op(ops::UnionAccess);
-                }
-            }
-        }
-    }
-
-    fn visit_source_info(&mut self, source_info: &SourceInfo) {
-        trace!("visit_source_info: source_info={:?}", source_info);
-        self.span = source_info.span;
-    }
-
-    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
-        trace!("visit_statement: statement={:?} location={:?}", statement, location);
-
-        self.super_statement(statement, location);
-
-        match statement.kind {
-            StatementKind::LlvmInlineAsm { .. } => {
-                self.check_op(ops::InlineAsm);
-            }
-
-            StatementKind::Assign(..)
-            | StatementKind::SetDiscriminant { .. }
-            | StatementKind::FakeRead(..)
-            | StatementKind::StorageLive(_)
-            | StatementKind::StorageDead(_)
-            | StatementKind::Retag { .. }
-            | StatementKind::AscribeUserType(..)
-            | StatementKind::Coverage(..)
-            | StatementKind::CopyNonOverlapping(..)
-            | StatementKind::Nop => {}
-        }
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-        use rustc_target::spec::abi::Abi::RustIntrinsic;
-
-        self.super_terminator(terminator, location);
-
-        match &terminator.kind {
-            TerminatorKind::Call { func, args, .. } => {
-                let ConstCx { tcx, body, param_env, .. } = *self.ccx;
-                let caller = self.def_id().to_def_id();
-
-                let fn_ty = func.ty(body, tcx);
-
-                let (mut callee, substs) = match *fn_ty.kind() {
-                    ty::FnDef(def_id, substs) => (def_id, substs),
-
-                    ty::FnPtr(_) => {
-                        self.check_op(ops::FnCallIndirect);
-                        return;
-                    }
-                    _ => {
-                        span_bug!(terminator.source_info.span, "invalid callee of type {:?}", fn_ty)
-                    }
-                };
-
-                // Attempting to call a trait method?
-                if let Some(trait_id) = tcx.trait_of_item(callee) {
-                    trace!("attempting to call a trait method");
-                    if !self.tcx.features().const_trait_impl {
-                        self.check_op(ops::FnCallNonConst);
-                        return;
-                    }
-
-                    let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
-                    let obligation = Obligation::new(
-                        ObligationCause::dummy(),
-                        param_env,
-                        Binder::dummy(TraitPredicate { trait_ref }),
-                    );
-
-                    let implsrc = tcx.infer_ctxt().enter(|infcx| {
-                        let mut selcx = SelectionContext::new(&infcx);
-                        selcx.select(&obligation).unwrap()
-                    });
-
-                    // If the method is provided via a where-clause that does not use the `?const`
-                    // opt-out, the call is allowed.
-                    if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc {
-                        debug!(
-                            "const_trait_impl: provided {:?} via where-clause in {:?}",
-                            trait_ref, param_env
-                        );
-                        return;
-                    }
-
-                    // Resolve a trait method call to its concrete implementation, which may be in a
-                    // `const` trait impl.
-                    let instance = Instance::resolve(tcx, param_env, callee, substs);
-                    debug!("Resolving ({:?}) -> {:?}", callee, instance);
-                    if let Ok(Some(func)) = instance {
-                        if let InstanceDef::Item(def) = func.def {
-                            callee = def.did;
-                        }
-                    }
-                }
-
-                // At this point, we are calling a function, `callee`, whose `DefId` is known...
-                if is_lang_panic_fn(tcx, callee) {
-                    self.check_op(ops::Panic);
-
-                    // const-eval of the `begin_panic` fn assumes the argument is `&str`
-                    if Some(callee) == tcx.lang_items().begin_panic_fn() {
-                        match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
-                            ty::Ref(_, ty, _) if ty.is_str() => (),
-                            _ => self.check_op(ops::PanicNonStr),
-                        }
-                    }
-
-                    return;
-                }
-
-                // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
-                let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
-                if is_async_block {
-                    let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block);
-                    self.check_op(ops::Generator(kind));
-                    return;
-                }
-
-                let is_intrinsic = tcx.fn_sig(callee).abi() == RustIntrinsic;
-
-                // HACK: This is to "unstabilize" the `transmute` intrinsic
-                // within const fns. `transmute` is allowed in all other const contexts.
-                // This won't really scale to more intrinsics or functions. Let's allow const
-                // transmutes in const fn before we add more hacks to this.
-                if is_intrinsic && tcx.item_name(callee) == sym::transmute {
-                    self.check_op(ops::Transmute);
-                    return;
-                }
-
-                if !tcx.is_const_fn_raw(callee) {
-                    let mut permitted = false;
-
-                    let callee_trait = tcx.trait_of_item(callee);
-                    if let Some(trait_id) = callee_trait {
-                        if tcx.has_attr(caller, sym::default_method_body_is_const) {
-                            // permit call to non-const fn when caller has default_method_body_is_const..
-                            if tcx.trait_of_item(caller) == callee_trait {
-                                // ..and caller and callee are in the same trait.
-                                permitted = true;
-                            }
-                        }
-                        if !permitted {
-                            // if trait's impls are all const, permit the call.
-                            let mut const_impls = true;
-                            tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| {
-                                if const_impls {
-                                    if let hir::Constness::NotConst = tcx.impl_constness(imp) {
-                                        const_impls = false;
-                                    }
-                                }
-                            });
-                            if const_impls {
-                                permitted = true;
-                            }
-                        }
-                    }
-
-                    if !permitted {
-                        self.check_op(ops::FnCallNonConst);
-                        return;
-                    }
-                }
-
-                // If the `const fn` we are trying to call is not const-stable, ensure that we have
-                // the proper feature gate enabled.
-                if let Some(gate) = is_unstable_const_fn(tcx, callee) {
-                    trace!(?gate, "calling unstable const fn");
-                    if self.span.allows_unstable(gate) {
-                        return;
-                    }
-
-                    // Calling an unstable function *always* requires that the corresponding gate
-                    // be enabled, even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`.
-                    if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
-                        self.check_op(ops::FnCallUnstable(callee, Some(gate)));
-                        return;
-                    }
-
-                    // If this crate is not using stability attributes, or the caller is not claiming to be a
-                    // stable `const fn`, that is all that is required.
-                    if !self.ccx.is_const_stable_const_fn() {
-                        trace!("crate not using stability attributes or caller not stably const");
-                        return;
-                    }
-
-                    // Otherwise, we are something const-stable calling a const-unstable fn.
-
-                    if super::rustc_allow_const_fn_unstable(tcx, caller, gate) {
-                        trace!("rustc_allow_const_fn_unstable gate active");
-                        return;
-                    }
-
-                    self.check_op(ops::FnCallUnstable(callee, Some(gate)));
-                    return;
-                }
-
-                // FIXME(ecstaticmorse); For compatibility, we consider `unstable` callees that
-                // have no `rustc_const_stable` attributes to be const-unstable as well. This
-                // should be fixed later.
-                let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none()
-                    && tcx.lookup_stability(callee).map_or(false, |s| s.level.is_unstable());
-                if callee_is_unstable_unmarked {
-                    trace!("callee_is_unstable_unmarked");
-                    // We do not use `const` modifiers for intrinsic "functions", as intrinsics are
-                    // `extern` funtions, and these have no way to get marked `const`. So instead we
-                    // use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
-                    if self.ccx.is_const_stable_const_fn() || is_intrinsic {
-                        self.check_op(ops::FnCallUnstable(callee, None));
-                        return;
-                    }
-                }
-                trace!("permitting call");
-            }
-
-            // Forbid all `Drop` terminators unless the place being dropped is a local with no
-            // projections that cannot be `NeedsDrop`.
-            TerminatorKind::Drop { place: dropped_place, .. }
-            | TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
-                // If we are checking live drops after drop-elaboration, don't emit duplicate
-                // errors here.
-                if super::post_drop_elaboration::checking_enabled(self.ccx) {
-                    return;
-                }
-
-                let mut err_span = self.span;
-
-                // Check to see if the type of this place can ever have a drop impl. If not, this
-                // `Drop` terminator is frivolous.
-                let ty_needs_drop =
-                    dropped_place.ty(self.body, self.tcx).ty.needs_drop(self.tcx, self.param_env);
-
-                if !ty_needs_drop {
-                    return;
-                }
-
-                let needs_drop = if let Some(local) = dropped_place.as_local() {
-                    // Use the span where the local was declared as the span of the drop error.
-                    err_span = self.body.local_decls[local].source_info.span;
-                    self.qualifs.needs_drop(self.ccx, local, location)
-                } else {
-                    true
-                };
-
-                if needs_drop {
-                    self.check_op_spanned(
-                        ops::LiveDrop { dropped_at: Some(terminator.source_info.span) },
-                        err_span,
-                    );
-                }
-            }
-
-            TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
-
-            TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
-                self.check_op(ops::Generator(hir::GeneratorKind::Gen))
-            }
-
-            TerminatorKind::Abort => {
-                // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
-                span_bug!(self.span, "`Abort` terminator outside of cleanup block")
-            }
-
-            TerminatorKind::Assert { .. }
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::FalseUnwind { .. }
-            | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Return
-            | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Unreachable => {}
-        }
-    }
-}
-
-fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) {
-    let ty = body.return_ty();
-    tcx.infer_ctxt().enter(|infcx| {
-        let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic);
-        let mut fulfillment_cx = traits::FulfillmentContext::new();
-        let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
-        fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
-        if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&err, None, false);
-        }
-    });
-}
-
-fn place_as_reborrow(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    place: Place<'tcx>,
-) -> Option<PlaceRef<'tcx>> {
-    match place.as_ref().last_projection() {
-        Some((place_base, ProjectionElem::Deref)) => {
-            // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
-            // that points to the allocation for the static. Don't treat these as reborrows.
-            if body.local_decls[place_base.local].is_ref_to_static() {
-                None
-            } else {
-                // Ensure the type being derefed is a reference and not a raw pointer.
-                // This is sufficient to prevent an access to a `static mut` from being marked as a
-                // reborrow, even if the check above were to disappear.
-                let inner_ty = place_base.ty(body, tcx).ty;
-
-                if let ty::Ref(..) = inner_ty.kind() {
-                    return Some(place_base);
-                } else {
-                    return None;
-                }
-            }
-        }
-        _ => None,
-    }
-}
-
-fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
-    ty.is_bool() || ty.is_integral() || ty.is_char()
-}
-
-fn is_async_fn(ccx: &ConstCx<'_, '_>) -> bool {
-    ccx.fn_sig().map_or(false, |sig| sig.header.asyncness == hir::IsAsync::Async)
-}
-
-fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) {
-    let attr_span = ccx.fn_sig().map_or(ccx.body.span, |sig| sig.span.shrink_to_lo());
-
-    ccx.tcx
-        .sess
-        .struct_span_err(
-            span,
-            &format!("const-stable function cannot use `#[feature({})]`", gate.as_str()),
-        )
-        .span_suggestion(
-            attr_span,
-            "if it is not part of the public API, make this function unstably const",
-            concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
-            Applicability::HasPlaceholders,
-        )
-        .span_suggestion(
-            attr_span,
-            "otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks",
-            format!("#[rustc_allow_const_fn_unstable({})]\n", gate),
-            Applicability::MaybeIncorrect,
-        )
-        .emit();
-}
index 5c201594ddd895f574f7122ea9576ffd4ee34ec7..3fbc81d5426eea5abad1bc4a0ccc1c39f2bfc10d 100644 (file)
@@ -48,6 +48,7 @@
 pub mod remove_zsts;
 pub mod required_consts;
 pub mod rustc_peek;
+pub mod separate_const_switch;
 pub mod simplify;
 pub mod simplify_branches;
 pub mod simplify_comparison_integral;
@@ -240,7 +241,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
 
     let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def.did) };
 
-    let mut validator = check_consts::validation::Validator::new(&ccx);
+    let mut validator = check_consts::check::Checker::new(&ccx);
     validator.check_body();
 
     // We return the qualifs in the return place for every MIR body, even though it is only used
@@ -501,6 +502,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // 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,
diff --git a/compiler/rustc_mir/src/transform/separate_const_switch.rs b/compiler/rustc_mir/src/transform/separate_const_switch.rs
new file mode 100644 (file)
index 0000000..87cd279
--- /dev/null
@@ -0,0 +1,343 @@
+//! A pass that duplicates switch-terminated blocks
+//! into a new copy for each predecessor, provided
+//! the predecessor sets the value being switched
+//! over to a constant.
+//!
+//! The purpose of this pass is to help constant
+//! propagation passes to simplify the switch terminator
+//! of the copied blocks into gotos when some predecessors
+//! statically determine the output of switches.
+//!
+//! ```text
+//!     x = 12 ---              ---> something
+//!               \            / 12
+//!                --> switch x
+//!               /            \ otherwise
+//!     x = y  ---              ---> something else
+//! ```
+//! becomes
+//! ```text
+//!     x = 12 ---> switch x ------> something
+//!                          \ / 12
+//!                           X
+//!                          / \ otherwise
+//!     x = y  ---> switch x ------> something else
+//! ```
+//! so it can hopefully later be turned by another pass into
+//! ```text
+//!     x = 12 --------------------> something
+//!                            / 12
+//!                           /
+//!                          /   otherwise
+//!     x = y  ---- switch x ------> something else
+//! ```
+//!
+//! This optimization is meant to cover simple cases
+//! like `?` desugaring. For now, it thus focuses on
+//! simplicity rather than completeness (it notably
+//! sometimes duplicates abusively).
+
+use crate::transform::MirPass;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use smallvec::SmallVec;
+
+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;
+        }
+
+        // If execution did something, applying a simplification layer
+        // helps later passes optimize the copy away.
+        if separate_const_switch(body) > 0 {
+            super::simplify::simplify_cfg(tcx, body);
+        }
+    }
+}
+
+/// Returns the amount of blocks that were duplicated
+pub fn separate_const_switch<'tcx>(body: &mut Body<'tcx>) -> usize {
+    let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new();
+    let predecessors = body.predecessors();
+    'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() {
+        if let TerminatorKind::SwitchInt {
+            discr: Operand::Copy(switch_place) | Operand::Move(switch_place),
+            ..
+        } = block.terminator().kind
+        {
+            // If the block is on an unwind path, do not
+            // apply the optimization as unwind paths
+            // rely on a unique parent invariant
+            if block.is_cleanup {
+                continue 'block_iter;
+            }
+
+            // If the block has fewer than 2 predecessors, ignore it
+            // we could maybe chain blocks that have exactly one
+            // predecessor, but for now we ignore that
+            if predecessors[block_id].len() < 2 {
+                continue 'block_iter;
+            }
+
+            // First, let's find a non-const place
+            // that determines the result of the switch
+            if let Some(switch_place) = find_determining_place(switch_place, block) {
+                // We now have an input place for which it would
+                // be interesting if predecessors assigned it from a const
+
+                let mut predecessors_left = predecessors[block_id].len();
+                'predec_iter: for predecessor_id in predecessors[block_id].iter().copied() {
+                    let predecessor = &body.basic_blocks()[predecessor_id];
+
+                    // First we make sure the predecessor jumps
+                    // in a reasonable way
+                    match &predecessor.terminator().kind {
+                        // The following terminators are
+                        // unconditionally valid
+                        TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } => {}
+
+                        TerminatorKind::FalseEdge { real_target, .. } => {
+                            if *real_target != block_id {
+                                continue 'predec_iter;
+                            }
+                        }
+
+                        // The following terminators are not allowed
+                        TerminatorKind::Resume
+                        | TerminatorKind::Drop { .. }
+                        | TerminatorKind::DropAndReplace { .. }
+                        | TerminatorKind::Call { .. }
+                        | TerminatorKind::Assert { .. }
+                        | TerminatorKind::FalseUnwind { .. }
+                        | TerminatorKind::Yield { .. }
+                        | TerminatorKind::Abort
+                        | TerminatorKind::Return
+                        | TerminatorKind::Unreachable
+                        | TerminatorKind::InlineAsm { .. }
+                        | TerminatorKind::GeneratorDrop => {
+                            continue 'predec_iter;
+                        }
+                    }
+
+                    if is_likely_const(switch_place, predecessor) {
+                        new_blocks.push((predecessor_id, block_id));
+                        predecessors_left -= 1;
+                        if predecessors_left < 2 {
+                            // If the original block only has one predecessor left,
+                            // we have nothing left to do
+                            break 'predec_iter;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Once the analysis is done, perform the duplication
+    let body_span = body.span;
+    let copied_blocks = new_blocks.len();
+    let blocks = body.basic_blocks_mut();
+    for (pred_id, target_id) in new_blocks {
+        let new_block = blocks[target_id].clone();
+        let new_block_id = blocks.push(new_block);
+        let terminator = blocks[pred_id].terminator_mut();
+
+        match terminator.kind {
+            TerminatorKind::Goto { ref mut target } => {
+                *target = new_block_id;
+            }
+
+            TerminatorKind::FalseEdge { ref mut real_target, .. } => {
+                if *real_target == target_id {
+                    *real_target = new_block_id;
+                }
+            }
+
+            TerminatorKind::SwitchInt { ref mut targets, .. } => {
+                targets.all_targets_mut().iter_mut().for_each(|x| {
+                    if *x == target_id {
+                        *x = new_block_id;
+                    }
+                });
+            }
+
+            TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::DropAndReplace { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::Drop { .. }
+            | TerminatorKind::Call { .. }
+            | TerminatorKind::InlineAsm { .. }
+            | TerminatorKind::Yield { .. } => {
+                span_bug!(
+                    body_span,
+                    "basic block terminator had unexpected kind {:?}",
+                    &terminator.kind
+                )
+            }
+        }
+    }
+
+    copied_blocks
+}
+
+/// This function describes a rough heuristic guessing
+/// whether a place is last set with a const within the block.
+/// Notably, it will be overly pessimistic in cases that are already
+/// not handled by `separate_const_switch`.
+fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<'tcx>) -> bool {
+    for statement in block.statements.iter().rev() {
+        match &statement.kind {
+            StatementKind::Assign(assign) => {
+                if assign.0 == tracked_place {
+                    match assign.1 {
+                        // These rvalues are definitely constant
+                        Rvalue::Use(Operand::Constant(_))
+                        | Rvalue::Ref(_, _, _)
+                        | Rvalue::AddressOf(_, _)
+                        | Rvalue::Cast(_, Operand::Constant(_), _)
+                        | Rvalue::NullaryOp(_, _)
+                        | Rvalue::UnaryOp(_, Operand::Constant(_)) => return true,
+
+                        // These rvalues make things ambiguous
+                        Rvalue::Repeat(_, _)
+                        | Rvalue::ThreadLocalRef(_)
+                        | Rvalue::Len(_)
+                        | Rvalue::BinaryOp(_, _)
+                        | Rvalue::CheckedBinaryOp(_, _)
+                        | Rvalue::Aggregate(_, _) => return false,
+
+                        // These rvalues move the place to track
+                        Rvalue::Cast(_, Operand::Copy(place) | Operand::Move(place), _)
+                        | Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
+                        | Rvalue::UnaryOp(_, Operand::Copy(place) | Operand::Move(place))
+                        | Rvalue::Discriminant(place) => tracked_place = place,
+                    }
+                }
+            }
+
+            // If the discriminant is set, it is always set
+            // as a constant, so the job is done.
+            // As we are **ignoring projections**, if the place
+            // we are tracking sees its discriminant be set,
+            // that means we had to be tracking the discriminant
+            // specifically (as it is impossible to switch over
+            // an enum directly, and if we were switching over
+            // its content, we would have had to at least cast it to
+            // some variant first)
+            StatementKind::SetDiscriminant { place, .. } => {
+                if **place == tracked_place {
+                    return true;
+                }
+            }
+
+            // If inline assembly is found, we probably should
+            // not try to analyze the code
+            StatementKind::LlvmInlineAsm(_) => return false,
+
+            // These statements have no influence on the place
+            // we are interested in
+            StatementKind::FakeRead(_)
+            | StatementKind::StorageLive(_)
+            | StatementKind::Retag(_, _)
+            | StatementKind::AscribeUserType(_, _)
+            | StatementKind::Coverage(_)
+            | StatementKind::StorageDead(_)
+            | StatementKind::CopyNonOverlapping(_)
+            | StatementKind::Nop => {}
+        }
+    }
+
+    // If no good reason for the place to be const is found,
+    // give up. We could maybe go up predecessors, but in
+    // most cases giving up now should be sufficient.
+    false
+}
+
+/// Finds a unique place that entirely determines the value
+/// of `switch_place`, if it exists. This is only a heuristic.
+/// Ideally we would like to track multiple determining places
+/// for some edge cases, but one is enough for a lot of situations.
+fn find_determining_place<'tcx>(
+    mut switch_place: Place<'tcx>,
+    block: &BasicBlockData<'tcx>,
+) -> Option<Place<'tcx>> {
+    for statement in block.statements.iter().rev() {
+        match &statement.kind {
+            StatementKind::Assign(op) => {
+                if op.0 != switch_place {
+                    continue;
+                }
+
+                match op.1 {
+                    // The following rvalues move the place
+                    // that may be const in the predecessor
+                    Rvalue::Use(Operand::Move(new) | Operand::Copy(new))
+                    | Rvalue::UnaryOp(_, Operand::Copy(new) | Operand::Move(new))
+                    | Rvalue::Cast(_, Operand::Move(new) | Operand::Copy(new), _)
+                    | Rvalue::Repeat(Operand::Move(new) | Operand::Copy(new), _)
+                    | Rvalue::Discriminant(new)
+                    => switch_place = new,
+
+                    // The following rvalues might still make the block
+                    // be valid but for now we reject them
+                    Rvalue::Len(_)
+                    | Rvalue::Ref(_, _, _)
+                    | Rvalue::BinaryOp(_, _)
+                    | Rvalue::CheckedBinaryOp(_, _)
+                    | Rvalue::Aggregate(_, _)
+
+                    // The following rvalues definitely mean we cannot
+                    // or should not apply this optimization
+                    | Rvalue::Use(Operand::Constant(_))
+                    | Rvalue::Repeat(Operand::Constant(_), _)
+                    | Rvalue::ThreadLocalRef(_)
+                    | Rvalue::AddressOf(_, _)
+                    | Rvalue::NullaryOp(_, _)
+                    | Rvalue::UnaryOp(_, Operand::Constant(_))
+                    | Rvalue::Cast(_, Operand::Constant(_), _)
+                    => return None,
+                }
+            }
+
+            // These statements have no influence on the place
+            // we are interested in
+            StatementKind::FakeRead(_)
+            | StatementKind::StorageLive(_)
+            | StatementKind::StorageDead(_)
+            | StatementKind::Retag(_, _)
+            | StatementKind::AscribeUserType(_, _)
+            | StatementKind::Coverage(_)
+            | StatementKind::CopyNonOverlapping(_)
+            | StatementKind::Nop => {}
+
+            // If inline assembly is found, we probably should
+            // not try to analyze the code
+            StatementKind::LlvmInlineAsm(_) => return None,
+
+            // If the discriminant is set, it is always set
+            // as a constant, so the job is already done.
+            // As we are **ignoring projections**, if the place
+            // we are tracking sees its discriminant be set,
+            // that means we had to be tracking the discriminant
+            // specifically (as it is impossible to switch over
+            // an enum directly, and if we were switching over
+            // its content, we would have had to at least cast it to
+            // some variant first)
+            StatementKind::SetDiscriminant { place, .. } => {
+                if **place == switch_place {
+                    return None;
+                }
+            }
+        }
+    }
+
+    Some(switch_place)
+}
index 82e19c0552720b8efebf8f1bce74c0ad1eba6fc3..21534290d129193acd58c14935790cb5a16a7d6f 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_hir as hir;
 use rustc_middle::mir::BorrowKind;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{self, ParamEnv, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -27,7 +27,9 @@ struct UnsafetyVisitor<'a, 'tcx> {
     /// The `#[target_feature]` attributes of the body. Used for checking
     /// calls to functions with `#[target_feature]` (RFC 2396).
     body_target_features: &'tcx Vec<Symbol>,
-    in_possible_lhs_union_assign: bool,
+    /// When inside the LHS of an assignment to a field, this is the type
+    /// of the LHS and the span of the assignment expression.
+    assignment_info: Option<(Ty<'tcx>, Span)>,
     in_union_destructure: bool,
     param_env: ParamEnv<'tcx>,
     inside_adt: bool,
@@ -287,7 +289,7 @@ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
     }
 
     fn visit_expr(&mut self, expr: &Expr<'tcx>) {
-        // could we be in a the LHS of an assignment of a union?
+        // could we be in the LHS of an assignment to a field?
         match expr.kind {
             ExprKind::Field { .. }
             | ExprKind::VarRef { .. }
@@ -329,7 +331,12 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
             | ExprKind::InlineAsm { .. }
             | ExprKind::LlvmInlineAsm { .. }
             | ExprKind::LogicalOp { .. }
-            | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false,
+            | ExprKind::Use { .. } => {
+                // We don't need to save the old value and restore it
+                // because all the place expressions can't have more
+                // than one child.
+                self.assignment_info = None;
+            }
         };
         match expr.kind {
             ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => {
@@ -409,11 +416,21 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 self.safety_context = closure_visitor.safety_context;
             }
             ExprKind::Field { lhs, .. } => {
-                // assigning to union field is okay for AccessToUnionField
-                if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() {
+                let lhs = &self.thir[lhs];
+                if let ty::Adt(adt_def, _) = lhs.ty.kind() {
                     if adt_def.is_union() {
-                        if self.in_possible_lhs_union_assign {
-                            // FIXME: trigger AssignToDroppingUnionField unsafety if needed
+                        if let Some((assigned_ty, assignment_span)) = self.assignment_info {
+                            // To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
+                            if !(assigned_ty
+                                .ty_adt_def()
+                                .map_or(false, |adt| adt.is_manually_drop())
+                                || assigned_ty
+                                    .is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env))
+                            {
+                                self.requires_unsafe(assignment_span, AssignToDroppingUnionField);
+                            } else {
+                                // write to non-drop union field, safe
+                            }
                         } else {
                             self.requires_unsafe(expr.span, AccessToUnionField);
                         }
@@ -421,9 +438,10 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 }
             }
             ExprKind::Assign { lhs, rhs } | ExprKind::AssignOp { lhs, rhs, .. } => {
+                let lhs = &self.thir[lhs];
                 // First, check whether we are mutating a layout constrained field
                 let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx);
-                visit::walk_expr(&mut visitor, &self.thir[lhs]);
+                visit::walk_expr(&mut visitor, lhs);
                 if visitor.found {
                     self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField);
                 }
@@ -431,10 +449,9 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 // Second, check for accesses to union fields
                 // don't have any special handling for AssignOp since it causes a read *and* write to lhs
                 if matches!(expr.kind, ExprKind::Assign { .. }) {
-                    // assigning to a union is safe, check here so it doesn't get treated as a read later
-                    self.in_possible_lhs_union_assign = true;
-                    visit::walk_expr(self, &self.thir()[lhs]);
-                    self.in_possible_lhs_union_assign = false;
+                    self.assignment_info = Some((lhs.ty, expr.span));
+                    visit::walk_expr(self, lhs);
+                    self.assignment_info = None;
                     visit::walk_expr(self, &self.thir()[rhs]);
                     return; // we have already visited everything by now
                 }
@@ -506,12 +523,9 @@ enum UnsafeOpKind {
     UseOfMutableStatic,
     UseOfExternStatic,
     DerefOfRawPointer,
-    #[allow(dead_code)] // FIXME
     AssignToDroppingUnionField,
     AccessToUnionField,
-    #[allow(dead_code)] // FIXME
     MutationOfLayoutConstrainedField,
-    #[allow(dead_code)] // FIXME
     BorrowOfLayoutConstrainedField,
     CallToFunctionWith,
 }
@@ -619,7 +633,7 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         hir_context: hir_id,
         body_unsafety,
         body_target_features,
-        in_possible_lhs_union_assign: false,
+        assignment_info: None,
         in_union_destructure: false,
         param_env: tcx.param_env(def.did),
         inside_adt: false,
index 22c07fbec68279e357e3afb09b315ddbff2ad1aa..a2e9ed1e37cd7e6490688044aa3ab8cfd0bd827c 100644 (file)
@@ -16,9 +16,8 @@
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
 use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
-use rustc_session::parse::feature_err;
 use rustc_session::Session;
-use rustc_span::{sym, Span};
+use rustc_span::Span;
 use std::slice;
 
 crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
@@ -115,9 +114,6 @@ fn span_e0158(&self, span: Span, text: &str) {
 impl<'tcx> MatchVisitor<'_, 'tcx> {
     fn check_patterns(&mut self, pat: &Pat<'_>) {
         pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
-        if !self.tcx.features().bindings_after_at {
-            check_legality_of_bindings_in_at_patterns(self, pat);
-        }
         check_for_bindings_named_same_as_variants(self, pat);
     }
 
@@ -732,46 +728,3 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_
         err.emit();
     }
 }
-
-/// Forbids bindings in `@` patterns. This used to be is necessary for memory safety,
-/// because of the way rvalues were handled in the borrow check. (See issue #14587.)
-fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_>) {
-    AtBindingPatternVisitor { cx, bindings_allowed: true }.visit_pat(pat);
-
-    struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
-        cx: &'a MatchVisitor<'b, 'tcx>,
-        bindings_allowed: bool,
-    }
-
-    impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
-        type Map = intravisit::ErasedMap<'v>;
-
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
-        fn visit_pat(&mut self, pat: &Pat<'_>) {
-            match pat.kind {
-                hir::PatKind::Binding(.., ref subpat) => {
-                    if !self.bindings_allowed {
-                        feature_err(
-                            &self.cx.tcx.sess.parse_sess,
-                            sym::bindings_after_at,
-                            pat.span,
-                            "pattern bindings after an `@` are unstable",
-                        )
-                        .emit();
-                    }
-
-                    if subpat.is_some() {
-                        let bindings_were_allowed = self.bindings_allowed;
-                        self.bindings_allowed = false;
-                        intravisit::walk_pat(self, pat);
-                        self.bindings_allowed = bindings_were_allowed;
-                    }
-                }
-                _ => intravisit::walk_pat(self, pat),
-            }
-        }
-    }
-}
index 51df06bd989455d82bb4baf4d0ff2e8d1697f786..ed3b51dc14a7864bd8c07c7b26b36e89c9d96074 100644 (file)
@@ -2,7 +2,7 @@
 
 #![feature(array_windows)]
 #![feature(crate_visibility_modifier)]
-#![feature(bindings_after_at)]
+#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
index b37caaebfb6895b4e098bfdb6f0ad430dd140490..9818bd8d314690391642690b0234e965102fbf1d 100644 (file)
@@ -242,6 +242,63 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
         expected.sort_by_cached_key(|x| x.to_string());
         expected.dedup();
 
+        let sm = self.sess.source_map();
+        let msg = format!("expected `;`, found {}", super::token_descr(&self.token));
+        let appl = Applicability::MachineApplicable;
+        if expected.contains(&TokenType::Token(token::Semi)) {
+            if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
+                // Likely inside a macro, can't provide meaningful suggestions.
+            } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) {
+                // The current token is in the same line as the prior token, not recoverable.
+            } else if [token::Comma, token::Colon].contains(&self.token.kind)
+                && self.prev_token.kind == token::CloseDelim(token::Paren)
+            {
+                // Likely typo: The current token is on a new line and is expected to be
+                // `.`, `;`, `?`, or an operator after a close delimiter token.
+                //
+                // let a = std::process::Command::new("echo")
+                //         .arg("1")
+                //         ,arg("2")
+                //         ^
+                // https://github.com/rust-lang/rust/issues/72253
+            } else if self.look_ahead(1, |t| {
+                t == &token::CloseDelim(token::Brace)
+                    || t.can_begin_expr() && t.kind != token::Colon
+            }) && [token::Comma, token::Colon].contains(&self.token.kind)
+            {
+                // Likely typo: `,` â†’ `;` or `:` â†’ `;`. This is triggered if the current token is
+                // either `,` or `:`, and the next token could either start a new statement or is a
+                // block close. For example:
+                //
+                //   let x = 32:
+                //   let y = 42;
+                self.bump();
+                let sp = self.prev_token.span;
+                self.struct_span_err(sp, &msg)
+                    .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
+                    .emit();
+                return Ok(false);
+            } else if self.look_ahead(0, |t| {
+                t == &token::CloseDelim(token::Brace)
+                    || (
+                        t.can_begin_expr() && t != &token::Semi && t != &token::Pound
+                        // Avoid triggering with too many trailing `#` in raw string.
+                    )
+            }) {
+                // Missing semicolon typo. This is triggered if the next token could either start a
+                // new statement or is a block close. For example:
+                //
+                //   let x = 32
+                //   let y = 42;
+                let sp = self.prev_token.span.shrink_to_hi();
+                self.struct_span_err(sp, &msg)
+                    .span_label(self.token.span, "unexpected token")
+                    .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
+                    .emit();
+                return Ok(false);
+            }
+        }
+
         let expect = tokens_to_string(&expected[..]);
         let actual = super::token_descr(&self.token);
         let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
@@ -303,7 +360,6 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
             return Err(err);
         }
 
-        let sm = self.sess.source_map();
         if self.prev_token.span == DUMMY_SP {
             // Account for macro context where the previous span might not be
             // available to avoid incorrect output (#54841).
@@ -1144,62 +1200,6 @@ pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> {
         if self.eat(&token::Semi) {
             return Ok(());
         }
-        let sm = self.sess.source_map();
-        let msg = format!("expected `;`, found {}", super::token_descr(&self.token));
-        let appl = Applicability::MachineApplicable;
-        if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
-            // Likely inside a macro, can't provide meaningful suggestions.
-            return self.expect(&token::Semi).map(drop);
-        } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) {
-            // The current token is in the same line as the prior token, not recoverable.
-        } else if [token::Comma, token::Colon].contains(&self.token.kind)
-            && self.prev_token.kind == token::CloseDelim(token::Paren)
-        {
-            // Likely typo: The current token is on a new line and is expected to be
-            // `.`, `;`, `?`, or an operator after a close delimiter token.
-            //
-            // let a = std::process::Command::new("echo")
-            //         .arg("1")
-            //         ,arg("2")
-            //         ^
-            // https://github.com/rust-lang/rust/issues/72253
-            self.expect(&token::Semi)?;
-            return Ok(());
-        } else if self.look_ahead(1, |t| {
-            t == &token::CloseDelim(token::Brace) || t.can_begin_expr() && t.kind != token::Colon
-        }) && [token::Comma, token::Colon].contains(&self.token.kind)
-        {
-            // Likely typo: `,` â†’ `;` or `:` â†’ `;`. This is triggered if the current token is
-            // either `,` or `:`, and the next token could either start a new statement or is a
-            // block close. For example:
-            //
-            //   let x = 32:
-            //   let y = 42;
-            self.bump();
-            let sp = self.prev_token.span;
-            self.struct_span_err(sp, &msg)
-                .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
-                .emit();
-            return Ok(());
-        } else if self.look_ahead(0, |t| {
-            t == &token::CloseDelim(token::Brace)
-                || (
-                    t.can_begin_expr() && t != &token::Semi && t != &token::Pound
-                    // Avoid triggering with too many trailing `#` in raw string.
-                )
-        }) {
-            // Missing semicolon typo. This is triggered if the next token could either start a
-            // new statement or is a block close. For example:
-            //
-            //   let x = 32
-            //   let y = 42;
-            let sp = self.prev_token.span.shrink_to_hi();
-            self.struct_span_err(sp, &msg)
-                .span_label(self.token.span, "unexpected token")
-                .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
-                .emit();
-            return Ok(());
-        }
         self.expect(&token::Semi).map(drop) // Error unconditionally
     }
 
index 71231830e99a7afe2b2746264eec5efbf97efc87..ee9057a3bab779af567d853b4a10e84fa1a57f56 100644 (file)
@@ -1644,11 +1644,11 @@ fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
 fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     let check_attr_visitor = &mut CheckAttrVisitor { tcx };
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut check_attr_visitor.as_deep_visitor());
-    tcx.hir().visit_exported_macros_in_krate(check_attr_visitor);
-    check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs);
     if module_def_id.is_top_level_module() {
         check_attr_visitor.check_attributes(CRATE_HIR_ID, &DUMMY_SP, Target::Mod, None);
         check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
+        tcx.hir().visit_exported_macros_in_krate(check_attr_visitor);
+        check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs);
     }
 }
 
index 713d572b93a0ba725696d49465d996d6465c64ce..b71ec700f81c80b77c38f38e7b9037d3838e8a6b 100644 (file)
@@ -134,6 +134,7 @@ fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
         }
     }
 
+    #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands.
     fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         if self
             .typeck_results()
@@ -150,6 +151,7 @@ fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         }
     }
 
+    #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands.
     fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) {
         fn check_for_self_assign_helper(
             tcx: TyCtxt<'tcx>,
@@ -338,12 +340,6 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::MethodCall(..) => {
                 self.lookup_and_handle_method(expr.hir_id);
             }
-            hir::ExprKind::Assign(ref left, ref right, ..) => {
-                self.handle_assign(left);
-                self.check_for_self_assign(expr);
-                self.visit_expr(right);
-                return;
-            }
             hir::ExprKind::Field(ref lhs, ..) => {
                 self.handle_field_access(&lhs, expr.hir_id);
             }
index ddcc6fc123f7bb7bb28cea10b24b481e7a3f9ebe..3cf1d0cdd94b7a59e9b79771ecce68031ea523e6 100644 (file)
@@ -108,7 +108,7 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap<Symbol
     // Collect diagnostic items in this crate.
     tcx.hir().krate().visit_all_item_likes(&mut collector);
 
-    for m in tcx.hir().krate().exported_macros {
+    for m in tcx.hir().krate().exported_macros() {
         collector.observe_item(m.def_id);
     }
 
index 550f4f148fd24abc74d07c4280a6e1ebb044a8a4..876edbd1f6d55569eaf9ae447193dd9e70e58640 100644 (file)
@@ -183,7 +183,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
 }
 
 fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
-    let sp = tcx.hir().krate().item.inner;
+    let sp = tcx.hir().krate().module().inner;
     if *tcx.sess.parse_sess.reached_eof.borrow() {
         // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
         // the missing `fn main()` then as it might have been hidden inside an unclosed block.
index 42a4753c29c9b325b9f0a3585db951f35cff55db..3db0409d8f009c959b9a7116f5be6ca87e974d5a 100644 (file)
@@ -732,7 +732,7 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
 
         annotator.annotate(
             hir::CRATE_HIR_ID,
-            krate.item.inner,
+            krate.module().inner,
             None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
@@ -929,7 +929,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir().krate();
         let mut missing = MissingStabilityAnnotations { tcx, access_levels };
-        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.inner);
+        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.module().inner);
         intravisit::walk_crate(&mut missing, krate);
         krate.visit_all_item_likes(&mut missing.as_deep_visitor());
     }
index 1993e0a602fa50a0e57576d3db27e5ace963cd3c..0ad360c7d89c37bdccc8997d24460b49f51f00e3 100644 (file)
@@ -1,9 +1,9 @@
 //! Defines the set of legal keys that can be used in queries.
 
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_hir::HirId;
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::mir;
+use rustc_middle::traits;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -397,7 +397,7 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
     }
 }
 
-impl<'tcx> Key for (ty::Predicate<'tcx>, HirId) {
+impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
index 71e67dfee538bdee7f553a687eb03e3aed6e8e72..c8a46e974f305e4f6f900746953e2859118c95b1 100644 (file)
@@ -1,7 +1,6 @@
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::profiling::QueryInvocationId;
-use rustc_data_structures::profiling::SelfProfilerRef;
+use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef};
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
@@ -36,6 +35,12 @@ pub struct DepGraph<K: DepKind> {
     /// each task has a `DepNodeIndex` that uniquely identifies it. This unique
     /// ID is used for self-profiling.
     virtual_dep_node_index: Lrc<AtomicU32>,
+
+    /// The cached event id for profiling node interning. This saves us
+    /// from having to look up the event id every time we intern a node
+    /// which may incur too much overhead.
+    /// This will be None if self-profiling is disabled.
+    node_intern_event_id: Option<EventId>,
 }
 
 rustc_index::newtype_index! {
@@ -130,6 +135,10 @@ pub fn new(
         );
         debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
 
+        let node_intern_event_id = profiler
+            .get_or_alloc_cached_string("incr_comp_intern_dep_graph_node")
+            .map(EventId::from_label);
+
         DepGraph {
             data: Some(Lrc::new(DepGraphData {
                 previous_work_products: prev_work_products,
@@ -141,11 +150,16 @@ pub fn new(
                 colors: DepNodeColorMap::new(prev_graph_node_count),
             })),
             virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
+            node_intern_event_id,
         }
     }
 
     pub fn new_disabled() -> DepGraph<K> {
-        DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
+        DepGraph {
+            data: None,
+            virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
+            node_intern_event_id: None,
+        }
     }
 
     /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
@@ -244,10 +258,15 @@ fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A, R>(
             let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
 
             let mut hcx = dcx.create_stable_hashing_context();
+            let hashing_timer = dcx.profiler().incr_result_hashing();
             let current_fingerprint = hash_result(&mut hcx, &result);
 
             let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
 
+            // Get timer for profiling `DepNode` interning
+            let node_intern_timer = self
+                .node_intern_event_id
+                .map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
             // Intern the new `DepNode`.
             let (dep_node_index, prev_and_color) = data.current.intern_node(
                 dcx.profiler(),
@@ -257,6 +276,9 @@ fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A, R>(
                 current_fingerprint,
                 print_status,
             );
+            drop(node_intern_timer);
+
+            hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             if let Some((prev_index, color)) = prev_and_color {
                 debug_assert!(
index ca7cdc4caf5053d1841358129e3c4cae446601e0..4329477404298e01b5a24e9b977c0bb66cad5ac1 100644 (file)
@@ -1015,24 +1015,17 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                                 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                                 // Ensure that the parent of the def is an item, not HRTB
                                 let parent_id = self.tcx.hir().get_parent_node(hir_id);
-                                let parent_is_item = if let Some(parent_def_id) =
-                                    parent_id.as_owner()
-                                {
-                                    let parent_item_id = hir::ItemId { def_id: parent_def_id };
-                                    let parent_impl_id = hir::ImplItemId { def_id: parent_def_id };
-                                    let parent_trait_id =
-                                        hir::TraitItemId { def_id: parent_def_id };
-                                    let parent_foreign_id =
-                                        hir::ForeignItemId { def_id: parent_def_id };
-                                    let krate = self.tcx.hir().krate();
-
-                                    krate.items.contains_key(&parent_item_id)
-                                        || krate.impl_items.contains_key(&parent_impl_id)
-                                        || krate.trait_items.contains_key(&parent_trait_id)
-                                        || krate.foreign_items.contains_key(&parent_foreign_id)
-                                } else {
-                                    false
-                                };
+                                // FIXME(cjgillot) Can this check be replaced by
+                                // `let parent_is_item = parent_id.is_owner();`?
+                                let parent_is_item =
+                                    if let Some(parent_def_id) = parent_id.as_owner() {
+                                        matches!(
+                                            self.tcx.hir().krate().owners.get(parent_def_id),
+                                            Some(Some(_)),
+                                        )
+                                    } else {
+                                        false
+                                    };
 
                                 if !parent_is_item {
                                     if !self.trait_definition_only {
@@ -2688,15 +2681,14 @@ fn visit_fn_like_elision(
                 Scope::Binder { hir_id, .. } => {
                     break *hir_id;
                 }
-                Scope::Body { id, .. } => break id.hir_id,
                 Scope::ObjectLifetimeDefault { ref s, .. }
                 | Scope::Elision { ref s, .. }
                 | Scope::Supertrait { ref s, .. }
                 | Scope::TraitRefBoundary { ref s, .. } => {
                     scope = *s;
                 }
-                Scope::Root => {
-                    // See issue #83907. Just bail out from looking inside.
+                Scope::Root | Scope::Body { .. } => {
+                    // See issues #83907 and #83693. Just bail out from looking inside.
                     self.tcx.sess.delay_span_bug(
                         rustc_span::DUMMY_SP,
                         "In fn_like_elision without appropriate scope above",
index 842f7f9deee38ed3e887a922be597154188857e6..4f8dc7d16d4b9578dea145825cf7d98ba19277de 100644 (file)
@@ -146,7 +146,7 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &hir::Crate<'_>) {
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
-            span: self.span_from_span(krate.item.inner),
+            span: self.span_from_span(krate.module().inner),
         };
 
         self.dumper.crate_prelude(data);
@@ -1092,11 +1092,12 @@ pub(crate) fn process_crate(&mut self, krate: &'tcx hir::Crate<'tcx>) {
             format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id()));
 
         let sm = self.tcx.sess.source_map();
-        let filename = sm.span_to_filename(krate.item.inner);
+        let krate_mod = krate.module();
+        let filename = sm.span_to_filename(krate_mod.inner);
         let data_id = id_from_hir_id(id, &self.save_ctxt);
         let children =
-            krate.item.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect();
-        let span = self.span_from_span(krate.item.inner);
+            krate_mod.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect();
+        let span = self.span_from_span(krate_mod.inner);
         let attrs = self.tcx.hir().attrs(id);
 
         self.dumper.dump_def(
index 9e5a38b8dc0b1e8c934ec62d476bb3f1cf321bcc..e7cb3188393fba60229531568ee5424d1e775222 100644 (file)
@@ -1101,7 +1101,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         ),
         opt::multi_s(
             "",
-            "force-warns",
+            "force-warn",
             "Specifiy lints that should warn even if \
              they are allowed somewhere else",
             "LINT",
@@ -1148,15 +1148,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                                  never  = never colorize output",
             "auto|always|never",
         ),
-        opt::opt(
-            "",
-            "pretty",
-            "Pretty-print the input instead of compiling;
-                  valid types are: `normal` (un-annotated source),
-                  `expanded` (crates expanded), or
-                  `expanded,identified` (fully parenthesized, AST nodes with IDs).",
-            "TYPE",
-        ),
         opt::multi_s(
             "",
             "remap-path-prefix",
@@ -1175,11 +1166,11 @@ pub fn get_cmd_lint_options(
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
-    if !debugging_opts.unstable_options && matches.opt_present("force-warns") {
+    if !debugging_opts.unstable_options && matches.opt_present("force-warn") {
         early_error(
             error_format,
             "the `-Z unstable-options` flag must also be passed to enable \
-            the flag `--force-warns=lints`",
+            the flag `--force-warn=lints`",
         );
     }
 
@@ -2073,7 +2064,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
 
-    let pretty = parse_pretty(matches, &debugging_opts, error_format);
+    let pretty = parse_pretty(&debugging_opts, error_format);
 
     if !debugging_opts.unstable_options
         && !target_triple.triple().contains("apple")
@@ -2150,69 +2141,39 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     }
 }
 
-fn parse_pretty(
-    matches: &getopts::Matches,
-    debugging_opts: &DebuggingOptions,
-    efmt: ErrorOutputType,
-) -> Option<PpMode> {
-    fn parse_pretty_inner(efmt: ErrorOutputType, name: &str, extended: bool) -> PpMode {
-        use PpMode::*;
-        let first = match (name, extended) {
-            ("normal", _) => Source(PpSourceMode::Normal),
-            ("identified", _) => Source(PpSourceMode::Identified),
-            ("everybody_loops", true) => Source(PpSourceMode::EveryBodyLoops),
-            ("expanded", _) => Source(PpSourceMode::Expanded),
-            ("expanded,identified", _) => Source(PpSourceMode::ExpandedIdentified),
-            ("expanded,hygiene", _) => Source(PpSourceMode::ExpandedHygiene),
-            ("ast-tree", true) => AstTree(PpAstTreeMode::Normal),
-            ("ast-tree,expanded", true) => AstTree(PpAstTreeMode::Expanded),
-            ("hir", true) => Hir(PpHirMode::Normal),
-            ("hir,identified", true) => Hir(PpHirMode::Identified),
-            ("hir,typed", true) => Hir(PpHirMode::Typed),
-            ("hir-tree", true) => HirTree,
-            ("thir-tree", true) => ThirTree,
-            ("mir", true) => Mir,
-            ("mir-cfg", true) => MirCFG,
-            _ => {
-                if extended {
-                    early_error(
-                        efmt,
-                        &format!(
-                            "argument to `unpretty` must be one of `normal`, \
-                                        `expanded`, `identified`, `expanded,identified`, \
-                                        `expanded,hygiene`, `everybody_loops`, \
-                                        `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
-                                        `hir,typed`, `hir-tree`, `mir` or `mir-cfg`; got {}",
-                            name
-                        ),
-                    );
-                } else {
-                    early_error(
-                        efmt,
-                        &format!(
-                            "argument to `pretty` must be one of `normal`, \
-                                        `expanded`, `identified`, or `expanded,identified`; got {}",
-                            name
-                        ),
-                    );
-                }
-            }
-        };
-        tracing::debug!("got unpretty option: {:?}", first);
-        first
-    }
-
-    if debugging_opts.unstable_options {
-        if let Some(a) = matches.opt_default("pretty", "normal") {
-            // stable pretty-print variants only
-            return Some(parse_pretty_inner(efmt, &a, false));
-        }
-    }
-
-    debugging_opts.unpretty.as_ref().map(|a| {
-        // extended with unstable pretty-print variants
-        parse_pretty_inner(efmt, &a, true)
-    })
+fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Option<PpMode> {
+    use PpMode::*;
+
+    let first = match debugging_opts.unpretty.as_deref()? {
+        "normal" => Source(PpSourceMode::Normal),
+        "identified" => Source(PpSourceMode::Identified),
+        "everybody_loops" => Source(PpSourceMode::EveryBodyLoops),
+        "expanded" => Source(PpSourceMode::Expanded),
+        "expanded,identified" => Source(PpSourceMode::ExpandedIdentified),
+        "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene),
+        "ast-tree" => AstTree(PpAstTreeMode::Normal),
+        "ast-tree,expanded" => AstTree(PpAstTreeMode::Expanded),
+        "hir" => Hir(PpHirMode::Normal),
+        "hir,identified" => Hir(PpHirMode::Identified),
+        "hir,typed" => Hir(PpHirMode::Typed),
+        "hir-tree" => HirTree,
+        "thir-tree" => ThirTree,
+        "mir" => Mir,
+        "mir-cfg" => MirCFG,
+        name => early_error(
+            efmt,
+            &format!(
+                "argument to `unpretty` must be one of `normal`, \
+                            `expanded`, `identified`, `expanded,identified`, \
+                            `expanded,hygiene`, `everybody_loops`, \
+                            `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
+                            `hir,typed`, `hir-tree`, `mir` or `mir-cfg`; got {}",
+                name
+            ),
+        ),
+    };
+    tracing::debug!("got unpretty option: {:?}", first);
+    Some(first)
 }
 
 pub fn make_crate_type_option() -> RustcOptGroup {
@@ -2320,17 +2281,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpSourceMode {
-    /// `--pretty=normal`
+    /// `-Zunpretty=normal`
     Normal,
     /// `-Zunpretty=everybody_loops`
     EveryBodyLoops,
-    /// `--pretty=expanded`
+    /// `-Zunpretty=expanded`
     Expanded,
-    /// `--pretty=identified`
+    /// `-Zunpretty=identified`
     Identified,
-    /// `--pretty=expanded,identified`
+    /// `-Zunpretty=expanded,identified`
     ExpandedIdentified,
-    /// `--pretty=expanded,hygiene`
+    /// `-Zunpretty=expanded,hygiene`
     ExpandedHygiene,
 }
 
@@ -2355,7 +2316,7 @@ pub enum PpHirMode {
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpMode {
     /// Options that print the source code, i.e.
-    /// `--pretty` and `-Zunpretty=everybody_loops`
+    /// `-Zunpretty=normal` and `-Zunpretty=everybody_loops`
     Source(PpSourceMode),
     AstTree(PpAstTreeMode),
     /// Options that print the HIR, i.e. `-Zunpretty=hir`
index d7b9c91173754da37c8ff18aa48c73de0b1ff708..0805d2f0e14449ce68fe58571421c3501d706473 100644 (file)
@@ -1148,6 +1148,8 @@ mod parse {
         (default: no)"),
     mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
+    move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
+        "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
     new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1250,7 +1252,7 @@ mod parse {
         "specify the events recorded by the self profiler;
         for example: `-Z self-profile-events=default,query-keys`
         all options: none, all, default, generic-activity, query-provider, query-cache-hit
-                     query-blocked, incr-cache-load, query-keys, function-args, args, llvm"),
+                     query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm"),
     share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "make the current crate share its generic instantiations"),
     show_span: Option<String> = (None, parse_opt_string, [TRACKED],
@@ -1308,7 +1310,7 @@ mod parse {
         "take the brakes off const evaluation. NOTE: this is unsound (default: no)"),
     unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
         "present the input source, unstable (and less-pretty) variants;
-        valid types are any of the types for `--pretty`, as well as:
+        `normal`, `identified`,
         `expanded`, `expanded,identified`,
         `expanded,hygiene` (with internal representations),
         `everybody_loops` (all function bodies replaced with `loop {}`),
index f3ce78d2d78f89042f146dd66cc99d449c04355a..369af437c43841ce3090ce8a9af1e429bf9ed15c 100644 (file)
@@ -1,7 +1,7 @@
 use crate::cgu_reuse_tracker::CguReuseTracker;
 use crate::code_stats::CodeStats;
 pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
-use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
+use crate::config::{self, CrateType, OutputType, SwitchWithOptPath};
 use crate::filesearch;
 use crate::lint::{self, LintId};
 use crate::parse::ParseSess;
@@ -219,7 +219,6 @@ pub struct Session {
     /// Set of enabled features for the current target.
     pub target_features: FxHashSet<Symbol>,
 
-    known_attrs: Lock<MarkedAttrs>,
     used_attrs: Lock<MarkedAttrs>,
 
     /// `Span`s for `if` conditions that we have suggested turning into `if let`.
@@ -1076,14 +1075,6 @@ pub fn instrument_coverage_except_unused_functions(&self) -> bool {
             == config::InstrumentCoverage::ExceptUnusedFunctions
     }
 
-    pub fn mark_attr_known(&self, attr: &Attribute) {
-        self.known_attrs.lock().mark(attr)
-    }
-
-    pub fn is_attr_known(&self, attr: &Attribute) -> bool {
-        self.known_attrs.lock().is_marked(attr)
-    }
-
     pub fn mark_attr_used(&self, attr: &Attribute) {
         self.used_attrs.lock().mark(attr)
     }
@@ -1389,7 +1380,6 @@ pub fn build_session(
         miri_unleashed_features: Lock::new(Default::default()),
         asm_arch,
         target_features: FxHashSet::default(),
-        known_attrs: Lock::new(MarkedAttrs::new()),
         used_attrs: Lock::new(MarkedAttrs::new()),
         if_let_suggestions: Default::default(),
     };
@@ -1440,25 +1430,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         }
     }
 
-    // PGO does not work reliably with panic=unwind on Windows. Let's make it
-    // an error to combine the two for now. It always runs into an assertions
-    // if LLVM is built with assertions, but without assertions it sometimes
-    // does not crash and will probably generate a corrupted binary.
-    // We should only display this error if we're actually going to run PGO.
-    // If we're just supposed to print out some data, don't show the error (#61002).
-    if sess.opts.cg.profile_generate.enabled()
-        && sess.target.is_like_msvc
-        && sess.panic_strategy() == PanicStrategy::Unwind
-        && sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs)
-    {
-        sess.err(
-            "Profile-guided optimization does not yet work in conjunction \
-                  with `-Cpanic=unwind` on Windows when targeting MSVC. \
-                  See issue #61002 <https://github.com/rust-lang/rust/issues/61002> \
-                  for more information.",
-        );
-    }
-
     // Sanitizers can only be used on platforms that we know have working sanitizer codegen.
     let supported_sanitizers = sess.target.options.supported_sanitizers;
     let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
index a8f969782b22daeb45d5253b27fa05eff65138b1..c0f63f40853da98e98cfd043d2e054bb5b903b70 100644 (file)
         rustc_dump_env_program_clauses,
         rustc_dump_program_clauses,
         rustc_dump_user_substs,
+        rustc_dump_vtable,
         rustc_error,
         rustc_evaluate_where_clauses,
         rustc_expected_cgu_reuse,
index 998d6ffe0fc668652b9a2d65ac07d93df7aba1a0..f2ec6aae9f2e62184f622d94489e2a3d617008c8 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{FramePointer, RelroLevel, TargetOptions};
+use crate::spec::{RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
@@ -8,7 +8,6 @@ pub fn opts() -> TargetOptions {
         families: vec!["unix".to_string()],
         has_rpath: true,
         position_independent_executables: true,
-        frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
         relro_level: RelroLevel::Full,
         abi_return_struct_as_int: true,
         dwarf_version: Some(2),
index 0185132ee3698efe85428487c0412ddef311ffe1..ad84e07edfba620ce90423e76861f287734f817e 100644 (file)
@@ -802,6 +802,7 @@ fn $module() {
     ("armv6-unknown-freebsd", armv6_unknown_freebsd),
     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
     ("i686-unknown-freebsd", i686_unknown_freebsd),
+    ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
     ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
     ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
new file mode 100644 (file)
index 0000000..e113180
--- /dev/null
@@ -0,0 +1,27 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::freebsd_base::opts();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    // Extra hint to linker that we are generating secure-PLT code.
+    base.pre_link_args
+        .entry(LinkerFlavor::Gcc)
+        .or_default()
+        .push("--target=powerpc-unknown-freebsd13.0".to_string());
+    base.max_atomic_width = Some(32);
+
+    Target {
+        llvm_target: "powerpc-unknown-freebsd13.0".to_string(),
+        pointer_width: 32,
+        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
+        arch: "powerpc".to_string(),
+        options: TargetOptions {
+            endian: Endian::Big,
+            features: "+secure-plt".to_string(),
+            relocation_model: RelocModel::Pic,
+            mcount: "_mcount".to_string(),
+            ..base
+        },
+    }
+}
index e932b1bca7c7ba1f358fef288fe7ae525354de1e..017a7c45bbf9d21fd8d6c49dad2264a9a6beac92 100644 (file)
@@ -31,6 +31,8 @@
 extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
+#[macro_use]
+extern crate smallvec;
 
 pub mod autoderef;
 pub mod infer;
index 39013a317fd9c494af6c94439bea66dbc5df7ad4..95c81c5c729be5be29ea0fafb84f7d5c66242d19 100644 (file)
@@ -83,6 +83,7 @@ pub struct OpaqueTypeDecl<'tcx> {
 }
 
 /// Whether member constraints should be generated for all opaque types
+#[derive(Debug)]
 pub enum GenerateMemberConstraints {
     /// The default, used by typeck
     WhenRequired,
@@ -354,8 +355,6 @@ fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
         opaque_types: &OpaqueTypeMap<'tcx>,
         free_region_relations: &FRR,
     ) {
-        debug!("constrain_opaque_types()");
-
         for &(opaque_type_key, opaque_defn) in opaque_types {
             self.constrain_opaque_type(
                 opaque_type_key,
@@ -367,6 +366,7 @@ fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
     }
 
     /// See `constrain_opaque_types` for documentation.
+    #[instrument(level = "debug", skip(self, free_region_relations))]
     fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -376,15 +376,11 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
     ) {
         let def_id = opaque_type_key.def_id;
 
-        debug!("constrain_opaque_type()");
-        debug!("constrain_opaque_type: def_id={:?}", def_id);
-        debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
-
         let tcx = self.tcx;
 
         let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
 
-        debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
+        debug!(?concrete_ty);
 
         let first_own_region = match opaque_defn.origin {
             hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
@@ -397,7 +393,7 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
                 // type foo::<'p0..'pn>::Foo<'q0..'qm>
                 // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
                 //
-                // For these types we onlt iterate over `'l0..lm` below.
+                // For these types we only iterate over `'l0..lm` below.
                 tcx.generics_of(def_id).parent_count
             }
             // These opaque type inherit all lifetime parameters from their
@@ -410,10 +406,10 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         // If there are required region bounds, we can use them.
         if opaque_defn.has_required_region_bounds {
             let bounds = tcx.explicit_item_bounds(def_id);
-            debug!("constrain_opaque_type: predicates: {:#?}", bounds);
+            debug!("{:#?}", bounds);
             let bounds: Vec<_> =
                 bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect();
-            debug!("constrain_opaque_type: bounds={:#?}", bounds);
+            debug!("{:#?}", bounds);
             let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
 
             let required_region_bounds =
@@ -452,8 +448,8 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
             };
 
             // Compute the least upper bound of it with the other regions.
-            debug!("constrain_opaque_types: least_region={:?}", least_region);
-            debug!("constrain_opaque_types: subst_region={:?}", subst_region);
+            debug!(?least_region);
+            debug!(?subst_region);
             match least_region {
                 None => least_region = Some(subst_region),
                 Some(lr) => {
@@ -484,7 +480,7 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         }
 
         let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
-        debug!("constrain_opaque_types: least_region={:?}", least_region);
+        debug!(?least_region);
 
         if let GenerateMemberConstraints::IfNoStaticBound = mode {
             if least_region != tcx.lifetimes.re_static {
index 5c4aef529e5ac775c24d6f042080e68a93c6d263..13a6733fb478abebca8f623ed2c8ae4eb930fd69 100644 (file)
@@ -242,11 +242,11 @@ fn report_selection_error(
             SelectionError::Unimplemented => {
                 // If this obligation was generated as a result of well-formed checking, see if we
                 // can get a better error message by performing HIR-based well formed checking.
-                if let ObligationCauseCode::WellFormed(Some(wf_hir_id)) =
+                if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code.peel_derives()
                 {
                     if let Some(cause) =
-                        self.tcx.diagnostic_hir_wf_check((obligation.predicate, *wf_hir_id))
+                        self.tcx.diagnostic_hir_wf_check((obligation.predicate, wf_loc.clone()))
                     {
                         obligation.cause = cause;
                         span = obligation.cause.span;
index 1c6a83b578305cce376304f40c9a956deedbbb37..9a33875d6e493f293d9e1efb9c24004b2821681e 100644 (file)
@@ -1857,12 +1857,37 @@ fn note_obligation_cause_for_async_await(
                 }
             }
             GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
+                // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
+                let refers_to_non_sync = match target_ty.kind() {
+                    ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
+                        Ok(eval) if !eval.may_apply() => Some(ref_ty),
+                        _ => None,
+                    },
+                    _ => None,
+                };
+
+                let (span_label, span_note) = match refers_to_non_sync {
+                    // if `target_ty` is `&T` and `T` fails to impl `Sync`,
+                    // include suggestions to make `T: Sync` so that `&T: Send`
+                    Some(ref_ty) => (
+                        format!(
+                            "has type `{}` which {}, because `{}` is not `Sync`",
+                            target_ty, trait_explanation, ref_ty
+                        ),
+                        format!(
+                            "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
+                            trait_explanation
+                        ),
+                    ),
+                    None => (
+                        format!("has type `{}` which {}", target_ty, trait_explanation),
+                        format!("captured value {}", trait_explanation),
+                    ),
+                };
+
                 let mut span = MultiSpan::from_span(upvar_span);
-                span.push_span_label(
-                    upvar_span,
-                    format!("has type `{}` which {}", target_ty, trait_explanation),
-                );
-                err.span_note(span, &format!("captured value {}", trait_explanation));
+                span.push_span_label(upvar_span, span_label);
+                err.span_note(span, &span_note);
             }
         }
 
index dfe2909498d1862ecaceed5bb5636f4cae822667..9ec1dd5c2ee3b302efd8c64613476c1c8b4a5820 100644 (file)
@@ -365,6 +365,7 @@ fn progress_changed_obligations(
                     let project_obligation = obligation.with(binder.rebind(data));
 
                     self.process_projection_obligation(
+                        obligation,
                         project_obligation,
                         &mut pending_obligation.stalled_on,
                     )
@@ -419,6 +420,7 @@ fn progress_changed_obligations(
                     let project_obligation = obligation.with(Binder::dummy(*data));
 
                     self.process_projection_obligation(
+                        obligation,
                         project_obligation,
                         &mut pending_obligation.stalled_on,
                     )
@@ -666,10 +668,22 @@ fn process_trait_obligation(
 
     fn process_projection_obligation(
         &mut self,
+        obligation: &PredicateObligation<'tcx>,
         project_obligation: PolyProjectionObligation<'tcx>,
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
+
+        if obligation.predicate.is_global() {
+            // no type variables present, can use evaluation for better caching.
+            // FIXME: consider caching errors too.
+            if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
+                return ProcessResult::Changed(vec![]);
+            } else {
+                tracing::debug!("Does NOT hold: {:?}", obligation);
+            }
+        }
+
         match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
             Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
             Ok(Ok(None)) => {
index 3a80e720e8c4b8560f2aed49e13628061de01430..693384602a75f7090aa2b245c57126c5d1b29df2 100644 (file)
     self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
     COMMON_VTABLE_ENTRIES,
 };
-use rustc_span::Span;
+use rustc_span::{sym, Span};
+use smallvec::SmallVec;
 
 use std::fmt::Debug;
+use std::ops::ControlFlow;
 
 pub use self::FulfillmentErrorCode::*;
 pub use self::ImplSource::*;
@@ -454,6 +456,174 @@ fn subst_and_check_impossible_predicates<'tcx>(
     result
 }
 
+#[derive(Clone, Debug)]
+enum VtblSegment<'tcx> {
+    MetadataDSA,
+    TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
+}
+
+/// Prepare the segments for a vtable
+fn prepare_vtable_segments<'tcx, T>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
+) -> Option<T> {
+    // The following constraints holds for the final arrangement.
+    // 1. The whole virtual table of the first direct super trait is included as the
+    //    the prefix. If this trait doesn't have any super traits, then this step
+    //    consists of the dsa metadata.
+    // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
+    //    other super traits except those already included as part of the first
+    //    direct super trait virtual table.
+    // 3. finally, the own methods of this trait.
+
+    // This has the advantage that trait upcasting to the first direct super trait on each level
+    // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
+    // while not using too much extra memory.
+
+    // For a single inheritance relationship like this,
+    //   D --> C --> B --> A
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, C, D
+
+    // For a multiple inheritance relationship like this,
+    //   D --> C --> A
+    //           \-> B
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, B-vptr, C, D
+
+    // For a diamond inheritance relationship like this,
+    //   D --> B --> A
+    //     \-> C -/
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, C, C-vptr, D
+
+    // For a more complex inheritance relationship like this:
+    //   O --> G --> C --> A
+    //     \     \     \-> B
+    //     |     |-> F --> D
+    //     |           \-> E
+    //     |-> N --> J --> H
+    //           \     \-> I
+    //           |-> M --> K
+    //                 \-> L
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
+    //  H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
+    //  N, N-vptr, O
+
+    // emit dsa segment first.
+    if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
+        return Some(v);
+    }
+
+    let mut emit_vptr_on_new_entry = false;
+    let mut visited = util::PredicateSet::new(tcx);
+    let predicate = trait_ref.without_const().to_predicate(tcx);
+    let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
+        smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
+    visited.insert(predicate);
+
+    // the main traversal loop:
+    // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
+    // that each node is emited after all its descendents have been emitted.
+    // so we convert the directed graph into a tree by skipping all previously visted nodes using a visited set.
+    // this is done on the fly.
+    // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
+    // stops after it finds a node that has a next-sibling node.
+    // This next-sibling node will used as the starting point of next slice.
+
+    // Example:
+    // For a diamond inheritance relationship like this,
+    //   D#1 --> B#0 --> A#0
+    //     \-> C#1 -/
+
+    // Starting point 0 stack [D]
+    // Loop run #0: Stack after diving in is [D B A], A is "childless"
+    // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
+    // Loop run #0: Emiting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
+    // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
+    // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
+    // Loop run #1: Emiting the slice [D C] (in reverse order). No one has a next-sibling node.
+    // Loop run #1: Stack after exiting out is []. Now the function exits.
+
+    loop {
+        // dive deeper into the stack, recording the path
+        'diving_in: loop {
+            if let Some((inner_most_trait_ref, _, _)) = stack.last() {
+                let inner_most_trait_ref = *inner_most_trait_ref;
+                let mut direct_super_traits_iter = tcx
+                    .super_predicates_of(inner_most_trait_ref.def_id())
+                    .predicates
+                    .into_iter()
+                    .filter_map(move |(pred, _)| {
+                        pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_ref()
+                    });
+
+                'diving_in_skip_visited_traits: loop {
+                    if let Some(next_super_trait) = direct_super_traits_iter.next() {
+                        if visited.insert(next_super_trait.to_predicate(tcx)) {
+                            stack.push((
+                                next_super_trait.value,
+                                emit_vptr_on_new_entry,
+                                Some(direct_super_traits_iter),
+                            ));
+                            break 'diving_in_skip_visited_traits;
+                        } else {
+                            continue 'diving_in_skip_visited_traits;
+                        }
+                    } else {
+                        break 'diving_in;
+                    }
+                }
+            }
+        }
+
+        // Other than the left-most path, vptr should be emitted for each trait.
+        emit_vptr_on_new_entry = true;
+
+        // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
+        'exiting_out: loop {
+            if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
+                if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
+                    trait_ref: *inner_most_trait_ref,
+                    emit_vptr: *emit_vptr,
+                }) {
+                    return Some(v);
+                }
+
+                'exiting_out_skip_visited_traits: loop {
+                    if let Some(siblings) = siblings_opt {
+                        if let Some(next_inner_most_trait_ref) = siblings.next() {
+                            if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
+                                *inner_most_trait_ref = next_inner_most_trait_ref.value;
+                                *emit_vptr = emit_vptr_on_new_entry;
+                                break 'exiting_out;
+                            } else {
+                                continue 'exiting_out_skip_visited_traits;
+                            }
+                        }
+                    }
+                    stack.pop();
+                    continue 'exiting_out;
+                }
+            }
+            // all done
+            return None;
+        }
+    }
+}
+
+fn dump_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sp: Span,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    entries: &[VtblEntry<'tcx>],
+) {
+    let msg = format!("Vtable entries for `{}`: {:#?}", trait_ref, entries);
+    tcx.sess.struct_span_err(sp, &msg).emit();
+}
+
 /// Given a trait `trait_ref`, iterates the vtable entries
 /// that come from `trait_ref`, including its supertraits.
 fn vtable_entries<'tcx>(
@@ -462,57 +632,86 @@ fn vtable_entries<'tcx>(
 ) -> &'tcx [VtblEntry<'tcx>] {
     debug!("vtable_entries({:?})", trait_ref);
 
-    let entries = COMMON_VTABLE_ENTRIES.iter().cloned().chain(
-        supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
-            let trait_methods = tcx
-                .associated_items(trait_ref.def_id())
-                .in_definition_order()
-                .filter(|item| item.kind == ty::AssocKind::Fn);
-
-            // Now list each method's DefId and InternalSubsts (for within its trait).
-            // If the method can never be called from this object, produce `Vacant`.
-            trait_methods.map(move |trait_method| {
-                debug!("vtable_entries: trait_method={:?}", trait_method);
-                let def_id = trait_method.def_id;
-
-                // Some methods cannot be called on an object; skip those.
-                if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                    debug!("vtable_entries: not vtable safe");
-                    return VtblEntry::Vacant;
-                }
+    let mut entries = vec![];
 
-                // The method may have some early-bound lifetimes; add regions for those.
-                let substs = trait_ref.map_bound(|trait_ref| {
-                    InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                        GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                        GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                            trait_ref.substs[param.index as usize]
-                        }
-                    })
+    let vtable_segment_callback = |segment| -> ControlFlow<()> {
+        match segment {
+            VtblSegment::MetadataDSA => {
+                entries.extend(COMMON_VTABLE_ENTRIES);
+            }
+            VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                let trait_methods = tcx
+                    .associated_items(trait_ref.def_id())
+                    .in_definition_order()
+                    .filter(|item| item.kind == ty::AssocKind::Fn);
+                // Now list each method's DefId and InternalSubsts (for within its trait).
+                // If the method can never be called from this object, produce `Vacant`.
+                let own_entries = trait_methods.map(move |trait_method| {
+                    debug!("vtable_entries: trait_method={:?}", trait_method);
+                    let def_id = trait_method.def_id;
+
+                    // Some methods cannot be called on an object; skip those.
+                    if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+                        debug!("vtable_entries: not vtable safe");
+                        return VtblEntry::Vacant;
+                    }
+
+                    // The method may have some early-bound lifetimes; add regions for those.
+                    let substs = trait_ref.map_bound(|trait_ref| {
+                        InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                            GenericParamDefKind::Type { .. }
+                            | GenericParamDefKind::Const { .. } => {
+                                trait_ref.substs[param.index as usize]
+                            }
+                        })
+                    });
+
+                    // The trait type may have higher-ranked lifetimes in it;
+                    // erase them if they appear, so that we get the type
+                    // at some particular call site.
+                    let substs = tcx
+                        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+
+                    // It's possible that the method relies on where-clauses that
+                    // do not hold for this particular set of type parameters.
+                    // Note that this method could then never be called, so we
+                    // do not want to try and codegen it, in that case (see #23435).
+                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+                    if impossible_predicates(tcx, predicates.predicates) {
+                        debug!("vtable_entries: predicates do not hold");
+                        return VtblEntry::Vacant;
+                    }
+
+                    let instance = ty::Instance::resolve_for_vtable(
+                        tcx,
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        substs,
+                    )
+                    .expect("resolution failed during building vtable representation");
+                    VtblEntry::Method(instance)
                 });
 
-                // The trait type may have higher-ranked lifetimes in it;
-                // erase them if they appear, so that we get the type
-                // at some particular call site.
-                let substs =
-                    tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
-
-                // It's possible that the method relies on where-clauses that
-                // do not hold for this particular set of type parameters.
-                // Note that this method could then never be called, so we
-                // do not want to try and codegen it, in that case (see #23435).
-                let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-                if impossible_predicates(tcx, predicates.predicates) {
-                    debug!("vtable_entries: predicates do not hold");
-                    return VtblEntry::Vacant;
+                entries.extend(own_entries);
+
+                if emit_vptr {
+                    entries.push(VtblEntry::TraitVPtr(trait_ref));
                 }
+            }
+        }
 
-                VtblEntry::Method(def_id, substs)
-            })
-        }),
-    );
+        ControlFlow::Continue(())
+    };
+
+    let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
+
+    if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
+        let sp = tcx.def_span(trait_ref.def_id());
+        dump_vtable_entries(tcx, sp, trait_ref, &entries);
+    }
 
-    tcx.arena.alloc_from_iter(entries)
+    tcx.arena.alloc_from_iter(entries.into_iter())
 }
 
 /// Find slot base for trait methods within vtable entries of another trait
@@ -525,20 +724,82 @@ fn vtable_trait_first_method_offset<'tcx>(
 ) -> usize {
     let (trait_to_be_found, trait_owning_vtable) = key;
 
-    let mut supertraits = util::supertraits(tcx, trait_owning_vtable);
+    let vtable_segment_callback = {
+        let mut vtable_base = 0;
+
+        move |segment| {
+            match segment {
+                VtblSegment::MetadataDSA => {
+                    vtable_base += COMMON_VTABLE_ENTRIES.len();
+                }
+                VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                    if trait_ref == trait_to_be_found {
+                        return ControlFlow::Break(vtable_base);
+                    }
+                    vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
+                    if emit_vptr {
+                        vtable_base += 1;
+                    }
+                }
+            }
+            ControlFlow::Continue(())
+        }
+    };
+
+    if let Some(vtable_base) =
+        prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
+    {
+        vtable_base
+    } else {
+        bug!("Failed to find info for expected trait in vtable");
+    }
+}
+
+/// Find slot offset for trait vptr within vtable entries of another trait
+/// FIXME: This function is not yet used. Remove `#[allow(dead_code)]` when it's used in upcoming pr.
+#[allow(dead_code)]
+fn vtable_trait_vptr_slot_offset<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (
+        ty::PolyTraitRef<'tcx>, // trait_to_be_found
+        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
+    ),
+) -> Option<usize> {
+    let (trait_to_be_found, trait_owning_vtable) = key;
+
+    let vtable_segment_callback = {
+        let mut vptr_offset = 0;
+        move |segment| {
+            match segment {
+                VtblSegment::MetadataDSA => {
+                    vptr_offset += COMMON_VTABLE_ENTRIES.len();
+                }
+                VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                    vptr_offset += util::count_own_vtable_entries(tcx, trait_ref);
+                    if trait_ref == trait_to_be_found {
+                        if emit_vptr {
+                            return ControlFlow::Break(Some(vptr_offset));
+                        } else {
+                            return ControlFlow::Break(None);
+                        }
+                    }
 
-    // For each of the non-matching predicates that
-    // we pass over, we sum up the set of number of vtable
-    // entries, so that we can compute the offset for the selected
-    // trait.
-    let vtable_base = ty::COMMON_VTABLE_ENTRIES.len()
-        + supertraits
-            .by_ref()
-            .take_while(|t| *t != trait_to_be_found)
-            .map(|t| util::count_own_vtable_entries(tcx, t))
-            .sum::<usize>();
+                    if emit_vptr {
+                        vptr_offset += 1;
+                    }
+                }
+            }
+            ControlFlow::Continue(())
+        }
+    };
 
-    vtable_base
+    if let Some(vptr_offset) =
+        prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
+    {
+        vptr_offset
+    } else {
+        bug!("Failed to find info for expected trait in vtable");
+    }
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
index b83a4cd1e5775c5af9a5195de09c37819c1669e2..2dc48e47efccdf6a9e150b8e3e88b844a82422ea 100644 (file)
@@ -64,8 +64,10 @@ fn evaluate_obligation(
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         let mut _orig_values = OriginalQueryValues::default();
-        let c_pred = self
-            .canonicalize_query(obligation.param_env.and(obligation.predicate), &mut _orig_values);
+        let c_pred = self.canonicalize_query_keep_static(
+            obligation.param_env.and(obligation.predicate),
+            &mut _orig_values,
+        );
         // Run canonical query. If overflow occurs, rerun from scratch but this time
         // in standard trait query mode so that overflow is handled appropriately
         // within `SelectionContext`.
index d65a378b1edec193ecd750f7c23ad6b76ffe6dab..3f6efa03b3a28b27694bab4c2743c857285f10ac 100644 (file)
@@ -180,7 +180,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // so we cannot canonicalize it.
                 let c_data = self
                     .infcx
-                    .canonicalize_hr_query_hack(self.param_env.and(data), &mut orig_values);
+                    .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                 match tcx.normalize_projection_ty(c_data) {
@@ -249,7 +249,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // so we cannot canonicalize it.
                 let c_data = self
                     .infcx
-                    .canonicalize_hr_query_hack(self.param_env.and(data), &mut orig_values);
+                    .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                 let normalized_ty = match tcx.normalize_projection_ty(c_data) {
index 130ffa1a33aebc7eb8aa89d2c2f37b13f4842371..fbff86618ade3172f15be2bbeb0259685ea84a8c 100644 (file)
@@ -77,12 +77,13 @@ fn fully_perform_into(
         }
 
         // FIXME(#33684) -- We need to use
-        // `canonicalize_hr_query_hack` here because of things
+        // `canonicalize_query_keep_static` here because of things
         // like the subtype query, which go awry around
         // `'static` otherwise.
         let mut canonical_var_values = OriginalQueryValues::default();
         let old_param_env = query_key.param_env;
-        let canonical_self = infcx.canonicalize_hr_query_hack(query_key, &mut canonical_var_values);
+        let canonical_self =
+            infcx.canonicalize_query_keep_static(query_key, &mut canonical_var_values);
         let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
 
         let InferOk { value, obligations } = infcx
index 1bdc8b34cf6ba7da8f5f5a909264156ee5ace152..95611ebc8188cfe54fc6a0258bd29d8e00ee7a35 100644 (file)
@@ -216,7 +216,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
@@ -227,7 +227,7 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
     pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: true,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
@@ -242,7 +242,7 @@ pub fn with_negative(
         debug!(?allow_negative_impls, "with_negative");
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls,
@@ -257,7 +257,7 @@ pub fn with_query_mode(
         debug!(?query_mode, "with_query_mode");
         SelectionContext {
             infcx,
-            freshener: infcx.freshener(),
+            freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
index 2e42d65cce29bef8d80f1c8663f8fd4cedda107a..b82437120ce98ff98965fbabfe27caa6bfc40436 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Constness, GenericArg, GenericArgs};
-use rustc_middle::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
+use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -488,12 +488,20 @@ fn inferred_kind(
                                 tcx.ty_error().into()
                             } else {
                                 // This is a default type parameter.
+                                let substs = substs.unwrap();
+                                if substs.iter().any(|arg| match arg.unpack() {
+                                    GenericArgKind::Type(ty) => ty.references_error(),
+                                    _ => false,
+                                }) {
+                                    // Avoid ICE #86756 when type error recovery goes awry.
+                                    return tcx.ty_error().into();
+                                }
                                 self.astconv
                                     .normalize_ty(
                                         self.span,
                                         tcx.at(self.span).type_of(param.def_id).subst_spanned(
                                             tcx,
-                                            substs.unwrap(),
+                                            substs,
                                             Some(self.span),
                                         ),
                                     )
@@ -838,6 +846,7 @@ pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bo
                              this does nothing because the given bound is not \
                              a default; only `?Sized` is supported",
                         );
+                        return false;
                     }
                 }
             }
index 4ed07ba358de3b3794d76c9f0f7538b37545dcc8..865e4ccc0b63f506b7c7e237e76fc764ffa20b1c 100644 (file)
@@ -40,6 +40,7 @@
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
+    WellFormedLoc,
 };
 
 use std::collections::hash_map::Entry;
@@ -419,13 +420,13 @@ pub(in super::super) fn normalize_associated_types_in_wf<T>(
         &self,
         span: Span,
         value: T,
-        hir_id: hir::HirId,
+        loc: WellFormedLoc,
     ) -> T
     where
         T: TypeFoldable<'tcx>,
     {
         self.inh.normalize_associated_types_in_with_cause(
-            ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(hir_id))),
+            ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))),
             self.param_env,
             value,
         )
index 39874f48eb014071aa5d279b5e3cf48bba7dc5e6..013cb2a49b29c145d07145fcb9a0e4aa1d999e5c 100644 (file)
@@ -1760,12 +1760,11 @@ fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::H
         self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow);
     }
 }
-
-/// Truncate projections so that following rules are obeyed by the captured `place`:
+/// Truncate `place` so that an `unsafe` block isn't required to capture it.
 /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
 ///   them completely.
-/// - No Index projections are captured, since arrays are captured completely.
-fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
+/// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
+fn restrict_precision_for_unsafe(mut place: Place<'tcx>) -> Place<'tcx> {
     if place.projections.is_empty() {
         // Nothing to do here
         return place;
@@ -1776,18 +1775,45 @@ fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
         return place;
     }
 
-    let mut truncated_length = usize::MAX;
+    if place.base_ty.is_union() {
+        place.projections.truncate(0);
+        return place;
+    }
 
     for (i, proj) in place.projections.iter().enumerate() {
         if proj.ty.is_unsafe_ptr() {
-            // Don't apply any projections on top of an unsafe ptr
-            truncated_length = truncated_length.min(i + 1);
+            // Don't apply any projections on top of an unsafe ptr.
+            place.projections.truncate(i + 1);
             break;
         }
+
+        if proj.ty.is_union() {
+            // Don't capture preicse fields of a union.
+            place.projections.truncate(i + 1);
+            break;
+        }
+    }
+
+    place
+}
+
+/// Truncate projections so that following rules are obeyed by the captured `place`:
+/// - No Index projections are captured, since arrays are captured completely.
+/// - No unsafe block is required to capture `place`
+/// Truncate projections so that following rules are obeyed by the captured `place`:
+fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
+    place = restrict_precision_for_unsafe(place);
+
+    if place.projections.is_empty() {
+        // Nothing to do here
+        return place;
+    }
+
+    for (i, proj) in place.projections.iter().enumerate() {
         match proj.kind {
             ProjectionKind::Index => {
                 // Arrays are completely captured, so we drop Index projections
-                truncated_length = truncated_length.min(i);
+                place.projections.truncate(i);
                 break;
             }
             ProjectionKind::Deref => {}
@@ -1796,10 +1822,6 @@ fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
         }
     }
 
-    let length = place.projections.len().min(truncated_length);
-
-    place.projections.truncate(length);
-
     place
 }
 
index b24d63917c1cf48a72eb97e8aced98dd93d95d00..e33cc603b5e543cc95cd8b3699642cb2ec2761e4 100644 (file)
@@ -22,8 +22,9 @@
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::may_define_opaque_type;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
+use std::convert::TryInto;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -386,7 +387,7 @@ fn check_associated_item(
     span: Span,
     sig_if_method: Option<&hir::FnSig<'_>>,
 ) {
-    let code = ObligationCauseCode::WellFormed(Some(item_id));
+    let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner())));
     for_id(tcx, item_id, span).with_fcx(|fcx| {
         let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
 
@@ -400,7 +401,11 @@ fn check_associated_item(
         match item.kind {
             ty::AssocKind::Const => {
                 let ty = fcx.tcx.type_of(item.def_id);
-                let ty = fcx.normalize_associated_types_in_wf(span, ty, item_id);
+                let ty = fcx.normalize_associated_types_in_wf(
+                    span,
+                    ty,
+                    WellFormedLoc::Ty(item_id.expect_owner()),
+                );
                 fcx.register_wf_obligation(ty.into(), span, code.clone());
             }
             ty::AssocKind::Fn => {
@@ -422,7 +427,11 @@ fn check_associated_item(
                 }
                 if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
-                    let ty = fcx.normalize_associated_types_in_wf(span, ty, item_id);
+                    let ty = fcx.normalize_associated_types_in_wf(
+                        span,
+                        ty,
+                        WellFormedLoc::Ty(item_id.expect_owner()),
+                    );
                     fcx.register_wf_obligation(ty.into(), span, code.clone());
                 }
             }
@@ -514,8 +523,7 @@ fn check_type_defn<'tcx, F>(
                 fcx.register_wf_obligation(
                     field.ty.into(),
                     field.span,
-                    // We don't have an HIR id for the field
-                    ObligationCauseCode::WellFormed(None),
+                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))),
                 )
             }
 
@@ -621,7 +629,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
 
     for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
         let ty = tcx.type_of(tcx.hir().local_def_id(item_id));
-        let item_ty = fcx.normalize_associated_types_in_wf(ty_span, ty, item_id);
+        let item_ty = fcx.normalize_associated_types_in_wf(
+            ty_span,
+            ty,
+            WellFormedLoc::Ty(item_id.expect_owner()),
+        );
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
@@ -634,7 +646,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         fcx.register_wf_obligation(
             item_ty.into(),
             ty_span,
-            ObligationCauseCode::WellFormed(Some(item_id)),
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))),
         );
         if forbid_unsized {
             fcx.register_bound(
@@ -684,7 +696,9 @@ fn check_impl<'tcx>(
                 fcx.register_wf_obligation(
                     self_ty.into(),
                     ast_self_ty.span,
-                    ObligationCauseCode::WellFormed(Some(item.hir_id())),
+                    ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(
+                        item.hir_id().expect_owner(),
+                    ))),
                 );
             }
         }
@@ -901,11 +915,48 @@ fn check_fn_or_method<'fcx, 'tcx>(
     implied_bounds: &mut Vec<Ty<'tcx>>,
 ) {
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
-    let sig = fcx.normalize_associated_types_in(span, sig);
 
-    for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) {
-        fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::WellFormed(None));
+    // 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`
+    // for each type, preventing the HIR wf check from generating
+    // a nice error message.
+    let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
+    inputs_and_output =
+        fcx.tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
+            fcx.normalize_associated_types_in_wf(
+                span,
+                ty,
+                WellFormedLoc::Param {
+                    function: def_id.expect_local(),
+                    // Note that the `param_idx` of the output type is
+                    // one greater than the index of the last input type.
+                    param_idx: i.try_into().unwrap(),
+                },
+            )
+        }));
+    // Manually call `normalize_assocaited_types_in` on the other types
+    // in `FnSig`. This ensures that if the types of these fields
+    // ever change to include projections, we will start normalizing
+    // them automatically.
+    let sig = ty::FnSig {
+        inputs_and_output,
+        c_variadic: fcx.normalize_associated_types_in(span, c_variadic),
+        unsafety: fcx.normalize_associated_types_in(span, unsafety),
+        abi: fcx.normalize_associated_types_in(span, abi),
+    };
+
+    for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
+        fcx.register_wf_obligation(
+            input_ty.into(),
+            ty.span,
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param {
+                function: def_id.expect_local(),
+                param_idx: i.try_into().unwrap(),
+            })),
+        );
     }
+
     implied_bounds.extend(sig.inputs());
 
     fcx.register_wf_obligation(
@@ -1415,6 +1466,7 @@ struct AdtVariant<'tcx> {
 
 struct AdtField<'tcx> {
     ty: Ty<'tcx>,
+    def_id: LocalDefId,
     span: Span,
 }
 
@@ -1425,11 +1477,12 @@ fn non_enum_variant(&self, struct_def: &hir::VariantData<'_>) -> AdtVariant<'tcx
             .fields()
             .iter()
             .map(|field| {
-                let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id));
+                let def_id = self.tcx.hir().local_def_id(field.hir_id);
+                let field_ty = self.tcx.type_of(def_id);
                 let field_ty = self.normalize_associated_types_in(field.ty.span, field_ty);
                 let field_ty = self.resolve_vars_if_possible(field_ty);
                 debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
-                AdtField { ty: field_ty, span: field.ty.span }
+                AdtField { ty: field_ty, span: field.ty.span, def_id }
             })
             .collect();
         AdtVariant { fields, explicit_discr: None }
index 1a4c2eb5155849168bcb719b3763737abc840ea3..46b3ec5cf40c774ce5259e3892b9c62c7918c3d0 100644 (file)
@@ -1437,6 +1437,52 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                 // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
                 None
             } else if tcx.lazy_normalization() {
+                if let Some(param_id) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) {
+                    // If the def_id we are calling generics_of on is an anon ct default i.e:
+                    //
+                    // struct Foo<const N: usize = { .. }>;
+                    //        ^^^       ^          ^^^^^^ def id of this anon const
+                    //        ^         ^ param_id
+                    //        ^ parent_def_id
+                    //
+                    // then we only want to return generics for params to the left of `N`. If we don't do that we
+                    // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`.
+                    //
+                    // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as
+                    // we substitute the defaults with the partially built substs when we build the substs. Subst'ing
+                    // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building.
+                    //
+                    // We fix this by having this function return the parent's generics ourselves and truncating the
+                    // generics to only include non-forward declared params (with the exception of the `Self` ty)
+                    //
+                    // For the above code example that means we want `substs: []`
+                    // For the following struct def we want `substs: [N#0]` when generics_of is called on
+                    // the def id of the `{ N + 1 }` anon const
+                    // struct Foo<const N: usize, const M: usize = { N + 1 }>;
+                    //
+                    // This has some implications for how we get the predicates available to the anon const
+                    // see `explicit_predicates_of` for more information on this
+                    let generics = tcx.generics_of(parent_def_id.to_def_id());
+                    let param_def = tcx.hir().local_def_id(param_id).to_def_id();
+                    let param_def_idx = generics.param_def_id_to_index[&param_def];
+                    // In the above example this would be .params[..N#0]
+                    let params = generics.params[..param_def_idx as usize].to_owned();
+                    let param_def_id_to_index =
+                        params.iter().map(|param| (param.def_id, param.index)).collect();
+
+                    return ty::Generics {
+                        // we set the parent of these generics to be our parent's parent so that we
+                        // dont end up with substs: [N, M, N] for the const default on a struct like this:
+                        // struct Foo<const N: usize, const M: usize = { ... }>;
+                        parent: generics.parent,
+                        parent_count: generics.parent_count,
+                        params,
+                        param_def_id_to_index,
+                        has_self: generics.has_self,
+                        has_late_bound_regions: generics.has_late_bound_regions,
+                    };
+                }
+
                 // HACK(eddyb) this provides the correct generics when
                 // `feature(const_generics)` is enabled, so that const expressions
                 // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
@@ -2355,7 +2401,8 @@ fn trait_explicit_predicates_and_bounds(
 }
 
 fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
-    if let DefKind::Trait = tcx.def_kind(def_id) {
+    let def_kind = tcx.def_kind(def_id);
+    if let DefKind::Trait = def_kind {
         // Remove bounds on associated types from the predicates, they will be
         // returned by `explicit_item_bounds`.
         let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
@@ -2400,6 +2447,26 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
             }
         }
     } else {
+        if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
+            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+            if let Some(_) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) {
+                // In `generics_of` we set the generics' parent to be our parent's parent which means that
+                // we lose out on the predicates of our actual parent if we dont return those predicates here.
+                // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
+                //
+                // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
+                //        ^^^                     ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
+                //        ^^^                                             explicit_predicates_of on
+                //        parent item we dont have set as the
+                //        parent of generics returned by `generics_of`
+                //
+                // In the above code we want the anon const to have predicates in its param env for `T: Trait`
+                let item_id = tcx.hir().get_parent_item(hir_id);
+                let item_def_id = tcx.hir().local_def_id(item_id).to_def_id();
+                // In the above code example we would be calling `explicit_predicates_of(Foo)` here
+                return tcx.explicit_predicates_of(item_def_id);
+            }
+        }
         gather_explicit_predicates_of(tcx, def_id)
     }
 }
index 15469cb0066c50ec60112fb493d8e0a32653d224..50e4ba4fe6c3e23cd22c40c364bb2f661905a552 100644 (file)
@@ -364,7 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     let concrete_ty = tcx
                         .mir_borrowck(owner.expect_local())
                         .concrete_opaque_types
-                        .get_by(|(key, _)| key.def_id == def_id.to_def_id())
+                        .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
                         .map(|concrete_ty| *concrete_ty)
                         .unwrap_or_else(|| {
                             tcx.sess.delay_span_bug(
@@ -512,8 +512,15 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
 
     struct ConstraintLocator<'tcx> {
         tcx: TyCtxt<'tcx>,
+
+        /// def_id of the opaque type whose defining uses are being checked
         def_id: DefId,
-        // (first found type span, actual type)
+
+        /// as we walk the defining uses, we are checking that all of them
+        /// define the same hidden type. This variable is set to `Some`
+        /// with the first type that we find, and then later types are
+        /// checked against it (we also carry the span of that first
+        /// type).
         found: Option<(Span, Ty<'tcx>)>,
     }
 
@@ -531,7 +538,7 @@ fn check(&mut self, def_id: LocalDefId) {
                 .tcx
                 .typeck(def_id)
                 .concrete_opaque_types
-                .get_by(|(key, _)| key.def_id == self.def_id)
+                .any_value_matching(|(key, _)| key.def_id == self.def_id)
                 .is_none()
             {
                 debug!("no constraints in typeck results");
index 806f1a2711c012b9d52d7830d5d40efd755a5b7a..6c76a8960bbe1a2a509ae6165787ef30c4c65822 100644 (file)
@@ -667,7 +667,7 @@ fn walk_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) {
     /// When the current body being handled is a closure, then we must make sure that
     /// - The parent closure only captures Places from the nested closure that are not local to it.
     ///
-    /// In the following example the closures `c` only captures `p.x`` even though `incr`
+    /// In the following example the closures `c` only captures `p.x` even though `incr`
     /// is a capture of the nested closure
     ///
     /// ```rust,ignore(cannot-test-this-because-pseudo-code)
index a8ec7b79e571f284141e7343e525a86ea6faba56..e7503d3d71ceaec5cb9480f521299b3d87a640fa 100644 (file)
@@ -3,10 +3,10 @@
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::HirId;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::TraitEngine;
+use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, ToPredicate, TyCtxt};
+use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_trait_selection::traits;
 
 pub fn provide(providers: &mut Providers) {
@@ -17,21 +17,20 @@ pub fn provide(providers: &mut Providers) {
 // need access to `ItemCtxt`
 fn diagnostic_hir_wf_check<'tcx>(
     tcx: TyCtxt<'tcx>,
-    (predicate, hir_id): (ty::Predicate<'tcx>, HirId),
+    (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
 ) -> Option<ObligationCause<'tcx>> {
     let hir = tcx.hir();
-    // HIR wfcheck should only ever happen as part of improving an existing error
-    tcx.sess.delay_span_bug(hir.span(hir_id), "Performed HIR wfcheck without an existing error!");
 
-    // Currently, we only handle WF checking for items (e.g. associated items).
-    // It would be nice to extend this to handle wf checks inside functions.
-    let def_id = match tcx.hir().opt_local_def_id(hir_id) {
-        Some(def_id) => def_id,
-        None => return None,
+    let def_id = match loc {
+        WellFormedLoc::Ty(def_id) => def_id,
+        WellFormedLoc::Param { function, param_idx: _ } => function,
     };
+    let hir_id = hir.local_def_id_to_hir_id(def_id);
+
+    // HIR wfcheck should only ever happen as part of improving an existing error
+    tcx.sess
+        .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
 
-    // FIXME - figure out how we want to handle wf-checking for
-    // things inside a function body.
     let icx = ItemCtxt::new(tcx, def_id.to_def_id());
 
     // To perform HIR-based WF checking, we iterate over all HIR types
@@ -72,7 +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);
+                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,
@@ -119,19 +119,67 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
         depth: 0,
     };
 
-    let ty = match tcx.hir().get(hir_id) {
-        hir::Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::TyAlias(ty) => Some(ty),
-            _ => None,
-        },
-        hir::Node::TraitItem(item) => match item.kind {
-            hir::TraitItemKind::Type(_, ty) => ty,
-            _ => None,
+    // Get the starting `hir::Ty` using our `WellFormedLoc`.
+    // We will walk 'into' this type to try to find
+    // a more precise span for our predicate.
+    let ty = match loc {
+        WellFormedLoc::Ty(_) => match hir.get(hir_id) {
+            hir::Node::ImplItem(item) => match item.kind {
+                hir::ImplItemKind::TyAlias(ty) => Some(ty),
+                ref item => bug!("Unexpected ImplItem {:?}", item),
+            },
+            hir::Node::TraitItem(item) => match item.kind {
+                hir::TraitItemKind::Type(_, ty) => ty,
+                ref item => bug!("Unexpected TraitItem {:?}", item),
+            },
+            hir::Node::Item(item) => match item.kind {
+                hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty),
+                hir::ItemKind::Impl(ref impl_) => {
+                    assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_);
+                    Some(impl_.self_ty)
+                }
+                ref item => bug!("Unexpected item {:?}", item),
+            },
+            hir::Node::Field(field) => Some(field.ty),
+            ref node => bug!("Unexpected node {:?}", node),
         },
-        _ => None,
+        WellFormedLoc::Param { function: _, param_idx } => {
+            let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap();
+            // Get return type
+            if param_idx as usize == fn_decl.inputs.len() {
+                match fn_decl.output {
+                    hir::FnRetTy::Return(ty) => Some(ty),
+                    // The unit type `()` is always well-formed
+                    hir::FnRetTy::DefaultReturn(_span) => None,
+                }
+            } else {
+                Some(&fn_decl.inputs[param_idx as usize])
+            }
+        }
     };
     if let Some(ty) = ty {
         visitor.visit_ty(ty);
     }
     visitor.cause
 }
+
+struct EraseAllBoundRegions<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+// Higher ranked regions are complicated.
+// To make matters worse, the HIR WF check can instantiate them
+// outside of a `Binder`, due to the way we (ab)use
+// `ItemCtxt::to_ty`. To make things simpler, we just erase all
+// of them, regardless of depth. At worse, this will give
+// us an inaccurate span for an error message, but cannot
+// lead to unsoundess (we call `delay_span_bug` at the start
+// of `diagnostic_hir_wf_check`).
+impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+        if let ty::ReLateBound(..) = r { &ty::ReErased } else { r }
+    }
+}
index 5b717862e020f9d2bc622b8c4a4991de85ebda03..faf00816994abc31d29f303cc64f3af1731e6139 100644 (file)
@@ -56,7 +56,7 @@
 */
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(bindings_after_at)]
+#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
index d7eb31c2abef51b927b9c759443a71e66dba2ad7..70a2ba7fcd9d9cc5e2c54238246e21b2d2ec86f0 100644 (file)
@@ -20,6 +20,27 @@ pub fn provide(providers: &mut Providers) {
 fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] {
     let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
 
+    if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization()
+    {
+        if let Some(_) = tcx.hir().opt_const_param_default_param_hir_id(id) {
+            // In `generics_of` we set the generics' parent to be our parent's parent which means that
+            // we lose out on the predicates of our actual parent if we dont return those predicates here.
+            // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
+            //
+            // struct Foo<'a, 'b, const N: usize = { ... }>(&'a &'b ());
+            //        ^^^                          ^^^^^^^ the def id we are calling
+            //        ^^^                                  inferred_outlives_of on
+            //        parent item we dont have set as the
+            //        parent of generics returned by `generics_of`
+            //
+            // In the above code we want the anon const to have predicates in its param env for `'b: 'a`
+            let item_id = tcx.hir().get_parent_item(id);
+            let item_def_id = tcx.hir().local_def_id(item_id).to_def_id();
+            // In the above code example we would be calling `inferred_outlives_of(Foo)` here
+            return tcx.inferred_outlives_of(item_def_id);
+        }
+    }
+
     match tcx.hir().get(id) {
         Node::Item(item) => match item.kind {
             hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
index 9a820f0803f0ade766ea8578cd536443c3cacf2b..775133f2ab3194f96dce98c507447f8617149542 100644 (file)
@@ -38,7 +38,7 @@ changelog-seen = 2
 # This is false by default so that distributions don't unexpectedly download
 # LLVM from the internet.
 #
-# All tier 1 targets are currently supported; set this to `"if-supported"` if
+# All tier 1 targets are currently supported; set this to `"if-available"` if
 # you are not sure whether you're on a tier 1 target.
 #
 # We also currently only support this when building LLVM for the build triple.
index 2f656e4a6b4acc2d5cb18ddd5c6c3a7a7462c90c..8a29af3fe07e605e248e3a77c48e7a1af64f3882 100644 (file)
 /// assert!(heap.is_empty())
 /// ```
 ///
+/// A `BinaryHeap` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::BinaryHeap;
+///
+/// let heap = BinaryHeap::from([1, 5, 2]);
+/// ```
+///
 /// ## Min-heap
 ///
 /// Either `std::cmp::Reverse` or a custom `Ord` implementation can be used to
@@ -1465,6 +1473,22 @@ fn from(vec: Vec<T>) -> BinaryHeap<T> {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+impl<T: Ord, const N: usize> From<[T; N]> for BinaryHeap<T> {
+    /// ```
+    /// use std::collections::BinaryHeap;
+    ///
+    /// let mut h1 = BinaryHeap::from([1, 4, 2, 3]);
+    /// let mut h2: BinaryHeap<_> = [1, 4, 2, 3].into();
+    /// while let Some((a, b)) = h1.pop().zip(h2.pop()) {
+    ///     assert_eq!(a, b);
+    /// }
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
+
 #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T> From<BinaryHeap<T>> for Vec<T> {
     /// Converts a `BinaryHeap<T>` into a `Vec<T>`.
index dfd693d13b330f51a222324e2970598f1800134d..2affbc032dce544104a6c252b1471eaeb7c367bb 100644 (file)
 /// }
 /// ```
 ///
-/// `BTreeMap` also implements an [`Entry API`], which allows for more complex
+/// A `BTreeMap` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::BTreeMap;
+///
+/// let solar_distance = BTreeMap::from([
+///     ("Mercury", 0.4),
+///     ("Venus", 0.7),
+///     ("Earth", 1.0),
+///     ("Mars", 1.5),
+/// ]);
+/// ```
+///
+/// `BTreeMap` implements an [`Entry API`], which allows for complex
 /// methods of getting, setting, updating and removing keys and their values:
 ///
 /// [`Entry API`]: BTreeMap::entry
@@ -935,6 +948,7 @@ pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
+    /// The elements are visited in ascending key order.
     ///
     /// # Examples
     ///
@@ -2011,6 +2025,20 @@ fn index(&self, key: &Q) -> &V {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+impl<K: Ord, V, const N: usize> From<[(K, V); N]> for BTreeMap<K, V> {
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let map1 = BTreeMap::from([(1, 2), (3, 4)]);
+    /// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into();
+    /// assert_eq!(map1, map2);
+    /// ```
+    fn from(arr: [(K, V); N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
+
 impl<K, V> BTreeMap<K, V> {
     /// Gets an iterator over the entries of the map, sorted by key.
     ///
index 3a74b6a6fa85c8f29d366769df6b37ce1b30a2c0..1e61692b7c63cb65be66a7d3ea5c8d019e1fbee7 100644 (file)
@@ -2173,3 +2173,10 @@ fn test_insert_remove_intertwined_ord_chaos() {
     }
     map.check_invariants();
 }
+
+#[test]
+fn from_array() {
+    let map = BTreeMap::from([(1, 2), (3, 4)]);
+    let unordered_duplicates = BTreeMap::from([(3, 4), (1, 2), (1, 2)]);
+    assert_eq!(map, unordered_duplicates);
+}
index be740b05fb8ee78b96fce064f7337e63797c45bc..0c268ad32b2612b4d0cd070ca99e2fbf2807e050 100644 (file)
 ///     println!("{}", book);
 /// }
 /// ```
+///
+/// A `BTreeSet` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::BTreeSet;
+///
+/// let set = BTreeSet::from([1, 2, 3]);
+/// ```
 #[derive(Hash, PartialEq, Eq, Ord, PartialOrd)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")]
@@ -846,6 +854,7 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// The elements are visited in ascending order.
     ///
     /// # Examples
     ///
@@ -1056,6 +1065,20 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+impl<T: Ord, const N: usize> From<[T; N]> for BTreeSet<T> {
+    /// ```
+    /// use std::collections::BTreeSet;
+    ///
+    /// let set1 = BTreeSet::from([1, 2, 3, 4]);
+    /// let set2: BTreeSet<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(set1, set2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> IntoIterator for BTreeSet<T> {
     type Item = T;
index 4cb6e3d6619dcb05ac25c1154f3151ee0b1a6343..de7a10dca7b8c5ccfe1c80d3924c26a5d4a1703a 100644 (file)
@@ -738,3 +738,10 @@ fn test_split_off_large_random_sorted() {
     assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
     assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
 }
+
+#[test]
+fn from_array() {
+    let set = BTreeSet::from([1, 2, 3, 4]);
+    let unordered_duplicates = BTreeSet::from([4, 1, 4, 3, 2]);
+    assert_eq!(set, unordered_duplicates);
+}
index 588ba2de2209bcd32e1ae3425a48c87bc2b44e5d..7aa24ff4afaeef919eb4c745b9d1e41da917dbdb 100644 (file)
 /// The `LinkedList` allows pushing and popping elements at either end
 /// in constant time.
 ///
+/// A `LinkedList` with a known list of items can be initialized from an array:
+/// ```
+/// use std::collections::LinkedList;
+///
+/// let list = LinkedList::from([1, 2, 3]);
+/// ```
+///
 /// NOTE: It is almost always better to use `Vec` or `VecDeque` because
 /// array-based containers are generally faster,
 /// more memory efficient, and make better use of CPU cache.
@@ -1901,6 +1908,20 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+impl<T, const N: usize> From<[T; N]> for LinkedList<T> {
+    /// ```
+    /// use std::collections::LinkedList;
+    ///
+    /// let list1 = LinkedList::from([1, 2, 3, 4]);
+    /// let list2: LinkedList<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(list1, list2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
+
 // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
 #[allow(dead_code)]
 fn assert_covariance() {
index 4ffb435d1e36670d3a2778eae55d94630cc454da..dfa0227dea3b8263f03af04c99d213e18c768cd1 100644 (file)
@@ -2,6 +2,8 @@
 use core::ptr::{self, NonNull};
 use core::{fmt, mem};
 
+use crate::alloc::{Allocator, Global};
+
 use super::{count, Iter, VecDeque};
 
 /// A draining iterator over the elements of a `VecDeque`.
 ///
 /// [`drain`]: VecDeque::drain
 #[stable(feature = "drain", since = "1.6.0")]
-pub struct Drain<'a, T: 'a> {
+pub struct Drain<
+    'a,
+    T: 'a,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
     pub(crate) after_tail: usize,
     pub(crate) after_head: usize,
     pub(crate) iter: Iter<'a, T>,
-    pub(crate) deque: NonNull<VecDeque<T>>,
+    pub(crate) deque: NonNull<VecDeque<T, A>>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
-impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("Drain")
             .field(&self.after_tail)
@@ -30,16 +36,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-unsafe impl<T: Sync> Sync for Drain<'_, T> {}
+unsafe impl<T: Sync, A: Allocator + Sync> Sync for Drain<'_, T, A> {}
 #[stable(feature = "drain", since = "1.6.0")]
-unsafe impl<T: Send> Send for Drain<'_, T> {}
+unsafe impl<T: Send, A: Allocator + Send> Send for Drain<'_, T, A> {}
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> Drop for Drain<'_, T> {
+impl<T, A: Allocator> Drop for Drain<'_, T, A> {
     fn drop(&mut self) {
-        struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>);
+        struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
 
-        impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> {
+        impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
             fn drop(&mut self) {
                 self.0.for_each(drop);
 
@@ -96,7 +102,7 @@ fn drop(&mut self) {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> Iterator for Drain<'_, T> {
+impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
     type Item = T;
 
     #[inline]
@@ -111,7 +117,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> DoubleEndedIterator for Drain<'_, T> {
+impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
         self.iter.next_back().map(|elt| unsafe { ptr::read(elt) })
@@ -119,7 +125,7 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-impl<T> ExactSizeIterator for Drain<'_, T> {}
+impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {}
 
 #[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for Drain<'_, T> {}
+impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
index 46a769a722a8bf3ce44873eb25186e63d3e84c7f..5f13c3bf30387bdb74c75ad497c00c35533a797f 100644 (file)
@@ -1,5 +1,7 @@
 use core::fmt;
-use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
+use core::iter::{FusedIterator, TrustedLen};
+
+use crate::alloc::{Allocator, Global};
 
 use super::VecDeque;
 
 /// [`into_iter`]: VecDeque::into_iter
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<T> {
-    pub(crate) inner: VecDeque<T>,
+pub struct IntoIter<
+    T,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
+    pub(crate) inner: VecDeque<T, A>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
-impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("IntoIter").field(&self.inner).finish()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Iterator for IntoIter<T> {
+impl<T, A: Allocator> Iterator for IntoIter<T, A> {
     type Item = T;
 
     #[inline]
@@ -36,27 +41,10 @@ fn size_hint(&self) -> (usize, Option<usize>) {
         let len = self.inner.len();
         (len, Some(len))
     }
-
-    #[inline]
-    #[doc(hidden)]
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
-    where
-        Self: TrustedRandomAccess,
-    {
-        // Safety: The TrustedRandomAccess contract requires that callers only pass an index
-        // that is in bounds.
-        // Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
-        // multiple repeated reads of the same index would be safe and the
-        // values are !Drop, thus won't suffer from double drops.
-        unsafe {
-            let idx = self.inner.wrap_add(self.inner.tail, idx);
-            self.inner.buffer_read(idx)
-        }
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> DoubleEndedIterator for IntoIter<T> {
+impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
         self.inner.pop_back()
@@ -64,25 +52,14 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ExactSizeIterator for IntoIter<T> {
+impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
     fn is_empty(&self) -> bool {
         self.inner.is_empty()
     }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for IntoIter<T> {}
+impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T> TrustedLen for IntoIter<T> {}
-
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
-// and thus we can't implement drop-handling
-unsafe impl<T> TrustedRandomAccess for IntoIter<T>
-where
-    T: Copy,
-{
-    const MAY_HAVE_SIDE_EFFECT: bool = false;
-}
+unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}
index 0d59d312cf406d35c224e88f27b6a748f3e54598..5c7913073fe8780f48c29f98b259caaf0f740a98 100644 (file)
@@ -1,9 +1,9 @@
 macro_rules! __impl_slice_eq1 {
     ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => {
         #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")]
-        impl<A, B, $($vars)*> PartialEq<$rhs> for $lhs
+        impl<T, U, A: Allocator, $($vars)*> PartialEq<$rhs> for $lhs
         where
-            A: PartialEq<B>,
+            T: PartialEq<U>,
             $($constraints)*
         {
             fn eq(&self, other: &$rhs) -> bool {
index 461e701be054ee82b9493ef0ba0d27ec95f14668..386c7c2612d572e91ece1bc0254b2a6407b3cf26 100644 (file)
@@ -17,6 +17,7 @@
 use core::ptr::{self, NonNull};
 use core::slice;
 
+use crate::alloc::{Allocator, Global};
 use crate::collections::TryReserveError;
 use crate::raw_vec::RawVec;
 use crate::vec::Vec;
 /// push onto the back in this manner, and iterating over `VecDeque` goes front
 /// to back.
 ///
+/// A `VecDeque` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::VecDeque;
+///
+/// let deq = VecDeque::from([-1, 0, 1]);
+/// ```
+///
 /// Since `VecDeque` is a ring buffer, its elements are not necessarily contiguous
 /// in memory. If you want to access the elements as a single slice, such as for
 /// efficient sorting, you can use [`make_contiguous`]. It rotates the `VecDeque`
 /// [`make_contiguous`]: VecDeque::make_contiguous
 #[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct VecDeque<T> {
+pub struct VecDeque<
+    T,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
     // tail and head are pointers into the buffer. Tail always points
     // to the first element that could be read, Head always points
     // to where data should be written.
@@ -88,13 +100,15 @@ pub struct VecDeque<T> {
     // is defined as the distance between the two.
     tail: usize,
     head: usize,
-    buf: RawVec<T>,
+    buf: RawVec<T, A>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Clone> Clone for VecDeque<T> {
-    fn clone(&self) -> VecDeque<T> {
-        self.iter().cloned().collect()
+impl<T: Clone, A: Allocator + Clone> Clone for VecDeque<T, A> {
+    fn clone(&self) -> Self {
+        let mut deq = Self::with_capacity_in(self.len(), self.allocator().clone());
+        deq.extend(self.iter().cloned());
+        deq
     }
 
     fn clone_from(&mut self, other: &Self) {
@@ -114,7 +128,7 @@ fn clone_from(&mut self, other: &Self) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<#[may_dangle] T> Drop for VecDeque<T> {
+unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque<T, A> {
     fn drop(&mut self) {
         /// Runs the destructor for all items in the slice when it gets dropped (normally or
         /// during unwinding).
@@ -147,7 +161,7 @@ fn default() -> VecDeque<T> {
     }
 }
 
-impl<T> VecDeque<T> {
+impl<T, A: Allocator> VecDeque<T, A> {
     /// Marginally more convenient
     #[inline]
     fn ptr(&self) -> *mut T {
@@ -457,9 +471,10 @@ impl<T> VecDeque<T> {
     ///
     /// let vector: VecDeque<u32> = VecDeque::new();
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> VecDeque<T> {
-        VecDeque::with_capacity(INITIAL_CAPACITY)
+        VecDeque::new_in(Global)
     }
 
     /// Creates an empty `VecDeque` with space for at least `capacity` elements.
@@ -471,13 +486,45 @@ pub fn new() -> VecDeque<T> {
     ///
     /// let vector: VecDeque<u32> = VecDeque::with_capacity(10);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize) -> VecDeque<T> {
+        Self::with_capacity_in(capacity, Global)
+    }
+}
+
+impl<T, A: Allocator> VecDeque<T, A> {
+    /// Creates an empty `VecDeque`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let vector: VecDeque<u32> = VecDeque::new();
+    /// ```
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn new_in(alloc: A) -> VecDeque<T, A> {
+        VecDeque::with_capacity_in(INITIAL_CAPACITY, alloc)
+    }
+
+    /// Creates an empty `VecDeque` with space for at least `capacity` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let vector: VecDeque<u32> = VecDeque::with_capacity(10);
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque<T, A> {
         // +1 since the ringbuffer always leaves one space empty
         let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
         assert!(cap > capacity, "capacity overflow");
 
-        VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity(cap) }
+        VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity_in(cap, alloc) }
     }
 
     /// Provides a reference to the element at the given index.
@@ -904,6 +951,13 @@ fn drop(&mut self) {
         }
     }
 
+    /// Returns a reference to the underlying allocator.
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn allocator(&self) -> &A {
+        self.buf.allocator()
+    }
+
     /// Returns a front-to-back iterator.
     ///
     /// # Examples
@@ -1176,7 +1230,7 @@ pub fn range_mut<R>(&mut self, range: R) -> IterMut<'_, T>
     /// ```
     #[inline]
     #[stable(feature = "drain", since = "1.6.0")]
-    pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
+    pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, A>
     where
         R: RangeBounds<usize>,
     {
@@ -1965,12 +2019,15 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
     #[inline]
     #[must_use = "use `.truncate()` if you don't need the other half"]
     #[stable(feature = "split_off", since = "1.4.0")]
-    pub fn split_off(&mut self, at: usize) -> Self {
+    pub fn split_off(&mut self, at: usize) -> Self
+    where
+        A: Clone,
+    {
         let len = self.len();
         assert!(at <= len, "`at` out of bounds");
 
         let other_len = len - at;
-        let mut other = VecDeque::with_capacity(other_len);
+        let mut other = VecDeque::with_capacity_in(other_len, self.allocator().clone());
 
         unsafe {
             let (first_half, second_half) = self.as_slices();
@@ -2593,7 +2650,7 @@ pub fn partition_point<P>(&self, mut pred: P) -> usize
     }
 }
 
-impl<T: Clone> VecDeque<T> {
+impl<T: Clone, A: Allocator> VecDeque<T, A> {
     /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
     /// either by removing excess elements from the back or by appending clones of `value`
     /// to the back.
@@ -2637,8 +2694,8 @@ fn count(tail: usize, head: usize, size: usize) -> usize {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: PartialEq> PartialEq for VecDeque<A> {
-    fn eq(&self, other: &VecDeque<A>) -> bool {
+impl<T: PartialEq, A: Allocator> PartialEq for VecDeque<T, A> {
+    fn eq(&self, other: &Self) -> bool {
         if self.len() != other.len() {
             return false;
         }
@@ -2676,32 +2733,32 @@ fn eq(&self, other: &VecDeque<A>) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Eq> Eq for VecDeque<A> {}
+impl<T: Eq, A: Allocator> Eq for VecDeque<T, A> {}
 
-__impl_slice_eq1! { [] VecDeque<A>, Vec<B>, }
-__impl_slice_eq1! { [] VecDeque<A>, &[B], }
-__impl_slice_eq1! { [] VecDeque<A>, &mut [B], }
-__impl_slice_eq1! { [const N: usize] VecDeque<A>, [B; N], }
-__impl_slice_eq1! { [const N: usize] VecDeque<A>, &[B; N], }
-__impl_slice_eq1! { [const N: usize] VecDeque<A>, &mut [B; N], }
+__impl_slice_eq1! { [] VecDeque<T, A>, Vec<U, A>, }
+__impl_slice_eq1! { [] VecDeque<T, A>, &[U], }
+__impl_slice_eq1! { [] VecDeque<T, A>, &mut [U], }
+__impl_slice_eq1! { [const N: usize] VecDeque<T, A>, [U; N], }
+__impl_slice_eq1! { [const N: usize] VecDeque<T, A>, &[U; N], }
+__impl_slice_eq1! { [const N: usize] VecDeque<T, A>, &mut [U; N], }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: PartialOrd> PartialOrd for VecDeque<A> {
-    fn partial_cmp(&self, other: &VecDeque<A>) -> Option<Ordering> {
+impl<T: PartialOrd, A: Allocator> PartialOrd for VecDeque<T, A> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         self.iter().partial_cmp(other.iter())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Ord> Ord for VecDeque<A> {
+impl<T: Ord, A: Allocator> Ord for VecDeque<T, A> {
     #[inline]
-    fn cmp(&self, other: &VecDeque<A>) -> Ordering {
+    fn cmp(&self, other: &Self) -> Ordering {
         self.iter().cmp(other.iter())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Hash> Hash for VecDeque<A> {
+impl<T: Hash, A: Allocator> Hash for VecDeque<T, A> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.len().hash(state);
         // It's not possible to use Hash::hash_slice on slices
@@ -2715,26 +2772,26 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A> Index<usize> for VecDeque<A> {
-    type Output = A;
+impl<T, A: Allocator> Index<usize> for VecDeque<T, A> {
+    type Output = T;
 
     #[inline]
-    fn index(&self, index: usize) -> &A {
+    fn index(&self, index: usize) -> &T {
         self.get(index).expect("Out of bounds access")
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A> IndexMut<usize> for VecDeque<A> {
+impl<T, A: Allocator> IndexMut<usize> for VecDeque<T, A> {
     #[inline]
-    fn index_mut(&mut self, index: usize) -> &mut A {
+    fn index_mut(&mut self, index: usize) -> &mut T {
         self.get_mut(index).expect("Out of bounds access")
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A> FromIterator<A> for VecDeque<A> {
-    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> VecDeque<A> {
+impl<T> FromIterator<T> for VecDeque<T> {
+    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
         let iterator = iter.into_iter();
         let (lower, _) = iterator.size_hint();
         let mut deq = VecDeque::with_capacity(lower);
@@ -2744,19 +2801,19 @@ fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> VecDeque<A> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> IntoIterator for VecDeque<T> {
+impl<T, A: Allocator> IntoIterator for VecDeque<T, A> {
     type Item = T;
-    type IntoIter = IntoIter<T>;
+    type IntoIter = IntoIter<T, A>;
 
     /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
     /// value.
-    fn into_iter(self) -> IntoIter<T> {
+    fn into_iter(self) -> IntoIter<T, A> {
         IntoIter { inner: self }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a VecDeque<T> {
+impl<'a, T, A: Allocator> IntoIterator for &'a VecDeque<T, A> {
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
 
@@ -2766,7 +2823,7 @@ fn into_iter(self) -> Iter<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
+impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque<T, A> {
     type Item = &'a mut T;
     type IntoIter = IterMut<'a, T>;
 
@@ -2776,8 +2833,8 @@ fn into_iter(self) -> IterMut<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A> Extend<A> for VecDeque<A> {
-    fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
+impl<T, A: Allocator> Extend<T> for VecDeque<T, A> {
+    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         // This function should be the moral equivalent of:
         //
         //      for item in iter.into_iter() {
@@ -2799,7 +2856,7 @@ fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
     }
 
     #[inline]
-    fn extend_one(&mut self, elem: A) {
+    fn extend_one(&mut self, elem: T) {
         self.push_back(elem);
     }
 
@@ -2810,7 +2867,7 @@ fn extend_reserve(&mut self, additional: usize) {
 }
 
 #[stable(feature = "extend_ref", since = "1.2.0")]
-impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque<T> {
+impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque<T, A> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
@@ -2827,14 +2884,14 @@ fn extend_reserve(&mut self, additional: usize) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
+impl<T: fmt::Debug, A: Allocator> fmt::Debug for VecDeque<T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self).finish()
     }
 }
 
 #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")]
-impl<T> From<Vec<T>> for VecDeque<T> {
+impl<T, A: Allocator> From<Vec<T, A>> for VecDeque<T, A> {
     /// Turn a [`Vec<T>`] into a [`VecDeque<T>`].
     ///
     /// [`Vec<T>`]: crate::vec::Vec
@@ -2843,7 +2900,7 @@ impl<T> From<Vec<T>> for VecDeque<T> {
     /// This avoids reallocating where possible, but the conditions for that are
     /// strict, and subject to change, and so shouldn't be relied upon unless the
     /// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
-    fn from(mut other: Vec<T>) -> Self {
+    fn from(mut other: Vec<T, A>) -> Self {
         let len = other.len();
         if mem::size_of::<T>() == 0 {
             // There's no actual allocation for ZSTs to worry about capacity,
@@ -2861,15 +2918,15 @@ fn from(mut other: Vec<T>) -> Self {
         }
 
         unsafe {
-            let (other_buf, len, capacity) = other.into_raw_parts();
-            let buf = RawVec::from_raw_parts(other_buf, capacity);
+            let (other_buf, len, capacity, alloc) = other.into_raw_parts_with_alloc();
+            let buf = RawVec::from_raw_parts_in(other_buf, capacity, alloc);
             VecDeque { tail: 0, head: len, buf }
         }
     }
 }
 
 #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")]
-impl<T> From<VecDeque<T>> for Vec<T> {
+impl<T, A: Allocator> From<VecDeque<T, A>> for Vec<T, A> {
     /// Turn a [`VecDeque<T>`] into a [`Vec<T>`].
     ///
     /// [`Vec<T>`]: crate::vec::Vec
@@ -2899,7 +2956,7 @@ impl<T> From<VecDeque<T>> for Vec<T> {
     /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]);
     /// assert_eq!(vec.as_ptr(), ptr);
     /// ```
-    fn from(mut other: VecDeque<T>) -> Self {
+    fn from(mut other: VecDeque<T, A>) -> Self {
         other.make_contiguous();
 
         unsafe {
@@ -2907,11 +2964,26 @@ fn from(mut other: VecDeque<T>) -> Self {
             let buf = other.buf.ptr();
             let len = other.len();
             let cap = other.cap();
+            let alloc = ptr::read(other.allocator());
 
             if other.tail != 0 {
                 ptr::copy(buf.add(other.tail), buf, len);
             }
-            Vec::from_raw_parts(buf, len, cap)
+            Vec::from_raw_parts_in(buf, len, cap, alloc)
         }
     }
 }
+
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let deq1 = VecDeque::from([1, 2, 3, 4]);
+    /// let deq2: VecDeque<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(deq1, deq2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
index 7b87090fb07138f18c17f990304dd15adf1db729..8e3ac9cfd1d87dc919b7cce59bd8fb1ee8a3b663 100644 (file)
@@ -1,6 +1,8 @@
 use core::cmp::{self};
 use core::mem::replace;
 
+use crate::alloc::Allocator;
+
 use super::VecDeque;
 
 /// PairSlices pairs up equal length slice parts of two deques
@@ -25,7 +27,7 @@ pub struct PairSlices<'a, 'b, T> {
 }
 
 impl<'a, 'b, T> PairSlices<'a, 'b, T> {
-    pub fn from(to: &'a mut VecDeque<T>, from: &'b VecDeque<T>) -> Self {
+    pub fn from<A: Allocator>(to: &'a mut VecDeque<T, A>, from: &'b VecDeque<T, A>) -> Self {
         let (a0, a1) = to.as_mut_slices();
         let (b0, b1) = from.as_slices();
         PairSlices { a0, a1, b0, b1 }
index e8bd4bcb01f29e6d3deafdc19112c06817c9b489..f04180127b1cdd0cee9513f2dc1d507f3010bfaa 100644 (file)
 //! [`Rc`]: rc
 //! [`RefCell`]: core::cell
 
+// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
+// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
+// rustc itself never sets the feature, so this line has no affect there.
+#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![doc(
@@ -81,6 +85,7 @@
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
 #![feature(async_stream)]
+#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(cfg_sanitize)]
 #![feature(associated_type_bounds)]
 #![feature(slice_group_by)]
 #![feature(decl_macro)]
-#![feature(bindings_after_at)]
 // Allow testing this library
 
 #[cfg(test)]
index 61599259735c7d5a25632b46f5c58f41227a8384..2b380c444b8abe332718f868c885fc4f506d953d 100644 (file)
 /// assert_eq!(vec, [7, 1, 2, 3]);
 /// ```
 ///
-/// The [`vec!`] macro is provided to make initialization more convenient:
+/// The [`vec!`] macro is provided for convenient initialization:
 ///
 /// ```
-/// let mut vec = vec![1, 2, 3];
-/// vec.push(4);
-/// assert_eq!(vec, [1, 2, 3, 4]);
+/// let mut vec1 = vec![1, 2, 3];
+/// vec1.push(4);
+/// let vec2 = Vec::from([1, 2, 3, 4]);
+/// assert_eq!(vec1, vec2);
 /// ```
 ///
 /// It can also initialize each element of a `Vec<T>` with a given value.
index a1e819cf8f9e44b1cdfb53905b3dcf92212c4661..d3a87c056cfb1867b588ad58fd33892a23de3587 100644 (file)
@@ -1873,6 +1873,47 @@ fn cmp_search_to_vec<'a>(
         "* \t",
         [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
     );
+
+    // See #85462
+    #[test]
+    fn str_searcher_empty_needle_after_done() {
+        // Empty needle and haystack
+        {
+            let mut searcher = "".into_searcher("");
+
+            assert_eq!(searcher.next(), SearchStep::Match(0, 0));
+            assert_eq!(searcher.next(), SearchStep::Done);
+            assert_eq!(searcher.next(), SearchStep::Done);
+            assert_eq!(searcher.next(), SearchStep::Done);
+
+            let mut searcher = "".into_searcher("");
+
+            assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
+            assert_eq!(searcher.next_back(), SearchStep::Done);
+            assert_eq!(searcher.next_back(), SearchStep::Done);
+            assert_eq!(searcher.next_back(), SearchStep::Done);
+        }
+        // Empty needle and non-empty haystack
+        {
+            let mut searcher = "".into_searcher("a");
+
+            assert_eq!(searcher.next(), SearchStep::Match(0, 0));
+            assert_eq!(searcher.next(), SearchStep::Reject(0, 1));
+            assert_eq!(searcher.next(), SearchStep::Match(1, 1));
+            assert_eq!(searcher.next(), SearchStep::Done);
+            assert_eq!(searcher.next(), SearchStep::Done);
+            assert_eq!(searcher.next(), SearchStep::Done);
+
+            let mut searcher = "".into_searcher("a");
+
+            assert_eq!(searcher.next_back(), SearchStep::Match(1, 1));
+            assert_eq!(searcher.next_back(), SearchStep::Reject(0, 1));
+            assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
+            assert_eq!(searcher.next_back(), SearchStep::Done);
+            assert_eq!(searcher.next_back(), SearchStep::Done);
+            assert_eq!(searcher.next_back(), SearchStep::Done);
+        }
+    }
 }
 
 macro_rules! generate_iterator_test {
index 6dcc110f1539c104ba3a560599bb47ffe7e096ca..0a098c8e2d98633d158e50f175ee7fda400e6cc7 100644 (file)
 ///
 /// # Example
 ///
-/// ```no_run
-/// use std::alloc::{GlobalAlloc, Layout, alloc};
+/// ```
+/// use std::alloc::{GlobalAlloc, Layout};
+/// use std::cell::UnsafeCell;
 /// use std::ptr::null_mut;
+/// use std::sync::atomic::{
+///     AtomicUsize,
+///     Ordering::{Acquire, SeqCst},
+/// };
 ///
-/// struct MyAllocator;
-///
-/// unsafe impl GlobalAlloc for MyAllocator {
-///     unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
-///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
+/// const ARENA_SIZE: usize = 128 * 1024;
+/// const MAX_SUPPORTED_ALIGN: usize = 4096;
+/// #[repr(C, align(4096))] // 4096 == MAX_SUPPORTED_ALIGN
+/// struct SimpleAllocator {
+///     arena: UnsafeCell<[u8; ARENA_SIZE]>,
+///     remaining: AtomicUsize, // we allocate from the top, counting down
 /// }
 ///
 /// #[global_allocator]
-/// static A: MyAllocator = MyAllocator;
+/// static ALLOCATOR: SimpleAllocator = SimpleAllocator {
+///     arena: UnsafeCell::new([0x55; ARENA_SIZE]),
+///     remaining: AtomicUsize::new(ARENA_SIZE),
+/// };
 ///
-/// fn main() {
-///     unsafe {
-///         assert!(alloc(Layout::new::<u32>()).is_null())
+/// unsafe impl Sync for SimpleAllocator {}
+///
+/// unsafe impl GlobalAlloc for SimpleAllocator {
+///     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+///         let size = layout.size();
+///         let align = layout.align();
+///
+///         // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.
+///         // So we can safely use a mask to ensure alignment without worrying about UB.
+///         let align_mask_to_round_down = !(align - 1);
+///
+///         if align > MAX_SUPPORTED_ALIGN {
+///             return null_mut();
+///         }
+///
+///         let mut allocated = 0;
+///         if self
+///             .remaining
+///             .fetch_update(SeqCst, SeqCst, |mut remaining| {
+///                 if size > remaining {
+///                     return None;
+///                 }
+///                 remaining -= size;
+///                 remaining &= align_mask_to_round_down;
+///                 allocated = remaining;
+///                 Some(remaining)
+///             })
+///             .is_err()
+///         {
+///             return null_mut();
+///         };
+///         (self.arena.get() as *mut u8).add(allocated)
 ///     }
+///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
+/// }
+///
+/// fn main() {
+///     let _s = format!("allocating a string!");
+///     let currently = ALLOCATOR.remaining.load(Acquire);
+///     println!("allocated so far: {}", ARENA_SIZE - currently);
 /// }
 /// ```
 ///
index 931ea77eca4dc4c1bff749d1f489cd259fe63eef..61ab1b1faff89826be67617085c9a6e0def438ae 100644 (file)
@@ -2,7 +2,7 @@
 
 use crate::{
     fmt,
-    iter::{self, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess},
+    iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
     mem::{self, MaybeUninit},
     ops::Range,
     ptr,
@@ -130,19 +130,6 @@ fn count(self) -> usize {
     fn last(mut self) -> Option<Self::Item> {
         self.next_back()
     }
-
-    #[inline]
-    #[doc(hidden)]
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
-    where
-        Self: TrustedRandomAccess,
-    {
-        // SAFETY: Callers are only allowed to pass an index that is in bounds
-        // Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
-        // multiple repeated reads of the same index would be safe and the
-        // values are !Drop, thus won't suffer from double drops.
-        unsafe { self.data.get_unchecked(self.alive.start + idx).assume_init_read() }
-    }
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
@@ -197,17 +184,6 @@ impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
 unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
 
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
-// and thus we can't implement drop-handling
-unsafe impl<T, const N: usize> TrustedRandomAccess for IntoIter<T, N>
-where
-    T: Copy,
-{
-    const MAY_HAVE_SIDE_EFFECT: bool = false;
-}
-
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
 impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
     fn clone(&self) -> Self {
index 8cb7aad28aa95e791ec479975f0fe6997c13cabf..16efd2f0eaff954adb1b2cf94a78b4eba725c051 100644 (file)
@@ -333,21 +333,22 @@ fn nth(&mut self, n: usize) -> Option<Self::Item> {
     /// regardless of the step given.
     ///
     /// Note 2: The time at which ignored elements are pulled is not fixed.
-    /// `StepBy` behaves like the sequence `next(), nth(step-1), nth(step-1), â€¦`,
-    /// but is also free to behave like the sequence
-    /// `advance_n_and_return_first(step), advance_n_and_return_first(step), â€¦`
+    /// `StepBy` behaves like the sequence `self.next()`, `self.nth(step-1)`,
+    /// `self.nth(step-1)`, â€¦, but is also free to behave like the sequence
+    /// `advance_n_and_return_first(&mut self, step)`,
+    /// `advance_n_and_return_first(&mut self, step)`, â€¦
     /// Which way is used may change for some iterators for performance reasons.
     /// The second way will advance the iterator earlier and may consume more items.
     ///
     /// `advance_n_and_return_first` is the equivalent of:
     /// ```
-    /// fn advance_n_and_return_first<I>(iter: &mut I, total_step: usize) -> Option<I::Item>
+    /// fn advance_n_and_return_first<I>(iter: &mut I, n: usize) -> Option<I::Item>
     /// where
     ///     I: Iterator,
     /// {
     ///     let next = iter.next();
-    ///     if total_step > 1 {
-    ///         iter.nth(total_step-2);
+    ///     if n > 1 {
+    ///         iter.nth(n - 2);
     ///     }
     ///     next
     /// }
index 540cdf124ee9cf5f1a0c12394b61e9e120c6eddf..6d87a7ab055c2daafb22330291bd342053d776eb 100644 (file)
 //
 // This cfg won't affect doc tests.
 #![cfg(not(test))]
+// To run libcore tests without x.py without ending up with two copies of libcore, Miri needs to be
+// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
+// rustc itself never sets the feature, so this line has no affect there.
+#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
     html_playground_url = "https://play.rust-lang.org/",
index 3ca8f27c79ab7f60b11610cdb50595a1b64e2efa..07ee589e29f562fa9d95e7721d9d4c5707974984 100644 (file)
@@ -845,6 +845,7 @@ macro_rules! format_args {
                   language use and is subject to change"
     )]
     #[allow_internal_unstable(fmt_internals)]
+    #[doc(hidden)]
     #[rustc_builtin_macro]
     #[macro_export]
     macro_rules! format_args_nl {
index 5122421ea8c852fdef7afbbba7c3f58075f49a0f..d3ebc1cebb67bf6913e5f5b6fc86716779177cc1 100644 (file)
@@ -461,7 +461,6 @@ pub fn zeroed() -> MaybeUninit<T> {
     /// With `write`, we can avoid the need to write through a raw pointer:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit_extra)]
     /// use core::pin::Pin;
     /// use core::mem::MaybeUninit;
     ///
index 508c522e71aa25b7f9d60e6c90186dff41b7270c..55ac1aa765c1fabc0cdf6166a1d9dfabfb9c032e 100644 (file)
@@ -928,6 +928,8 @@ struct EmptyNeedle {
     end: usize,
     is_match_fw: bool,
     is_match_bw: bool,
+    // Needed in case of an empty haystack, see #85462
+    is_finished: bool,
 }
 
 impl<'a, 'b> StrSearcher<'a, 'b> {
@@ -941,6 +943,7 @@ fn new(haystack: &'a str, needle: &'b str) -> StrSearcher<'a, 'b> {
                     end: haystack.len(),
                     is_match_fw: true,
                     is_match_bw: true,
+                    is_finished: false,
                 }),
             }
         } else {
@@ -966,13 +969,19 @@ fn haystack(&self) -> &'a str {
     fn next(&mut self) -> SearchStep {
         match self.searcher {
             StrSearcherImpl::Empty(ref mut searcher) => {
+                if searcher.is_finished {
+                    return SearchStep::Done;
+                }
                 // empty needle rejects every char and matches every empty string between them
                 let is_match = searcher.is_match_fw;
                 searcher.is_match_fw = !searcher.is_match_fw;
                 let pos = searcher.position;
                 match self.haystack[pos..].chars().next() {
                     _ if is_match => SearchStep::Match(pos, pos),
-                    None => SearchStep::Done,
+                    None => {
+                        searcher.is_finished = true;
+                        SearchStep::Done
+                    }
                     Some(ch) => {
                         searcher.position += ch.len_utf8();
                         SearchStep::Reject(pos, searcher.position)
@@ -1045,12 +1054,18 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
     fn next_back(&mut self) -> SearchStep {
         match self.searcher {
             StrSearcherImpl::Empty(ref mut searcher) => {
+                if searcher.is_finished {
+                    return SearchStep::Done;
+                }
                 let is_match = searcher.is_match_bw;
                 searcher.is_match_bw = !searcher.is_match_bw;
                 let end = searcher.end;
                 match self.haystack[..end].chars().next_back() {
                     _ if is_match => SearchStep::Match(end, end),
-                    None => SearchStep::Done,
+                    None => {
+                        searcher.is_finished = true;
+                        SearchStep::Done
+                    }
                     Some(ch) => {
                         searcher.end -= ch.len_utf8();
                         SearchStep::Reject(searcher.end, end)
index fac285c96f00d3f4e2212d7976ce5181933b23df..b102fd9d5bfdc3a0bc917efeaa94fc1f6d947eab 100644 (file)
 /// }
 /// ```
 ///
-/// `HashMap` also implements an [`Entry API`](#method.entry), which allows
-/// for more complex methods of getting, setting, updating and removing keys and
+/// A `HashMap` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let solar_distance = HashMap::from([
+///     ("Mercury", 0.4),
+///     ("Venus", 0.7),
+///     ("Earth", 1.0),
+///     ("Mars", 1.5),
+/// ]);
+/// ```
+///
+/// `HashMap` implements an [`Entry API`](#method.entry), which allows
+/// for complex methods of getting, setting, updating and removing keys and
 /// their values:
 ///
 /// ```
 /// }
 ///
 /// // Use a HashMap to store the vikings' health points.
-/// let mut vikings = HashMap::new();
-///
-/// vikings.insert(Viking::new("Einar", "Norway"), 25);
-/// vikings.insert(Viking::new("Olaf", "Denmark"), 24);
-/// vikings.insert(Viking::new("Harald", "Iceland"), 12);
+/// let vikings = HashMap::from([
+///     (Viking::new("Einar", "Norway"), 25),
+///     (Viking::new("Olaf", "Denmark"), 24),
+///     (Viking::new("Harald", "Iceland"), 12),
+/// ]);
 ///
 /// // Use derived implementation to print the status of the vikings.
 /// for (viking, health) in &vikings {
 ///     println!("{:?} has {} hp", viking, health);
 /// }
 /// ```
-///
-/// A `HashMap` with fixed list of elements can be initialized from an array:
-///
-/// ```
-/// use std::collections::HashMap;
-///
-/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)]
-///     .iter().cloned().collect();
-/// // use the values stored in map
-/// ```
 
 #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -934,6 +937,7 @@ pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
+    /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
     ///
@@ -1147,6 +1151,37 @@ fn index(&self, key: &Q) -> &V {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+// Note: as what is currently the most convenient built-in way to construct
+// a HashMap, a simple usage of this function must not *require* the user
+// to provide a type annotation in order to infer the third type parameter
+// (the hasher parameter, conventionally "S").
+// To that end, this impl is defined using RandomState as the concrete
+// type of S, rather than being generic over `S: BuildHasher + Default`.
+// It is expected that users who want to specify a hasher will manually use
+// `with_capacity_and_hasher`.
+// If type parameter defaults worked on impls, and if type parameter
+// defaults could be mixed with const generics, then perhaps
+// this could be generalized.
+// See also the equivalent impl on HashSet.
+impl<K, V, const N: usize> From<[(K, V); N]> for HashMap<K, V, RandomState>
+where
+    K: Eq + Hash,
+{
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let map1 = HashMap::from([(1, 2), (3, 4)]);
+    /// let map2: HashMap<_, _> = [(1, 2), (3, 4)].into();
+    /// assert_eq!(map1, map2);
+    /// ```
+    fn from(arr: [(K, V); N]) -> Self {
+        crate::array::IntoIter::new(arr).collect()
+    }
+}
+
 /// An iterator over the entries of a `HashMap`.
 ///
 /// This `struct` is created by the [`iter`] method on [`HashMap`]. See its
index 819be14222752e1eb5724713361f22e504d90798..def085e380b19953dfbb86d830f3a9591e438167 100644 (file)
@@ -1085,3 +1085,15 @@ fn drop(&mut self) {
         assert_eq!(map.len(), 2);
     }
 }
+
+#[test]
+fn from_array() {
+    let map = HashMap::from([(1, 2), (3, 4)]);
+    let unordered_duplicates = HashMap::from([(3, 4), (1, 2), (1, 2)]);
+    assert_eq!(map, unordered_duplicates);
+
+    // This next line must infer the hasher type parameter.
+    // If you make a change that causes this line to no longer infer,
+    // that's a problem!
+    let _must_not_require_type_annotation = HashMap::from([(1, 2)]);
+}
index 272e1c2be2b409dc9d3e3eb9ee2044e6139b81c3..c381481e006a9e5e9f1dde7c6278d8d6d1d8281c 100644 (file)
 /// }
 /// ```
 ///
-/// A `HashSet` with fixed list of elements can be initialized from an array:
+/// A `HashSet` with a known list of items can be initialized from an array:
 ///
 /// ```
 /// use std::collections::HashSet;
 ///
-/// let viking_names: HashSet<&'static str> =
-///     [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
-/// // use the values stored in the set
+/// let viking_names = HashSet::from(["Einar", "Olaf", "Harald"]);
 /// ```
 ///
 /// [hash set]: crate::collections#use-the-set-variant-of-any-of-these-maps-when
@@ -912,6 +910,7 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
     ///
@@ -996,6 +995,37 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+// Note: as what is currently the most convenient built-in way to construct
+// a HashSet, a simple usage of this function must not *require* the user
+// to provide a type annotation in order to infer the third type parameter
+// (the hasher parameter, conventionally "S").
+// To that end, this impl is defined using RandomState as the concrete
+// type of S, rather than being generic over `S: BuildHasher + Default`.
+// It is expected that users who want to specify a hasher will manually use
+// `with_capacity_and_hasher`.
+// If type parameter defaults worked on impls, and if type parameter
+// defaults could be mixed with const generics, then perhaps
+// this could be generalized.
+// See also the equivalent impl on HashMap.
+impl<T, const N: usize> From<[T; N]> for HashSet<T, RandomState>
+where
+    T: Eq + Hash,
+{
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let set1 = HashSet::from([1, 2, 3, 4]);
+    /// let set2: HashSet<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(set1, set2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        crate::array::IntoIter::new(arr).collect()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Extend<T> for HashSet<T, S>
 where
index 40f8467fd93fddf18907d1a9d55440164a9a522f..6a625e6243c2157f4416502f28b3240b56480e3b 100644 (file)
@@ -484,3 +484,15 @@ fn drop(&mut self) {
     assert_eq!(DROPS.load(Ordering::SeqCst), 3);
     assert_eq!(set.len(), 0);
 }
+
+#[test]
+fn from_array() {
+    let set = HashSet::from([1, 2, 3, 4]);
+    let unordered_duplicates = HashSet::from([4, 1, 4, 3, 2]);
+    assert_eq!(set, unordered_duplicates);
+
+    // This next line must infer the hasher type parameter.
+    // If you make a change that causes this line to no longer infer,
+    // that's a problem!
+    let _must_not_require_type_annotation = HashSet::from([1, 2]);
+}
index 64f88c1aba68e602e336408d95d1a5aed18ac7bb..5709d97d6430f6209e154c1f78ad564cc2338dd2 100644 (file)
@@ -294,7 +294,7 @@ fn description(&self) -> &str {
     }
 }
 
-/// Sets the environment variable `k` to the value `v` for the currently running
+/// Sets the environment variable `key` to the value `value` for the currently running
 /// process.
 ///
 /// Note that while concurrent access to environment variables is safe in Rust,
@@ -310,9 +310,8 @@ fn description(&self) -> &str {
 ///
 /// # Panics
 ///
-/// This function may panic if `key` is empty, contains an ASCII equals sign
-/// `'='` or the NUL character `'\0'`, or when the value contains the NUL
-/// character.
+/// This function may panic if `key` is empty, contains an ASCII equals sign `'='`
+/// or the NUL character `'\0'`, or when `value` contains the NUL character.
 ///
 /// # Examples
 ///
index ef2769d431fbbbd9bba5246059d3d3918cc7303d..c98244132befd62e3be3eb547b7feb841a3c1b18 100644 (file)
@@ -68,7 +68,7 @@
 /// [`flush`]: BufWriter::flush
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufWriter<W: Write> {
-    inner: Option<W>,
+    inner: W,
     // The buffer. Avoid using this like a normal `Vec` in common code paths.
     // That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
     // methods that require bounds checking or the like. This makes an enormous
@@ -112,7 +112,7 @@ pub fn new(inner: W) -> BufWriter<W> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
-        BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
+        BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false }
     }
 
     /// Send data in our local buffer into the inner writer, looping as
@@ -161,10 +161,9 @@ fn drop(&mut self) {
         }
 
         let mut guard = BufGuard::new(&mut self.buf);
-        let inner = self.inner.as_mut().unwrap();
         while !guard.done() {
             self.panicked = true;
-            let r = inner.write(guard.remaining());
+            let r = self.inner.write(guard.remaining());
             self.panicked = false;
 
             match r {
@@ -212,7 +211,7 @@ pub(super) fn write_to_buf(&mut self, buf: &[u8]) -> usize {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_ref(&self) -> &W {
-        self.inner.as_ref().unwrap()
+        &self.inner
     }
 
     /// Gets a mutable reference to the underlying writer.
@@ -232,7 +231,7 @@ pub fn get_ref(&self) -> &W {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut W {
-        self.inner.as_mut().unwrap()
+        &mut self.inner
     }
 
     /// Returns a reference to the internally buffered data.
@@ -308,7 +307,7 @@ pub fn capacity(&self) -> usize {
     pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
         match self.flush_buf() {
             Err(e) => Err(IntoInnerError::new(self, e)),
-            Ok(()) => Ok(self.inner.take().unwrap()),
+            Ok(()) => Ok(self.into_raw_parts().0),
         }
     }
 
@@ -339,7 +338,12 @@ pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
     pub fn into_raw_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
         let buf = mem::take(&mut self.buf);
         let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
-        (self.inner.take().unwrap(), buf)
+
+        // SAFETY: forget(self) prevents double dropping inner
+        let inner = unsafe { ptr::read(&mut self.inner) };
+        mem::forget(self);
+
+        (inner, buf)
     }
 
     // Ensure this function does not get inlined into `write`, so that it
@@ -643,7 +647,7 @@ impl<W: Write> fmt::Debug for BufWriter<W>
 {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("BufWriter")
-            .field("writer", &self.inner.as_ref().unwrap())
+            .field("writer", &self.inner)
             .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
             .finish()
     }
@@ -663,7 +667,7 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> Drop for BufWriter<W> {
     fn drop(&mut self) {
-        if self.inner.is_some() && !self.panicked {
+        if !self.panicked {
             // dtors should not panic, so we ignore a failed flush
             let _r = self.flush_buf();
         }
index 65497817f8160d55c688275fbd19763cbbe1dd02..38076ab3a2b7bc04255d7848e0c3e71af9c23c2b 100644 (file)
@@ -133,7 +133,6 @@ pub fn into_inner(self) -> W {
     ///
     /// # Example
     /// ```
-    /// #![feature(io_into_inner_error_parts)]
     /// use std::io::{BufWriter, ErrorKind, Write};
     ///
     /// let mut not_enough_space = [0u8; 10];
@@ -143,7 +142,7 @@ pub fn into_inner(self) -> W {
     /// let err = into_inner_err.into_error();
     /// assert_eq!(err.kind(), ErrorKind::WriteZero);
     /// ```
-    #[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
+    #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")]
     pub fn into_error(self) -> Error {
         self.1
     }
@@ -156,7 +155,6 @@ pub fn into_error(self) -> Error {
     ///
     /// # Example
     /// ```
-    /// #![feature(io_into_inner_error_parts)]
     /// use std::io::{BufWriter, ErrorKind, Write};
     ///
     /// let mut not_enough_space = [0u8; 10];
@@ -167,7 +165,7 @@ pub fn into_error(self) -> Error {
     /// assert_eq!(err.kind(), ErrorKind::WriteZero);
     /// assert_eq!(recovered_writer.buffer(), b"t be actually written");
     /// ```
-    #[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
+    #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")]
     pub fn into_parts(self) -> (Error, W) {
         (self.1, self.0)
     }
index 6fc1c89a2ba800922cea428547cc2297ca3fe518..73489c0f1620a5148106c0b7ebe79bc5fe4b68fb 100644 (file)
@@ -82,6 +82,7 @@ mod platform {
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "netbsd",
     target_os = "openbsd"
 ))]
 pub mod ucred;
index a6f6e091305d51cb7c7a41f228ac248d693a1919..fba084375e5f8512494c7dfab5995c2df342b589 100644 (file)
@@ -21,6 +21,7 @@
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "netbsd",
     target_os = "openbsd"
 ))]
 use crate::os::unix::ucred;
@@ -38,6 +39,7 @@
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "netbsd",
     target_os = "openbsd"
 ))]
 pub use ucred::UCred;
@@ -208,6 +210,7 @@ pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         target_os = "freebsd",
         target_os = "ios",
         target_os = "macos",
+        target_os = "netbsd",
         target_os = "openbsd"
     ))]
     pub fn peer_cred(&self) -> io::Result<UCred> {
index 1b4c18d3d84c420c3a20d0214f9ee3ddd68a9070..32e6430d3f62795d2d4ef0164c069cedf24f9394 100644 (file)
@@ -28,7 +28,12 @@ pub struct UCred {
 #[cfg(any(target_os = "android", target_os = "linux"))]
 pub use self::impl_linux::peer_cred;
 
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
+#[cfg(any(
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "openbsd",
+    target_os = "netbsd"
+))]
 pub use self::impl_bsd::peer_cred;
 
 #[cfg(any(target_os = "macos", target_os = "ios",))]
@@ -70,7 +75,12 @@ pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
     }
 }
 
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
+#[cfg(any(
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "openbsd",
+    target_os = "netbsd"
+))]
 pub mod impl_bsd {
     use super::UCred;
     use crate::io;
index 879d716052497f626ce5cb41c946251300ab70fa..1488bf94841ded3fda921ead4e983140a24ea0f4 100644 (file)
 #[cfg(target_os = "vxworks")]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024;
 
+#[cfg(target_os = "fuchsia")]
+mod zircon {
+    type zx_handle_t = u32;
+    type zx_status_t = i32;
+    pub const ZX_PROP_NAME: u32 = 3;
+
+    extern "C" {
+        pub fn zx_object_set_property(
+            handle: zx_handle_t,
+            property: u32,
+            value: *const libc::c_void,
+            value_size: libc::size_t,
+        ) -> zx_status_t;
+        pub fn zx_thread_self() -> zx_handle_t;
+    }
+}
+
 pub struct Thread {
     id: libc::pthread_t,
 }
@@ -134,6 +151,19 @@ fn pthread_setname_np(
         }
     }
 
+    #[cfg(target_os = "fuchsia")]
+    pub fn set_name(name: &CStr) {
+        use self::zircon::*;
+        unsafe {
+            zx_object_set_property(
+                zx_thread_self(),
+                ZX_PROP_NAME,
+                name.as_ptr() as *const libc::c_void,
+                name.to_bytes().len(),
+            );
+        }
+    }
+
     #[cfg(any(
         target_env = "newlib",
         target_os = "haiku",
@@ -145,10 +175,6 @@ fn pthread_setname_np(
     pub fn set_name(_name: &CStr) {
         // Newlib, Haiku, Emscripten, and VxWorks have no way to set a thread name.
     }
-    #[cfg(target_os = "fuchsia")]
-    pub fn set_name(_name: &CStr) {
-        // FIXME: determine whether Fuchsia has a way to set a thread name.
-    }
 
     pub fn sleep(dur: Duration) {
         let mut secs = dur.as_secs();
index 77d2684b5d2a4870ff1826df2e0a1244eea2eaa1..78c9a25262243bca4be37e44f3aa990d26d5696f 100644 (file)
@@ -3,7 +3,7 @@
 //!
 //! This module contains some of the real meat in the rustbuild build system
 //! which is where Cargo is used to compile the standard library, libtest, and
-//! compiler. This module is also responsible for assembling the sysroot as it
+//! the compiler. This module is also responsible for assembling the sysroot as it
 //! goes along from the output of the previous stage.
 
 use std::borrow::Cow;
index 483816b98d689e34594df52e9a688017d4c2706b..4b3c25b02c2789ca327b318a6688e566e222b08c 100644 (file)
@@ -13,6 +13,7 @@
 use std::str::FromStr;
 
 use crate::cache::{Interned, INTERNER};
+use crate::channel::GitInfo;
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags};
 use crate::util::exe;
@@ -48,7 +49,7 @@ pub struct Config {
     /// Call Build::ninja() instead of this.
     pub ninja_in_file: bool,
     pub verbose: usize,
-    pub submodules: bool,
+    pub submodules: Option<bool>,
     pub fast_submodules: bool,
     pub compiler_docs: bool,
     pub docs_minification: bool,
@@ -552,7 +553,7 @@ pub fn default_opts() -> Config {
         config.backtrace = true;
         config.rust_optimize = true;
         config.rust_optimize_tests = true;
-        config.submodules = true;
+        config.submodules = None;
         config.fast_submodules = true;
         config.docs = true;
         config.docs_minification = true;
@@ -658,11 +659,11 @@ pub fn parse(args: &[String]) -> Config {
         config.npm = build.npm.map(PathBuf::from);
         config.gdb = build.gdb.map(PathBuf::from);
         config.python = build.python.map(PathBuf::from);
+        config.submodules = build.submodules;
         set(&mut config.low_priority, build.low_priority);
         set(&mut config.compiler_docs, build.compiler_docs);
         set(&mut config.docs_minification, build.docs_minification);
         set(&mut config.docs, build.docs);
-        set(&mut config.submodules, build.submodules);
         set(&mut config.fast_submodules, build.fast_submodules);
         set(&mut config.locked_deps, build.locked_deps);
         set(&mut config.vendor, build.vendor);
@@ -792,8 +793,16 @@ pub fn parse(args: &[String]) -> Config {
 
                 // CI-built LLVM can be either dynamic or static.
                 let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm");
-                let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt")));
-                config.llvm_link_shared = link_type == "dynamic";
+                config.llvm_link_shared = if config.dry_run {
+                    // just assume dynamic for now
+                    true
+                } else {
+                    let link_type = t!(
+                        std::fs::read_to_string(ci_llvm.join("link-type.txt")),
+                        format!("CI llvm missing: {}", ci_llvm.display())
+                    );
+                    link_type == "dynamic"
+                };
             }
 
             if config.llvm_thin_lto {
@@ -1075,6 +1084,10 @@ pub fn any_profiler_enabled(&self) -> bool {
     pub fn llvm_enabled(&self) -> bool {
         self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
     }
+
+    pub fn submodules(&self, rust_info: &GitInfo) -> bool {
+        self.submodules.unwrap_or(rust_info.is_git())
+    }
 }
 
 fn set<T>(field: &mut T, val: Option<T>) {
index 999882a1c04b0526525c21f4600e3dc0830868fc..8d9f169e6c50d495f6ffa7461ec05fea57b9a559 100755 (executable)
@@ -160,6 +160,7 @@ o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of tw
 o("extended", "build.extended", "build an extended rust tool set")
 
 v("tools", None, "List of extended tools will be installed")
+v("codegen-backends", None, "List of codegen backends to build")
 v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
 v("host", None, "GNUs ./configure syntax LLVM host triples")
 v("target", None, "GNUs ./configure syntax LLVM target triples")
@@ -339,6 +340,8 @@ for key in known_args:
         set('target.{}.llvm-filecheck'.format(build()), value)
     elif option.name == 'tools':
         set('build.tools', value.split(','))
+    elif option.name == 'codegen-backends':
+        set('rust.codegen-backends', value.split(','))
     elif option.name == 'host':
         set('build.host', value.split(','))
     elif option.name == 'target':
index 92853378e588133460a3fa33bc229c46df2e760c..c37763243c0a55ab118318e3f8506f6decbcb568 100644 (file)
@@ -1955,8 +1955,16 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
         cmd.arg("--libfiles");
         builder.verbose(&format!("running {:?}", cmd));
         let files = output(&mut cmd);
+        let build_llvm_out = &builder.llvm_out(builder.config.build);
+        let target_llvm_out = &builder.llvm_out(target);
         for file in files.trim_end().split(' ') {
-            builder.install(Path::new(file), dst_libdir, 0o644);
+            // If we're not using a custom LLVM, make sure we package for the target.
+            let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
+                target_llvm_out.join(relative_path)
+            } else {
+                PathBuf::from(file)
+            };
+            builder.install(&file, dst_libdir, 0o644);
         }
         !builder.config.dry_run
     } else {
index 80a60c79edfe4c0801e54eb59a6fd2ce8d3e8d5c..1b7614b29896f39cac308d5ceb613b689ac7bc59 100644 (file)
@@ -152,7 +152,7 @@ pub fn parse(args: &[String]) -> Flags {
     fmt         Run rustfmt
     test, t     Build and run some test suites
     bench       Build and run some benchmarks
-    doc         Build documentation
+    doc, d      Build documentation
     clean       Clean out build directories
     dist        Build distribution artifacts
     install     Install distribution artifacts
@@ -244,6 +244,7 @@ pub fn parse(args: &[String]) -> Flags {
                 || (s == "t")
                 || (s == "bench")
                 || (s == "doc")
+                || (s == "d")
                 || (s == "clean")
                 || (s == "dist")
                 || (s == "install")
@@ -312,7 +313,7 @@ pub fn parse(args: &[String]) -> Flags {
             "clippy" => {
                 opts.optflag("", "fix", "automatically apply lint suggestions");
             }
-            "doc" => {
+            "doc" | "d" => {
                 opts.optflag("", "open", "open the docs in a browser");
             }
             "clean" => {
@@ -487,7 +488,7 @@ pub fn parse(args: &[String]) -> Flags {
         ./x.py test --stage 1",
                 );
             }
-            "doc" => {
+            "doc" | "d" => {
                 subcommand_help.push_str(
                     "\n
 Arguments:
@@ -573,7 +574,7 @@ pub fn parse(args: &[String]) -> Flags {
                 },
             },
             "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
-            "doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
+            "doc" | "d" => Subcommand::Doc { paths, open: matches.opt_present("open") },
             "clean" => {
                 if !paths.is_empty() {
                     println!("\nclean does not take a path argument\n");
index 2fe9b06e42643916d84a2c59f52f34b28cae789a..5c0322e18a4ab9fff09fa2b62be5592c546aa08d 100644 (file)
@@ -103,12 +103,20 @@ pub unsafe fn setup(build: &mut Build) {
     };
 
     let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
-    assert!(
-        !parent.is_null(),
-        "PID `{}` doesn't seem to exist: {}",
-        pid,
-        io::Error::last_os_error()
-    );
+
+    // If we get a null parent pointer here, it is possible that either
+    // we have got an invalid pid or the parent process has been closed.
+    // Since the first case rarely happens
+    // (only when wrongly setting the environmental variable),
+    // so it might be better to improve the experience of the second case
+    // when users have interrupted the parent process and we don't finish
+    // duplicating the handle yet.
+    // We just need close the job object if that occurs.
+    if parent.is_null() {
+        CloseHandle(job);
+        return;
+    }
+
     let mut parent_handle = ptr::null_mut();
     let r = DuplicateHandle(
         GetCurrentProcess(),
index 6bcdbe3e4bbbb33a5faeffb0e4855c8367a04589..245f3eada2af7719d6ab33a61912ed15b3257883 100644 (file)
@@ -486,7 +486,7 @@ fn dir_is_empty(dir: &Path) -> bool {
             t!(std::fs::read_dir(dir)).next().is_none()
         }
 
-        if !self.config.submodules {
+        if !self.config.submodules(&self.rust_info) {
             return;
         }
 
@@ -562,7 +562,7 @@ pub fn maybe_update_submodules(&self) {
             "library/stdarch",
         ];
         // Avoid running git when there isn't a git checkout.
-        if !self.config.submodules {
+        if !self.config.submodules(&self.rust_info) {
             return;
         }
         let output = output(
index 1be414b29a1aec2ebf195cdd4055e11f56b1ee39..b8a1513f2a696a810928343df5c63b4315363611 100644 (file)
@@ -118,6 +118,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             let idx = target.triple.find('-').unwrap();
 
             format!("riscv{}{}", &target.triple[5..7], &target.triple[idx..])
+        } else if self.target.starts_with("powerpc") && self.target.ends_with("freebsd") {
+            // FreeBSD 13 had incompatible ABI changes on all PowerPC platforms.
+            // Set the version suffix to 13.0 so the correct target details are used.
+            format!("{}{}", self.target, "13.0")
         } else {
             target.to_string()
         };
@@ -277,6 +281,11 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             }
         }
 
+        // Workaround for ppc32 lld limitation
+        if target == "powerpc-unknown-freebsd" {
+            cfg.define("CMAKE_EXE_LINKER_FLAGS", "-fuse-ld=bfd");
+        }
+
         // https://llvm.org/docs/HowToCrossCompileLLVM.html
         if target != builder.config.build {
             builder.ensure(Llvm { target: builder.config.build });
index 50980d25cb2885179c68aea704db0cf529caf925..31f18d81c7c0fb403892b9eebdde35e19699e406 100644 (file)
@@ -907,18 +907,27 @@ fn run(self, builder: &Builder<'_>) {
         // We remove existing folder to be sure there won't be artifacts remaining.
         let _ = fs::remove_dir_all(&out_dir);
 
-        let src_path = "src/test/rustdoc-gui/src";
+        let src_path = builder.build.src.join("src/test/rustdoc-gui/src");
         // We generate docs for the libraries present in the rustdoc-gui's src folder.
-        let mut cargo = Command::new(&builder.initial_cargo);
-        cargo
-            .arg("doc")
-            .arg("--workspace")
-            .arg("--target-dir")
-            .arg(&out_dir)
-            .env("RUSTDOC", builder.rustdoc(self.compiler))
-            .env("RUSTC", builder.rustc(self.compiler))
-            .current_dir(&builder.build.src.join(src_path));
-        builder.run(&mut cargo);
+        for entry in src_path.read_dir().expect("read_dir call failed") {
+            if let Ok(entry) = entry {
+                let path = entry.path();
+
+                if !path.is_dir() {
+                    continue;
+                }
+
+                let mut cargo = Command::new(&builder.initial_cargo);
+                cargo
+                    .arg("doc")
+                    .arg("--target-dir")
+                    .arg(&out_dir)
+                    .env("RUSTDOC", builder.rustdoc(self.compiler))
+                    .env("RUSTC", builder.rustc(self.compiler))
+                    .current_dir(path);
+                builder.run(&mut cargo);
+            }
+        }
 
         // We now run GUI tests.
         let mut command = Command::new(&nodejs);
index 885010b039eacd7d0422f6110286c4a2b711f8eb..90ef48798ddabc7ad465fdd91326a90e55f6a085 100644 (file)
@@ -249,6 +249,7 @@ target | std | host | notes
 `powerpc-wrs-vxworks` | ? |  |
 `powerpc64-unknown-freebsd` | âœ“ | âœ“ | PPC64 FreeBSD (ELFv1 and ELFv2)
 `powerpc64le-unknown-freebsd` |   |   | PPC64LE FreeBSD
+`powerpc-unknown-freebsd` |   |   | PowerPC FreeBSD
 `powerpc64-unknown-linux-musl` | ? |  |
 `powerpc64-wrs-vxworks` | ? |  |
 `powerpc64le-unknown-linux-musl` | ? |  |
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warn.md b/src/doc/unstable-book/src/compiler-flags/force-warn.md
new file mode 100644 (file)
index 0000000..052de0f
--- /dev/null
@@ -0,0 +1,21 @@
+# `force-warn`
+
+The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
+
+------------------------
+
+This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warn` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
+
+## Example
+
+```rust,ignore (partial-example)
+#![allow(dead_code)]
+
+fn dead_function() {}
+// This would normally not produce a warning even though the
+// function is not used, because dead code is being allowed
+
+fn main() {}
+```
+
+We can force a warning to be produced by providing `--force-warn dead_code` to rustc.
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warns.md b/src/doc/unstable-book/src/compiler-flags/force-warns.md
deleted file mode 100644 (file)
index 0a205be..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# `force-warns`
-
-The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
-
-------------------------
-
-This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warns` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
-
-## Example
-
-```rust,ignore (partial-example)
-#![allow(dead_code)]
-
-fn dead_function() {}
-// This would normally not produce a warning even though the
-// function is not used, because dead code is being allowed
-
-fn main() {}
-```
-
-We can force a warning to be produced by providing `--force-warns dead_code` to rustc.
diff --git a/src/doc/unstable-book/src/compiler-flags/move-size-limit.md b/src/doc/unstable-book/src/compiler-flags/move-size-limit.md
new file mode 100644 (file)
index 0000000..88f022a
--- /dev/null
@@ -0,0 +1,10 @@
+# `move_size_limit`
+
+--------------------
+
+The `-Zmove-size-limit=N` compiler flag enables `large_assignments` lints which
+will warn when moving objects whose size exceeds `N` bytes.
+
+Lint warns only about moves in functions that participate in code generation.
+Consequently it will be ineffective for compiler invocatation that emit
+metadata only, i.e., `cargo check` like workflows.
old mode 100755 (executable)
new mode 100644 (file)
index 2fd2d14bcabc3ec25a6ace935a70a58246cb57aa..101d3b400c3dfaf62173c06025a4f2e9677031cb 100644 (file)
@@ -227,7 +227,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
         if root.is_local() {
             tcx.hir()
                 .krate()
-                .item
+                .module()
                 .item_ids
                 .iter()
                 .filter_map(|&id| {
@@ -293,7 +293,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
         if root.is_local() {
             tcx.hir()
                 .krate()
-                .item
+                .module()
                 .item_ids
                 .iter()
                 .filter_map(|&id| {
index e552542464082df558bef8e3fdbd34eab7a3b80d..abd1fd2bf39a29c13702beaf484680ae232f53f8 100644 (file)
@@ -459,7 +459,31 @@ fn println_condition(condition: Condition) {
                 })
                 .collect(),
         ];
-        let default_settings = default_settings.into_iter().flatten().collect();
+        let default_settings = default_settings
+            .into_iter()
+            .flatten()
+            .map(
+                // The keys here become part of `data-` attribute names in the generated HTML.  The
+                // browser does a strange mapping when converting them into attributes on the
+                // `dataset` property on the DOM HTML Node:
+                //   https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset
+                //
+                // The original key values we have are the same as the DOM storage API keys and the
+                // command line options, so contain `-`.  Our Javascript needs to be able to look
+                // these values up both in `dataset` and in the storage API, so it needs to be able
+                // to convert the names back and forth.  Despite doing this kebab-case to
+                // StudlyCaps transformation automatically, the JS DOM API does not provide a
+                // mechanism for doing the just transformation on a string.  So we want to avoid
+                // the StudlyCaps representation in the `dataset` property.
+                //
+                // We solve this by replacing all the `-`s with `_`s.  We do that here, when we
+                // generate the `data-` attributes, and in the JS, when we look them up.  (See
+                // `getSettingValue` in `storage.js.`) Converting `-` to `_` is simple in JS.
+                //
+                // The values will be HTML-escaped by the default Tera escaping.
+                |(k, v)| (k.replace('-', "_"), v),
+            )
+            .collect();
 
         let test_args = matches.opt_strs("test-args");
         let test_args: Vec<String> =
index 5ce7c49278d23baea4b41267e8931ff2a0f9af42..d5268abeec79584c55e41b5f4f23ff7284a00c9b 100644 (file)
         registry: rustc_driver::diagnostics_registry(),
     };
 
-    let mut test_args = options.test_args.clone();
+    let test_args = options.test_args.clone();
     let display_warnings = options.display_warnings;
     let nocapture = options.nocapture;
     let externs = options.externs.clone();
                 hir_collector.visit_testable(
                     "".to_string(),
                     CRATE_HIR_ID,
-                    krate.item.inner,
+                    krate.module().inner,
                     |this| {
                         intravisit::walk_crate(this, krate);
                     },
         Err(ErrorReported) => return Err(ErrorReported),
     };
 
-    test_args.insert(0, "rustdoctest".to_string());
-    if nocapture {
-        test_args.push("--nocapture".to_string());
-    }
-
-    test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
+    run_tests(test_args, nocapture, display_warnings, tests);
 
     // Collect and warn about unused externs, but only if we've gotten
     // reports for each doctest
     Ok(())
 }
 
+crate fn run_tests(
+    mut test_args: Vec<String>,
+    nocapture: bool,
+    display_warnings: bool,
+    tests: Vec<test::TestDescAndFn>,
+) {
+    test_args.insert(0, "rustdoctest".to_string());
+    if nocapture {
+        test_args.push("--nocapture".to_string());
+    }
+    test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
+}
+
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
 fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
     use rustc_ast_pretty::pprust;
index e21469dc9c343e84d17f295b3bc9588356cb8a83..b8756d2526edf1a78c89178e8a72d8c71b21e8ed 100644 (file)
@@ -34,6 +34,7 @@
 use crate::clean::RenderedLink;
 use crate::doctest;
 use crate::html::escape::Escape;
+use crate::html::format::Buffer;
 use crate::html::highlight;
 use crate::html::toc::TocBuilder;
 
@@ -41,8 +42,6 @@
     html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
 };
 
-use super::format::Buffer;
-
 #[cfg(test)]
 mod tests;
 
@@ -57,7 +56,7 @@ pub(crate) fn opts() -> Options {
 
 /// A subset of [`opts()`] used for rendering summaries.
 pub(crate) fn summary_opts() -> Options {
-    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION
+    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES
 }
 
 /// When `to_string` is called, this struct will emit the HTML corresponding to
@@ -235,9 +234,9 @@ fn next(&mut self) -> Option<Self::Item> {
                     return Some(Event::Html(
                         format!(
                             "<div class=\"example-wrap\">\
-                                 <pre{}>{}</pre>\
+                                 <pre class=\"language-{}\">{}</pre>\
                              </div>",
-                            format!(" class=\"language-{}\"", lang),
+                            lang,
                             Escape(&text),
                         )
                         .into(),
@@ -522,6 +521,10 @@ fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
     )
 }
 
+fn is_forbidden_tag(t: &Tag<'_>) -> bool {
+    matches!(t, Tag::CodeBlock(_) | Tag::Table(_) | Tag::TableHead | Tag::TableRow | Tag::TableCell)
+}
+
 impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
     type Item = Event<'a>;
 
@@ -535,14 +538,17 @@ fn next(&mut self) -> Option<Self::Item> {
         if let Some(event) = self.inner.next() {
             let mut is_start = true;
             let is_allowed_tag = match event {
-                Event::Start(Tag::CodeBlock(_)) | Event::End(Tag::CodeBlock(_)) => {
-                    return None;
-                }
                 Event::Start(ref c) => {
+                    if is_forbidden_tag(c) {
+                        return None;
+                    }
                     self.depth += 1;
                     check_if_allowed_tag(c)
                 }
                 Event::End(ref c) => {
+                    if is_forbidden_tag(c) {
+                        return None;
+                    }
                     self.depth -= 1;
                     is_start = false;
                     check_if_allowed_tag(c)
@@ -1079,7 +1085,7 @@ fn markdown_summary_with_limit(
     let mut stopped_early = false;
 
     fn push(s: &mut String, text_length: &mut usize, text: &str) {
-        s.push_str(text);
+        write!(s, "{}", Escape(text)).unwrap();
         *text_length += text.len();
     }
 
index d10da64ccfaa5447a50e4610d046e21e6e3dd520..1e4bdc2d15199525b173ed084984cfcc50ff04e2 100644 (file)
@@ -234,7 +234,17 @@ fn t(input: &str, expect: &str) {
     t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
     t("dud [link]", "dud [link]");
     t("code `let x = i32;` ...", "code <code>let x = i32;</code> â€¦");
-    t("type `Type<'static>` ...", "type <code>Type<'static></code> â€¦");
+    t("type `Type<'static>` ...", "type <code>Type&lt;&#39;static&gt;</code> â€¦");
+    // Test to ensure escaping and length-limiting work well together.
+    // The output should be limited based on the input length,
+    // rather than the output, because escaped versions of characters
+    // are usually longer than how the character is actually displayed.
+    t(
+        "& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &",
+        "&amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; \
+         &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; &amp; \
+         &amp; &amp; &amp; &amp; &amp; â€¦",
+    );
     t("# top header", "top header");
     t("# top header\n\nfollowed by a paragraph", "top header");
     t("## header", "header");
index 68c59612ccc448d58c4c508ada7f1e675e3c8da4..2b7f7aa3691bdc476259a98b806c1aca07b0ca1f 100644 (file)
@@ -1194,7 +1194,7 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
                     if out.is_empty() {
                         write!(
                             &mut out,
-                            "<h3 class=\"notable\">Notable traits for {}</h3>\
+                            "<div class=\"notable\">Notable traits for {}</div>\
                              <code class=\"content\">",
                             impl_.for_.print(cx)
                         );
@@ -1350,7 +1350,7 @@ fn doc_impl_item(
                     );
                     render_rightside(w, cx, item, containing_item);
                     write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                    w.write_str("<code>");
+                    w.write_str("<h4 class=\"code-header\">");
                     render_assoc_item(
                         w,
                         item,
@@ -1358,7 +1358,7 @@ fn doc_impl_item(
                         ItemType::Impl,
                         cx,
                     );
-                    w.write_str("</code>");
+                    w.write_str("</h4>");
                     w.write_str("</div>");
                 }
             }
@@ -1371,7 +1371,7 @@ fn doc_impl_item(
                     id, item_type, in_trait_class
                 );
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                w.write_str("<code>");
+                w.write_str("<h4 class=\"code-header\">");
                 assoc_type(
                     w,
                     item,
@@ -1381,7 +1381,7 @@ fn doc_impl_item(
                     "",
                     cx,
                 );
-                w.write_str("</code>");
+                w.write_str("</h4>");
                 w.write_str("</div>");
             }
             clean::AssocConstItem(ref ty, ref default) => {
@@ -1394,7 +1394,7 @@ fn doc_impl_item(
                 );
                 render_rightside(w, cx, item, containing_item);
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                w.write_str("<code>");
+                w.write_str("<h4 class=\"code-header\">");
                 assoc_const(
                     w,
                     item,
@@ -1404,7 +1404,7 @@ fn doc_impl_item(
                     "",
                     cx,
                 );
-                w.write_str("</code>");
+                w.write_str("</h4>");
                 w.write_str("</div>");
             }
             clean::AssocTypeItem(ref bounds, ref default) => {
@@ -1412,7 +1412,7 @@ fn doc_impl_item(
                 let id = cx.derive_id(source_id.clone());
                 write!(w, "<div id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class,);
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                w.write_str("<code>");
+                w.write_str("<h4 class=\"code-header\">");
                 assoc_type(
                     w,
                     item,
@@ -1422,7 +1422,7 @@ fn doc_impl_item(
                     "",
                     cx,
                 );
-                w.write_str("</code>");
+                w.write_str("</h4>");
                 w.write_str("</div>");
             }
             clean::StrippedItem(..) => return,
@@ -1613,7 +1613,7 @@ pub(crate) fn render_impl_summary(
     write!(w, "<div id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
     render_rightside(w, cx, &i.impl_item, containing_item);
     write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-    write!(w, "<code class=\"in-band\">");
+    write!(w, "<h3 class=\"code-header in-band\">");
 
     if let Some(use_absolute) = use_absolute {
         write!(w, "{}", i.inner_impl().print(use_absolute, cx));
@@ -1629,7 +1629,7 @@ pub(crate) fn render_impl_summary(
     } else {
         write!(w, "{}", i.inner_impl().print(false, cx));
     }
-    write!(w, "</code>");
+    write!(w, "</h3>");
 
     let is_trait = i.inner_impl().trait_.is_some();
     if is_trait {
index f7073a8751fa18723622c06d15c6e26a29adae86..83ad4f7097bdf625e5acc532037e41bcc2444553 100644 (file)
@@ -1,6 +1,7 @@
 use clean::AttributesExt;
 
 use std::cmp::Ordering;
+use std::fmt;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
@@ -155,7 +156,7 @@ fn should_hide_fields(n_fields: usize) -> bool {
     n_fields > 12
 }
 
-fn toggle_open(w: &mut Buffer, text: &str) {
+fn toggle_open(w: &mut Buffer, text: impl fmt::Display) {
     write!(
         w,
         "<details class=\"rustdoc-toggle type-contents-toggle\">\
@@ -481,6 +482,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
     let required = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
     let provided = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>();
+    let count_types = types.len();
+    let count_consts = consts.len();
+    let count_methods = required.len() + provided.len();
 
     // Output the trait definition
     wrap_into_docblock(w, |w| {
@@ -511,9 +515,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             let mut toggle = false;
 
             // If there are too many associated types, hide _everything_
-            if should_hide_fields(types.len()) {
+            if should_hide_fields(count_types) {
                 toggle = true;
-                toggle_open(w, "associated items");
+                toggle_open(
+                    w,
+                    format_args!("{} associated items", count_types + count_consts + count_methods),
+                );
             }
             for t in &types {
                 render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
@@ -523,9 +530,18 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
             // We also do this if the types + consts is large because otherwise we could
             // render a bunch of types and _then_ a bunch of consts just because both were
             // _just_ under the limit
-            if !toggle && should_hide_fields(types.len() + consts.len()) {
+            if !toggle && should_hide_fields(count_types + count_consts) {
                 toggle = true;
-                toggle_open(w, "associated constants and methods");
+                toggle_open(
+                    w,
+                    format_args!(
+                        "{} associated constant{} and {} method{}",
+                        count_consts,
+                        pluralize(count_consts),
+                        count_methods,
+                        pluralize(count_methods),
+                    ),
+                );
             }
             if !types.is_empty() && !consts.is_empty() {
                 w.write_str("\n");
@@ -534,9 +550,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                 render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
                 w.write_str(";\n");
             }
-            if !toggle && should_hide_fields(required.len() + provided.len()) {
+            if !toggle && should_hide_fields(count_methods) {
                 toggle = true;
-                toggle_open(w, "methods");
+                toggle_open(w, format_args!("{} methods", count_methods));
             }
             if !consts.is_empty() && !required.is_empty() {
                 w.write_str("\n");
@@ -605,9 +621,9 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         render_stability_since(w, m, t, cx.tcx());
         write_srclink(cx, m, w);
         write!(w, "</div>");
-        write!(w, "<code>");
+        write!(w, "<h4 class=\"code-header\">");
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx);
-        w.write_str("</code>");
+        w.write_str("</h4>");
         w.write_str("</div>");
         if toggled {
             write!(w, "</summary>");
@@ -872,7 +888,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
     wrap_into_docblock(w, |w| {
         w.write_str("<pre class=\"rust union\">");
         render_attributes_in_pre(w, it, "");
-        render_union(w, it, Some(&s.generics), &s.fields, "", true, cx);
+        render_union(w, it, Some(&s.generics), &s.fields, "", cx);
         w.write_str("</pre>")
     });
 
@@ -933,9 +949,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             w.write_str(" {}");
         } else {
             w.write_str(" {\n");
-            let toggle = should_hide_fields(e.variants.len());
+            let count_variants = e.variants.len();
+            let toggle = should_hide_fields(count_variants);
             if toggle {
-                toggle_open(w, "variants");
+                toggle_open(w, format_args!("{} variants", count_variants));
             }
             for v in &e.variants {
                 w.write_str("    ");
@@ -1012,13 +1029,12 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
 
             use crate::clean::Variant;
             if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind {
-                toggle_open(w, "fields");
                 let variant_id = cx.derive_id(format!(
                     "{}.{}.fields",
                     ItemType::Variant,
                     variant.name.as_ref().unwrap()
                 ));
-                write!(w, "<div class=\"autohide sub-variant\" id=\"{id}\">", id = variant_id);
+                write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
                 write!(
                     w,
                     "<h3>Fields of <b>{name}</b></h3><div>",
@@ -1046,7 +1062,6 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     }
                 }
                 w.write_str("</div></div>");
-                toggle_close(w);
             }
         }
     }
@@ -1365,14 +1380,12 @@ fn render_union(
     g: Option<&clean::Generics>,
     fields: &[clean::Item],
     tab: &str,
-    structhead: bool,
     cx: &Context<'_>,
 ) {
     write!(
         w,
-        "{}{}{}",
+        "{}union {}",
         it.visibility.print_with_space(it.def_id, cx),
-        if structhead { "union " } else { "" },
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
@@ -1385,7 +1398,7 @@ fn render_union(
         fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
     let toggle = should_hide_fields(count_fields);
     if toggle {
-        toggle_open(w, "fields");
+        toggle_open(w, format_args!("{} fields", count_fields));
     }
 
     for field in fields {
@@ -1441,7 +1454,7 @@ fn render_struct(
             let has_visible_fields = count_fields > 0;
             let toggle = should_hide_fields(count_fields);
             if toggle {
-                toggle_open(w, "fields");
+                toggle_open(w, format_args!("{} fields", count_fields));
             }
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = *field.kind {
@@ -1618,3 +1631,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
 
     writeln!(w, "</div>");
 }
+
+fn pluralize(count: usize) -> &'static str {
+    if count > 1 { "s" } else { "" }
+}
index 6672093eb7bc60cc83ce13eb0d450474125724f0..91243a4086ced2f2fc2fa9948ede2b0ffb2beb80 100644 (file)
@@ -146,6 +146,13 @@ h1.fqn > .in-band > a:hover {
 h2, h3, h4 {
        border-bottom: 1px solid;
 }
+h3.code-header, h4.code-header {
+       font-size: 1em;
+       font-weight: 600;
+       border: none;
+       padding: 0;
+       margin: 0;
+}
 .impl,
 .impl-items .method,
 .methods .method,
@@ -233,7 +240,7 @@ details:not(.rustdoc-toggle) summary {
        margin-bottom: .6em;
 }
 
-code, pre, a.test-arrow {
+code, pre, a.test-arrow, .code-header {
        font-family: "Source Code Pro", monospace;
 }
 .docblock code, .docblock-short code {
@@ -329,6 +336,7 @@ nav.sub {
 .logo-container > img {
        max-width: 100px;
        max-height: 100px;
+       height: 100%;
        position: absolute;
        left: 50%;
        top: 50%;
@@ -520,7 +528,7 @@ nav.sub {
        font-weight: normal;
 }
 
-.method > code, .trait-impl > code, .invisible > code {
+.method > .code-header, .trait-impl > .code-header, .invisible > .code-header {
        max-width: calc(100% - 41px);
        display: block;
 }
@@ -536,7 +544,7 @@ nav.sub {
        padding: 0px;
 }
 
-.in-band > code {
+.in-band > code, .in-band > .code-header {
        display: inline-block;
 }
 
@@ -742,7 +750,7 @@ a {
 }
 
 .invisible > .srclink,
-.method > code + .srclink {
+.method > .code-header + .srclink {
        position: absolute;
        top: 0;
        right: 0;
@@ -1072,7 +1080,7 @@ a.test-arrow:hover{
        padding-top: 1px;
 }
 
-#main > details > .sub-variant > h3 {
+#main .sub-variant > h3 {
        font-size: 15px;
        margin-left: 25px;
        margin-bottom: 5px;
@@ -1103,7 +1111,7 @@ a.test-arrow:hover{
        left: -10px;
 }
 
-:target > code {
+:target > code, :target > .code-header {
        opacity: 1;
 }
 
index 354cdd2fb035b2d9e9d7e471b0ce551fa5c13aa9..df386fb66a33f4c9d309d03e97ba441fa062b59e 100644 (file)
@@ -334,7 +334,7 @@ a.test-arrow:hover {
        color: #999;
 }
 
-:target, :target * {
+:target, :target * {
        background: rgba(255, 236, 164, 0.06);
 }
 
index b4f5a13c815095282834bf8cca2b5bc394d1e673..c8a5dbdc66aaf98832a0f07e6d7fb0b46994db7b 100644 (file)
@@ -282,7 +282,7 @@ a.test-arrow:hover{
        color: #999;
 }
 
-:target, :target * {
+:target, :target * {
        background-color: #494a3d;
 }
 
index 29cbcd65ce81de54800ed4ecadf9de47cf67fc83..bc18a72450896eb5044d951a4f5dcad686bc0c17 100644 (file)
@@ -274,7 +274,7 @@ a.test-arrow:hover{
        color: #999;
 }
 
-:target, :target * {
+:target, :target * {
        background: #FDFFD3;
 }
 
index 38ddbb3ad74278d68d2c9623fbdb46f7ca07b603..869aff5376649da4d57bc01304c0aa6f72641b8c 100644 (file)
@@ -706,8 +706,9 @@ function hideThemeButtonState() {
                     }
                 }
 
-                var code = document.createElement("code");
+                var code = document.createElement("h3");
                 code.innerHTML = struct.text;
+                addClass(code, "code-header");
                 addClass(code, "in-band");
 
                 onEachLazy(code.getElementsByTagName("a"), function(elem) {
index 2eaa81a97d8c5e46f59d1441a4f0bae37eed007e..78ed17e6899e9aa17c0d526b7f93ba64cf3d51a2 100644 (file)
@@ -22,6 +22,8 @@ function getSettingValue(settingName) {
         return current;
     }
     if (settingsDataset !== null) {
+        // See the comment for `default_settings.into_iter()` etc. in
+        // `Options::from_matches` in `librustdoc/config.rs`.
         var def = settingsDataset[settingName.replace(/-/g,'_')];
         if (def !== undefined) {
             return def;
index 9b1bef5e4476760d880ae4f8b4ce685b10b6ba2c..cc9c488db7c43bf9c05add8d1f2290f1225863d3 100644 (file)
@@ -83,7 +83,7 @@
                     </select> {#- -#}
                     {%- endif -%}
                     <input {# -#}
-                        class="search-input"{# -#}
+                        class="search-input" {# -#}
                         name="search" {# -#}
                         disabled {# -#}
                         autocomplete="off" {# -#}
index 19deaa11388d8601d012b03a6299d3ba44939506..fa755777584f3cdacb58abe4cc4aa6722ce4d7e9 100644 (file)
@@ -511,10 +511,10 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
-        unstable("force-warns", |o| {
+        unstable("force-warn", |o| {
             o.optopt(
                 "",
-                "force-warns",
+                "force-warn",
                 "Lints that will warn even if allowed somewhere else",
                 "LINTS",
             )
index 6c8b95c04c9e4be674830bf15916feed5b805e3c..80af2a7aaf5c8ab820ef593534f023a9dc22d073 100644 (file)
@@ -115,7 +115,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
 }
 
 /// Runs any tests/code examples in the markdown file `input`.
-crate fn test(mut options: Options) -> Result<(), String> {
+crate fn test(options: Options) -> Result<(), String> {
     let input_str = read_to_string(&options.input)
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
     let mut opts = TestOptions::default();
@@ -135,14 +135,11 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
 
     find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
 
-    options.test_args.insert(0, "rustdoctest".to_string());
-    if options.nocapture {
-        options.test_args.push("--nocapture".to_string());
-    }
-    test::test_main(
-        &options.test_args,
+    crate::doctest::run_tests(
+        options.test_args,
+        options.nocapture,
+        options.display_warnings,
         collector.tests,
-        Some(test::Options::new().display_output(options.display_warnings)),
     );
     Ok(())
 }
index b563c4f479935b2c70edad4ff5ab2938cfcf9e79..d74b3b4627284321b391a4de5363ef2517e3a5aa 100644 (file)
@@ -72,18 +72,18 @@ fn store_path(&mut self, did: DefId) {
     }
 
     crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
-        let span = krate.item.inner;
+        let span = krate.module().inner;
         let mut top_level_module = self.visit_mod_contents(
             &Spanned { span, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
-            &krate.item,
+            &krate.module(),
             self.cx.tcx.crate_name(LOCAL_CRATE),
         );
         // Attach the crate's exported macros to the top-level module.
         // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
         // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
         // moving them back to their correct locations.
-        'exported_macros: for def in krate.exported_macros {
+        'exported_macros: for def in krate.exported_macros() {
             // The `def` of a macro in `exported_macros` should correspond to either:
             //  - a `#[macro_export] macro_rules!` macro,
             //  - a built-in `derive` (or attribute) macro such as the ones in `::core`,
index c085f3c829ea440f7b7954b61587fea1a2f42916..05c2d2fc0d8c1cd354521ff7b9d2169dc7123ce9 100644 (file)
@@ -1,8 +1,7 @@
 // Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
-// Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms.
 
 // needs-profiler-support
-// compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort
+// compile-flags: -Cprofile-generate -Ccodegen-units=1
 
 // CHECK: @__llvm_profile_raw_version =
 // CHECK-DAG: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = {{.*}}global
index a190a29eec2a59491f32fa85884e1bf8082d7f56..baeada69d1c9a2883ff095deed89c8fc9b5b4d6b 100644 (file)
 // cdb-check:    [0x1]            : 42 [Type: int]
 
 // cdb-command: dx vecdeque
-// cdb-check:vecdeque         : { len=0x2 } [Type: alloc::collections::vec_deque::VecDeque<i32>]
-// cdb-check:    [<Raw View>]     [Type: alloc::collections::vec_deque::VecDeque<i32>]
+// cdb-check:vecdeque         : { len=0x2 } [Type: alloc::collections::vec_deque::VecDeque<i32,alloc::alloc::Global>]
+// cdb-check:    [<Raw View>]     [Type: alloc::collections::vec_deque::VecDeque<i32,alloc::alloc::Global>]
 // cdb-check:    [len]            : 0x2
 // cdb-check:    [capacity]       : 0x8 [Type: unsigned [...]]
 // cdb-check:    [0x0]            : 90 [Type: int]
diff --git a/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff b/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
new file mode 100644 (file)
index 0000000..57299ce
--- /dev/null
@@ -0,0 +1,140 @@
+- // MIR for `identity` before ConstProp
++ // MIR for `identity` after ConstProp
+  
+  fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
+      debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
+      let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
+      let mut _2: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+      let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+      let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+      let mut _5: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let mut _7: !;                       // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let _9: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+      scope 1 {
+          debug residual => _6;            // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
+          scope 2 {
+              scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+                  debug residual => _8;    // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  let _16: i32;            // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  let mut _17: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  let mut _18: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  scope 9 {
+                      debug e => _16;      // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+                      scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+                          debug t => _18;  // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
+                      }
+                  }
+              }
+          }
+      }
+      scope 3 {
+          debug val => _9;                 // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
+          scope 4 {
+          }
+      }
+      scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+          debug self => _4;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _10: isize;              // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let _11: i32;                    // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _12: i32;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let _13: i32;                    // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _15: i32;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          scope 6 {
+              debug v => _11;              // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          }
+          scope 7 {
+              debug e => _13;              // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_3);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+          _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+          StorageLive(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _10 = discriminant(_4);          // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+      }
+  
+      bb1: {
+          StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _9 = ((_3 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _2 = _9;                         // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          ((_0 as Ok).0: i32) = move _2;   // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
+          discriminant(_0) = 0;            // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
+          StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
+      }
+  
+      bb2: {
+          StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageLive(_8);                 // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+          _8 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageLive(_16);                // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _16 = move ((_8 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_17);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_18);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _18 = move _16;                  // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _17 = move _18;                  // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_18);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_0 as Err).0: i32) = move _17; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_0) = 1;            // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_17);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_16);                // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_8);                 // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
+          StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
+      }
+  
+      bb3: {
+          StorageLive(_13);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _13 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_14);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_15);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _15 = move _13;                  // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_14 as Err).0: i32) = move _15; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_14) = 1;           // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_15);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_3) = 1;            // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_14);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_13);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         _5 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         switchInt(const 1_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      }
+  
+      bb4: {
+          unreachable;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+      }
+  
+      bb5: {
+          StorageLive(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _11 = move ((_4 as Ok).0: i32);  // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_12);                // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _12 = move _11;                  // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_3 as Continue).0: i32) = move _12; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_3) = 0;            // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_12);                // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         _5 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         switchInt(const 0_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      }
+  }
+  
diff --git a/src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir b/src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..dee45c5
--- /dev/null
@@ -0,0 +1,122 @@
+// MIR for `identity` after PreCodegen
+
+fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
+    debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
+    let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
+    let mut _2: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+    let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+    let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+    let _5: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+    let mut _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+    let _7: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+    scope 1 {
+        debug residual => _5;            // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
+        scope 2 {
+            scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+                debug residual => _6;    // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                let _14: i32;            // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                let mut _15: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                let mut _16: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                scope 9 {
+                    debug e => _14;      // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+                    scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+                        debug t => _16;  // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
+                    }
+                }
+            }
+        }
+    }
+    scope 3 {
+        debug val => _7;                 // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
+        scope 4 {
+        }
+    }
+    scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+        debug self => _4;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        let mut _8: isize;               // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        let _9: i32;                     // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        let mut _10: i32;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        let _11: i32;                    // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        let mut _12: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        let mut _13: i32;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        scope 6 {
+            debug v => _9;               // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+        }
+        scope 7 {
+            debug e => _11;              // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        }
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_3);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+        _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+        StorageLive(_8);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _8 = discriminant(_4);           // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        switchInt(move _8) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+    }
+
+    bb1: {
+        StorageLive(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _11 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_12);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_13);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _13 = move _11;                  // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        ((_12 as Err).0: i32) = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        discriminant(_12) = 1;           // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_13);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _12; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        discriminant(_3) = 1;            // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_12);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_8);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+        StorageLive(_5);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+        _5 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+        StorageLive(_6);                 // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+        _6 = _5;                         // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+        StorageLive(_14);                // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _14 = move ((_6 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_15);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_16);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _16 = move _14;                  // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _15 = move _16;                  // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_16);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        ((_0 as Err).0: i32) = move _15; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        discriminant(_0) = 1;            // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_15);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_14);                // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_6);                 // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+        StorageDead(_5);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+        StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
+        StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
+        return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
+    }
+
+    bb2: {
+        unreachable;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+    }
+
+    bb3: {
+        StorageLive(_9);                 // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _9 = move ((_4 as Ok).0: i32);   // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageLive(_10);                // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _10 = move _9;                   // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+        ((_3 as Continue).0: i32) = move _10; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+        discriminant(_3) = 0;            // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_10);                // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_9);                 // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_8);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+        StorageLive(_7);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _7 = ((_3 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+        _2 = _7;                         // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
+        StorageDead(_7);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+        ((_0 as Ok).0: i32) = move _2;   // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
+        discriminant(_0) = 0;            // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
+        StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
+        StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
+        return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
+    }
+}
diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
new file mode 100644 (file)
index 0000000..4bfd084
--- /dev/null
@@ -0,0 +1,150 @@
+- // MIR for `identity` before SeparateConstSwitch
++ // MIR for `identity` after SeparateConstSwitch
+  
+  fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
+      debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
+      let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
+      let mut _2: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+      let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+      let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+      let mut _5: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let mut _7: !;                       // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      let _9: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+      scope 1 {
+          debug residual => _6;            // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
+          scope 2 {
+              scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+                  debug residual => _8;    // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  let _16: i32;            // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  let mut _17: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  let mut _18: i32;        // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+                  scope 9 {
+                      debug e => _16;      // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+                      scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+                          debug t => _18;  // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
+                      }
+                  }
+              }
+          }
+      }
+      scope 3 {
+          debug val => _9;                 // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
+          scope 4 {
+          }
+      }
+      scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+          debug self => _4;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _10: isize;              // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let _11: i32;                    // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _12: i32;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let _13: i32;                    // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          let mut _15: i32;                // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          scope 6 {
+              debug v => _11;              // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          }
+          scope 7 {
+              debug e => _13;              // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_3);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+          _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
+          StorageLive(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _10 = discriminant(_4);          // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
++         switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+      }
+  
+      bb1: {
+-         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-     }
+- 
+-     bb2: {
+          StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _9 = ((_3 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _2 = _9;                         // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          ((_0 as Ok).0: i32) = move _2;   // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
+          discriminant(_0) = 0;            // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
+          StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
+      }
+  
+-     bb3: {
++     bb2: {
+          StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageLive(_8);                 // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+          _8 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageLive(_16);                // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _16 = move ((_8 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_17);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_18);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _18 = move _16;                  // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _17 = move _18;                  // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_18);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_0 as Err).0: i32) = move _17; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_0) = 1;            // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_17);                // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_16);                // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_8);                 // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
+          StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
+      }
+  
+-     bb4: {
++     bb3: {
+          StorageLive(_13);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _13 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_14);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_15);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _15 = move _13;                  // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_14 as Err).0: i32) = move _15; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_14) = 1;           // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_15);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_3) = 1;            // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_14);                // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_13);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         goto -> bb1;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
++         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      }
+  
+-     bb5: {
++     bb4: {
+          unreachable;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+      }
+  
+-     bb6: {
++     bb5: {
+          StorageLive(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _11 = move ((_4 as Ok).0: i32);  // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageLive(_12);                // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          _12 = move _11;                  // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          ((_3 as Continue).0: i32) = move _12; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          discriminant(_3) = 0;            // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_12);                // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
+          StorageDead(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         goto -> bb1;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
++         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+      }
+  }
+  
diff --git a/src/test/mir-opt/separate_const_switch.rs b/src/test/mir-opt/separate_const_switch.rs
new file mode 100644 (file)
index 0000000..5d82acf
--- /dev/null
@@ -0,0 +1,35 @@
+#![feature(control_flow_enum)]
+#![feature(try_trait_v2)]
+
+use std::ops::ControlFlow;
+
+// EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff
+// EMIT_MIR separate_const_switch.too_complex.ConstProp.diff
+// EMIT_MIR separate_const_switch.too_complex.PreCodegen.after.mir
+fn too_complex(x: Result<i32, usize>) -> Option<i32> {
+    // The pass should break the outer match into
+    // two blocks that only have one parent each.
+    // Parents are one of the two branches of the first
+    // match, so a later pass can propagate constants.
+    match {
+        match x {
+            Ok(v) => ControlFlow::Continue(v),
+            Err(r) => ControlFlow::Break(r),
+        }
+    } {
+        ControlFlow::Continue(v) => Some(v),
+        ControlFlow::Break(r) => None,
+    }
+}
+
+// EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff
+// EMIT_MIR separate_const_switch.identity.ConstProp.diff
+// EMIT_MIR separate_const_switch.identity.PreCodegen.after.mir
+fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
+    Ok(x?)
+}
+
+fn main() {
+    too_complex(Ok(0));
+    identity(Ok(0));
+}
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff b/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff
new file mode 100644 (file)
index 0000000..973b783
--- /dev/null
@@ -0,0 +1,91 @@
+- // MIR for `too_complex` before ConstProp
++ // MIR for `too_complex` after ConstProp
+  
+  fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
+      debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
+      let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
+      let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+      let mut _3: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+      let _4: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+      let mut _5: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
+      let _6: usize;                       // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+      let mut _7: usize;                   // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
+      let mut _8: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+      let _9: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+      let mut _10: i32;                    // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
+      let _11: usize;                      // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+      scope 1 {
+          debug v => _4;                   // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
+      }
+      scope 2 {
+          debug r => _6;                   // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
+      }
+      scope 3 {
+          debug v => _9;                   // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
+      }
+      scope 4 {
+          debug r => _11;                  // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+          _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+      }
+  
+      bb1: {
+          StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+          _6 = ((_1 as Err).0: usize);     // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+          StorageLive(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
+          _7 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
+          ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
+          discriminant(_2) = 1;            // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
+          StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
+          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
+-         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+-         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
++         _8 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
++         switchInt(const 1_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+      }
+  
+      bb2: {
+          StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+          _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+          StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
+          _5 = _4;                         // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
+          ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
+          discriminant(_2) = 0;            // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
+          StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
+          StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
+-         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+-         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
++         _8 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
++         switchInt(const 0_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+      }
+  
+      bb3: {
+          StorageLive(_11);                // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+          _11 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+          discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
+          StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
+          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+      }
+  
+      bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+          _9 = ((_2 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+          StorageLive(_10);                // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
+          _10 = _9;                        // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
+          ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
+          discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
+          StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
+          StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
+          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+      }
+  
+      bb5: {
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir b/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..cc941f2
--- /dev/null
@@ -0,0 +1,74 @@
+// MIR for `too_complex` after PreCodegen
+
+fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
+    debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
+    let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
+    let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+    let mut _3: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+    let _4: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+    let mut _5: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
+    let _6: usize;                       // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+    let mut _7: usize;                   // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
+    let _8: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+    let mut _9: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
+    let _10: usize;                      // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+    scope 1 {
+        debug v => _4;                   // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
+    }
+    scope 2 {
+        debug r => _6;                   // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
+    }
+    scope 3 {
+        debug v => _8;                   // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
+    }
+    scope 4 {
+        debug r => _10;                  // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+        _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+        switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+    }
+
+    bb1: {
+        StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+        _6 = ((_1 as Err).0: usize);     // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+        StorageLive(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
+        _7 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
+        ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
+        discriminant(_2) = 1;            // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
+        StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
+        StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
+        StorageLive(_10);                // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+        _10 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+        discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
+        StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
+        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+    }
+
+    bb2: {
+        StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+        _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+        StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
+        _5 = _4;                         // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
+        ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
+        discriminant(_2) = 0;            // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
+        StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
+        StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
+        StorageLive(_8);                 // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+        _8 = ((_2 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+        StorageLive(_9);                 // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
+        _9 = _8;                         // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
+        ((_0 as Some).0: i32) = move _9; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
+        discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
+        StorageDead(_9);                 // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
+        StorageDead(_8);                 // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
+        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+    }
+
+    bb3: {
+        StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
+        return;                          // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
+    }
+}
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
new file mode 100644 (file)
index 0000000..ce32227
--- /dev/null
@@ -0,0 +1,98 @@
+- // MIR for `too_complex` before SeparateConstSwitch
++ // MIR for `too_complex` after SeparateConstSwitch
+  
+  fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
+      debug x => _1;                       // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
+      let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
+      let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+      let mut _3: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+      let _4: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+      let mut _5: i32;                     // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
+      let _6: usize;                       // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+      let mut _7: usize;                   // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
+      let mut _8: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+      let _9: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+      let mut _10: i32;                    // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
+      let _11: usize;                      // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+      scope 1 {
+          debug v => _4;                   // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
+      }
+      scope 2 {
+          debug r => _6;                   // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
+      }
+      scope 3 {
+          debug v => _9;                   // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
+      }
+      scope 4 {
+          debug r => _11;                  // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+          _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+      }
+  
+      bb1: {
+          StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+          _6 = ((_1 as Err).0: usize);     // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
+          StorageLive(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
+          _7 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
+          ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
+          discriminant(_2) = 1;            // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
+          StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
+          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
+-         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
++         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
++         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+      }
+  
+      bb2: {
+          StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+          _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
+          StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
+          _5 = _4;                         // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
+          ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
+          discriminant(_2) = 0;            // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
+          StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
+          StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
+-         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
+-     }
+- 
+-     bb3: {
+          _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+-         switchInt(move _8) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
++         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+      }
+  
+-     bb4: {
++     bb3: {
+          StorageLive(_11);                // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+          _11 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
+          discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
+          StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
+-         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
++         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+      }
+  
+-     bb5: {
++     bb4: {
+          StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+          _9 = ((_2 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
+          StorageLive(_10);                // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
+          _10 = _9;                        // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
+          ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
+          discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
+          StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
+          StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
+-         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
++         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+      }
+  
+-     bb6: {
++     bb5: {
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
+      }
+  }
+  
index 2d0a10d4c27d231a10285a46a7d3433055f60557..385afa4f33ec115675e6ab531990b5847281a4cb 100644 (file)
@@ -1,6 +1,6 @@
 // This is meant as a test case for Issue 3961.
 //
-// Test via: rustc --pretty normal src/test/pretty/block-comment-wchar.rs
+// Test via: rustc -Zunpretty normal src/test/pretty/block-comment-wchar.rs
 // ignore-tidy-cr
 // ignore-tidy-tab
 // pp-exact:block-comment-wchar.pp
index 075230196e3923176a2c210af4ba7d1d7da737bf..e0606e49752c9697b5c68b21ba32fdc4a6e15bc6 100644 (file)
@@ -1,6 +1,6 @@
 // This is meant as a test case for Issue 3961.
 //
-// Test via: rustc --pretty normal src/test/pretty/block-comment-wchar.rs
+// Test via: rustc -Zunpretty normal src/test/pretty/block-comment-wchar.rs
 // ignore-tidy-cr
 // ignore-tidy-tab
 // pp-exact:block-comment-wchar.pp
index 18828b66ce874977fc54d9547ceaca32340e328e..9773e3f1fdfc4b8c8949e94f2c936674171da94b 100644 (file)
@@ -6,19 +6,6 @@
 
 -include ../tools.mk
 
-# This test makes sure that instrumented binaries record the right counts for
-# functions being called and branches being taken. We run an instrumented binary
-# with an argument that causes a know path through the program and then check
-# that the expected counts get added to the use-phase LLVM IR.
-
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS=-Cpanic=abort
-endif
-
 # For some very small programs GNU ld seems to not properly handle
 # instrumentation sections correctly. Neither Gold nor LLD have that problem.
 ifeq ($(UNAME),Linux)
index f1ac39aa0ea8a0bf6107d857666af2110c59d167..a7d5c561632574b485db2251f2cec14c8152da85 100644 (file)
@@ -8,14 +8,6 @@
 
 COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
 
-# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMPILE_FLAGS+= -Cpanic=abort
-endif
-
 all:
        $(RUSTC) $(COMPILE_FLAGS) test.rs
        $(call RUN,test) || exit 1
index 3fbfeb09eb373d308e67a25b53b04084e5fe6b3c..425bfc28a9766d058b44aa1b18750867e8138093 100644 (file)
@@ -4,14 +4,6 @@
 
 COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)"
 
-# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMPILE_FLAGS+= -Cpanic=abort
-endif
-
 all:
        $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs
        # We expect symbols starting with "__llvm_profile_".
index 69b19801bf0916073335613120688faf93fcf2ca..6533355be34182e3bc1dd7033de138f7bdf27664 100644 (file)
@@ -8,14 +8,6 @@
 
 COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)"
 
-# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMPILE_FLAGS+= -Cpanic=abort
-endif
-
 all:
        $(RUSTC) $(COMPILE_FLAGS) test.rs
        $(call RUN,test) || exit 1
index 876a9b2c439918353eb6c4c1f3a4685665206481..c0195dcbb31be047bb1d16677c6c8b76c231f65e 100644 (file)
@@ -6,20 +6,6 @@
 
 -include ../tools.mk
 
-# This test makes sure that indirect call promotion is performed. The test
-# programs calls the same function a thousand times through a function pointer.
-# Only PGO data provides the information that it actually always is the same
-# function. We verify that the indirect call promotion pass inserts a check
-# whether it can make a direct call instead of the indirect call.
-
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS=-Cpanic=abort
-endif
-
 all:
        # We don't compile `opaque` with either optimizations or instrumentation.
        # We don't compile `opaque` with either optimizations or instrumentation.
index 01bc211df161650f8b794f5035e8a6c41e747bb5..d7863c9c587a50481b18b08b765b8fee1c00ebe0 100644 (file)
 
 COMMON_FLAGS=-Copt-level=2 -Ccodegen-units=1 -Cllvm-args=-disable-preinline
 
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://github.com/rust-lang/rust/issues/61002
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS+= -Cpanic=abort
-endif
-
 ifeq ($(UNAME),Darwin)
 # macOS does not have the `tac` command, but `tail -r` does the same thing
 TAC := tail -r
index 7a8dc8d871ca77f47ce4f966b2af0fb3ddde0dff..e721c5afdd7bc03901a6bd5baab46592172f411e 100644 (file)
@@ -1,5 +1,4 @@
 -include ../tools.mk
 
 all:
-       $(RUSTC) -o $(TMPDIR)/input.expanded.rs -Z unstable-options \
-               --pretty=expanded input.rs
+       $(RUSTC) -o $(TMPDIR)/input.expanded.rs -Zunpretty=expanded input.rs
index 8909dee11f0fa00c79d353f043337231d2fb5f15..b224c52fcadde215ab1b23b9e46bfeeb64d6e73c 100644 (file)
@@ -1,5 +1,5 @@
 -include ../tools.mk
 
 all:
-       $(RUSTC) -o $(TMPDIR)/input.out --pretty=normal -Z unstable-options input.rs
+       $(RUSTC) -o $(TMPDIR)/input.out -Zunpretty=normal input.rs
        diff -u $(TMPDIR)/input.out input.pp
index aa20d6aa4bf27b35accfeaed036ec6f0ebd77d1d..a9aad54162f110749cd45699c399452f27e61ed9 100644 (file)
@@ -2,4 +2,4 @@
 
 all:
        $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
-       $(RUSTC) --force-warns dead_code x.rs 2>&1 | diff - force-warns.stderr
+       $(RUSTC) --force-warn dead_code x.rs 2>&1 | diff - force-warn.stderr
diff --git a/src/test/run-make/unstable-flag-required/force-warn.stderr b/src/test/run-make/unstable-flag-required/force-warn.stderr
new file mode 100644 (file)
index 0000000..1b70dc8
--- /dev/null
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warn=lints`
+
diff --git a/src/test/run-make/unstable-flag-required/force-warns.stderr b/src/test/run-make/unstable-flag-required/force-warns.stderr
deleted file mode 100644 (file)
index e093619..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warns=lints`
-
diff --git a/src/test/rustdoc-gui/default-settings.goml b/src/test/rustdoc-gui/default-settings.goml
new file mode 100644 (file)
index 0000000..68b674a
--- /dev/null
@@ -0,0 +1,8 @@
+// This test ensures that the default settings are correctly applied.
+//
+// The "settings" crate uses "ayu" as default setting, which is what we will
+// check.
+goto: file://|DOC_PATH|/settings/index.html
+// Wait a bit to be sure the default theme is applied.
+wait-for: 1000
+assert-css: ("body", {"background-color": "rgb(15, 20, 25)"})
index 84e898660fae72f46b4d137689339177083cc270..92ad92a8c34155320f488a76b382d9af08a571a2 100644 (file)
@@ -2,9 +2,9 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
 // This test checks that the font weight is correctly applied.
 assert-css: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
 assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
-assert-css: ("#method\.a_method > code", {"font-weight": "600"})
-assert-css: ("#associatedtype\.X > code", {"font-weight": "600"})
-assert-css: ("#associatedconstant\.Y > code", {"font-weight": "600"})
+assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"})
+assert-css: ("#associatedtype\.X > .code-header", {"font-weight": "600"})
+assert-css: ("#associatedconstant\.Y > .code-header", {"font-weight": "600"})
 
 goto: file://|DOC_PATH|/test_docs/type.SomeType.html
 assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL)
index a4db5cee7c76842ba5c7dd84a0a6a1fbdc8c314f..87e4f2a7bd141d158b8ce9e42637a922d244475e 100644 (file)
@@ -8,9 +8,9 @@ assert-count: ("#implementors-list > .impl", 2)
 assert: ("#implementors-list > .impl:nth-child(1) > a.anchor")
 assert-attribute: ("#implementors-list > .impl:nth-child(1)", {"id": "impl-Whatever"})
 assert-attribute: ("#implementors-list > .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"})
-assert: "#implementors-list > .impl:nth-child(1) > code.in-band"
+assert: "#implementors-list > .impl:nth-child(1) > .code-header.in-band"
 
 assert: ("#implementors-list > .impl:nth-child(2) > a.anchor")
 assert-attribute: ("#implementors-list > .impl:nth-child(2)", {"id": "impl-Whatever-1"})
 assert-attribute: ("#implementors-list > .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
-assert: "#implementors-list > .impl:nth-child(2) > code.in-band"
+assert: "#implementors-list > .impl:nth-child(2) > .code-header.in-band"
diff --git a/src/test/rustdoc-gui/item-summary-table.goml b/src/test/rustdoc-gui/item-summary-table.goml
new file mode 100644 (file)
index 0000000..6bf4e28
--- /dev/null
@@ -0,0 +1,6 @@
+// This test ensures that <table> elements aren't display in items summary.
+goto: file://|DOC_PATH|/lib2/summary_table/index.html
+// We check that we picked the right item first.
+assert-text: (".item-table .item-left", "Foo")
+// Then we check that its summary is empty.
+assert-text: (".item-table .item-right", "")
diff --git a/src/test/rustdoc-gui/module-items-font.goml b/src/test/rustdoc-gui/module-items-font.goml
new file mode 100644 (file)
index 0000000..817b148
--- /dev/null
@@ -0,0 +1,4 @@
+// This test checks that the correct font is used on module items (in index.html pages).
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, sans-serif'}, ALL)
+assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'}, ALL)
diff --git a/src/test/rustdoc-gui/src/Cargo.lock b/src/test/rustdoc-gui/src/Cargo.lock
deleted file mode 100644 (file)
index a72ccff..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "implementors"
-version = "0.1.0"
-
-[[package]]
-name = "lib2"
-version = "0.1.0"
-dependencies = [
- "implementors",
-]
-
-[[package]]
-name = "test_docs"
-version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/Cargo.toml b/src/test/rustdoc-gui/src/Cargo.toml
deleted file mode 100644 (file)
index 9c8c0c6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[workspace]
-members = [
-    "test_docs",
-    "lib2",
-    "implementors",
-]
diff --git a/src/test/rustdoc-gui/src/implementors/Cargo.toml b/src/test/rustdoc-gui/src/implementors/Cargo.toml
deleted file mode 100644 (file)
index 7ef1052..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-[package]
-name = "implementors"
-version = "0.1.0"
-edition = "2018"
-
-[lib]
-path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/implementors/lib.rs b/src/test/rustdoc-gui/src/implementors/lib.rs
deleted file mode 100644 (file)
index 4b2f696..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-pub trait Whatever {
-    fn method() {}
-}
-
-pub struct Struct;
-
-impl Whatever for Struct {}
diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.lock b/src/test/rustdoc-gui/src/lib2/Cargo.lock
new file mode 100644 (file)
index 0000000..a5873ce
--- /dev/null
@@ -0,0 +1,14 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "implementors"
+version = "0.1.0"
+
+[[package]]
+name = "lib2"
+version = "0.1.0"
+dependencies = [
+ "implementors",
+]
index 6041a793f08dae9f952d45d2593edd69eb86563b..2e37f3f667a02f9ae583ede9650964a0e720d1fd 100644 (file)
@@ -7,4 +7,4 @@ edition = "2018"
 path = "lib.rs"
 
 [dependencies]
-implementors = { path = "../implementors" }
+implementors = { path = "./implementors" }
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock
new file mode 100644 (file)
index 0000000..cad99a9
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "implementors"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml
new file mode 100644 (file)
index 0000000..7ef1052
--- /dev/null
@@ -0,0 +1,7 @@
+[package]
+name = "implementors"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs
new file mode 100644 (file)
index 0000000..4b2f696
--- /dev/null
@@ -0,0 +1,7 @@
+pub trait Whatever {
+    fn method() {}
+}
+
+pub struct Struct;
+
+impl Whatever for Struct {}
index 86ae330e0098f09350812e7b290567fded87ce7f..36373d24971c992a76d2532f0ff8dbad6ac29552 100644 (file)
@@ -66,3 +66,10 @@ pub mod long_table {
     /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
     pub struct Foo;
 }
+
+pub mod summary_table {
+    /// | header 1 | header 2 |
+    /// | -------- | -------- |
+    /// | content | content |
+    pub struct Foo;
+}
diff --git a/src/test/rustdoc-gui/src/settings/.cargo/config.toml b/src/test/rustdoc-gui/src/settings/.cargo/config.toml
new file mode 100644 (file)
index 0000000..bbb8d11
--- /dev/null
@@ -0,0 +1,2 @@
+[build]
+rustdocflags = ["--default-theme", "ayu"]
diff --git a/src/test/rustdoc-gui/src/settings/Cargo.lock b/src/test/rustdoc-gui/src/settings/Cargo.lock
new file mode 100644 (file)
index 0000000..6f0de1a
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "settings"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/settings/Cargo.toml b/src/test/rustdoc-gui/src/settings/Cargo.toml
new file mode 100644 (file)
index 0000000..c8a211a
--- /dev/null
@@ -0,0 +1,7 @@
+[package]
+name = "settings"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/settings/lib.rs b/src/test/rustdoc-gui/src/settings/lib.rs
new file mode 100644 (file)
index 0000000..b76b432
--- /dev/null
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.lock b/src/test/rustdoc-gui/src/test_docs/Cargo.lock
new file mode 100644 (file)
index 0000000..6b80f6e
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "test_docs"
+version = "0.1.0"
index a3dd166e65171c07b3d7ac562382b1918777c643..ff7fd66391628a4f8707295d851b2511733376f0 100644 (file)
@@ -13,7 +13,7 @@ pub trait Foo {
 pub struct Bar;
 
 impl Foo for Bar {
-    // @has assoc_consts/struct.Bar.html '//code' 'impl Foo for Bar'
+    // @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Foo for Bar'
     // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
     const FOO: usize = 12;
     // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
@@ -77,7 +77,7 @@ pub trait Qux {
     const QUX_DEFAULT2: u32 = 3;
 }
 
-// @has assoc_consts/struct.Bar.html '//code' 'impl Qux for Bar'
+// @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Qux for Bar'
 impl Qux for Bar {
     // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8'
     // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait."
index 8fda171002ba045f1166a80b5a652df20473ff27..d9e4ffab1c7d50434ba02f00e143170bf409e93f 100644 (file)
@@ -2,11 +2,11 @@
 
 // @has assoc_types/trait.Index.html
 pub trait Index<I: ?Sized> {
-    // @has - '//*[@id="associatedtype.Output"]//code' 'type Output: ?Sized'
+        // @has - '//*[@id="associatedtype.Output"]//h4[@class="code-header"]' 'type Output: ?Sized'
     type Output: ?Sized;
-    // @has - '//*[@id="tymethod.index"]//code' \
+    // @has - '//*[@id="tymethod.index"]//h4[@class="code-header"]' \
     //      "fn index<'a>(&'a self, index: I) -> &'a Self::Output"
-    // @has - '//*[@id="tymethod.index"]//code//a[@href="trait.Index.html#associatedtype.Output"]' \
+    // @has - '//*[@id="tymethod.index"]//h4[@class="code-header"]//a[@href="trait.Index.html#associatedtype.Output"]' \
     //      "Output"
     fn index<'a>(&'a self, index: I) -> &'a Self::Output;
 }
index 9f95d9a994b17c93a1ef7e746caba2327db6ebb9..6d85171edf784f805bbe5a88f395307f9ccdca90 100644 (file)
@@ -35,9 +35,9 @@ pub async fn quux() -> impl Bar {
 }
 
 // @has async_fn/struct.Foo.html
-// @matches - '//code' 'pub async fn f\(\)$'
-// @matches - '//code' 'pub async unsafe fn g\(\)$'
-// @matches - '//code' 'pub async fn mut_self\(self, first: usize\)$'
+// @matches - '//h4[@class="code-header"]' 'pub async fn f\(\)$'
+// @matches - '//h4[@class="code-header"]' 'pub async unsafe fn g\(\)$'
+// @matches - '//h4[@class="code-header"]' 'pub async fn mut_self\(self, first: usize\)$'
 pub struct Foo;
 
 impl Foo {
index 6f0c15cb5aca6c2ad37a6d910ce50450ed2cf779..b934d84a9f616e290036907b4ad620e19c41ddb7 100644 (file)
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
-// @has foo/struct.S.html '//div[@id="impl-Into%3CU%3E"]//code' 'impl<T, U> Into<U> for T'
+// @has foo/struct.S.html '//div[@id="impl-Into%3CU%3E"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T'
 pub struct S2 {}
 mod m {
     pub struct S {}
index 8c995b9426bbbec12dbae23ef631fc420387d4e4..fb8ea7e33c28ce2f419bd60d7eee6ca6b770616d 100644 (file)
@@ -49,19 +49,19 @@ pub const fn bar2() -> u32 { 42 }
 pub struct Foo;
 
 impl Foo {
-    // @has 'foo/struct.Foo.html' '//div[@id="method.gated"]/code' 'pub fn gated() -> u32'
+    // @has 'foo/struct.Foo.html' '//div[@id="method.gated"]/h4[@class="code-header"]' 'pub fn gated() -> u32'
     // @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature="foo", issue = "none")]
     pub const fn gated() -> u32 { 42 }
 
-    // @has 'foo/struct.Foo.html' '//div[@id="method.gated_unsafe"]/code' 'pub unsafe fn gated_unsafe() -> u32'
+    // @has 'foo/struct.Foo.html' '//div[@id="method.gated_unsafe"]/h4[@class="code-header"]' 'pub unsafe fn gated_unsafe() -> u32'
     // @has - '//span[@class="since"]' '1.0.0 (const: unstable)'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature="foo", issue = "none")]
     pub const unsafe fn gated_unsafe() -> u32 { 42 }
 
-    // @has 'foo/struct.Foo.html' '//div[@id="method.stable_impl"]/code' 'pub const fn stable_impl() -> u32'
+    // @has 'foo/struct.Foo.html' '//div[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32'
     // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "rust1", since = "1.2.0")]
index 8f412aa8c402681e707bc85d7f5b83adfd81135a..123dbaa406b83eeb8fe5eba1ee6832736c4abdc5 100644 (file)
@@ -8,7 +8,7 @@ pub struct Simd<T, const WIDTH: usize> {
     inner: T,
 }
 
-// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//div/code' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>'
+// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//div/h3[@class="code-header in-band"]' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>'
 impl Add for Simd<u8, 16> {
     type Output = Self;
 
index 7c4c70432c762267c383ca1694a1f0b613edf633..92d2c4697e7edea020355356ed6f78308a48fb7f 100644 (file)
 
 // @has foo/trait.Trait.html '//pre[@class="rust trait"]' \
 //      'pub trait Trait<const N: usize>'
-// @has - '//*[@id="impl-Trait%3C1_usize%3E-for-u8"]//code' 'impl Trait<1_usize> for u8'
-// @has - '//*[@id="impl-Trait%3C2_usize%3E-for-u8"]//code' 'impl Trait<2_usize> for u8'
-// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//code' 'impl Trait<{1 + 2}> for u8'
-// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//code' \
+// @has - '//*[@id="impl-Trait%3C1_usize%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1_usize> for u8'
+// @has - '//*[@id="impl-Trait%3C2_usize%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2_usize> for u8'
+// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8'
+// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \
 //      'impl<const N: usize> Trait<N> for [u8; N]'
 pub trait Trait<const N: usize> {}
 impl Trait<1> for u8 {}
@@ -36,7 +36,7 @@ impl Trait<{1 + 2}> for u8 {}
 // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)'
 pub struct Bar<T, const N: usize>([T; N]);
 
-// @has foo/struct.Foo.html '//div[@id="impl"]/code' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
+// @has foo/struct.Foo.html '//div[@id="impl"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
 impl<const M: usize> Foo<M> where u8: Trait<M> {
     // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
     pub const FOO_ASSOC: usize = M + 13;
@@ -47,7 +47,7 @@ pub fn hey<const N: usize>(&self) -> Bar<u8, N> {
     }
 }
 
-// @has foo/struct.Bar.html '//div[@id="impl"]/code' 'impl<const M: usize> Bar<u8, M>'
+// @has foo/struct.Bar.html '//div[@id="impl"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>'
 impl<const M: usize> Bar<u8, M> {
     // @has - '//*[@id="method.hey"]' \
     //      'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>'
index e4e504dd83b5b6cfc5d48ea42db91a1e89144050..7ddcb3a29f28b21c7c44c9bebc1e53706d001897 100644 (file)
@@ -9,20 +9,20 @@ pub enum Order {
 }
 
 // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
-// @has foo/struct.VSet.html '//div[@id="impl-Send"]/code' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
-// @has foo/struct.VSet.html '//div[@id="impl-Sync"]/code' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//div[@id="impl-Send"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//div[@id="impl-Sync"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
 pub struct VSet<T, const ORDER: Order> {
     inner: Vec<T>,
 }
 
-// @has foo/struct.VSet.html '//div[@id="impl"]/code' '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"]/code' '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 +31,7 @@ pub fn new() -> Self {
 
 pub struct Escape<const S: &'static str>;
 
-// @has foo/struct.Escape.html '//div[@id="impl"]/code' '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 6cc02f78c625d622f5f5018420f52a7a2d3094c7..f4c5dcc72259d3e6e6f4424e195a9aef6d799b68 100644 (file)
@@ -12,7 +12,7 @@ pub struct Hasher<T> {
 unsafe impl<T: Default> Send for Hasher<T> {}
 
 // @has foo/struct.Foo.html
-// @has - '//code' 'impl Send for Foo'
+// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foo'
 pub struct Foo {
     hasher: Hasher<[u8; 3]>,
 }
index 638de3292becbafb83eee6c48aecd6370b118f2c..587ad4db4782947836a50555d2a8bed8a4b5516f 100644 (file)
@@ -3,7 +3,7 @@
 pub struct Foo;
 
 impl Foo {
-    // @has const/struct.Foo.html '//*[@id="method.new"]//code' 'const unsafe fn new'
+    // @has const/struct.Foo.html '//*[@id="method.new"]//h4[@class="code-header"]' 'const unsafe fn new'
     pub const unsafe fn new() -> Foo {
         Foo
     }
diff --git a/src/test/rustdoc/default-theme.rs b/src/test/rustdoc/default-theme.rs
new file mode 100644 (file)
index 0000000..ecb8f0b
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: --default-theme ayu
+
+// @has default_theme/index.html
+// @has - '//script[@id="default-settings"]/@data-theme' 'ayu'
+// @has - '//script[@id="default-settings"]/@data-use_system_theme' 'false'
+
+pub fn whatever() {}
index 15c3444606c158f13edc549c47edee2be004b821..7ace13fe3a6b56dce0f24d2bb9cd61ebad400992 100644 (file)
@@ -1,10 +1,10 @@
 // @has issue_33054/impls/struct.Foo.html
-// @has - '//code' 'impl Foo'
-// @has - '//code' 'impl Bar for Foo'
+// @has - '//h3[@class="code-header in-band"]' 'impl Foo'
+// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo'
 // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
 // @count - '//*[@id="main"]/details/summary/*[@class="impl has-srclink"]' 1
 // @has issue_33054/impls/bar/trait.Bar.html
-// @has - '//code' 'impl Bar for Foo'
+// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo'
 // @count - '//*[@class="struct"]' 1
 pub mod impls;
 
index 58bd650feb4669cb39a2f4fc12a1e50e13892e14..8ab026afd1b8dd4807c693ee22288da402c4b2b5 100644 (file)
@@ -4,8 +4,8 @@
 
 extern crate extern_impl_trait;
 
-// @has 'foo/struct.X.html' '//code' "impl Foo<Associated = ()> + 'a"
+// @has 'foo/struct.X.html' '//h4[@class="code-header"]' "impl Foo<Associated = ()> + 'a"
 pub use extern_impl_trait::X;
 
-// @has 'foo/struct.Y.html' '//code' "impl ?Sized + Foo<Associated = ()> + 'a"
+// @has 'foo/struct.Y.html' '//h4[@class="code-header"]' "impl ?Sized + Foo<Associated = ()> + 'a"
 pub use extern_impl_trait::Y;
index f68e10a4d092c3ea45af7471b29a7b5af5b49d10..f357d65df94beed593775e82b33c4910932bcaa1 100644 (file)
@@ -4,24 +4,24 @@
 pub struct Foo;
 
 impl Foo {
-    // @has - '//code' 'fn rust0()'
+    // @has - '//h4[@class="code-header"]' 'fn rust0()'
     pub fn rust0() {}
-    // @has - '//code' 'fn rust1()'
+    // @has - '//h4[@class="code-header"]' 'fn rust1()'
     pub extern "Rust" fn rust1() {}
-    // @has - '//code' 'extern "C" fn c0()'
+    // @has - '//h4[@class="code-header"]' 'extern "C" fn c0()'
     pub extern fn c0() {}
-    // @has - '//code' 'extern "C" fn c1()'
+    // @has - '//h4[@class="code-header"]' 'extern "C" fn c1()'
     pub extern "C" fn c1() {}
-    // @has - '//code' 'extern "system" fn system0()'
+    // @has - '//h4[@class="code-header"]' 'extern "system" fn system0()'
     pub extern "system" fn system0() {}
 }
 
 // @has foo/trait.Bar.html
 pub trait Bar {}
 
-// @has - '//code' 'impl Bar for fn()'
+// @has - '//h3[@class="code-header in-band"]' 'impl Bar for fn()'
 impl Bar for fn() {}
-// @has - '//code' 'impl Bar for extern "C" fn()'
+// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "C" fn()'
 impl Bar for extern fn() {}
-// @has - '//code' 'impl Bar for extern "system" fn()'
+// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "system" fn()'
 impl Bar for extern "system" fn() {}
index 7fbe5fe43274d310c7a0a8be6d5a3e3bd4a60b8c..9cf5fc190af0f390538b8e2f664127160e348ca5 100644 (file)
@@ -6,14 +6,14 @@
 extern crate rustdoc_extern_method as foo;
 
 // @has extern_method/trait.Foo.html //pre "pub trait Foo"
-// @has - '//*[@id="tymethod.foo"]//code' 'extern "rust-call" fn foo'
-// @has - '//*[@id="method.foo_"]//code' 'extern "rust-call" fn foo_'
+// @has - '//*[@id="tymethod.foo"]//h4[@class="code-header"]' 'extern "rust-call" fn foo'
+// @has - '//*[@id="method.foo_"]//h4[@class="code-header"]' 'extern "rust-call" fn foo_'
 pub use foo::Foo;
 
 // @has extern_method/trait.Bar.html //pre "pub trait Bar"
 pub trait Bar {
-    // @has - '//*[@id="tymethod.bar"]//code' 'extern "rust-call" fn bar'
+    // @has - '//*[@id="tymethod.bar"]//h4[@class="code-header"]' 'extern "rust-call" fn bar'
     extern "rust-call" fn bar(&self, _: ());
-    // @has - '//*[@id="method.bar_"]//code' 'extern "rust-call" fn bar_'
+    // @has - '//*[@id="method.bar_"]//h4[@class="code-header"]' 'extern "rust-call" fn bar_'
     extern "rust-call" fn bar_(&self, _: ()) { }
 }
index 96ced021041ff174c91e995796ce7df9d1460ca0..906316d2ebcc00799a62bc3cd75e1c338fbea089 100644 (file)
@@ -2,10 +2,10 @@
 
 use std::fmt;
 
-// @!has foo/struct.Bar.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T'
+// @!has foo/struct.Bar.html '//div[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
 pub struct Bar;
 
-// @has foo/struct.Foo.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T'
+// @has foo/struct.Foo.html '//div[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
 pub struct Foo;
 // @has foo/struct.Foo.html '//div[@class="sidebar-links"]/a[@href="#impl-ToString"]' 'ToString'
 
index 41940b0884e4307a9312d373eba97d87a0d2960d..b75b8de52f9cb6c3fab04e3a1dbf86caa7d4e019 100644 (file)
@@ -38,7 +38,7 @@ pub struct Foo<'a> {
 // @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>"
 
 impl<'a> Foo<'a> {
-    // @has - '//code' "pub fn bar<T>() where T: Trait<'a>,"
+    // @has - '//h4[@class="code-header"]' "pub fn bar<T>() where T: Trait<'a>,"
     pub fn bar<T>()
     where
         T: Trait<'a>,
@@ -49,7 +49,7 @@ pub fn bar<T>()
 // @has foo/trait.B.html
 pub trait B<'x> {}
 
-// @has - '//code[@class="in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>"
+// @has - '//h3[@class="code-header in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>"
 impl<'a> B<'a> for dyn for<'b> Trait<'b> {}
 
 // @has foo/struct.Bar.html
index 9f5531856393748a70062b5a07d4f843e285b7f6..d1d39ccff328f8b02bf3610ad6175d3140ccc334 100644 (file)
@@ -4,13 +4,13 @@ pub trait Foo {}
 
 pub struct Bar<T> { field: T }
 
-// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
 //     "impl Foo for Bar<u8>"
 impl Foo for Bar<u8> {}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
 //     "impl Foo for Bar<u16>"
 impl Foo for Bar<u16> {}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
 //     "impl<'a> Foo for &'a Bar<u8>"
 impl<'a> Foo for &'a Bar<u8> {}
 
@@ -22,9 +22,9 @@ pub mod mod2 {
     pub enum Baz {}
 }
 
-// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
 //     "impl Foo for foo::mod1::Baz"
 impl Foo for mod1::Baz {}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
 //     "impl<'a> Foo for &'a foo::mod2::Baz"
 impl<'a> Foo for &'a mod2::Baz {}
index e4039eecb71323f8e1e30861604b3967cf5d4d47..249158c1a1f89bca9a9f1b63f1da16c76785e388 100644 (file)
@@ -5,8 +5,8 @@
 
 pub struct Foo<T> { field: T }
 
-// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//code' \
+// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 //     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
-// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//code' \
+// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
 //     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
 impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {}
index a2adc0e63c9c01560e4e1ba970ae7a3401030d35..ef615472b0e98a194a54433af0b32b00d70cd6f7 100644 (file)
@@ -31,8 +31,8 @@
 pub use impl_trait_aux::async_fn;
 
 // @has impl_trait/struct.Foo.html
-// @has - '//*[@id="method.method"]//code' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
-// @!has - '//*[@id="method.method"]//code' 'where'
+// @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
 pub use impl_trait_aux::Foo;
 
 // @has impl_trait/struct.Bar.html
index 390f0b845e00b905e552283a6accb7c214d3589b..be8585dd16e175f5f1f8aafe2b503db94af2eff2 100644 (file)
@@ -5,22 +5,22 @@
 extern crate rustdoc_nonreachable_impls;
 
 // @has issue_31948_1/struct.Wobble.html
-// @has - '//*[@class="impl has-srclink"]//code' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//code' 'Woof for'
-// @!has - '//*[@class="impl"]//code' 'Bar for'
-// @!has - '//*[@class="impl"]//code' 'Qux for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Qux for'
 pub use rustdoc_nonreachable_impls::hidden::Wobble;
 
 // @has issue_31948_1/trait.Bark.html
-// @has - '//code' 'for Foo'
-// @has - '//code' 'for Wobble'
-// @!has - '//code' 'for Wibble'
+// @has - '//h3[@class="code-header in-band"]' 'for Foo'
+// @has - '//h3[@class="code-header in-band"]' 'for Wobble'
+// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
 pub use rustdoc_nonreachable_impls::Bark;
 
 // @has issue_31948_1/trait.Woof.html
-// @has - '//code' 'for Foo'
-// @has - '//code' 'for Wobble'
-// @!has - '//code' 'for Wibble'
+// @has - '//h3[@class="code-header in-band"]' 'for Foo'
+// @has - '//h3[@class="code-header in-band"]' 'for Wobble'
+// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
 pub use rustdoc_nonreachable_impls::Woof;
 
 // @!has issue_31948_1/trait.Bar.html
index 013e777440f1a83bbb3ca8459f67c9f2f91ccc87..7aa994f19d6f141e5d0e05357a6635aeebdd627c 100644 (file)
@@ -5,15 +5,15 @@
 extern crate rustdoc_nonreachable_impls;
 
 // @has issue_31948_2/struct.Wobble.html
-// @has - '//*[@class="impl has-srclink"]//code' 'Qux for'
-// @has - '//*[@class="impl has-srclink"]//code' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//code' 'Woof for'
-// @!has - '//*[@class="impl"]//code' 'Bar for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Qux for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for'
 pub use rustdoc_nonreachable_impls::hidden::Wobble;
 
 // @has issue_31948_2/trait.Qux.html
-// @has - '//code' 'for Foo'
-// @has - '//code' 'for Wobble'
+// @has - '//h3[@class="code-header in-band"]' 'for Foo'
+// @has - '//h3[@class="code-header in-band"]' 'for Wobble'
 pub use rustdoc_nonreachable_impls::hidden::Qux;
 
 // @!has issue_31948_2/trait.Bar.html
index 82dcc2d2cc3efcdd3e692221a7a441626604349d..7bf4110d32ac10f19fcceaa8c197db822b96cbac 100644 (file)
@@ -5,22 +5,22 @@
 extern crate rustdoc_nonreachable_impls;
 
 // @has issue_31948/struct.Foo.html
-// @has - '//*[@class="impl has-srclink"]//code' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//code' 'Woof for'
-// @!has - '//*[@class="impl has-srclink"]//code' 'Bar for'
-// @!has - '//*[@class="impl"]//code' 'Qux for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for'
+// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bar for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Qux for'
 pub use rustdoc_nonreachable_impls::Foo;
 
 // @has issue_31948/trait.Bark.html
-// @has - '//code' 'for Foo'
-// @!has - '//code' 'for Wibble'
-// @!has - '//code' 'for Wobble'
+// @has - '//h3[@class="code-header in-band"]' 'for Foo'
+// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
+// @!has - '//h3[@class="code-header in-band"]' 'for Wobble'
 pub use rustdoc_nonreachable_impls::Bark;
 
 // @has issue_31948/trait.Woof.html
-// @has - '//code' 'for Foo'
-// @!has - '//code' 'for Wibble'
-// @!has - '//code' 'for Wobble'
+// @has - '//h3[@class="code-header in-band"]' 'for Foo'
+// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
+// @!has - '//h3[@class="code-header in-band"]' 'for Wobble'
 pub use rustdoc_nonreachable_impls::Woof;
 
 // @!has issue_31948/trait.Bar.html
index 5f31e6cd3ad1f7ff8b86c08ebabb60fa329a2676..8052339a83b6d3bbad43065a416474e1c9a91c02 100644 (file)
@@ -5,7 +5,7 @@
 extern crate rustdoc_trait_object_impl;
 
 // @has issue_32881/trait.Bar.html
-// @has - '//code' "impl<'a> dyn Bar"
-// @has - '//code' "impl<'a> Debug for dyn Bar"
+// @has - '//h3[@class="code-header in-band"]' "impl<'a> dyn Bar"
+// @has - '//h3[@class="code-header in-band"]' "impl<'a> Debug for dyn Bar"
 
 pub use rustdoc_trait_object_impl::Bar;
index 1e633600aeff1638e27cf445bb3370860e7926fa..c60859bbcea98662a9829379ed6aabceaadd09ca 100644 (file)
@@ -5,6 +5,6 @@
 extern crate bar;
 
 // @has issue_33113/trait.Bar.html
-// @has - '//code' "for &'a char"
-// @has - '//code' "for Foo"
+// @has - '//h3[@class="code-header in-band"]' "for &'a char"
+// @has - '//h3[@class="code-header in-band"]' "for Foo"
 pub use bar::Bar;
index e6585449cb64e149a674ed558f630f9a496d4765..363c52a336e42043b7f0a8a7ff45082af29e9cba 100644 (file)
@@ -3,5 +3,5 @@
 extern crate inner;
 
 // @has trait_vis/struct.SomeStruct.html
-// @has - '//code' 'impl Clone for SomeStruct'
+// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct'
 pub use inner::SomeStruct;
index a9b54fbe79edc7235a8a09c3eab6bcd963b2280c..e7b08088f4032c92224d29ce5e7e17061952cbc0 100644 (file)
@@ -13,6 +13,6 @@ impl PrivateTrait for SomeStruct {}
 }
 
 // @has trait_vis/struct.SomeStruct.html
-// @has - '//code' 'impl ThisTrait for SomeStruct'
-// @!has - '//code' 'impl PrivateTrait for SomeStruct'
+// @has - '//h3[@class="code-header in-band"]' 'impl ThisTrait for SomeStruct'
+// @!has - '//h3[@class="code-header in-band"]' 'impl PrivateTrait for SomeStruct'
 pub use asdf::SomeStruct;
index 9dac49c6413d803ca7906b8b5dc11864a68e5625..2046273e2c1baed7448a2353d974cb114f6ff44f 100644 (file)
@@ -14,7 +14,7 @@ fn deref(&self) -> &Foo { loop {} }
 }
 
 // @has issue_19190/struct.Bar.html
-// @has - '//*[@id="method.foo"]//code' 'fn foo(&self)'
+// @has - '//*[@id="method.foo"]//h4[@class="code-header"]' 'fn foo(&self)'
 // @has - '//*[@id="method.foo"]' 'fn foo(&self)'
-// @!has - '//*[@id="method.static_foo"]//code' 'fn static_foo()'
+// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()'
 // @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
index e53cf6451353f733a6da031e3b447d9bca4996c6..c97b35adaf22eb6bb70f5793791b9263ebc4788e 100644 (file)
@@ -8,36 +8,36 @@ pub trait Bar {
 }
 
 impl Foo<u8> {
-    // @has - '//*[@id="method.pass"]//code' 'fn pass()'
+    // @has - '//*[@id="method.pass"]//h4[@class="code-header"]' 'fn pass()'
     pub fn pass() {}
 }
 impl Foo<u16> {
-    // @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize'
+    // @has - '//*[@id="method.pass-1"]//h4[@class="code-header"]' 'fn pass() -> usize'
     pub fn pass() -> usize { 42 }
 }
 impl Foo<u32> {
-    // @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
+    // @has - '//*[@id="method.pass-2"]//h4[@class="code-header"]' 'fn pass() -> isize'
     pub fn pass() -> isize { 42 }
 }
 
 impl<T> Bar for Foo<T> {
-    // @has - '//*[@id="associatedtype.Item"]//code' 'type Item = T'
+    // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' 'type Item = T'
     type Item=T;
 
-    // @has - '//*[@id="method.quux"]//code' 'fn quux(self)'
+    // @has - '//*[@id="method.quux"]//h4[@class="code-header"]' 'fn quux(self)'
     fn quux(self) {}
 }
 impl<'a, T> Bar for &'a Foo<T> {
-    // @has - '//*[@id="associatedtype.Item-1"]//code' "type Item = &'a T"
+    // @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item = &'a T"
     type Item=&'a T;
 
-    // @has - '//*[@id="method.quux-1"]//code' 'fn quux(self)'
+    // @has - '//*[@id="method.quux-1"]//h4[@class="code-header"]' 'fn quux(self)'
     fn quux(self) {}
 }
 impl<'a, T> Bar for &'a mut Foo<T> {
-    // @has - '//*[@id="associatedtype.Item-2"]//code' "type Item = &'a mut T"
+    // @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item = &'a mut T"
     type Item=&'a mut T;
 
-    // @has - '//*[@id="method.quux-2"]//code' 'fn quux(self)'
+    // @has - '//*[@id="method.quux-2"]//h4[@class="code-header"]' 'fn quux(self)'
     fn quux(self) {}
 }
index 1cbba4b663df89dd20e9b61971384c9866b4dc84..097e4e3b03d9db1a0f2b522961854f20d5a31a4b 100644 (file)
@@ -7,4 +7,4 @@
 
 // @matches issue_27362/fn.foo.html '//pre' "pub const fn foo()"
 // @matches issue_27362/fn.bar.html '//pre' "pub const unsafe fn bar()"
-// @matches issue_27362/struct.Foo.html '//code' "const unsafe fn baz()"
+// @matches issue_27362/struct.Foo.html '//h4[@class="code-header"]' "const unsafe fn baz()"
index 23d9e73b567d0a9174b577a9e7da4ab36e877425..90a2b76eab67bcdaa32a780bc5f5d1b52fc81cc1 100644 (file)
@@ -5,7 +5,7 @@ pub trait MyTrait {
     fn my_string(&self) -> String;
 }
 
-// @has - "//div[@id='implementors-list']//div[@id='impl-MyTrait']//code" "impl<T> MyTrait for T where T: Debug"
+// @has - "//div[@id='implementors-list']//div[@id='impl-MyTrait']//h3[@class='code-header in-band']" "impl<T> MyTrait for T where T: Debug"
 impl<T> MyTrait for T where T: fmt::Debug {
     fn my_string(&self) -> String {
         format!("{:?}", self)
index 81450f15c207822bd8d1cac03f34ae8d8dd8879c..815439db9bfd23c8e4fcaf54dee57f236b4f55b9 100644 (file)
@@ -6,8 +6,8 @@ pub trait Foo<T> {}
 
 pub struct Baz;
 
-// @has foo/trait.Foo.html '//code' 'impl Foo<i32> for Bar'
+// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl Foo<i32> for Bar'
 impl Foo<i32> for Bar {}
 
-// @has foo/trait.Foo.html '//code' 'impl<T> Foo<T> for Baz'
+// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl<T> Foo<T> for Baz'
 impl<T> Foo<T> for Baz {}
index a688ae48d00ce84bbf01b5908c3be9ae8662f5b2..f08466baf8b05fa5f369563fa40b1f0dfb9f1294 100644 (file)
@@ -24,17 +24,17 @@ fn deref_mut(&mut self) -> &mut Foo { loop {} }
 }
 
 // @has issue_35169_2/struct.Bar.html
-// @has - '//*[@id="method.by_ref"]//code' 'fn by_ref(&self)'
+// @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)'
 // @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)'
-// @has - '//*[@id="method.by_explicit_ref"]//code' 'fn by_explicit_ref(self: &Foo)'
+// @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)'
 // @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)'
-// @has - '//*[@id="method.by_mut_ref"]//code' 'fn by_mut_ref(&mut self)'
+// @has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)'
 // @has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)'
-// @has - '//*[@id="method.by_explicit_mut_ref"]//code' 'fn by_explicit_mut_ref(self: &mut Foo)'
+// @has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
 // @has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
-// @!has - '//*[@id="method.by_explicit_box"]//code' 'fn by_explicit_box(self: Box<Foo>)'
+// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box<Foo>)'
 // @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box<Foo>)'
-// @!has - '//*[@id="method.by_explicit_self_box"]//code' 'fn by_explicit_self_box(self: Box<Self>)'
+// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box<Self>)'
 // @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box<Self>)'
-// @!has - '//*[@id="method.static_foo"]//code' 'fn static_foo()'
+// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()'
 // @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
index 4f10c04a616b382f839978f2a148b8e7ae39b77c..70a2265c80632504c4f939ea7e18b1c1e0863a8d 100644 (file)
@@ -19,17 +19,17 @@ fn deref(&self) -> &Foo { loop {} }
 }
 
 // @has issue_35169/struct.Bar.html
-// @has - '//*[@id="method.by_ref"]//code' 'fn by_ref(&self)'
+// @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)'
 // @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)'
-// @has - '//*[@id="method.by_explicit_ref"]//code' 'fn by_explicit_ref(self: &Foo)'
+// @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)'
 // @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)'
-// @!has - '//*[@id="method.by_mut_ref"]//code' 'fn by_mut_ref(&mut self)'
+// @!has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)'
 // @!has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)'
-// @!has - '//*[@id="method.by_explicit_mut_ref"]//code' 'fn by_explicit_mut_ref(self: &mut Foo)'
+// @!has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
 // @!has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)'
-// @!has - '//*[@id="method.by_explicit_box"]//code' 'fn by_explicit_box(self: Box<Foo>)'
+// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box<Foo>)'
 // @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box<Foo>)'
-// @!has - '//*[@id="method.by_explicit_self_box"]//code' 'fn by_explicit_self_box(self: Box<Self>)'
+// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box<Self>)'
 // @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box<Self>)'
-// @!has - '//*[@id="method.static_foo"]//code' 'fn static_foo()'
+// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()'
 // @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
index 0f991cf676ff7834fccd428d71401c8681218a1a..00e9127a34d2027edb8fe1989e8ba2d8b8291614 100644 (file)
@@ -3,5 +3,5 @@
 extern crate issue_46727;
 
 // @has issue_46727/trait.Foo.html
-// @has - '//code' 'impl<T> Foo for Bar<[T; 3]>'
+// @has - '//h3[@class="code-header in-band"]' 'impl<T> Foo for Bar<[T; 3]>'
 pub use issue_46727::{Foo, Bar};
index 69774aa351f173fc5e395d246fc44e8ff7aabc72..d88c29217023a9f9b5da233a3766297a872eeb0b 100644 (file)
@@ -11,8 +11,8 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
 }
 
 // @has issue_50159/struct.Switch.html
-// @has - '//code' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send'
-// @has - '//code' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync'
+// @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send'
+// @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
 pub struct Switch<B: Signal> {
index e01dae6c7f183ca81782a7d0721873de1355002d..ee11ccc6811633fac9cd3f6b09abfc35b7e0a62f 100644 (file)
@@ -7,7 +7,7 @@ pub trait Owned<'a> {
 }
 
 // @has issue_51236/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> Send for Owned<T> where <T as Owned<'static>>::Reader: Send"
 pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
     marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
index 7fe962c506188caed9f155006b93431a6faf2525..52ce4159d823ec85b2fd5b8f9f42a88e2ed6b72b 100644 (file)
@@ -6,7 +6,7 @@
 
 // @has foo/trait.MyTrait.html
 // @!has - 'MyStruct'
-// @count - '//*[code="impl<T> MyTrait for T"]' 1
+// @count - '//*[h3="impl<T> MyTrait for T"]' 1
 pub trait MyTrait {}
 
 impl<T> MyTrait for T {}
index 5a94d36ed70d067f3acacc10111cccd6f4daf324..bedaf5c4ddc360a311c83fc415943cab0b1e08f2 100644 (file)
@@ -3,10 +3,10 @@ pub trait ScopeHandle<'scope> {}
 
 
 // @has issue_54705/struct.ScopeFutureContents.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync"
 pub struct ScopeFutureContents<'scope, S>
     where S: ScopeHandle<'scope>,
index b664733487b3defb952ec1ce4658ca6f3f1ab14d..ee2420d86d236fa95e4674ae39a0dbb9698d9d9d 100644 (file)
@@ -1,9 +1,9 @@
 #![feature(negative_impls)]
 
 // @has issue_55321/struct.A.html
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl !Send for A"
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl !Sync for A"
 pub struct A();
 
@@ -11,8 +11,8 @@ impl !Send for A {}
 impl !Sync for A {}
 
 // @has issue_55321/struct.B.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> !Send for B<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> !Sync for B<T>"
 pub struct B<T: ?Sized>(A, Box<T>);
index 977596e0b90884e6bcfa622ee77fff74e0558180..aef6ddd8d23bc658840f42e9fd786cff18f7ad3d 100644 (file)
@@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> {
 }
 
 // @has issue_56822/struct.Parser.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'a> Send for Parser<'a>"
 pub struct Parser<'a> {
     field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output
index e0417f1a4f4b8c9df243d30e126e8d2f1d10e45b..167f0f039c15e16b2cff56dd81e73d75e43f51c4 100644 (file)
@@ -26,9 +26,9 @@ unsafe impl<I> Send for DynTrait<I>
 {}
 
 // @has issue_60726/struct.IntoIter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> !Send for IntoIter<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> !Sync for IntoIter<T>"
 pub struct IntoIter<T>{
     hello:DynTrait<FooInterface<T>>,
index aebffeff5f05e5a0c8f1c5225741c721d5e50f41..ac97b94fb351b558258671d7529e8c5825373591 100644 (file)
@@ -10,8 +10,8 @@
 extern crate real_gimli;
 
 // issue #74672
-// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//code' 'impl Deref for EndianSlice'
+// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice'
 pub use realcore::Deref;
 
-// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//code' 'impl Join for Foo'
+// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo'
 pub use realcore::Join;
index 585a0864bb25d5fe529dfbad84a3af930780827f..515e617b4f4cef1468785a1a35451a1c13d9a2e9 100644 (file)
@@ -31,7 +31,7 @@ impl<T: Trait3> Trait3 for Vec<T> {
 pub struct Struct1 {}
 
 // @has issue_80233_normalize_auto_trait/struct.Question.html
-// @has - '//code' 'impl<T> Send for Question<T>'
+// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Question<T>'
 pub struct Question<T: Trait1> {
     pub ins: <<Vec<T> as Trait3>::Type3 as Trait2>::Type2,
 }
index 618ac20ac487d99ba7a25774124b1679e2f57ad7..8999e6a889bda2662c9fc5c79959fd729bdcf264 100644 (file)
@@ -1,14 +1,14 @@
 use std::convert::AsRef;
 pub struct Local;
 
-// @has issue_82465_asref_for_and_of_local/struct.Local.html '//code' 'impl AsRef<str> for Local'
+// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header in-band"]' 'impl AsRef<str> for Local'
 impl AsRef<str> for Local {
     fn as_ref(&self) -> &str {
         todo!()
     }
 }
 
-// @has - '//code' 'impl AsRef<Local> for str'
+// @has - '//h3[@class="code-header in-band"]' 'impl AsRef<Local> for str'
 impl AsRef<Local> for str {
     fn as_ref(&self) -> &Local {
         todo!()
index ee65a7d5f3902a0ecb07555c44ea6a5e4cf15df0..61a23986862309e05b7fd4c6641dd3bd4d311a93 100644 (file)
@@ -5,10 +5,10 @@
 // @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo<B>"
 pub struct Bravo<B>(B);
 
-// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//code' \
+// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl !Send for Alpha"
 impl !Send for Alpha {}
 
-// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//code' "\
+// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' "\
 // impl<B> !Send for Bravo<B>"
 impl<B> !Send for Bravo<B> {}
index 2951f5128e07402229b190d5fef9a64b4324d575..0bf6157fed34825ab136423c09fd2ae0e25a7a9e 100644 (file)
@@ -2,4 +2,4 @@
 
 include!("primitive/primitive-generic-impl.rs");
 
-// @has foo/primitive.i32.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T'
+// @has foo/primitive.i32.html '//div[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
index 91db01177c5818f02d1aa86ebbf725b2ba245c52..3d17bce472154e7de09411c3ab85e27b633edcf4 100644 (file)
@@ -3,7 +3,7 @@
 pub struct A;
 pub struct B;
 
-// @has recursive_deref/struct.A.html '//code' 'impl Deref for A'
+// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A'
 impl Deref for A {
     type Target = B;
 
@@ -12,7 +12,7 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-// @has recursive_deref/struct.B.html '//code' 'impl Deref for B'
+// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B'
 impl Deref for B {
     type Target = A;
 
index e73c5b4f640cf3d4eb3baa695de1cd990937e2c3..d1083c487642d7ad668299fe02f53528820affc9 100644 (file)
@@ -6,9 +6,9 @@
 // @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
 // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
 // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-u32"]' 'u32'
-// @has - '//div[@id="impl-Foo-for-u32"]//code' 'impl Foo for u32'
+// @has - '//div[@id="impl-Foo-for-u32"]//h3[@class="code-header in-band"]' 'impl Foo for u32'
 // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str"
-// @has - '//div[@id="impl-Foo-for-%26%27a%20str"]//code' "impl<'a> Foo for &'a str"
+// @has - '//div[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header in-band"]' "impl<'a> Foo for &'a str"
 pub trait Foo {}
 
 impl Foo for u32 {}
index 6730c71e90f885318ac8155570f8355e9730f940..ac4a4ad394c1bb23f4768be96a8f7112689f5603 100644 (file)
@@ -11,7 +11,7 @@ pub struct Bar {
 pub struct Foo<T: ?Sized>(T);
 
 // @has foo/struct.Unsized.html
-// @has - '//div[@id="impl-Sized"]/code' 'impl !Sized for Unsized'
+// @has - '//div[@id="impl-Sized"]//h3[@class="code-header in-band"]' 'impl !Sized for Unsized'
 pub struct Unsized {
     data: [u8],
 }
index 1952f723465d66c709f88ac903aa77d28346c822..f9ac836c9b18faa33fe5c4c2ac1340d9eca864b4 100644 (file)
@@ -1,11 +1,11 @@
 #![crate_name = "foo"]
 
 // @has foo/struct.Unsized.html
-// @has - '//div[@id="impl-Sized"]/code' 'impl !Sized for Unsized'
+// @has - '//div[@id="impl-Sized"]/h3[@class="code-header in-band"]' 'impl !Sized for Unsized'
 // @!has - '//div[@id="impl-Sized"]//a[@class="srclink"]' '[src]'
-// @has - '//div[@id="impl-Sync"]/code' 'impl Sync for Unsized'
+// @has - '//div[@id="impl-Sync"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized'
 // @!has - '//div[@id="impl-Sync"]//a[@class="srclink"]' '[src]'
-// @has - '//div[@id="impl-Any"]/code' 'impl<T> Any for T'
+// @has - '//div[@id="impl-Any"]/h3[@class="code-header in-band"]' 'impl<T> Any for T'
 // @has - '//div[@id="impl-Any"]//a[@class="srclink"]' '[src]'
 pub struct Unsized {
     data: [u8],
index 943596a0c851815959646259adedf269d2dab269..54c54fdbf68a8acafc9e50e48d0af6f9f7d3bc7b 100644 (file)
@@ -1,6 +1,6 @@
 // @has basic/struct.Foo.html
-// @has - '//code' 'impl<T> Send for Foo<T> where T: Send'
-// @has - '//code' 'impl<T> Sync for Foo<T> where T: Sync'
+// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T> where T: Send'
+// @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T> where T: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0
 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
 pub struct Foo<T> {
index 0213142266feb4d9caa367b9d607a46fe3f96e37..f9017b90caee774d2022797e0321002bb77b630f 100644 (file)
@@ -20,7 +20,7 @@ pub struct Foo<T> {
 }
 
 // @has complex/struct.NotOuter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
 // -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
 
index 3346ac05ffe47dbef9412a5d345f141248d588c4..58b787dfafc7c48923dc0fca98ca945b8718df52 100644 (file)
@@ -3,7 +3,7 @@
 pub auto trait Banana {}
 
 // @has crate_local/struct.Peach.html
-// @has - '//code' 'impl Banana for Peach'
-// @has - '//code' 'impl Send for Peach'
-// @has - '//code' 'impl Sync for Peach'
+// @has - '//h3[@class="code-header in-band"]' 'impl Banana for Peach'
+// @has - '//h3[@class="code-header in-band"]' 'impl Send for Peach'
+// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Peach'
 pub struct Peach;
index c2e9b6f404677442129cb83a49e44c64d1a29557..ee1393f9729c176ccff505f02e489c9e2116a2dc 100644 (file)
@@ -9,10 +9,10 @@ unsafe impl<'a, T> Send for Inner<'a, T>
 {}
 
 // @has lifetimes/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'c, K> Sync for Foo<'c, K> where K: Sync"
 pub struct Foo<'c, K: 'c> {
     inner_field: Inner<'c, K>,
index 91fe6c351c5fcaf07c7268ddabeef7819983f6fb..49bad162211b7041be4ba179022091d2d11f3b9f 100644 (file)
@@ -1,8 +1,8 @@
 // @has manual/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // 'impl<T> Sync for Foo<T> where T: Sync'
 //
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // 'impl<T> Send for Foo<T>'
 //
 // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
index 16b36b56b68076058d7df5eb04f9df9531ac2d43..66e749ac38d9623237d03be982a5899b06d825fb 100644 (file)
@@ -3,10 +3,10 @@ pub struct Inner<T: Copy> {
 }
 
 // @has negative/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> !Send for Outer<T>"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> !Sync for Outer<T>"
 pub struct Outer<T: Copy> {
     inner_field: Inner<T>,
index a6cf5890dcab458c41465d2c9aeabb71d1caff05..69edbee619e31e8316c1796bcc7916cfd9cd9c28 100644 (file)
@@ -9,10 +9,10 @@ unsafe impl<T> Send for Inner<T>
 }
 
 // @has nested/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // 'impl<T> Send for Foo<T> where T: Copy'
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // 'impl<T> Sync for Foo<T> where T: Sync'
 pub struct Foo<T> {
     inner_field: Inner<T>,
index 5c744e3eb3c9423a98672c61acfd16ec393e827b..f727c9a47f2687095f84cf8929affbc71a57a515 100644 (file)
@@ -9,7 +9,7 @@ unsafe impl<T> Send for Inner<T>
 }
 
 // @has no_redundancy/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> Send for Outer<T> where T: Copy + Send"
 pub struct Outer<T> {
     inner_field: Inner<T>,
index 546b3e07793e15982bdbf9282ecf66b49c4b3eea..c132ab6fb1b3e856c774cd0bf21b6d9799ec7e02 100644 (file)
@@ -21,7 +21,7 @@ enum TyData<I: Interner> {
 struct VariableKind<I: Interner>(I::InternedType);
 
 // @has overflow/struct.BoundVarsCollector.html
-// @has - '//code' "impl<'tcx> Send for BoundVarsCollector<'tcx>"
+// @has - '//h3[@class="code-header in-band"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>"
 pub struct BoundVarsCollector<'tcx> {
     val: VariableKind<RustInterner<'tcx>>
 }
index baf9924b1ae66465fc954790596ca8f99e47cb29..8b020582563f3d3ac9fe6cd6be4975c2c66641bf 100644 (file)
@@ -23,10 +23,10 @@ unsafe impl<'a, T> Sync for Inner<'a, T>
 }
 
 // @has project/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'c, K> Send for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
 // 'c: 'static,"
 pub struct Foo<'c, K: 'c> {
index e96187e2c9632a3d1c15731b914258413b386d0a..ccef901b18da3e57b359973eb52e04cb3f5f19ad 100644 (file)
@@ -23,7 +23,7 @@ impl<T> Pattern for Wrapper<T> {
 
 
 // @has self_referential/struct.WriteAndThen.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<P1> Send for WriteAndThen<P1>  where  <P1 as Pattern>::Value: Send"
 pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
     where P1: Pattern;
index fc732a08ed404732984e8c74dd574f71e32297c8..36e985144b0e09026e60796a8908419b766eb363 100644 (file)
@@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> {
 }
 
 // @has static_region/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // "impl<T> Send for Owned<T> where <T as OwnedTrait<'static>>::Reader: Send"
 pub struct Owned<T> where T: OwnedTrait<'static> {
     marker: <T as OwnedTrait<'static>>::Reader,
index 6e3c0b4c681f7c6e3b8604eb4a67f1465fe3e3e4..8d2046591d08ac42244212c68e20a691d754a17c 100644 (file)
@@ -9,7 +9,7 @@ pub struct PubStruct {
 
 // @has 'toggle_item_contents/struct.BigPubStruct.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields'
 pub struct BigPubStruct {
     pub a: usize,
     pub b: usize,
@@ -28,7 +28,7 @@ pub struct BigPubStruct {
 
 // @has 'toggle_item_contents/union.BigUnion.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields'
 pub union BigUnion {
     pub a: usize,
     pub b: usize,
@@ -62,8 +62,7 @@ pub struct PrivStruct {
 }
 
 // @has 'toggle_item_contents/enum.Enum.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields'
+// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]'
 pub enum Enum {
     A, B, C,
     D {
@@ -72,9 +71,18 @@ pub enum Enum {
     }
 }
 
+// @has 'toggle_item_contents/enum.EnumStructVariant.html'
+// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]'
+pub enum EnumStructVariant {
+    A, B, C,
+    D {
+        a: u8,
+    }
+}
+
 // @has 'toggle_item_contents/enum.LargeEnum.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show variants'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants'
 pub enum LargeEnum {
     A, B, C, D, E, F(u8), G, H, I, J, K, L, M
 }
@@ -90,7 +98,7 @@ pub trait Trait {
 
 // @has 'toggle_item_contents/trait.GinormousTrait.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated items'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items'
 pub trait GinormousTrait {
     type A;
     type B;
@@ -113,7 +121,7 @@ pub trait GinormousTrait {
 
 // @has 'toggle_item_contents/trait.HugeTrait.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated constants and methods'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods'
 pub trait HugeTrait {
     type A;
     const M: usize = 1;
@@ -133,9 +141,30 @@ pub trait HugeTrait {
     fn bar();
 }
 
+// @has 'toggle_item_contents/trait.GiganticTrait.html'
+// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method'
+pub trait GiganticTrait {
+    type A;
+    type B;
+    type C;
+    type D;
+    type E;
+    type F;
+    type G;
+    type H;
+    type I;
+    type J;
+    type K;
+    type L;
+    const M: usize = 1;
+    #[must_use]
+    fn foo();
+}
+
 // @has 'toggle_item_contents/trait.BigTrait.html'
 // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show methods'
+// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods'
 pub trait BigTrait {
     type A;
     #[must_use]
index f7f6086a4cb10ceedc537520107712029b76b376..1aa74e5965960e56c8abdd6b95d5bc375195db4d 100644 (file)
@@ -4,9 +4,9 @@
 // summary. Struct methods with no documentation should not be wrapped.
 //
 // @has foo/struct.Foo.html
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//code' 'is_documented()'
+// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
 // @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
-// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//code' 'not_documented()'
+// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
 pub struct Foo {
 }
 
index 0bc5eba75a12db149af22545f9aec8203895aa87..65e8daeb06619ca1250f58f396201fad2945c4ea 100644 (file)
@@ -4,11 +4,11 @@
 // summary. Trait methods with no documentation should not be wrapped.
 //
 // @has foo/trait.Foo.html
-// @has -  '//details[@class="rustdoc-toggle"]//summary//code' 'is_documented()'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//code' 'not_documented()'
+// @has -  '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
 // @has -  '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented is documented'
-// @has -  '//details[@class="rustdoc-toggle"]//summary//code' 'is_documented_optional()'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//code' 'not_documented_optional()'
+// @has -  '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
+// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
 // @has -  '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
 pub trait Foo {
     fn not_documented();
index 931691db3e6d9a3d7fa5e4c379a82f8f2da6d1c4..05ccc074bf1102ef4030dce39012af2baf098d7c 100644 (file)
@@ -43,5 +43,5 @@ fn c() {}
     // @!has - '//*[@id="method.d"]/../../div[@class="docblock"]/p/em'
     fn d() {}
 
-    // @has - '//*[@id="impl-Trait"]/code/a/@href' 'trait.Trait.html'
+    // @has - '//*[@id="impl-Trait"]/h3//a/@href' 'trait.Trait.html'
 }
index 1c3727a5748e63dfd8135ded14a0c32393b516e4..6d450a625d0bfa9a47e32f24482ceed7e12470f9 100644 (file)
@@ -4,7 +4,7 @@
 pub struct Bounded<T: Clone>(T);
 
 // @has traits_in_bodies/struct.SomeStruct.html
-// @has - '//code' 'impl Clone for SomeStruct'
+// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct'
 pub struct SomeStruct;
 
 fn asdf() -> Bounded<SomeStruct> {
@@ -18,7 +18,7 @@ fn clone(&self) -> SomeStruct {
 }
 
 // @has traits_in_bodies/struct.Point.html
-// @has - '//code' 'impl Copy for Point'
+// @has - '//h3[@class="code-header in-band"]' 'impl Copy for Point'
 #[derive(Clone)]
 pub struct Point {
     x: i32,
@@ -31,7 +31,7 @@ impl Copy for Point {}
 };
 
 // @has traits_in_bodies/struct.Inception.html
-// @has - '//code' 'impl Clone for Inception'
+// @has - '//h3[@class="code-header in-band"]' 'impl Clone for Inception'
 pub struct Inception;
 
 static _BAR: usize = {
index 479cd91a9dc6043e8971ccf755aeb39634f210c5..1fb28ee99702f7dc2eae764330cd0f291293c26c 100644 (file)
@@ -9,8 +9,8 @@ pub fn method_on_mystruct() {}
 }
 
 // @has typedef/type.MyAlias.html
-// @has - '//*[@class="impl has-srclink"]//code' 'impl MyAlias'
-// @has - '//*[@class="impl has-srclink"]//code' 'impl MyTrait for MyAlias'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyAlias'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyTrait for MyAlias'
 // @has - 'Alias docstring'
 // @has - '//*[@class="sidebar"]//*[@class="location"]' 'Type Definition MyAlias'
 // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
index beb638406c4bed54cc3683ead73f57ee53bb15ca..cd284dad390e76965c10c6b2e69f9fdcf116631d 100644 (file)
@@ -60,14 +60,14 @@ pub trait PubTrait {
     fn function();
 }
 
-// @has 'foo/struct.FooPublic.html' '//code' 'type Type'
-// @!has 'foo/struct.FooPublic.html' '//code' 'pub type Type'
+// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'type Type'
+// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub type Type'
 //
-// @has 'foo/struct.FooPublic.html' '//code' 'const CONST: usize'
-// @!has 'foo/struct.FooPublic.html' '//code' 'pub const CONST: usize'
+// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'const CONST: usize'
+// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub const CONST: usize'
 //
-// @has 'foo/struct.FooPublic.html' '//code' 'fn function()'
-// @!has 'foo/struct.FooPublic.html' '//code' 'pub fn function()'
+// @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'fn function()'
+// @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub fn function()'
 
 impl PubTrait for FooPublic {
     type Type = usize;
index f204a27d7d3c1908d0b576021f3bbe5086a45565..549cfff96cb6dc37e5c56aa7f06c99ff778e60dd 100644 (file)
@@ -11,7 +11,7 @@ pub fn charlie<C>() where C: MyTrait {}
 
 pub struct Delta<D>(D);
 
-// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//code' \
+// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 //          "impl<D> Delta<D> where D: MyTrait"
 impl<D> Delta<D> where D: MyTrait {
     pub fn delta() {}
@@ -19,17 +19,17 @@ pub fn delta() {}
 
 pub struct Echo<E>(E);
 
-// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//code' \
+// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 //          "impl<E> MyTrait for Echo<E> where E: MyTrait"
-// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
+// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
 //          "impl<E> MyTrait for Echo<E> where E: MyTrait"
 impl<E> MyTrait for Echo<E> where E: MyTrait {}
 
 pub enum Foxtrot<F> { Foxtrot1(F) }
 
-// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//code' \
+// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 //          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
-// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
+// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
 //          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
 impl<F> MyTrait for Foxtrot<F> where F: MyTrait {}
 
index 51cea4f6ba91bdd280423f180e9385b6571564eb..1f494e444846fa3555aa3e2907120090684607fc 100644 (file)
@@ -33,7 +33,7 @@ fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
                     if !cx.sess().contains_name(attrs, $attr) {
                         cx.lint(CRATE_NOT_OKAY, |lint| {
                              let msg = format!("crate is not marked with #![{}]", $attr);
-                             lint.build(&msg).set_span(krate.item.inner).emit()
+                             lint.build(&msg).set_span(krate.module().inner).emit()
                         });
                     }
                 )*
index ef5353e6d8cf1127b1a9731c4beae8635d224071..122a544e9d4699706fff947e2d274eb0a16af64d 100644 (file)
@@ -31,7 +31,7 @@ fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
         if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) {
             cx.lint(CRATE_NOT_OKAY, |lint| {
                 lint.build("crate is not marked with #![crate_okay]")
-                    .set_span(krate.item.inner)
+                    .set_span(krate.module().inner)
                     .emit()
             });
         }
index 33ab4bb967a9704135fa83e75bb38cff50417d56..77915a80a79b07713b60cd863739a309aa3be642 100644 (file)
@@ -1,18 +1,3 @@
-error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/issue-48027.rs:6:6
-   |
-LL | impl dyn Bar {}
-   |      ^^^^^^^ `Bar` cannot be made into an object
-   |
-   = help: consider moving `X` to another trait
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-48027.rs:2:11
-   |
-LL | trait Bar {
-   |       --- this trait cannot be made into an object...
-LL |     const X: usize;
-   |           ^ ...because it contains this associated `const`
-
 error[E0283]: type annotations needed
   --> $DIR/issue-48027.rs:3:32
    |
@@ -30,6 +15,21 @@ note: required by `Bar::X`
 LL |     const X: usize;
    |     ^^^^^^^^^^^^^^^
 
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/issue-48027.rs:6:6
+   |
+LL | impl dyn Bar {}
+   |      ^^^^^^^ `Bar` cannot be made into an object
+   |
+   = help: consider moving `X` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-48027.rs:2:11
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     const X: usize;
+   |           ^ ...because it contains this associated `const`
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0283.
index 73b23da5bcb66528d55385ef3179ca718852de42..7950dd3e99e29b11b14606560844698b27d16aa9 100644 (file)
@@ -29,7 +29,6 @@ impl Bar for AssocNoCopy {
 impl Thing for AssocNoCopy {
     type Out = Box<dyn Bar<Assoc: Copy>>;
     //~^ ERROR the trait bound `String: Copy` is not satisfied
-    //~| ERROR the trait bound `String: Copy` is not satisfied
 
     fn func() -> Self::Out {
         Box::new(AssocNoCopy)
index 414d74d4786d97ce6d2da284b35b21a023ca975d..0f1d35be0eb7a19c970be8f52f1de83e30c6dd7c 100644 (file)
@@ -4,12 +4,6 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
    |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
 
-error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
-   |
-LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
-   |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index e8c11a32bf7fdabb47d0fea9e4dd73725e86af4a..25e80159b0b180cf5e7080206c5a23bb56595df9 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-for-unimpl-trait.rs:10:8
+  --> $DIR/associated-types-for-unimpl-trait.rs:10:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index e3be434698ab9897ad8d5be41eda0450692cd8e7..19500f58aa6883d721d6dbd02e94220635693b2f 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `T: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-bound.rs:11:8
+  --> $DIR/associated-types-no-suitable-bound.rs:11:21
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `T`
+   |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 9dc3414e9edf0de03844b6a79aa388014848f977..0e978f20a6634237dc8ca2a383025ba0b44d3158 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:8
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index c2aed3f9de548f953162878e5ed4880a21e2e135..1ec3c05983aefdc193557b482cd82ba8f4945ebc 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:17:8
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
@@ -10,10 +13,13 @@ LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Ge
    |                                                              ^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:8
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |        ^^^^ the trait `Get` is not implemented for `(T, U)`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
 
 error: aborting due to 2 previous errors
 
index fb842d968676d40d44105519ac78342f41076a36..b6ee1ed733c3e99cc0f82f280bc964083bd170bc 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:8
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
    |
+LL | trait Get {
+   | --------- required by this bound in `Get`
+...
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |        ^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 0afa340f7a14809cc145484bc3cc109277b528b2..853705dae09f2d4c75b65e55a17cc1f92b888a13 100644 (file)
@@ -14,31 +14,31 @@ LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
              <&T as Clone>
 
 error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:16:14
+  --> $DIR/hr-associated-type-bound-param-2.rs:4:8
    |
 LL | trait Z<'a, T: ?Sized>
    |       - required by a bound in this
+LL | where
+LL |     T: Z<'a, u16>,
+   |        ^^^^^^^^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
 ...
 LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ----- required by this bound in `Z`
-...
-LL |     type W = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
    |
    = help: the following implementations were found:
              <&T as Clone>
 
 error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:4:8
+  --> $DIR/hr-associated-type-bound-param-2.rs:16:14
    |
 LL | trait Z<'a, T: ?Sized>
    |       - required by a bound in this
-LL | where
-LL |     T: Z<'a, u16>,
-   |        ^^^^^^^^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
 ...
 LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ----- required by this bound in `Z`
+...
+LL |     type W = str;
+   |              ^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
    |
    = help: the following implementations were found:
              <&T as Clone>
index 1270cd6706aef85ffd6c3c696c76e2c58802ba01..bad736b64c038122dc7988cae58fb89600e997c7 100644 (file)
@@ -11,7 +11,7 @@ fn bug(item: &Self::Item) -> () {
 }
 
 impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-    //~^ ERROR the trait bound `<T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
+    //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
     type Item = T;
     //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref
 }
index cf4ec0babfc219a04b89a9b2bdc0af659c068e4b..49fad4e1b1cb80e975cd9bad2e36fd1c8d9a9eb7 100644 (file)
@@ -14,16 +14,16 @@ LL |     type Item = T;
              <&T as Deref>
              <&mut T as Deref>
 
-error[E0277]: the trait bound `<T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
+error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
   --> $DIR/hr-associated-type-projection-1.rs:13:33
    |
 LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-   |                                 ^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
+   |                                 ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
    |
 help: consider further restricting the associated type
    |
-LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where <T as UnsafeCopy<'b, T>>::Item: Deref {
-   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref {
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/issue-87261.rs b/src/test/ui/associated-types/issue-87261.rs
new file mode 100644 (file)
index 0000000..a70f771
--- /dev/null
@@ -0,0 +1,99 @@
+trait Foo {}
+
+trait Trait {
+    type Associated;
+}
+trait DerivedTrait: Trait {}
+trait GenericTrait<A> {
+    type Associated;
+}
+
+struct Impl;
+impl Foo for Impl {}
+impl Trait for Impl {
+    type Associated = ();
+}
+impl DerivedTrait for Impl {}
+impl<A> GenericTrait<A> for Impl {
+    type Associated = ();
+}
+
+fn returns_opaque() -> impl Trait + 'static {
+    Impl
+}
+fn returns_opaque_derived() -> impl DerivedTrait + 'static {
+    Impl
+}
+fn returns_opaque_foo() -> impl Trait + Foo {
+    Impl
+}
+fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo {
+    Impl
+}
+fn returns_opaque_generic() -> impl GenericTrait<()> + 'static {
+    Impl
+}
+fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo {
+    Impl
+}
+fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait<u8> {
+    Impl
+}
+
+fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+
+fn check_generics<A, B, C, D, E, F, G>(a: A, b: B, c: C, d: D, e: E, f: F, g: G)
+where
+    A: Trait + 'static,
+    B: DerivedTrait + 'static,
+    C: Trait + Foo,
+    D: DerivedTrait + Foo,
+    E: GenericTrait<()> + 'static,
+    F: GenericTrait<()> + Foo,
+    G: GenericTrait<()> + GenericTrait<u8>,
+{
+    accepts_trait(a);
+    //~^ ERROR type mismatch resolving `<A as Trait>::Associated == ()`
+
+    accepts_trait(b);
+    //~^ ERROR type mismatch resolving `<B as Trait>::Associated == ()`
+
+    accepts_trait(c);
+    //~^ ERROR type mismatch resolving `<C as Trait>::Associated == ()`
+
+    accepts_trait(d);
+    //~^ ERROR type mismatch resolving `<D as Trait>::Associated == ()`
+
+    accepts_generic_trait(e);
+    //~^ ERROR type mismatch resolving `<E as GenericTrait<()>>::Associated == ()`
+
+    accepts_generic_trait(f);
+    //~^ ERROR type mismatch resolving `<F as GenericTrait<()>>::Associated == ()`
+
+    accepts_generic_trait(g);
+    //~^ ERROR type mismatch resolving `<G as GenericTrait<()>>::Associated == ()`
+}
+
+fn main() {
+    accepts_trait(returns_opaque());
+    //~^ ERROR type mismatch resolving `<impl Trait as Trait>::Associated == ()`
+
+    accepts_trait(returns_opaque_derived());
+    //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
+
+    accepts_trait(returns_opaque_foo());
+    //~^ ERROR type mismatch resolving `<impl Trait+Foo as Trait>::Associated == ()`
+
+    accepts_trait(returns_opaque_derived_foo());
+    //~^ ERROR type mismatch resolving `<impl DerivedTrait+Foo as Trait>::Associated == ()`
+
+    accepts_generic_trait(returns_opaque_generic());
+    //~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
+
+    accepts_generic_trait(returns_opaque_generic_foo());
+    //~^ ERROR type mismatch resolving `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated == ()`
+
+    accepts_generic_trait(returns_opaque_generic_duplicate());
+    //~^ ERROR type mismatch resolving `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
+}
diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr
new file mode 100644 (file)
index 0000000..0725acf
--- /dev/null
@@ -0,0 +1,238 @@
+error[E0271]: type mismatch resolving `<A as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:56:5
+   |
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(a);
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<A as Trait>::Associated`
+help: consider constraining the associated type `<A as Trait>::Associated` to `()`
+   |
+LL |     A: Trait<Associated = ()> + 'static,
+   |             ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<B as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:59:5
+   |
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(b);
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<B as Trait>::Associated`
+   = help: consider constraining the associated type `<B as Trait>::Associated` to `()`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `<C as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:62:5
+   |
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(c);
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<C as Trait>::Associated`
+help: consider constraining the associated type `<C as Trait>::Associated` to `()`
+   |
+LL |     C: Trait<Associated = ()> + Foo,
+   |             ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<D as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:65:5
+   |
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(d);
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<D as Trait>::Associated`
+   = help: consider constraining the associated type `<D as Trait>::Associated` to `()`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `<E as GenericTrait<()>>::Associated == ()`
+  --> $DIR/issue-87261.rs:68:5
+   |
+LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+   |                                              --------------- required by this bound in `accepts_generic_trait`
+...
+LL |     accepts_generic_trait(e);
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<E as GenericTrait<()>>::Associated`
+help: consider constraining the associated type `<E as GenericTrait<()>>::Associated` to `()`
+   |
+LL |     E: GenericTrait<(), Associated = ()> + 'static,
+   |                       ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<F as GenericTrait<()>>::Associated == ()`
+  --> $DIR/issue-87261.rs:71:5
+   |
+LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+   |                                              --------------- required by this bound in `accepts_generic_trait`
+...
+LL |     accepts_generic_trait(f);
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<F as GenericTrait<()>>::Associated`
+help: consider constraining the associated type `<F as GenericTrait<()>>::Associated` to `()`
+   |
+LL |     F: GenericTrait<(), Associated = ()> + Foo,
+   |                       ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<G as GenericTrait<()>>::Associated == ()`
+  --> $DIR/issue-87261.rs:74:5
+   |
+LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+   |                                              --------------- required by this bound in `accepts_generic_trait`
+...
+LL |     accepts_generic_trait(g);
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<G as GenericTrait<()>>::Associated`
+   = help: consider constraining the associated type `<G as GenericTrait<()>>::Associated` to `()`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `<impl Trait as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:79:5
+   |
+LL | fn returns_opaque() -> impl Trait + 'static {
+   |                        -------------------- the found opaque type
+...
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(returns_opaque());
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl Trait as Trait>::Associated`
+help: consider constraining the associated type `<impl Trait as Trait>::Associated` to `()`
+   |
+LL | fn returns_opaque() -> impl Trait<Associated = ()> + 'static {
+   |                                  ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:82:5
+   |
+LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static {
+   |                                --------------------------- the found opaque type
+...
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(returns_opaque_derived());
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl DerivedTrait as Trait>::Associated`
+help: consider constraining the associated type `<impl DerivedTrait as Trait>::Associated` to `()`
+   |
+LL | fn returns_opaque_derived() -> impl DerivedTrait<Associated = ()> + 'static {
+   |                                                 ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<impl Trait+Foo as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:85:5
+   |
+LL | fn returns_opaque_foo() -> impl Trait + Foo {
+   |                            ---------------- the found opaque type
+...
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(returns_opaque_foo());
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl Trait+Foo as Trait>::Associated`
+help: consider constraining the associated type `<impl Trait+Foo as Trait>::Associated` to `()`
+   |
+LL | fn returns_opaque_foo() -> impl Trait<Associated = ()> + Foo {
+   |                                      ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<impl DerivedTrait+Foo as Trait>::Associated == ()`
+  --> $DIR/issue-87261.rs:88:5
+   |
+LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo {
+   |                                    ----------------------- the found opaque type
+...
+LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
+   |                           --------------- required by this bound in `accepts_trait`
+...
+LL |     accepts_trait(returns_opaque_derived_foo());
+   |     ^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl DerivedTrait+Foo as Trait>::Associated`
+   = help: consider constraining the associated type `<impl DerivedTrait+Foo as Trait>::Associated` to `()`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0271]: type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
+  --> $DIR/issue-87261.rs:91:5
+   |
+LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static {
+   |                                ------------------------------- the found opaque type
+...
+LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+   |                                              --------------- required by this bound in `accepts_generic_trait`
+...
+LL |     accepts_generic_trait(returns_opaque_generic());
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl GenericTrait<()> as GenericTrait<()>>::Associated`
+help: consider constraining the associated type `<impl GenericTrait<()> as GenericTrait<()>>::Associated` to `()`
+   |
+LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static {
+   |                                                    ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated == ()`
+  --> $DIR/issue-87261.rs:94:5
+   |
+LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo {
+   |                                    --------------------------- the found opaque type
+...
+LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+   |                                              --------------- required by this bound in `accepts_generic_trait`
+...
+LL |     accepts_generic_trait(returns_opaque_generic_foo());
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated`
+help: consider constraining the associated type `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated` to `()`
+   |
+LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo {
+   |                                                        ^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated == ()`
+  --> $DIR/issue-87261.rs:97:5
+   |
+LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait<u8> {
+   |                                          ---------------------------------------- the found opaque type
+...
+LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
+   |                                              --------------- required by this bound in `accepts_generic_trait`
+...
+LL |     accepts_generic_trait(returns_opaque_generic_duplicate());
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated`
+   = help: consider constraining the associated type `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated` to `()`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/async-await/issue-86507.rs b/src/test/ui/async-await/issue-86507.rs
new file mode 100644 (file)
index 0000000..317f031
--- /dev/null
@@ -0,0 +1,25 @@
+// edition:2018
+
+use ::core::pin::Pin;
+use ::core::future::Future;
+use ::core::marker::Send;
+
+trait Foo {
+    fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+        -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
+        where 'me: 'async_trait;
+}
+
+impl Foo for () {
+    fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+        -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
+        where 'me:'async_trait {
+            Box::pin( //~ ERROR future cannot be sent between threads safely
+                async move {
+                    let x = x;
+                }
+            )
+         }
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr
new file mode 100644 (file)
index 0000000..51e8f61
--- /dev/null
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+  --> $DIR/issue-86507.rs:17:13
+   |
+LL | /             Box::pin(
+LL | |                 async move {
+LL | |                     let x = x;
+LL | |                 }
+LL | |             )
+   | |_____________^ future created by async block is not `Send`
+   |
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+  --> $DIR/issue-86507.rs:19:29
+   |
+LL |                     let x = x;
+   |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
+   = note: required for the cast to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting type parameter `T`
+   |
+LL |         where 'me:'async_trait, T: std::marker::Sync {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/large_moves.attribute.stderr b/src/test/ui/async-await/large_moves.attribute.stderr
new file mode 100644 (file)
index 0000000..39b7e7c
--- /dev/null
@@ -0,0 +1,38 @@
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:12:13
+   |
+LL |       let x = async {
+   |  _____________^
+LL | |         let y = [0; 9999];
+LL | |         dbg!(y);
+LL | |         thing(&y).await;
+LL | |         dbg!(y);
+LL | |     };
+   | |_____^ value moved from here
+   |
+note: the lint level is defined here
+  --> $DIR/large_moves.rs:1:9
+   |
+LL | #![deny(large_assignments)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:18:14
+   |
+LL |     let z = (x, 42);
+   |              ^ value moved from here
+
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:18:13
+   |
+LL |     let z = (x, 42);
+   |             ^^^^^^^ value moved from here
+
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:20:13
+   |
+LL |     let a = z.0;
+   |             ^^^ value moved from here
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/async-await/large_moves.option.stderr b/src/test/ui/async-await/large_moves.option.stderr
new file mode 100644 (file)
index 0000000..39b7e7c
--- /dev/null
@@ -0,0 +1,38 @@
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:12:13
+   |
+LL |       let x = async {
+   |  _____________^
+LL | |         let y = [0; 9999];
+LL | |         dbg!(y);
+LL | |         thing(&y).await;
+LL | |         dbg!(y);
+LL | |     };
+   | |_____^ value moved from here
+   |
+note: the lint level is defined here
+  --> $DIR/large_moves.rs:1:9
+   |
+LL | #![deny(large_assignments)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:18:14
+   |
+LL |     let z = (x, 42);
+   |              ^ value moved from here
+
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:18:13
+   |
+LL |     let z = (x, 42);
+   |             ^^^^^^^ value moved from here
+
+error: moving 10024 bytes
+  --> $DIR/large_moves.rs:20:13
+   |
+LL |     let a = z.0;
+   |             ^^^ value moved from here
+
+error: aborting due to 4 previous errors
+
index 4fac046beef62367aa124ef2d81bc9ace2b1f569..18bb538a81eb1390014c584aa6a96a4c8b813703 100644 (file)
@@ -1,8 +1,10 @@
 #![deny(large_assignments)]
 #![feature(large_assignments)]
-#![move_size_limit = "1000"]
+#![cfg_attr(attribute, move_size_limit = "1000")]
 // build-fail
 // only-x86_64
+// revisions: attribute option
+// [option]compile-flags: -Zmove-size-limit=1000
 
 // edition:2018
 
diff --git a/src/test/ui/async-await/large_moves.stderr b/src/test/ui/async-await/large_moves.stderr
deleted file mode 100644 (file)
index 8c47ec0..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-error: moving 10024 bytes
-  --> $DIR/large_moves.rs:10:13
-   |
-LL |       let x = async {
-   |  _____________^
-LL | |         let y = [0; 9999];
-LL | |         dbg!(y);
-LL | |         thing(&y).await;
-LL | |         dbg!(y);
-LL | |     };
-   | |_____^ value moved from here
-   |
-note: the lint level is defined here
-  --> $DIR/large_moves.rs:1:9
-   |
-LL | #![deny(large_assignments)]
-   |         ^^^^^^^^^^^^^^^^^
-
-error: moving 10024 bytes
-  --> $DIR/large_moves.rs:16:14
-   |
-LL |     let z = (x, 42);
-   |              ^ value moved from here
-
-error: moving 10024 bytes
-  --> $DIR/large_moves.rs:16:13
-   |
-LL |     let z = (x, 42);
-   |             ^^^^^^^ value moved from here
-
-error: moving 10024 bytes
-  --> $DIR/large_moves.rs:18:13
-   |
-LL |     let a = z.0;
-   |             ^^^ value moved from here
-
-error: aborting due to 4 previous errors
-
index eed90772d29e39e4485f362f2b39082a3c9e1d88..b6841da1f0ba9b0690a7b0c34f8a34faf66efe14 100644 (file)
@@ -1,15 +1,11 @@
 error: lifetime may not live long enough
-  --> $DIR/ret-impl-trait-one.rs:10:80
+  --> $DIR/ret-impl-trait-one.rs:10:65
    |
-LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |  ________________________________--__--__________________________________________^
-   | |                                |   |
-   | |                                |   lifetime `'b` defined here
-   | |                                lifetime `'a` defined here
-LL | |
-LL | |     (a, b)
-LL | | }
-   | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |                                --  --                           ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
+   |                                |   |
+   |                                |   lifetime `'b` defined here
+   |                                lifetime `'a` defined here
    |
    = help: consider adding the following bound: `'b: 'a`
 
index d9ca7ddc7cab731c95b4949ad2dc8f3a4c54462f..233ddbbe11784694a672bd1c1575638e7f353141 100644 (file)
 //
 // My heart aches in sorrow, for I know I am defeated. Let this be a warning
 // to all those who come after. Here stands the bastion of the Turbofish.
+//
+// RIP Anna Harren, Guardian Angel of the Hallowed Turbofish. <3
 
 // See https://github.com/rust-lang/rust/pull/53562
 // and https://github.com/rust-lang/rfcs/pull/2527
+// and https://twitter.com/garblefart/status/1393236602856611843
 // for context.
 
 fn main() {
index 2839a65deaa4bd4dd0c477cbb245feb0c346bda5..baf31bd89f40aa32205010d8c65bb678c72ed917 100644 (file)
@@ -1,5 +1,4 @@
 // Tests using a combination of pattern features has the expected borrow checking behavior
-#![feature(bindings_after_at)]
 #![feature(box_patterns)]
 
 enum Test {
index 2204dcabc9e474f5f5a5249926efc79df63c52f7..d4f81930843bfa5f52786449030dc0bc6fc2e393 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:37:9
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:36:9
    |
 LL |         ref foo @ [.., ref mut bar] => (),
    |         -------^^^^^^^^-----------^
@@ -8,7 +8,7 @@ LL |         ref foo @ [.., ref mut bar] => (),
    |         immutable borrow, by `foo`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:121:9
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9
    |
 LL |         ref foo @ Some(box ref mut s) => (),
    |         -------^^^^^^^^^^^^---------^
@@ -17,7 +17,7 @@ LL |         ref foo @ Some(box ref mut s) => (),
    |         immutable borrow, by `foo`, occurs here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:19:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:18:5
    |
 LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
    |                                                  - move occurs because `x` has type `[String; 4]`, which does not implement the `Copy` trait
@@ -29,7 +29,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:29:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:28:5
    |
 LL |         ref mut foo @ [.., _] => Some(foo),
    |         --------------------- mutable borrow occurs here
@@ -41,7 +41,7 @@ LL |     drop(r);
    |          - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:51:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:50:5
    |
 LL |         [ref foo @ .., ref bar] => Some(foo),
    |          ------------ immutable borrow occurs here
@@ -53,7 +53,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:63:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:62:5
    |
 LL |         ref foo @ [.., ref bar] => Some(foo),
    |         ----------------------- immutable borrow occurs here
@@ -65,7 +65,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:77:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:76:5
    |
 LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
    |                                       - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait
@@ -80,7 +80,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:87:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:86:5
    |
 LL |         ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
    |         ------------------------------------- immutable borrow occurs here
@@ -92,7 +92,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:99:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:98:5
    |
 LL |         ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
    |         ----------------------------------------- mutable borrow occurs here
@@ -104,7 +104,7 @@ LL |     drop(r);
    |          - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:113:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:112:5
    |
 LL |         ref foo @ Some(box ref s) => Some(foo),
    |         ------------------------- immutable borrow occurs here
@@ -116,7 +116,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:135:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:134:5
    |
 LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
    |                                                       - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait
@@ -131,7 +131,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:145:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:144:5
    |
 LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
    |         ------------------------------------------------- immutable borrow occurs here
@@ -143,7 +143,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:157:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:156:5
    |
 LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
    |                  ---------- immutable borrow occurs here
@@ -155,7 +155,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:171:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:170:5
    |
 LL |         [_, ref a @ Some(box ref b), ..] => Some(a),
    |             ----------------------- immutable borrow occurs here
@@ -167,7 +167,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:187:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:186:5
    |
 LL |         [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
    |             ------------------------------------------- immutable borrow occurs here
@@ -179,7 +179,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:201:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:200:5
    |
 LL |         [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
    |             ----------------------------------------------- mutable borrow occurs here
@@ -191,7 +191,7 @@ LL |     drop(r);
    |          - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:215:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:214:5
    |
 LL |         ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
    |         ------------------------------------------------------------ immutable borrow occurs here
index dfa3a561ec7ee1b9968635620b200094a89407a6..050d702b625ab4f4a49121ec609251f563d300cd 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // pretty-expanded FIXME #23616
-#![allow(dead_code)]
 
 pub fn main() {
     struct A {
index 1a5f7434fe2bb2173d8183a060bfa7d8790033cd..2b1ab2f705057cc4da4c307cbc9e9f1cfd95d702 100644 (file)
@@ -12,4 +12,18 @@ fn main() {
     *r = 0;
     //~^ ERROR cannot assign to `*r`, which is behind a `&` reference
     //~| NOTE `r` is a `&` reference, so the data it refers to cannot be written
+
+    #[rustfmt::skip]
+    let x: &usize = &mut{0};
+    //~^ HELP consider changing this to be a mutable reference
+    *x = 1;
+    //~^ ERROR cannot assign to `*x`, which is behind a `&` reference
+    //~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
+
+    #[rustfmt::skip]
+    let y: &usize = &mut(0);
+    //~^ HELP consider changing this to be a mutable reference
+    *y = 1;
+    //~^ ERROR cannot assign to `*y`, which is behind a `&` reference
+    //~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
 }
index 4da4c8f59466666baa5f47b4094fd9296aea4abb..af83c6ea6d903a9e259f0457d9b80586f63f6f5f 100644 (file)
@@ -16,7 +16,25 @@ LL |
 LL |     *r = 0;
    |     ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written
 
-error: aborting due to 2 previous errors
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
+  --> $DIR/issue-85765.rs:19:5
+   |
+LL |     let x: &usize = &mut{0};
+   |         - help: consider changing this to be a mutable reference: `&mut usize`
+LL |
+LL |     *x = 1;
+   |     ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*y`, which is behind a `&` reference
+  --> $DIR/issue-85765.rs:26:5
+   |
+LL |     let y: &usize = &mut(0);
+   |         - help: consider changing this to be a mutable reference: `&mut usize`
+LL |
+LL |     *y = 1;
+   |     ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0594, E0596.
 For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87378.rs b/src/test/ui/closures/2229_closure_analysis/issue-87378.rs
new file mode 100644 (file)
index 0000000..75901a5
--- /dev/null
@@ -0,0 +1,26 @@
+#![feature(rustc_attrs)]
+
+// edition:2021
+
+// Test that any precise capture on a union is truncated because it's unsafe to do so.
+
+union Union {
+    value: u64,
+}
+
+fn main() {
+    let u = Union { value: 42 };
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    || {
+    //~^ ERROR: First Pass analysis includes:
+    //~| ERROR: Min Capture analysis includes:
+       unsafe { u.value }
+        //~^ NOTE: Capturing u[(0, 0)] -> ImmBorrow
+        //~| NOTE: Min Capture u[] -> ImmBorrow
+    };
+
+    c();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87378.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87378.stderr
new file mode 100644 (file)
index 0000000..16c3f7c
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/issue-87378.rs:14:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+  --> $DIR/issue-87378.rs:17:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |        unsafe { u.value }
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Capturing u[(0, 0)] -> ImmBorrow
+  --> $DIR/issue-87378.rs:20:17
+   |
+LL |        unsafe { u.value }
+   |                 ^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/issue-87378.rs:17:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |        unsafe { u.value }
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Min Capture u[] -> ImmBorrow
+  --> $DIR/issue-87378.rs:20:17
+   |
+LL |        unsafe { u.value }
+   |                 ^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs
new file mode 100644 (file)
index 0000000..c64475f
--- /dev/null
@@ -0,0 +1,16 @@
+// edition:2021
+// check-pass
+
+union Union {
+    value: u64,
+}
+
+fn main() {
+    let u = Union { value: 42 };
+
+    let c = || {
+       unsafe { u.value }
+    };
+
+    c();
+}
index 72ef5b3b962c734d5386c07b0796aca96c57007b..ffe0bce6f0fd8b01d0c079e221c4ba9e3092a07e 100644 (file)
@@ -5,7 +5,7 @@ LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
    |     ^^------^
    |     | |
    |     | found signature of `fn(u16) -> _`
-   |     expected signature of `fn(<u32 as T<'x>>::V) -> _`
+   |     expected signature of `for<'x> fn(<u32 as T<'x>>::V) -> _`
    |
    = note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)`
 
index 7dabd97b94e823d93462b0cc5c8b61ff4789cddf..cfcef9699f3721f7c91af8e607cb7eaa414168bc 100644 (file)
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
+error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(for<'r> fn(&'r ()))`
   --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
    |
 LL | impl Trait for for<'r> fn(fn(&'r ())) {}
    | ------------------------------------- first implementation here
 LL | impl<'a> Trait for fn(fn(&'a ())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(for<'r> fn(&'r ()))`
    |
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/auxiliary/impl-const.rs
deleted file mode 100644 (file)
index 4a6b578..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct Num<const N: usize>;
-
-// Braces around const expression causes crash
-impl Num<{5}> {
-    pub fn five(&self) {
-    }
-}
index 48d33a785aead0e12ce56e04081b063fbbcab319..613918f78f36c84364310452a6847dbf15d1756c 100644 (file)
@@ -47,28 +47,28 @@ LL | impl<const N: &u8> A<N> {
    = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:23:15
+  --> $DIR/const-param-elided-lifetime.rs:18:21
    |
-LL | impl<const N: &u8> B for A<N> {}
-   |               ^^^
+LL |     fn foo<const M: &u8>(&self) {}
+   |                     ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:27:17
+  --> $DIR/const-param-elided-lifetime.rs:23:15
    |
-LL | fn bar<const N: &u8>() {}
-   |                 ^^^
+LL | impl<const N: &u8> B for A<N> {}
+   |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:18:21
+  --> $DIR/const-param-elided-lifetime.rs:27:17
    |
-LL |     fn foo<const M: &u8>(&self) {}
-   |                     ^^^
+LL | fn bar<const N: &u8>() {}
+   |                 ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: more complex types are supported with `#![feature(const_generics)]`
index e0e6029252c00b3471084c478d037e1e4e86f45e..319e6c2c032a0e067bf9fd2009cfe3416fbc63f9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/object-safety-err-ret.rs:17:15
+  --> $DIR/object-safety-err-ret.rs:17:16
    |
 LL | fn use_dyn(v: &dyn Foo) {
-   |               ^^^^^^^^ `Foo` cannot be made into an object
+   |                ^^^^^^^ `Foo` cannot be made into an object
    |
    = help: consider moving `test` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/const-generics/defaults/cec-concrete-default.rs b/src/test/ui/const-generics/defaults/cec-concrete-default.rs
new file mode 100644 (file)
index 0000000..c2a41cf
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+fn no_constraining() -> Foo<10> {
+    Foo::<10, 11>
+}
+
+pub fn different_than_default() -> Foo<10> {
+    Foo::<10, 12>
+    //~^ error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/cec-concrete-default.stderr b/src/test/ui/const-generics/defaults/cec-concrete-default.stderr
new file mode 100644 (file)
index 0000000..090e507
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/cec-concrete-default.rs:10:5
+   |
+LL |     Foo::<10, 12>
+   |     ^^^^^^^^^^^^^ expected `11_usize`, found `12_usize`
+   |
+   = note: expected type `11_usize`
+              found type `12_usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.rs b/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.rs
new file mode 100644 (file)
index 0000000..15822df
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+fn should_unify<const N: usize>() -> Foo<N> where [(); { N + 1 }]: {
+    Foo::<N, { N + 1 }>
+}
+pub fn shouldnt_unify<const N: usize>() -> Foo<N>
+where
+    [(); { N + 1 }]:,
+    [(); { N + 2 }]:, {
+    Foo::<N, { N + 2 }>
+    //~^ error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.stderr b/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.stderr
new file mode 100644 (file)
index 0000000..f97fc26
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/cec-generic-default-mismatched-types.rs:12:5
+   |
+LL |     Foo::<N, { N + 2 }>
+   |     ^^^^^^^^^^^^^^^^^^^ expected `{ N + 1 }`, found `{ N + 2 }`
+   |
+   = note: expected type `{ N + 1 }`
+              found type `{ N + 2 }`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default.rs b/src/test/ui/const-generics/defaults/cec-generic-default.rs
new file mode 100644 (file)
index 0000000..76ff7c7
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(const_evaluatable_checked, const_generics, const_generics_defaults)]
+#![allow(incomplete_features)]
+
+pub struct Foo<const N: usize, const M: usize = { N + 1 }>;
+pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
+    //~^ error: unconstrained generic constant
+    loop {}
+}
+pub fn has_evaluatable_bound<const N1: usize>() -> Foo<N1> where [(); N1 + 1]: {
+    loop {}
+}
+
+type FooAlias<const N: usize, const NP: usize = { N + 1 }> = [(); NP];
+fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
+{
+    //~^^ error: unconstrained generic constant
+    todo!()
+}
+fn has_evaluatable_bound_alias<const N: usize>() -> FooAlias<N>
+where [(); N + 1]: {
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default.stderr b/src/test/ui/const-generics/defaults/cec-generic-default.stderr
new file mode 100644 (file)
index 0000000..0234ea8
--- /dev/null
@@ -0,0 +1,18 @@
+error: unconstrained generic constant
+  --> $DIR/cec-generic-default.rs:5:54
+   |
+LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
+   |                                                      ^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
+
+error: unconstrained generic constant
+  --> $DIR/cec-generic-default.rs:14:58
+   |
+LL | fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
+   |                                                          ^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr
deleted file mode 100644 (file)
index 56deec1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:6:40
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                        ^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:11:24
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                        ^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr
deleted file mode 100644 (file)
index 36a0a37..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61522-array-len-succ.rs:6:45
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                             ^^^^^ cannot perform const operation using `COUNT`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61522-array-len-succ.rs:11:30
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                              ^^^^^ cannot perform const operation using `COUNT`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issue-61522-array-len-succ.rs
deleted file mode 100644 (file)
index d4a948b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used
-
-impl<const COUNT: usize> MyArray<COUNT> {
-    fn inner(&self) -> &[u8; COUNT + 1] {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        //[min]~^^ ERROR generic parameters may not be used
-        &self.0
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
deleted file mode 100644 (file)
index e96b9e7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:8:25
-   |
-LL | trait Trait<const NAME: &'static str> {
-   |                         ^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs
deleted file mode 100644 (file)
index 2a741ba..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-//[full] check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-
-trait Trait<const NAME: &'static str> {
-//[min]~^ ERROR `&'static str` is forbidden
-    type Assoc;
-}
-
-impl Trait<"0"> for () {
-    type Assoc = ();
-}
-
-fn main() {
-    let _: <() as Trait<"0">>::Assoc = ();
-}
diff --git a/src/test/ui/const-generics/issue-67375.full.stderr b/src/test/ui/const-generics/issue-67375.full.stderr
deleted file mode 100644 (file)
index 0fe6527..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/issue-67375.rs:8:12
-   |
-LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(const_evaluatable_unchecked)]` 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 #76200 <https://github.com/rust-lang/rust/issues/76200>
-
-error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:6:12
-   |
-LL | struct Bug<T> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67375.min.stderr b/src/test/ui/const-generics/issue-67375.min.stderr
deleted file mode 100644 (file)
index be81fa9..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67375.rs:8:25
-   |
-LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |                         ^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:6:12
-   |
-LL | struct Bug<T> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67375.rs b/src/test/ui/const-generics/issue-67375.rs
deleted file mode 100644 (file)
index a8875b8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-struct Bug<T> {
-    //~^ ERROR parameter `T` is never used
-    inner: [(); { [|_: &T| {}; 0].len() }],
-    //[min]~^ ERROR generic parameters may not be used in const operations
-    //[full]~^^ WARN cannot use constants which depend on generic parameters in types
-    //[full]~^^^ WARN this was previously accepted by the compiler
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-67945-1.full.stderr b/src/test/ui/const-generics/issue-67945-1.full.stderr
deleted file mode 100644 (file)
index 63c50b5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-67945-1.rs:13:20
-   |
-LL | struct Bug<S> {
-   |            - this type parameter
-...
-LL |         let x: S = MaybeUninit::uninit();
-   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
-   |                |
-   |                expected due to this
-   |
-   = note: expected type parameter `S`
-                       found union `MaybeUninit<_>`
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:10:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issue-67945-1.min.stderr b/src/test/ui/const-generics/issue-67945-1.min.stderr
deleted file mode 100644 (file)
index 074d36c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-1.rs:13:16
-   |
-LL |         let x: S = MaybeUninit::uninit();
-   |                ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-1.rs:16:45
-   |
-LL |         let b = &*(&x as *const _ as *const S);
-   |                                             ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:10:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67945-1.rs b/src/test/ui/const-generics/issue-67945-1.rs
deleted file mode 100644 (file)
index 84737e4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-use std::marker::PhantomData;
-
-use std::mem::{self, MaybeUninit};
-
-struct Bug<S> {
-    //~^ ERROR parameter `S` is never used
-    A: [(); {
-        let x: S = MaybeUninit::uninit();
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        //[full]~^^ ERROR mismatched types
-        let b = &*(&x as *const _ as *const S);
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        0
-    }],
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-67945-2.full.stderr b/src/test/ui/const-generics/issue-67945-2.full.stderr
deleted file mode 100644 (file)
index b900406..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-67945-2.rs:11:20
-   |
-LL | struct Bug<S> {
-   |            - this type parameter
-...
-LL |         let x: S = MaybeUninit::uninit();
-   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
-   |                |
-   |                expected due to this
-   |
-   = note: expected type parameter `S`
-                       found union `MaybeUninit<_>`
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-2.rs:8:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issue-67945-2.min.stderr b/src/test/ui/const-generics/issue-67945-2.min.stderr
deleted file mode 100644 (file)
index c06df79..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-2.rs:11:16
-   |
-LL |         let x: S = MaybeUninit::uninit();
-   |                ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-2.rs:14:45
-   |
-LL |         let b = &*(&x as *const _ as *const S);
-   |                                             ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-2.rs:8:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issue-67945-2.rs b/src/test/ui/const-generics/issue-67945-2.rs
deleted file mode 100644 (file)
index 4a46786..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-use std::mem::MaybeUninit;
-
-struct Bug<S> {
-    //~^ ERROR parameter `S` is never used
-    A: [(); {
-        let x: S = MaybeUninit::uninit();
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        //[full]~^^ ERROR mismatched types
-        let b = &*(&x as *const _ as *const S);
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        0
-    }],
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-67945-3.full.stderr b/src/test/ui/const-generics/issue-67945-3.full.stderr
deleted file mode 100644 (file)
index fa66252..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-67945-3.rs:7:8
-   |
-LL |       A: [(); {
-   |  ________^
-LL | |
-LL | |         let x: Option<Box<Self>> = None;
-LL | |
-LL | |         0
-LL | |     }],
-   | |______^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issue-67945-3.min.stderr b/src/test/ui/const-generics/issue-67945-3.min.stderr
deleted file mode 100644 (file)
index 5c30429..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: generic `Self` types are currently not permitted in anonymous constants
-  --> $DIR/issue-67945-3.rs:9:27
-   |
-LL |         let x: Option<Box<Self>> = None;
-   |                           ^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issue-67945-3.rs b/src/test/ui/const-generics/issue-67945-3.rs
deleted file mode 100644 (file)
index 5bad61c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-struct Bug<S: ?Sized> {
-    A: [(); {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        let x: Option<Box<Self>> = None;
-        //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants
-        0
-    }],
-    B: S
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs
deleted file mode 100644 (file)
index 43c3999..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// aux-build:impl-const.rs
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-extern crate impl_const;
-
-use impl_const::*;
-
-pub fn main() {
-    let n = Num::<5>;
-    n.five();
-}
diff --git a/src/test/ui/const-generics/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issue-70180-1-stalled_on.rs
deleted file mode 100644 (file)
index f055482..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// build-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub fn works() {
-    let array/*: [_; _]*/ = default_array();
-    let _: [_; 4] = array;
-    Foo::foo(&array);
-}
-
-pub fn didnt_work() {
-    let array/*: [_; _]*/ = default_array();
-    Foo::foo(&array);
-    let _: [_; 4] = array;
-}
-
-trait Foo {
-    fn foo(&self) {}
-}
-
-impl Foo for [i32; 4] {}
-impl Foo for [i64; 8] {}
-
-// Only needed because `[_; _]` is not valid type syntax.
-fn default_array<T, const N: usize>() -> [T; N]
-where
-    [T; N]: Default,
-{
-    Default::default()
-}
-
-fn main() {
-    works();
-    didnt_work();
-}
diff --git a/src/test/ui/const-generics/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issue-70180-2-stalled_on.rs
deleted file mode 100644 (file)
index 21cefc0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// build-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-fn works() {
-    let array/*: [u8; _]*/ = default_byte_array();
-    let _: [_; 4] = array;
-    Foo::foo(&array);
-}
-
-fn didnt_work() {
-    let array/*: [u8; _]*/ = default_byte_array();
-    Foo::foo(&array);
-    let _: [_; 4] = array;
-}
-
-trait Foo<T> {
-    fn foo(&self) {}
-}
-
-impl Foo<i32> for [u8; 4] {}
-impl Foo<i64> for [u8; 8] {}
-
-// Only needed because `[u8; _]` is not valid type syntax.
-fn default_byte_array<const N: usize>() -> [u8; N]
-where
-    [u8; N]: Default,
-{
-    Default::default()
-}
-
-fn main() {
-    works();
-    didnt_work();
-}
diff --git a/src/test/ui/const-generics/issue-71202.rs b/src/test/ui/const-generics/issue-71202.rs
deleted file mode 100644 (file)
index 78dee17..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// check-pass
-
-#![feature(const_generics)]
-#![allow(incomplete_features, const_evaluatable_unchecked)]
-
-use std::marker::PhantomData;
-
-struct DataHolder<T> {
-    item: T,
-}
-
-impl<T: Copy> DataHolder<T> {
-    const ITEM_IS_COPY: [(); 1 - {
-        trait NotCopy {
-            const VALUE: bool = false;
-        }
-
-        impl<__Type: ?Sized> NotCopy for __Type {}
-
-        struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
-
-        impl<__Type> IsCopy<__Type>
-        where
-            __Type: Sized + Copy,
-        {
-            const VALUE: bool = true;
-        }
-
-        <IsCopy<T>>::VALUE
-    } as usize] = [];
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-71986.rs b/src/test/ui/const-generics/issue-71986.rs
deleted file mode 100644 (file)
index 6bfdba5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub trait Foo<const B: bool> {}
-pub fn bar<T: Foo<{ true }>>() {}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-73899.rs b/src/test/ui/const-generics/issue-73899.rs
deleted file mode 100644 (file)
index 2a3a5ab..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-#![feature(const_evaluatable_checked)]
-#![feature(const_generics)]
-#![allow(incomplete_features)]
-
-trait Foo {}
-
-impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
-
-trait FooImpl<const IS_ZERO: bool> {}
-
-impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
-
-impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
-
-fn foo<T: Foo>(_v: T) {}
-
-fn main() {
-    foo([]);
-    foo([()]);
-}
diff --git a/src/test/ui/const-generics/issue-74906.rs b/src/test/ui/const-generics/issue-74906.rs
deleted file mode 100644 (file)
index dc3c337..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// edition:2018
-// check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-const SIZE: usize = 16;
-
-struct Bar<const H: usize> {}
-
-struct Foo<const H: usize> {}
-
-impl<const H: usize> Foo<H> {
-    async fn biz(_: &[[u8; SIZE]]) -> Vec<()> {
-        vec![]
-    }
-
-    pub async fn baz(&self) -> Bar<H> {
-        Self::biz(&vec![]).await;
-        Bar {}
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/const-generics/issue-75763.rs b/src/test/ui/const-generics/issue-75763.rs
deleted file mode 100644 (file)
index c311de0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// ignore-test
-// FIXME(const_generics): This test causes an ICE after reverting #76030.
-
-#![allow(incomplete_features)]
-#![feature(const_generics)]
-
-struct Bug<const S: &'static str>;
-
-fn main() {
-    let b: Bug::<{
-        unsafe {
-            // FIXME(const_generics): Decide on how to deal with invalid values as const params.
-            std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5])
-        }
-    }>;
-}
diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs
deleted file mode 100644 (file)
index 8f02bfb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This test is a minimized reproduction for #79518 where
-// during error handling for the type mismatch we would try
-// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
-
-trait Foo {
-    type Assoc: PartialEq;
-    const AssocInstance: Self::Assoc;
-
-    fn foo()
-    where
-        [(); std::mem::size_of::<Self::Assoc>()]: ,
-    {
-        Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-        //~^ Error: mismatched types
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr
deleted file mode 100644 (file)
index c90774e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
-   |
-LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
-   |
-   = note: expected associated type `<Self as Foo>::Assoc`
-                        found array `[(); _]`
-   = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs
deleted file mode 100644 (file)
index a34d74b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// check-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This tests that the correct `param_env` is used so that
-// attempting to normalize `Self::N` does not cause an ICE.
-
-pub struct Foo<const N: usize>;
-
-impl<const N: usize> Foo<N> {
-    pub fn foo() {}
-}
-
-pub trait Bar {
-    const N: usize;
-    fn bar()
-    where
-        [(); Self::N]: ,
-    {
-        Foo::<{ Self::N }>::foo();
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-86820.rs b/src/test/ui/const-generics/issue-86820.rs
deleted file mode 100644 (file)
index 0465040..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Regression test for the ICE described in #86820.
-
-#![allow(unused,dead_code)]
-use std::ops::BitAnd;
-
-const C: fn() = || is_set();
-fn is_set() {
-    0xffu8.bit::<0>();
-}
-
-trait Bits {
-    fn bit<const I : u8>(self) -> bool;
-    //~^ NOTE: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
-}
-
-impl Bits for u8 {
-    fn bit<const I : usize>(self) -> bool {
-    //~^ ERROR: method `bit` has an incompatible const parameter type for trait [E0053]
-        let i = 1 << I;
-        let mask = u8::from(i);
-        mask & self == mask
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-86820.stderr b/src/test/ui/const-generics/issue-86820.stderr
deleted file mode 100644 (file)
index f4396f2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0053]: method `bit` has an incompatible const parameter type for trait
-  --> $DIR/issue-86820.rs:17:18
-   |
-LL |     fn bit<const I : usize>(self) -> bool {
-   |                  ^
-   |
-note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
-  --> $DIR/issue-86820.rs:12:18
-   |
-LL |     fn bit<const I : u8>(self) -> bool;
-   |                  ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/const-generics/issues/auxiliary/impl-const.rs b/src/test/ui/const-generics/issues/auxiliary/impl-const.rs
new file mode 100644 (file)
index 0000000..4a6b578
--- /dev/null
@@ -0,0 +1,10 @@
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub struct Num<const N: usize>;
+
+// Braces around const expression causes crash
+impl Num<{5}> {
+    pub fn five(&self) {
+    }
+}
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr
new file mode 100644 (file)
index 0000000..56deec1
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-61522-array-len-succ.rs:6:40
+   |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                        ^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-61522-array-len-succ.rs:11:24
+   |
+LL |     fn inner(&self) -> &[u8; COUNT + 1] {
+   |                        ^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr
new file mode 100644 (file)
index 0000000..36a0a37
--- /dev/null
@@ -0,0 +1,20 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-61522-array-len-succ.rs:6:45
+   |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                             ^^^^^ cannot perform const operation using `COUNT`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-61522-array-len-succ.rs:11:30
+   |
+LL |     fn inner(&self) -> &[u8; COUNT + 1] {
+   |                              ^^^^^ cannot perform const operation using `COUNT`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs
new file mode 100644 (file)
index 0000000..d4a948b
--- /dev/null
@@ -0,0 +1,18 @@
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used
+
+impl<const COUNT: usize> MyArray<COUNT> {
+    fn inner(&self) -> &[u8; COUNT + 1] {
+        //[full]~^ ERROR constant expression depends on a generic parameter
+        //[min]~^^ ERROR generic parameters may not be used
+        &self.0
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr
new file mode 100644 (file)
index 0000000..e96b9e7
--- /dev/null
@@ -0,0 +1,11 @@
+error: `&'static str` is forbidden as the type of a const generic parameter
+  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:8:25
+   |
+LL | trait Trait<const NAME: &'static str> {
+   |                         ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(const_generics)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs
new file mode 100644 (file)
index 0000000..2a741ba
--- /dev/null
@@ -0,0 +1,19 @@
+//[full] check-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+
+trait Trait<const NAME: &'static str> {
+//[min]~^ ERROR `&'static str` is forbidden
+    type Assoc;
+}
+
+impl Trait<"0"> for () {
+    type Assoc = ();
+}
+
+fn main() {
+    let _: <() as Trait<"0">>::Assoc = ();
+}
diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr
new file mode 100644 (file)
index 0000000..0fe6527
--- /dev/null
@@ -0,0 +1,22 @@
+warning: cannot use constants which depend on generic parameters in types
+  --> $DIR/issue-67375.rs:8:12
+   |
+LL |     inner: [(); { [|_: &T| {}; 0].len() }],
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(const_evaluatable_unchecked)]` 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 #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-67375.rs:6:12
+   |
+LL | struct Bug<T> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67375.min.stderr b/src/test/ui/const-generics/issues/issue-67375.min.stderr
new file mode 100644 (file)
index 0000000..be81fa9
--- /dev/null
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67375.rs:8:25
+   |
+LL |     inner: [(); { [|_: &T| {}; 0].len() }],
+   |                         ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/issue-67375.rs:6:12
+   |
+LL | struct Bug<T> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67375.rs b/src/test/ui/const-generics/issues/issue-67375.rs
new file mode 100644 (file)
index 0000000..a8875b8
--- /dev/null
@@ -0,0 +1,14 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+struct Bug<T> {
+    //~^ ERROR parameter `T` is never used
+    inner: [(); { [|_: &T| {}; 0].len() }],
+    //[min]~^ ERROR generic parameters may not be used in const operations
+    //[full]~^^ WARN cannot use constants which depend on generic parameters in types
+    //[full]~^^^ WARN this was previously accepted by the compiler
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr
new file mode 100644 (file)
index 0000000..63c50b5
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-67945-1.rs:13:20
+   |
+LL | struct Bug<S> {
+   |            - this type parameter
+...
+LL |         let x: S = MaybeUninit::uninit();
+   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
+   |                |
+   |                expected due to this
+   |
+   = note: expected type parameter `S`
+                       found union `MaybeUninit<_>`
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-1.rs:10:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0392.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.min.stderr b/src/test/ui/const-generics/issues/issue-67945-1.min.stderr
new file mode 100644 (file)
index 0000000..074d36c
--- /dev/null
@@ -0,0 +1,30 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-1.rs:13:16
+   |
+LL |         let x: S = MaybeUninit::uninit();
+   |                ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-1.rs:16:45
+   |
+LL |         let b = &*(&x as *const _ as *const S);
+   |                                             ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-1.rs:10:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-1.rs b/src/test/ui/const-generics/issues/issue-67945-1.rs
new file mode 100644 (file)
index 0000000..84737e4
--- /dev/null
@@ -0,0 +1,22 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+use std::marker::PhantomData;
+
+use std::mem::{self, MaybeUninit};
+
+struct Bug<S> {
+    //~^ ERROR parameter `S` is never used
+    A: [(); {
+        let x: S = MaybeUninit::uninit();
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        //[full]~^^ ERROR mismatched types
+        let b = &*(&x as *const _ as *const S);
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        0
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
new file mode 100644 (file)
index 0000000..b900406
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-67945-2.rs:11:20
+   |
+LL | struct Bug<S> {
+   |            - this type parameter
+...
+LL |         let x: S = MaybeUninit::uninit();
+   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
+   |                |
+   |                expected due to this
+   |
+   = note: expected type parameter `S`
+                       found union `MaybeUninit<_>`
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-2.rs:8:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0392.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.min.stderr b/src/test/ui/const-generics/issues/issue-67945-2.min.stderr
new file mode 100644 (file)
index 0000000..c06df79
--- /dev/null
@@ -0,0 +1,30 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-2.rs:11:16
+   |
+LL |         let x: S = MaybeUninit::uninit();
+   |                ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-2.rs:14:45
+   |
+LL |         let b = &*(&x as *const _ as *const S);
+   |                                             ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-2.rs:8:12
+   |
+LL | struct Bug<S> {
+   |            ^ unused parameter
+   |
+   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.rs b/src/test/ui/const-generics/issues/issue-67945-2.rs
new file mode 100644 (file)
index 0000000..4a46786
--- /dev/null
@@ -0,0 +1,20 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+use std::mem::MaybeUninit;
+
+struct Bug<S> {
+    //~^ ERROR parameter `S` is never used
+    A: [(); {
+        let x: S = MaybeUninit::uninit();
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        //[full]~^^ ERROR mismatched types
+        let b = &*(&x as *const _ as *const S);
+        //[min]~^ ERROR generic parameters may not be used in const operations
+        0
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.full.stderr b/src/test/ui/const-generics/issues/issue-67945-3.full.stderr
new file mode 100644 (file)
index 0000000..fa66252
--- /dev/null
@@ -0,0 +1,16 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-67945-3.rs:7:8
+   |
+LL |       A: [(); {
+   |  ________^
+LL | |
+LL | |         let x: Option<Box<Self>> = None;
+LL | |
+LL | |         0
+LL | |     }],
+   | |______^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.min.stderr b/src/test/ui/const-generics/issues/issue-67945-3.min.stderr
new file mode 100644 (file)
index 0000000..5c30429
--- /dev/null
@@ -0,0 +1,8 @@
+error: generic `Self` types are currently not permitted in anonymous constants
+  --> $DIR/issue-67945-3.rs:9:27
+   |
+LL |         let x: Option<Box<Self>> = None;
+   |                           ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.rs b/src/test/ui/const-generics/issues/issue-67945-3.rs
new file mode 100644 (file)
index 0000000..5bad61c
--- /dev/null
@@ -0,0 +1,16 @@
+// revisions: full min
+
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics))]
+
+struct Bug<S: ?Sized> {
+    A: [(); {
+        //[full]~^ ERROR constant expression depends on a generic parameter
+        let x: Option<Box<Self>> = None;
+        //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants
+        0
+    }],
+    B: S
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs
new file mode 100644 (file)
index 0000000..43c3999
--- /dev/null
@@ -0,0 +1,15 @@
+// aux-build:impl-const.rs
+// run-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+extern crate impl_const;
+
+use impl_const::*;
+
+pub fn main() {
+    let n = Num::<5>;
+    n.five();
+}
diff --git a/src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs
new file mode 100644 (file)
index 0000000..f055482
--- /dev/null
@@ -0,0 +1,37 @@
+// build-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub fn works() {
+    let array/*: [_; _]*/ = default_array();
+    let _: [_; 4] = array;
+    Foo::foo(&array);
+}
+
+pub fn didnt_work() {
+    let array/*: [_; _]*/ = default_array();
+    Foo::foo(&array);
+    let _: [_; 4] = array;
+}
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+impl Foo for [i32; 4] {}
+impl Foo for [i64; 8] {}
+
+// Only needed because `[_; _]` is not valid type syntax.
+fn default_array<T, const N: usize>() -> [T; N]
+where
+    [T; N]: Default,
+{
+    Default::default()
+}
+
+fn main() {
+    works();
+    didnt_work();
+}
diff --git a/src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs
new file mode 100644 (file)
index 0000000..21cefc0
--- /dev/null
@@ -0,0 +1,37 @@
+// build-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+fn works() {
+    let array/*: [u8; _]*/ = default_byte_array();
+    let _: [_; 4] = array;
+    Foo::foo(&array);
+}
+
+fn didnt_work() {
+    let array/*: [u8; _]*/ = default_byte_array();
+    Foo::foo(&array);
+    let _: [_; 4] = array;
+}
+
+trait Foo<T> {
+    fn foo(&self) {}
+}
+
+impl Foo<i32> for [u8; 4] {}
+impl Foo<i64> for [u8; 8] {}
+
+// Only needed because `[u8; _]` is not valid type syntax.
+fn default_byte_array<const N: usize>() -> [u8; N]
+where
+    [u8; N]: Default,
+{
+    Default::default()
+}
+
+fn main() {
+    works();
+    didnt_work();
+}
diff --git a/src/test/ui/const-generics/issues/issue-71202.rs b/src/test/ui/const-generics/issues/issue-71202.rs
new file mode 100644 (file)
index 0000000..78dee17
--- /dev/null
@@ -0,0 +1,33 @@
+// check-pass
+
+#![feature(const_generics)]
+#![allow(incomplete_features, const_evaluatable_unchecked)]
+
+use std::marker::PhantomData;
+
+struct DataHolder<T> {
+    item: T,
+}
+
+impl<T: Copy> DataHolder<T> {
+    const ITEM_IS_COPY: [(); 1 - {
+        trait NotCopy {
+            const VALUE: bool = false;
+        }
+
+        impl<__Type: ?Sized> NotCopy for __Type {}
+
+        struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
+
+        impl<__Type> IsCopy<__Type>
+        where
+            __Type: Sized + Copy,
+        {
+            const VALUE: bool = true;
+        }
+
+        <IsCopy<T>>::VALUE
+    } as usize] = [];
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-71986.rs b/src/test/ui/const-generics/issues/issue-71986.rs
new file mode 100644 (file)
index 0000000..6bfdba5
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub trait Foo<const B: bool> {}
+pub fn bar<T: Foo<{ true }>>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-73899.rs b/src/test/ui/const-generics/issues/issue-73899.rs
new file mode 100644 (file)
index 0000000..2a3a5ab
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+#![feature(const_evaluatable_checked)]
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait Foo {}
+
+impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
+
+trait FooImpl<const IS_ZERO: bool> {}
+
+impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
+
+impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
+
+fn foo<T: Foo>(_v: T) {}
+
+fn main() {
+    foo([]);
+    foo([()]);
+}
diff --git a/src/test/ui/const-generics/issues/issue-74906.rs b/src/test/ui/const-generics/issues/issue-74906.rs
new file mode 100644 (file)
index 0000000..dc3c337
--- /dev/null
@@ -0,0 +1,24 @@
+// edition:2018
+// check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+const SIZE: usize = 16;
+
+struct Bar<const H: usize> {}
+
+struct Foo<const H: usize> {}
+
+impl<const H: usize> Foo<H> {
+    async fn biz(_: &[[u8; SIZE]]) -> Vec<()> {
+        vec![]
+    }
+
+    pub async fn baz(&self) -> Bar<H> {
+        Self::biz(&vec![]).await;
+        Bar {}
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/const-generics/issues/issue-75763.rs b/src/test/ui/const-generics/issues/issue-75763.rs
new file mode 100644 (file)
index 0000000..c311de0
--- /dev/null
@@ -0,0 +1,16 @@
+// ignore-test
+// FIXME(const_generics): This test causes an ICE after reverting #76030.
+
+#![allow(incomplete_features)]
+#![feature(const_generics)]
+
+struct Bug<const S: &'static str>;
+
+fn main() {
+    let b: Bug::<{
+        unsafe {
+            // FIXME(const_generics): Decide on how to deal with invalid values as const params.
+            std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5])
+        }
+    }>;
+}
diff --git a/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs
new file mode 100644 (file)
index 0000000..8f02bfb
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+// This test is a minimized reproduction for #79518 where
+// during error handling for the type mismatch we would try
+// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
+
+trait Foo {
+    type Assoc: PartialEq;
+    const AssocInstance: Self::Assoc;
+
+    fn foo()
+    where
+        [(); std::mem::size_of::<Self::Assoc>()]: ,
+    {
+        Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
+        //~^ Error: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr
new file mode 100644 (file)
index 0000000..c90774e
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
+   |
+LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |
+   = note: expected associated type `<Self as Foo>::Assoc`
+                        found array `[(); _]`
+   = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs
new file mode 100644 (file)
index 0000000..a34d74b
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+// This tests that the correct `param_env` is used so that
+// attempting to normalize `Self::N` does not cause an ICE.
+
+pub struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+    pub fn foo() {}
+}
+
+pub trait Bar {
+    const N: usize;
+    fn bar()
+    where
+        [(); Self::N]: ,
+    {
+        Foo::<{ Self::N }>::foo();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86820.rs b/src/test/ui/const-generics/issues/issue-86820.rs
new file mode 100644 (file)
index 0000000..0465040
--- /dev/null
@@ -0,0 +1,25 @@
+// Regression test for the ICE described in #86820.
+
+#![allow(unused,dead_code)]
+use std::ops::BitAnd;
+
+const C: fn() = || is_set();
+fn is_set() {
+    0xffu8.bit::<0>();
+}
+
+trait Bits {
+    fn bit<const I : u8>(self) -> bool;
+    //~^ NOTE: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
+}
+
+impl Bits for u8 {
+    fn bit<const I : usize>(self) -> bool {
+    //~^ ERROR: method `bit` has an incompatible const parameter type for trait [E0053]
+        let i = 1 << I;
+        let mask = u8::from(i);
+        mask & self == mask
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86820.stderr b/src/test/ui/const-generics/issues/issue-86820.stderr
new file mode 100644 (file)
index 0000000..f4396f2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0053]: method `bit` has an incompatible const parameter type for trait
+  --> $DIR/issue-86820.rs:17:18
+   |
+LL |     fn bit<const I : usize>(self) -> bool {
+   |                  ^
+   |
+note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
+  --> $DIR/issue-86820.rs:12:18
+   |
+LL |     fn bit<const I : u8>(self) -> bool;
+   |                  ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/const-generics/issues/issue-87076.rs b/src/test/ui/const-generics/issues/issue-87076.rs
new file mode 100644 (file)
index 0000000..5dfda94
--- /dev/null
@@ -0,0 +1,20 @@
+// build-pass
+
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+#[derive(PartialEq, Eq)]
+pub struct UnitDims {
+    pub time: u8,
+    pub length: u8,
+}
+
+pub struct UnitValue<const DIMS: UnitDims>;
+
+impl<const DIMS: UnitDims> UnitValue<DIMS> {
+    fn crash() {}
+}
+
+fn main() {
+    UnitValue::<{ UnitDims { time: 1, length: 2 } }>::crash();
+}
index de4ccc185608c82ebadf5dbdd65a099ece02130a..1a34c21ba541370129ee2d367550506a06ec9f14 100644 (file)
@@ -1,7 +1,6 @@
 // compile-flags: --target x86_64-unknown-uefi
 // needs-llvm-components: x86
 // rustc-env:CARGO=/usr/bin/cargo
-// rustc-env:RUSTUP_HOME=/home/bors/.rustup
 #![no_core]
 extern crate core;
 //~^ ERROR can't find crate for `core`
index e61486fdc6ffd22069596fdb3f80b9b45293b904..25808efdfa6993e94c45af96bfd0878e1598f4ad 100644 (file)
@@ -1,5 +1,5 @@
 error[E0463]: can't find crate for `core`
-  --> $DIR/missing-std.rs:6:1
+  --> $DIR/missing-std.rs:5:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ can't find crate
index 9d1644a00d0024eab79548a7af3d05551022efbd..b81aeabab7ff1b0dc483f4211acfc2fb12c01a5b 100644 (file)
@@ -16,6 +16,12 @@ error: no path from `WillChange` to `trait_def`
 LL |     #[rustc_then_this_would_need(trait_def)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:31:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:35:5
    |
@@ -46,12 +52,36 @@ error: OK
 LL |     #[rustc_then_this_would_need(type_of)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:47:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:48:9
+   |
+LL |         #[rustc_then_this_would_need(typeck)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:52:5
    |
 LL |     #[rustc_then_this_would_need(type_of)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:54:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-struct-signature.rs:55:9
+   |
+LL |         #[rustc_then_this_would_need(typeck)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:60:9
    |
@@ -76,6 +106,12 @@ error: no path from `WillChange` to `type_of`
 LL |     #[rustc_then_this_would_need(type_of)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: no path from `WillChange` to `fn_sig`
+  --> $DIR/dep-graph-struct-signature.rs:76:9
+   |
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: no path from `WillChange` to `fn_sig`
   --> $DIR/dep-graph-struct-signature.rs:80:5
    |
@@ -94,41 +130,5 @@ error: no path from `WillChange` to `typeck`
 LL |     #[rustc_then_this_would_need(typeck)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: OK
-  --> $DIR/dep-graph-struct-signature.rs:31:9
-   |
-LL |         #[rustc_then_this_would_need(fn_sig)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: no path from `WillChange` to `fn_sig`
-  --> $DIR/dep-graph-struct-signature.rs:76:9
-   |
-LL |         #[rustc_then_this_would_need(fn_sig)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: OK
-  --> $DIR/dep-graph-struct-signature.rs:47:9
-   |
-LL |         #[rustc_then_this_would_need(fn_sig)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: OK
-  --> $DIR/dep-graph-struct-signature.rs:48:9
-   |
-LL |         #[rustc_then_this_would_need(typeck)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: OK
-  --> $DIR/dep-graph-struct-signature.rs:54:9
-   |
-LL |         #[rustc_then_this_would_need(fn_sig)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: OK
-  --> $DIR/dep-graph-struct-signature.rs:55:9
-   |
-LL |         #[rustc_then_this_would_need(typeck)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 22 previous errors
 
index 9baaf746fc2107b45e1410a1c49163a9a0d80b82..e698ce8f628b4e898947fcd7db2a4fee01120dda 100644 (file)
@@ -28,12 +28,30 @@ error: no path from `TypeAlias` to `type_of`
 LL | #[rustc_then_this_would_need(type_of)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:35:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: no path from `TypeAlias` to `type_of`
   --> $DIR/dep-graph-type-alias.rs:41:1
    |
 LL | #[rustc_then_this_would_need(type_of)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:43:5
+   |
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: OK
+  --> $DIR/dep-graph-type-alias.rs:44:5
+   |
+LL |     #[rustc_then_this_would_need(typeck)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: OK
   --> $DIR/dep-graph-type-alias.rs:48:1
    |
@@ -52,23 +70,5 @@ error: OK
 LL | #[rustc_then_this_would_need(typeck)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: OK
-  --> $DIR/dep-graph-type-alias.rs:35:5
-   |
-LL |     #[rustc_then_this_would_need(fn_sig)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: OK
-  --> $DIR/dep-graph-type-alias.rs:43:5
-   |
-LL |     #[rustc_then_this_would_need(fn_sig)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: OK
-  --> $DIR/dep-graph-type-alias.rs:44:5
-   |
-LL |     #[rustc_then_this_would_need(typeck)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 12 previous errors
 
index e90ea1c55b0c1707c58f9f7b04b7f178f6259491..7bb43d5b50360467fa4ec60004e0e2428efbabae 100644 (file)
@@ -2,7 +2,6 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait)]
-#![feature(bindings_after_at)]
 
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
index eb68a6298d1ac1217a3deca57ec8d270478359df..cead9776e4abb3a4a4d96319cbc747a6d84df428 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/E0038.rs:5:16
+  --> $DIR/E0038.rs:5:20
    |
 LL | fn call_foo(x: Box<dyn Trait>) {
-   |                ^^^^^^^^^^^^^^ `Trait` cannot be made into an object
+   |                    ^^^^^^^^^ `Trait` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index a80f9befcafdcdca85bd4f4e3ac107a95967d4c6..f9c53a66c4b84a1cb63cd66661bb9e460f125059 100644 (file)
@@ -1,17 +1,17 @@
-error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
+error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18
    |
-LL |     fn bar(self: *const Self);
+LL |     fn foo(self: *const Self) {}
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
    |
-LL |     fn foo(self: *const Self) {}
+LL |     fn bar(self: *const Self);
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
index 12195bc1071a08144f9eb6851e0eb96a63a8e2d4..c13c05f146a7e676f94dadf53f7ca31eb8b773a9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39
    |
 LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
-   |                                      ^^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
+   |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23
@@ -35,10 +35,10 @@ LL |     fn static_fn() where Self: Sized {}
    |                    ^^^^^^^^^^^^^^^^^
 
 error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39
    |
 LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
+   |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index eb8e101a83d799cbae56e5eec1ac0965c47bb797..8651789688eaa75d4f850b00e1a19382a6f23eb3 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/gat-in-trait-path.rs:21:13
+  --> $DIR/gat-in-trait-path.rs:21:17
    |
 LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
    = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index 8cc9f2816a166a30e05548ba800dd156a1c899b4..b4b89ab047363ce28c2cf43558a2c455b4484b8a 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `X` cannot be made into an object
-  --> $DIR/issue-67510-pass.rs:7:19
+  --> $DIR/issue-67510-pass.rs:7:23
    |
 LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
+   |                       ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
    |
    = help: consider moving `Y` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
diff --git a/src/test/ui/generic-associated-types/issue-81487.rs b/src/test/ui/generic-associated-types/issue-81487.rs
new file mode 100644 (file)
index 0000000..7f399c4
--- /dev/null
@@ -0,0 +1,19 @@
+// build-pass
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    type Ref<'a>;
+}
+
+impl Trait for () {
+    type Ref<'a> = &'a i8;
+}
+
+struct RefRef<'a, T: Trait>(&'a <T as Trait>::Ref<'a>);
+
+fn wrap<'a, T: Trait>(reff: &'a <T as Trait>::Ref<'a>) -> RefRef<'a, T> {
+    RefRef(reff)
+}
+
+fn main() {}
index a121566bbd884be69a820ede9604e4f355d3bcd5..6429bb8159e1f9899debc6bce4e7d442e6148a3e 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `StreamingIterator` cannot be made into an object
-  --> $DIR/trait-objects.rs:10:16
+  --> $DIR/trait-objects.rs:10:21
    |
 LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
    |
    = help: consider moving `Item` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index 087f4582b21c3b3db46753486e2e479980b3444e..c2fbbf94fd66623678df17d392e4507993b2330e 100644 (file)
@@ -12,7 +12,6 @@ fn main() {
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
     send(cycle2().clone());
-    //~^ ERROR cannot be sent between threads safely
 
     Rc::new(Cell::new(5))
 }
index e578c4b4f819ee79581cbb3c1d2ec06c078b836e..3eb141cc2bb55276341e1b22549c3aa553c0fb74 100644 (file)
@@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:20:16
+  --> $DIR/auto-trait-leak.rs:19:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,22 +84,6 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error[E0277]: `Rc<String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:14:5
-   |
-LL | fn send<T: Send>(_: T) {}
-   |            ---- required by this bound in `send`
-...
-LL |     send(cycle2().clone());
-   |     ^^^^ `Rc<String>` cannot be sent between threads safely
-...
-LL | fn cycle2() -> impl Clone {
-   |                ---------- within this `impl Clone`
-   |
-   = help: within `impl Clone`, the trait `Send` is not implemented for `Rc<String>`
-   = note: required because it appears within the type `impl Clone`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0391.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs
new file mode 100644 (file)
index 0000000..23a3748
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(min_type_alias_impl_trait)]
+
+type X<'a, 'b> = impl std::fmt::Debug;
+
+fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    (a, a)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr
new file mode 100644 (file)
index 0000000..595b16a
--- /dev/null
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/issue-86465.rs:5:1
+   |
+LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32`
+   |
+note: previous use here
+  --> $DIR/issue-86465.rs:5:1
+   |
+LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issues/issue-54600.rs b/src/test/ui/impl-trait/issues/issue-54600.rs
new file mode 100644 (file)
index 0000000..7a64799
--- /dev/null
@@ -0,0 +1,7 @@
+use std::fmt::Debug;
+
+fn main() {
+    let x: Option<impl Debug> = Some(44_u32);
+    //~^ `impl Trait` not allowed outside of function and method return types
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54600.stderr b/src/test/ui/impl-trait/issues/issue-54600.stderr
new file mode 100644 (file)
index 0000000..4d0c32c
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-54600.rs:4:19
+   |
+LL |     let x: Option<impl Debug> = Some(44_u32);
+   |                   ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-54840.rs b/src/test/ui/impl-trait/issues/issue-54840.rs
new file mode 100644 (file)
index 0000000..030d571
--- /dev/null
@@ -0,0 +1,7 @@
+use std::ops::Add;
+
+fn main() {
+    let i: i32 = 0;
+    let j: &impl Add = &i;
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54840.stderr b/src/test/ui/impl-trait/issues/issue-54840.stderr
new file mode 100644 (file)
index 0000000..b8046b7
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-54840.rs:5:13
+   |
+LL |     let j: &impl Add = &i;
+   |             ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-58504.rs b/src/test/ui/impl-trait/issues/issue-58504.rs
new file mode 100644 (file)
index 0000000..aac33b3
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(generators, generator_trait, never_type)]
+
+use std::ops::Generator;
+
+fn mk_gen() -> impl Generator<Return=!, Yield=()> {
+    || { loop { yield; } }
+}
+
+fn main() {
+    let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-58504.stderr b/src/test/ui/impl-trait/issues/issue-58504.stderr
new file mode 100644 (file)
index 0000000..ff1010f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-58504.rs:10:16
+   |
+LL |     let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-58956.rs b/src/test/ui/impl-trait/issues/issue-58956.rs
new file mode 100644 (file)
index 0000000..5fe18b6
--- /dev/null
@@ -0,0 +1,14 @@
+trait Lam {}
+
+pub struct B;
+impl Lam for B {}
+pub struct Wrap<T>(T);
+
+const _A: impl Lam = {
+    //~^ `impl Trait` not allowed outside of function and method return types
+    let x: Wrap<impl Lam> = Wrap(B);
+    //~^ `impl Trait` not allowed outside of function and method return types
+    x.0
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-58956.stderr b/src/test/ui/impl-trait/issues/issue-58956.stderr
new file mode 100644 (file)
index 0000000..00ebf17
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-58956.rs:7:11
+   |
+LL | const _A: impl Lam = {
+   |           ^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-58956.rs:9:17
+   |
+LL |     let x: Wrap<impl Lam> = Wrap(B);
+   |                 ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-70971.rs b/src/test/ui/impl-trait/issues/issue-70971.rs
new file mode 100644 (file)
index 0000000..d4dc2fd
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    let x : (impl Copy,) = (true,);
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-70971.stderr b/src/test/ui/impl-trait/issues/issue-70971.stderr
new file mode 100644 (file)
index 0000000..31993da
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-70971.rs:2:14
+   |
+LL |     let x : (impl Copy,) = (true,);
+   |              ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-79099.rs b/src/test/ui/impl-trait/issues/issue-79099.rs
new file mode 100644 (file)
index 0000000..f72533d
--- /dev/null
@@ -0,0 +1,10 @@
+struct Bug {
+    V1: [(); {
+        let f: impl core::future::Future<Output = u8> = async { 1 };
+        //~^ `impl Trait` not allowed outside of function and method return types
+        //~| expected identifier
+        1
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-79099.stderr b/src/test/ui/impl-trait/issues/issue-79099.stderr
new file mode 100644 (file)
index 0000000..121536d
--- /dev/null
@@ -0,0 +1,20 @@
+error: expected identifier, found `1`
+  --> $DIR/issue-79099.rs:3:65
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |                                                         -----   ^ expected identifier
+   |                                                         |
+   |                                                         `async` blocks are only allowed in Rust 2018 or later
+   |
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-79099.rs:3:16
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-84919.rs b/src/test/ui/impl-trait/issues/issue-84919.rs
new file mode 100644 (file)
index 0000000..479bad9
--- /dev/null
@@ -0,0 +1,9 @@
+trait Trait {}
+impl Trait for () {}
+
+fn foo<'a: 'a>() {
+    let _x: impl Trait = ();
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-84919.stderr b/src/test/ui/impl-trait/issues/issue-84919.stderr
new file mode 100644 (file)
index 0000000..bb1bcfe
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-84919.rs:5:13
+   |
+LL |     let _x: impl Trait = ();
+   |             ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs
new file mode 100644 (file)
index 0000000..8dc76f4
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(unboxed_closures)]
+#![feature(min_type_alias_impl_trait)]
+
+type FunType = impl Fn<()>;
+//~^ could not find defining uses
+static STATIC_FN: FunType = some_fn;
+//~^ mismatched types
+
+fn some_fn() {}
+
+fn main() {
+    let _: <FunType as FnOnce<()>>::Output = STATIC_FN();
+}
diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr
new file mode 100644 (file)
index 0000000..b146009
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-86201.rs:6:29
+   |
+LL | type FunType = impl Fn<()>;
+   |                ----------- the expected opaque type
+LL |
+LL | static STATIC_FN: FunType = some_fn;
+   |                             ^^^^^^^ expected opaque type, found fn item
+   |
+   = note: expected opaque type `impl Fn<()>`
+                  found fn item `fn() {some_fn}`
+
+error: could not find defining uses
+  --> $DIR/issue-86201.rs:4:16
+   |
+LL | type FunType = impl Fn<()>;
+   |                ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issues/issue-86642.rs b/src/test/ui/impl-trait/issues/issue-86642.rs
new file mode 100644 (file)
index 0000000..8953ff8
--- /dev/null
@@ -0,0 +1,8 @@
+static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
+    //~^ `impl Trait` not allowed outside of function and method return types
+    let res = (move |source| Ok(source))(source);
+    let res = res.or((move |source| Ok(source))(source));
+    res
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-86642.stderr b/src/test/ui/impl-trait/issues/issue-86642.stderr
new file mode 100644 (file)
index 0000000..2fc0a6f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-86642.rs:1:11
+   |
+LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-87295.rs b/src/test/ui/impl-trait/issues/issue-87295.rs
new file mode 100644 (file)
index 0000000..2f2bfe1
--- /dev/null
@@ -0,0 +1,18 @@
+trait Trait {
+    type Output;
+}
+impl Trait for () {
+    type Output = i32;
+}
+
+struct Struct<F>(F);
+impl<F> Struct<F> {
+    pub fn new(_: F) -> Self {
+        todo!()
+    }
+}
+
+fn main() {
+    let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
+    //~^ `impl Trait` not allowed outside of function and method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-87295.stderr b/src/test/ui/impl-trait/issues/issue-87295.stderr
new file mode 100644 (file)
index 0000000..f5c7603
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/issue-87295.rs:16:31
+   |
+LL |     let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
index 8872f51753c94789fa0841a9a635e7d00c3fdfe2..0e942e80e254436dca5792928e63162bcb2811ef 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `isize: HasState` is not satisfied
-  --> $DIR/issue-18611.rs:1:4
+  --> $DIR/issue-18611.rs:1:18
    |
 LL | fn add_state(op: <isize as HasState>::State) {
-   |    ^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+...
+LL | trait HasState {
+   | -------------- required by this bound in `HasState`
 
 error: aborting due to previous error
 
index 86b530e85a80ac8091e6d411ab9d1bf7fb9d5e34..2a5416ce85ba65e78140c4a40aaa85dce68c7338 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Bar` cannot be made into an object
-  --> $DIR/issue-18959.rs:11:11
+  --> $DIR/issue-18959.rs:11:12
    |
 LL | fn foo(b: &dyn Bar) {
-   |           ^^^^^^^^ `Bar` cannot be made into an object
+   |            ^^^^^^^ `Bar` cannot be made into an object
    |
    = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
index c3a5d3dfeee7ddcfd68ce29bafba5aeef6acf117..4400b6179c6f8ad782b870d846de1618226cc6e1 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Qiz` cannot be made into an object
-  --> $DIR/issue-19380.rs:11:9
+  --> $DIR/issue-19380.rs:11:29
    |
 LL |   foos: &'static [&'static (dyn Qiz + 'static)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object
+   |                             ^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-19380.rs:2:6
index 6bcff7aff2dc4fa59982c14a7299c509ce1dfb0d..28f87a75f0f1521691ce67fd81b335f68b429b44 100644 (file)
@@ -25,6 +25,24 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    = note: 127 redundant requirements hidden
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
 
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+  --> $DIR/issue-20413.rs:8:36
+   |
+LL | trait Foo {
+   | --------- required by this bound in `Foo`
+...
+LL | impl<T> Foo for T where NoData<T>: Foo {
+   |                                    ^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/issue-20413.rs:8:9
+   |
+LL | impl<T> Foo for T where NoData<T>: Foo {
+   |         ^^^     ^
+   = note: 127 redundant requirements hidden
+   = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
+
 error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
   --> $DIR/issue-20413.rs:28:42
    |
@@ -48,47 +66,6 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    = note: 126 redundant requirements hidden
    = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>`
 
-error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
-  --> $DIR/issue-20413.rs:36:42
-   |
-LL | trait Bar {
-   | --------- required by this bound in `Bar`
-...
-LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
-   |                                          ^^^
-   |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:36:9
-   |
-LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
-   |         ^^^     ^
-note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:28:9
-   |
-LL | impl<T> Bar for T where EvenLessData<T>: Baz {
-   |         ^^^     ^
-   = note: 126 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
-
-error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
-  --> $DIR/issue-20413.rs:8:36
-   |
-LL | trait Foo {
-   | --------- required by this bound in `Foo`
-...
-LL | impl<T> Foo for T where NoData<T>: Foo {
-   |                                    ^^^
-   |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-20413.rs:8:9
-   |
-LL | impl<T> Foo for T where NoData<T>: Foo {
-   |         ^^^     ^
-   = note: 127 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
-
 error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
   --> $DIR/issue-20413.rs:28:42
    |
@@ -135,6 +112,29 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    = note: 126 redundant requirements hidden
    = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
 
+error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
+  --> $DIR/issue-20413.rs:36:42
+   |
+LL | trait Bar {
+   | --------- required by this bound in `Bar`
+...
+LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
+   |                                          ^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/issue-20413.rs:36:9
+   |
+LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
+   |         ^^^     ^
+note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/issue-20413.rs:28:9
+   |
+LL | impl<T> Bar for T where EvenLessData<T>: Baz {
+   |         ^^^     ^
+   = note: 126 redundant requirements hidden
+   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
+
 error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0275, E0392.
index 660a6935f36cb852b72974aeb5fcc9d934ad2a1b..b45574f0c49af80d563b5a5404b2a12f6728939f 100644 (file)
@@ -1,6 +1,8 @@
 error[E0463]: can't find crate for `std`
    |
    = note: the `thumbv6m-none-eabi` target may not be installed
+   = 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
 
index 80aca482b3d29b8c8e614353bd7e9f4360d02178..4bc5eb03e922cb26ffcf205feef26df4ed3467e4 100644 (file)
@@ -10,7 +10,7 @@ LL | {
 LL |     break_me::<Type, fn(_)>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |     |
-   |     expected signature of `fn(<Type as Trait<'b>>::Assoc) -> _`
+   |     expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
    |     found signature of `fn(()) -> _`
 
 error: aborting due to previous error
index 7e23e0fd747fb5e906f5296786cd13b5896f5461..d963c07ea91750ac12704dc65c4af389233d6d91 100644 (file)
@@ -1,6 +1,8 @@
 error[E0463]: can't find crate for `core`
    |
    = note: the `thumbv7em-none-eabihf` target may not be installed
+   = 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
 
index 650570b6471eb13266ce99e8273e68350eaaf272..149562f8fb31c7e61d832fc8e1e9fcf1c2350628 100644 (file)
@@ -10,7 +10,7 @@ LL |     F: for<'a> FnMut(<T as Trait<'a>>::Item),
 LL |     foo((), drop)
    |             ^^^^
    |             |
-   |             expected signature of `fn(<() as Trait<'a>>::Item) -> _`
+   |             expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
    |             found signature of `fn(()) -> _`
 
 error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
diff --git a/src/test/ui/issues/issue-86756.rs b/src/test/ui/issues/issue-86756.rs
new file mode 100644 (file)
index 0000000..7f864eb
--- /dev/null
@@ -0,0 +1,12 @@
+trait Foo<T, T = T> {}
+//~^ ERROR the name `T` is already used for a generic parameter in this item's generic parameters
+
+fn eq<A, B>() {
+    eq::<dyn, Foo>
+    //~^ ERROR cannot find type `dyn` in this scope
+    //~| ERROR missing generics for trait `Foo`
+    //~| WARN trait objects without an explicit `dyn` are deprecated
+    //~| WARN this is accepted in the current edition
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-86756.stderr b/src/test/ui/issues/issue-86756.stderr
new file mode 100644 (file)
index 0000000..1ef2198
--- /dev/null
@@ -0,0 +1,46 @@
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/issue-86756.rs:1:14
+   |
+LL | trait Foo<T, T = T> {}
+   |           -  ^ already used
+   |           |
+   |           first use of `T`
+
+error[E0412]: cannot find type `dyn` in this scope
+  --> $DIR/issue-86756.rs:5:10
+   |
+LL | fn eq<A, B>() {
+   |           - help: you might be missing a type parameter: `, dyn`
+LL |     eq::<dyn, Foo>
+   |          ^^^ not found in this scope
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/issue-86756.rs:5:15
+   |
+LL |     eq::<dyn, Foo>
+   |               ^^^ help: use `dyn`: `dyn Foo`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+error[E0107]: missing generics for trait `Foo`
+  --> $DIR/issue-86756.rs:5:15
+   |
+LL |     eq::<dyn, Foo>
+   |               ^^^ expected at least 1 generic argument
+   |
+note: trait defined here, with at least 1 generic parameter: `T`
+  --> $DIR/issue-86756.rs:1:7
+   |
+LL | trait Foo<T, T = T> {}
+   |       ^^^ -
+help: add missing generic argument
+   |
+LL |     eq::<dyn, Foo<T>>
+   |               ^^^^^^
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0107, E0403, E0412.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-87199.rs b/src/test/ui/issues/issue-87199.rs
new file mode 100644 (file)
index 0000000..a80a64a
--- /dev/null
@@ -0,0 +1,20 @@
+// Regression test for issue #87199, where attempting to relax a bound
+// other than the only supported `?Sized` would still cause the compiler
+// to assume that the `Sized` bound was relaxed.
+
+// check-fail
+
+// Check that these function definitions only emit warnings, not errors
+fn arg<T: ?Send>(_: T) {}
+//~^ warning: default bound relaxed for a type parameter, but this does nothing
+fn ref_arg<T: ?Send>(_: &T) {}
+//~^ warning: default bound relaxed for a type parameter, but this does nothing
+fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
+//~^ warning: default bound relaxed for a type parameter, but this does nothing
+
+// Check that there's no `?Sized` relaxation!
+fn main() {
+    ref_arg::<i32>(&5);
+    ref_arg::<[i32]>(&[5]);
+    //~^ the size for values of type `[i32]` cannot be known
+}
diff --git a/src/test/ui/issues/issue-87199.stderr b/src/test/ui/issues/issue-87199.stderr
new file mode 100644 (file)
index 0000000..e3a8e82
--- /dev/null
@@ -0,0 +1,36 @@
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/issue-87199.rs:8:8
+   |
+LL | fn arg<T: ?Send>(_: T) {}
+   |        ^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/issue-87199.rs:10:12
+   |
+LL | fn ref_arg<T: ?Send>(_: &T) {}
+   |            ^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/issue-87199.rs:12:13
+   |
+LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/issue-87199.rs:18:22
+   |
+LL | fn ref_arg<T: ?Send>(_: &T) {}
+   |            - required by this bound in `ref_arg`
+...
+LL |     ref_arg::<[i32]>(&[5]);
+   |                      ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | fn ref_arg<T: ?Send + ?Sized>(_: &T) {}
+   |                     ^^^^^^^^
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.
index 50c58ea6e151a82f4096edfc922d3f1509ce4434..74e7823e1ffc13d2c63eff53b3bceee3dc03b12d 100644 (file)
@@ -4,7 +4,7 @@ warning: extern declarations without an explicit ABI are deprecated
 LL | extern fn foo() {}
    | ^^^^^^^^^^^^^^^ ABI should be specified here
    |
-   = note: requested on the command line with `--force-warns missing-abi`
+   = note: requested on the command line with `--force-warn missing-abi`
    = help: the default ABI is C
 
 warning: 1 warning emitted
index 6814c15e65686142ae2206577bedb01225e73366..a0a96d01be3f59389e6d1c0fd824206367060a4e 100644 (file)
@@ -5,7 +5,7 @@
 //
 //[warn_deny] compile-flags: --warn missing_abi --deny missing_abi
 //[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi
-//[force_warn_deny] compile-flags: -Z unstable-options --force-warns missing_abi --allow missing_abi
+//[force_warn_deny] compile-flags: -Z unstable-options --force-warn missing_abi --allow missing_abi
 //[force_warn_deny] check-pass
 
 
index 201161296baf4da6d6b23f601280da6f4a9c5c7e..55544cc73781a6dd86700b8dccfd2bc71cae4d9a 100644 (file)
@@ -1,7 +1,7 @@
 // Checks that rustc correctly errors when passed an invalid lint with
-// `--force-warns`. This is a regression test for issue #86958.
+// `--force-warn`. This is a regression test for issue #86958.
 //
-// compile-flags: -Z unstable-options --force-warns foo-qux
+// compile-flags: -Z unstable-options --force-warn foo-qux
 // error-pattern: unknown lint: `foo_qux`
 
 fn main() {}
index 3a9aebb996c9312ebdf9e49582ed3c7c5704e1ba..4367c3b4500d5fe1f471d745436f822ec08bc6e8 100644 (file)
@@ -1,14 +1,14 @@
 error[E0602]: unknown lint: `foo_qux`
    |
-   = note: requested on the command line with `--force-warns foo_qux`
+   = note: requested on the command line with `--force-warn foo_qux`
 
 error[E0602]: unknown lint: `foo_qux`
    |
-   = note: requested on the command line with `--force-warns foo_qux`
+   = note: requested on the command line with `--force-warn foo_qux`
 
 error[E0602]: unknown lint: `foo_qux`
    |
-   = note: requested on the command line with `--force-warns foo_qux`
+   = note: requested on the command line with `--force-warn foo_qux`
 
 error: aborting due to 3 previous errors
 
index b8bf7d860c415a34311c1299cd5fb44af14dd529..ea7ce98d88413da8fccb5138ef622713c9b3f244 100644 (file)
@@ -1,6 +1,8 @@
 // Test that dead code warnings are issued for superfluous assignments of
 // fields or variables to themselves (issue #75356).
 
+// ignore-test FIXME(81658, 83171)
+
 // check-pass
 #![allow(unused_assignments)]
 #![warn(dead_code)]
diff --git a/src/test/ui/lint/dead-code/write-only-field.rs b/src/test/ui/lint/dead-code/write-only-field.rs
deleted file mode 100644 (file)
index 7b3f1e9..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#![deny(dead_code)]
-
-struct S {
-    f: i32, //~ ERROR: field is never read
-    sub: Sub, //~ ERROR: field is never read
-}
-
-struct Sub {
-    f: i32, //~ ERROR: field is never read
-}
-
-fn field_write(s: &mut S) {
-    s.f = 1;
-    s.sub.f = 2;
-}
-
-fn main() {
-    let mut s = S { f: 0, sub: Sub { f: 0 } };
-    field_write(&mut s);
-
-    auto_deref();
-    nested_boxes();
-}
-
-fn auto_deref() {
-    struct E {
-        x: bool,
-        y: bool, //~ ERROR: field is never read
-    }
-
-    struct P<'a> {
-        e: &'a mut E
-    }
-
-    impl P<'_> {
-        fn f(&mut self) {
-            self.e.x = true;
-            self.e.y = true;
-        }
-    }
-
-    let mut e = E { x: false, y: false };
-    let mut p = P { e: &mut e };
-    p.f();
-    assert!(e.x);
-}
-
-fn nested_boxes() {
-    struct A {
-        b: Box<B>,
-    }
-
-    struct B {
-        c: Box<C>,
-    }
-
-    struct C {
-        u: u32, //~ ERROR: field is never read
-        v: u32, //~ ERROR: field is never read
-    }
-
-    let mut a = A {
-        b: Box::new(B {
-            c: Box::new(C { u: 0, v: 0 }),
-        }),
-    };
-    a.b.c.v = 10;
-    a.b.c = Box::new(C { u: 1, v: 2 });
-}
diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr
deleted file mode 100644 (file)
index a191d22..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error: field is never read: `f`
-  --> $DIR/write-only-field.rs:4:5
-   |
-LL |     f: i32,
-   |     ^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/write-only-field.rs:1:9
-   |
-LL | #![deny(dead_code)]
-   |         ^^^^^^^^^
-
-error: field is never read: `sub`
-  --> $DIR/write-only-field.rs:5:5
-   |
-LL |     sub: Sub,
-   |     ^^^^^^^^
-
-error: field is never read: `f`
-  --> $DIR/write-only-field.rs:9:5
-   |
-LL |     f: i32,
-   |     ^^^^^^
-
-error: field is never read: `y`
-  --> $DIR/write-only-field.rs:28:9
-   |
-LL |         y: bool,
-   |         ^^^^^^^
-
-error: field is never read: `u`
-  --> $DIR/write-only-field.rs:58:9
-   |
-LL |         u: u32,
-   |         ^^^^^^
-
-error: field is never read: `v`
-  --> $DIR/write-only-field.rs:59:9
-   |
-LL |         v: u32,
-   |         ^^^^^^
-
-error: aborting due to 6 previous errors
-
index 0a3e20b4f7d66dbff56971c0fd45df3f1dec2659..4799429ea2c69317f6e084e84fd4ccea37578160 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns elided_lifetimes_in_paths -Zunstable-options
+// compile-flags: --force-warn elided_lifetimes_in_paths -Zunstable-options
 // check-pass
 
 struct Foo<'a> {
index 37c61e614f3e338f2a9db94d16fb7e851ac5d142..05513de81d1c85c521b2c14027bd6ac37c150c6e 100644 (file)
@@ -4,7 +4,7 @@ warning: hidden lifetime parameters in types are deprecated
 LL | fn foo(x: &Foo) {}
    |            ^^^- help: indicate the anonymous lifetime: `<'_>`
    |
-   = note: requested on the command line with `--force-warns elided-lifetimes-in-paths`
+   = note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
 
 warning: 1 warning emitted
 
index 0abc49137269d93e6a7f5d0d9a8e472e3b0e6e1b..d066feba86984c99395a78b7460a7cf032d77637 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns const_err -Zunstable-options
+// compile-flags: --force-warn const_err -Zunstable-options
 // check-pass
 
 #![allow(const_err)]
index 56b2f0236a5d373c4f037e0eef314b98141fc011..dd4f88a3b533ee90579ab13a6527e9e7e291bf1b 100644 (file)
@@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0;
    |                |
    |                attempt to divide `1_i32` by zero
    |
-   = note: requested on the command line with `--force-warns const-err`
+   = note: requested on the command line with `--force-warn const-err`
    = 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>
 
index bac0e4f8f8e866559d19e08e9c1d033b9ecb6c9f..280de5064720ae7deb70d6aa5fbbcb0ada2121e7 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code -Zunstable-options
 // check-pass
 
 #![allow(dead_code)]
index 7eb980a129708d8f4e2bc562d9463bb1f767ff1e..fced147254e82483f9b8bd4e45986a6299eebb3b 100644 (file)
@@ -4,7 +4,7 @@ warning: function is never used: `dead_function`
 LL | fn dead_function() {}
    |    ^^^^^^^^^^^^^
    |
-   = note: requested on the command line with `--force-warns dead-code`
+   = note: requested on the command line with `--force-warn dead-code`
 
 warning: 1 warning emitted
 
index e721760ab2da0a4785e80012eba114842b88b063..8331df02da7637de159e97e103736641747aa0c5 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns const_err -Zunstable-options
+// compile-flags: --force-warn const_err -Zunstable-options
 // check-pass
 
 const C: i32 = 1 / 0;
index 8b9bb5a74cfc10762a0174b8f8849d5ac7640515..68cd3a392f5830c6db2bdf4426ff38811c62d9dd 100644 (file)
@@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0;
    |                |
    |                attempt to divide `1_i32` by zero
    |
-   = note: requested on the command line with `--force-warns const-err`
+   = note: requested on the command line with `--force-warn const-err`
    = 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>
 
index 0dc1ce28ac4f5f2e8f42fb00d3d81aa276160d4d..0e8a65a41173d050e599a47acbd8dfbc69aa5597 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code -Zunstable-options
 // check-pass
 
 #![allow(warnings)]
index ebdb022f2a20b05770ff6b0f5805beaff854ff44..3305f2c02834d7571ef7024e20d65a47b2dada84 100644 (file)
@@ -4,7 +4,7 @@ warning: function is never used: `dead_function`
 LL | fn dead_function() {}
    |    ^^^^^^^^^^^^^
    |
-   = note: requested on the command line with `--force-warns dead-code`
+   = note: requested on the command line with `--force-warn dead-code`
 
 warning: 1 warning emitted
 
index 4f637c7fefa2b873670b3e7d5f5dc81cf0b5f643..aaca59a2a2aabba9700515c49dad81d9d10dc33d 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns nonstandard_style -Zunstable-options
+// compile-flags: --force-warn nonstandard_style -Zunstable-options
 // check-pass
 
 #![allow(warnings)]
index 7429e77fe83e11aae881ec46aca12eb86b4d634e..065a8f6a556a0d9613c857af8b9abb897a2fa2d4 100644 (file)
@@ -4,7 +4,7 @@ warning: function `FUNCTION` should have a snake case name
 LL | pub fn FUNCTION() {}
    |        ^^^^^^^^ help: convert the identifier to snake case: `function`
    |
-   = note: `--force-warns non-snake-case` implied by `--force-warns nonstandard-style`
+   = note: `--force-warn non-snake-case` implied by `--force-warn nonstandard-style`
 
 warning: 1 warning emitted
 
index b4c2c505aa560dae2499c2955ceeaf34b866e038..d8447bd23824440ca3140732cf9f0b9f338af1f3 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns bare_trait_objects -Zunstable-options
+// compile-flags: --force-warn bare_trait_objects -Zunstable-options
 // check-pass
 
 #![allow(rust_2018_idioms)]
index 4f7bba6bba1c9fdb5b5e282350631ec323432c18..185c0e8e3d0eba88105739eb1e0821a59ba31dd5 100644 (file)
@@ -4,7 +4,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL | pub fn function(_x: Box<SomeTrait>) {}
    |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = note: requested on the command line with `--force-warns bare-trait-objects`
+   = note: requested on the command line with `--force-warn bare-trait-objects`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs
new file mode 100644 (file)
index 0000000..e10d161
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: --cap-lints allow  --force-warn bare_trait_objects -Zunstable-options
+// check-pass
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr
new file mode 100644 (file)
index 0000000..a899705
--- /dev/null
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warn-cap-lints-allow.rs:6:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: requested on the command line with `--force-warn bare-trait-objects`
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
index bcfe6e5a5bd6e8a4b61bee859b3d59b6d5933ba0..4afc0868608d389ef1fee5cbc761da280c3babb5 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --cap-lints warn  --force-warns rust-2021-compatibility -Zunstable-options
+// compile-flags: --cap-lints warn  --force-warn rust-2021-compatibility -Zunstable-options
 // check-pass
 #![allow(ellipsis_inclusive_range_patterns)]
 
index 07e786ce7d2663745aac2ab0dfb9c7b5c52d5afe..1d5f88086c5c410c97bb0a6d79bcae15e42e27cc 100644 (file)
@@ -4,7 +4,7 @@ warning: `...` range patterns are deprecated
 LL |         0...100 => true,
    |          ^^^ help: use `..=` for an inclusive range
    |
-   = note: `--force-warns ellipsis-inclusive-range-patterns` implied by `--force-warns rust-2021-compatibility`
+   = note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
index 83a1c078f062f5bec33de0fe76f30c9b3f5bfa6a..193ba2b6f0da52bbeb597cb0d4443a5c383b0dd6 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns rust-2018-idioms -Zunstable-options
+// compile-flags: --force-warn rust-2018-idioms -Zunstable-options
 // check-pass
 
 #![allow(bare_trait_objects)]
index 65de6c9e287f0045f52a30c7ae0efe9b77aba8d2..d242ef266b8d1a2e2f36ceeef1dd0225927086fe 100644 (file)
@@ -4,7 +4,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL | pub fn function(_x: Box<SomeTrait>) {}
    |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = note: `--force-warns bare-trait-objects` implied by `--force-warns rust-2018-idioms`
+   = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
index 5e5fda973d54e7fcfd7234e61151b88d84f3e7c9..0198610b78e10c8e8fecb7a94588a324c6cf2804 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: --force-warns rust_2018_idioms -Zunstable-options
+// compile-flags: --force-warn rust_2018_idioms -Zunstable-options
 // check-pass
 
 #![allow(rust_2018_idioms)]
index fd3397c916a6dc9c3580f1ac35f8576ece1ba685..180dff880a65828356280598b923880db57b1045 100644 (file)
@@ -4,7 +4,7 @@ warning: trait objects without an explicit `dyn` are deprecated
 LL | pub fn function(_x: Box<SomeTrait>) {}
    |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
-   = note: `--force-warns bare-trait-objects` implied by `--force-warns rust-2018-idioms`
+   = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
 
diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs
deleted file mode 100644 (file)
index e364897..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// compile-flags: --cap-lints allow  --force-warns bare_trait_objects -Zunstable-options
-// check-pass
-
-pub trait SomeTrait {}
-
-pub fn function(_x: Box<SomeTrait>) {}
-//~^ WARN trait objects without an explicit `dyn` are deprecated
-//~| WARN this is accepted in the current edition
-
-fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr
deleted file mode 100644 (file)
index 2153202..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/force-warns-cap-lints-allow.rs:6:25
-   |
-LL | pub fn function(_x: Box<SomeTrait>) {}
-   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
-   |
-   = note: requested on the command line with `--force-warns bare-trait-objects`
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/lint/inert-attr-macro.rs b/src/test/ui/lint/inert-attr-macro.rs
new file mode 100644 (file)
index 0000000..dc0bb8a
--- /dev/null
@@ -0,0 +1,20 @@
+// check-pass
+
+#![warn(unused)]
+
+macro_rules! foo {
+    () => {}
+}
+
+fn main() {
+    #[inline] foo!(); //~ WARN unused attribute `inline`
+
+    // This does nothing, since `#[allow(warnings)]` is itself
+    // an inert attribute on a macro call
+    #[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow`
+    //~^ WARN unused attribute `inline`
+
+    // This does work, since the attribute is on a parent
+    // of the macro invocation.
+    #[allow(warnings)] { #[inline] foo!(); }
+}
diff --git a/src/test/ui/lint/inert-attr-macro.stderr b/src/test/ui/lint/inert-attr-macro.stderr
new file mode 100644 (file)
index 0000000..3b3aa5d
--- /dev/null
@@ -0,0 +1,44 @@
+warning: unused attribute `inline`
+  --> $DIR/inert-attr-macro.rs:10:5
+   |
+LL |     #[inline] foo!();
+   |     ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/inert-attr-macro.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
+note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
+  --> $DIR/inert-attr-macro.rs:10:15
+   |
+LL |     #[inline] foo!();
+   |               ^^^
+
+warning: unused attribute `allow`
+  --> $DIR/inert-attr-macro.rs:14:5
+   |
+LL |     #[allow(warnings)] #[inline] foo!();
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
+  --> $DIR/inert-attr-macro.rs:14:34
+   |
+LL |     #[allow(warnings)] #[inline] foo!();
+   |                                  ^^^
+
+warning: unused attribute `inline`
+  --> $DIR/inert-attr-macro.rs:14:24
+   |
+LL |     #[allow(warnings)] #[inline] foo!();
+   |                        ^^^^^^^^^
+   |
+note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
+  --> $DIR/inert-attr-macro.rs:14:34
+   |
+LL |     #[allow(warnings)] #[inline] foo!();
+   |                                  ^^^
+
+warning: 3 warnings emitted
+
index c00c3d77dcedc8bd961f165d6a7551b2b001374b..84ad32bddd55b3991f6099d97af6402271df8abc 100644 (file)
@@ -14,6 +14,8 @@ LL | #![warn(semicolon_in_expressions_from_macros)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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 #79813 <https://github.com/rust-lang/rust/issues/79813>
+   = note: macro invocations at the end of a block are treated as expressions
+   = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo`
    = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: trailing semicolon in macro used in expression position
diff --git a/src/test/ui/parser/issue-87197-missing-semicolon.fixed b/src/test/ui/parser/issue-87197-missing-semicolon.fixed
new file mode 100644 (file)
index 0000000..53f071d
--- /dev/null
@@ -0,0 +1,10 @@
+// run-rustfix
+// Parser should know when a semicolon is missing.
+// https://github.com/rust-lang/rust/issues/87197
+
+fn main() {
+    let x = 100; //~ ERROR: expected `;`
+    println!("{}", x); //~ ERROR: expected `;`
+    let y = 200; //~ ERROR: expected `;`
+    println!("{}", y);
+}
diff --git a/src/test/ui/parser/issue-87197-missing-semicolon.rs b/src/test/ui/parser/issue-87197-missing-semicolon.rs
new file mode 100644 (file)
index 0000000..db0edf4
--- /dev/null
@@ -0,0 +1,10 @@
+// run-rustfix
+// Parser should know when a semicolon is missing.
+// https://github.com/rust-lang/rust/issues/87197
+
+fn main() {
+    let x = 100 //~ ERROR: expected `;`
+    println!("{}", x) //~ ERROR: expected `;`
+    let y = 200 //~ ERROR: expected `;`
+    println!("{}", y);
+}
diff --git a/src/test/ui/parser/issue-87197-missing-semicolon.stderr b/src/test/ui/parser/issue-87197-missing-semicolon.stderr
new file mode 100644 (file)
index 0000000..57772de
--- /dev/null
@@ -0,0 +1,26 @@
+error: expected `;`, found `println`
+  --> $DIR/issue-87197-missing-semicolon.rs:6:16
+   |
+LL |     let x = 100
+   |                ^ help: add `;` here
+LL |     println!("{}", x)
+   |     ------- unexpected token
+
+error: expected `;`, found keyword `let`
+  --> $DIR/issue-87197-missing-semicolon.rs:7:22
+   |
+LL |     println!("{}", x)
+   |                      ^ help: add `;` here
+LL |     let y = 200
+   |     --- unexpected token
+
+error: expected `;`, found `println`
+  --> $DIR/issue-87197-missing-semicolon.rs:8:16
+   |
+LL |     let y = 200
+   |                ^ help: add `;` here
+LL |     println!("{}", y);
+   |     ------- unexpected token
+
+error: aborting due to 3 previous errors
+
index fd79fa8df7a68662366042af17216e78bb1c4157..24d1ae9e6236851a48eaec549a098695e793f049 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
-    assert_eq!(1, 2)
-    assert_eq!(3, 4) //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `assert_eq`
+    assert_eq!(1, 2) //~ ERROR: expected `;`
+    assert_eq!(3, 4) //~ ERROR: expected `;`
     println!("hello");
 }
index 9492191b8df143072fab8bce813895b56636f248..f310662dbb0e790799099057c8bdc6d2f2a95016 100644 (file)
@@ -1,10 +1,18 @@
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `assert_eq`
-  --> $DIR/macros-no-semicolon.rs:3:5
+error: expected `;`, found `assert_eq`
+  --> $DIR/macros-no-semicolon.rs:2:21
    |
 LL |     assert_eq!(1, 2)
-   |                     - expected one of `.`, `;`, `?`, `}`, or an operator
+   |                     ^ help: add `;` here
 LL |     assert_eq!(3, 4)
-   |     ^^^^^^^^^ unexpected token
+   |     --------- unexpected token
 
-error: aborting due to previous error
+error: expected `;`, found `println`
+  --> $DIR/macros-no-semicolon.rs:3:21
+   |
+LL |     assert_eq!(3, 4)
+   |                     ^ help: add `;` here
+LL |     println!("hello");
+   |     ------- unexpected token
+
+error: aborting due to 2 previous errors
 
index 508e486afec7253ce604ac209312a578e663d274..2b349f0ed5f997e8ee9d7dc0f3ca6417cc5a3138 100644 (file)
@@ -2,8 +2,6 @@
 
 // Test copy
 
-#![feature(bindings_after_at)]
-
 struct A { a: i32, b: i32 }
 struct B { a: i32, b: C }
 struct D { a: i32, d: C }
index 71503ecf2622bec748e8b838c64fa642aa21ebd4..9d1f08d6eea39fdf899d1c07f326d24bdf346e00 100644 (file)
@@ -2,8 +2,6 @@
 // It checks that you cannot use an AND-pattern (`binding @ pat`)
 // where one side is by-ref and the other is by-move.
 
-#![feature(bindings_after_at)]
-
 struct X {
     x: (),
 }
index e50ae3e7eebd30ebde48585294e817948f8188db..6ff0dadf0d1f3da7e78b9caaf48996d2e457fe80 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14
    |
 LL |         Some(ref _y @ _z) => {}
    |              ------^^^--
@@ -8,7 +8,7 @@ LL |         Some(ref _y @ _z) => {}
    |              value borrowed, by `_y`, here
 
 error: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14
    |
 LL |         Some(_z @ ref _y) => {}
    |              --^^^------
@@ -18,7 +18,7 @@ LL |         Some(_z @ ref _y) => {}
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14
    |
 LL |         Some(ref mut _y @ _z) => {}
    |              ----------^^^--
@@ -27,7 +27,7 @@ LL |         Some(ref mut _y @ _z) => {}
    |              value borrowed, by `_y`, here
 
 error: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14
    |
 LL |         Some(_z @ ref mut _y) => {}
    |              --^^^----------
@@ -37,7 +37,7 @@ LL |         Some(_z @ ref mut _y) => {}
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14
    |
 LL |         Some(ref _y @ _z) => {}
    |              ^^^^^^^^^--
@@ -52,7 +52,7 @@ LL |         Some(ref _y @ ref _z) => {}
    |                       ^^^
 
 error[E0382]: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14
    |
 LL |         Some(ref mut _y @ _z) => {}
    |              ^^^^^^^^^^^^^--
index 08240db4472ed76ced0354b999d0a0ae096b48ad..1816a74a0ba3d02a15b3ea3ec4c95399db256070 100644 (file)
@@ -1,7 +1,5 @@
 // See issue #12534.
 
-#![feature(bindings_after_at)]
-
 fn main() {}
 
 struct A(Box<u8>);
index a77b866d8373d4231f640c18daa3c13fc9f4a686..ee0885a014aa44c15ccdbb2d2f20d4e1b2584a55 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of partially moved value
-  --> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:6
+  --> $DIR/bind-by-move-no-subbindings-fun-param.rs:7:6
    |
 LL | fn f(a @ A(u): A) -> Box<u8> {
    |      ^^^^^^-^
index bce43f9df85c841d84b27aaabfb02bd9186a03e9..a61d682152407cd3d7463963c6f16da5e5cfe282 100644 (file)
@@ -1,7 +1,5 @@
 // Test that moving on both sides of an `@` pattern is not allowed.
 
-#![feature(bindings_after_at)]
-
 fn main() {
     struct U; // Not copy!
 
index ff8183e87635f557100357cb7523accacf2b71e8..8e00bf5c328be6fcac7781d88d090c0447ceec45 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:13:9
+  --> $DIR/borrowck-move-and-move.rs:11:9
    |
 LL |     let a @ b = U;
    |         ^^^^-   - move occurs because value has type `U`, which does not implement the `Copy` trait
@@ -8,7 +8,7 @@ LL |     let a @ b = U;
    |         value used here after move
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-move-and-move.rs:15:9
+  --> $DIR/borrowck-move-and-move.rs:13:9
    |
 LL |     let a @ (b, c) = (U, U);
    |         ^^^^^^^^-^
@@ -19,7 +19,7 @@ LL |     let a @ (b, c) = (U, U);
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-move-and-move.rs:17:9
+  --> $DIR/borrowck-move-and-move.rs:15:9
    |
 LL |     let a @ (b, c) = (u(), u());
    |         ^^^^^^^^-^
@@ -30,7 +30,7 @@ LL |     let a @ (b, c) = (u(), u());
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:20:16
+  --> $DIR/borrowck-move-and-move.rs:18:16
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait
@@ -41,7 +41,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:20:29
+  --> $DIR/borrowck-move-and-move.rs:18:29
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait
@@ -52,7 +52,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     value moved here
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-move-and-move.rs:27:9
+  --> $DIR/borrowck-move-and-move.rs:25:9
    |
 LL |         xs @ [a, .., b] => {}
    |         ^^^^^^^^^^^^^-^
@@ -63,7 +63,7 @@ LL |         xs @ [a, .., b] => {}
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-move-and-move.rs:31:9
+  --> $DIR/borrowck-move-and-move.rs:29:9
    |
 LL |         xs @ [_, ys @ .., _] => {}
    |         ^^^^^^^^^-------^^^^
@@ -74,7 +74,7 @@ LL |         xs @ [_, ys @ .., _] => {}
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:24:12
+  --> $DIR/borrowck-move-and-move.rs:22:12
    |
 LL |     fn fun(a @ b: U) {}
    |            ^^^^-
index f1ee87bc9c69b40671e55458aa4a3d25b3eb9378..fbdefd9d36c90b0b4e4cf3b9ebf613cdfcd42817 100644 (file)
@@ -2,7 +2,6 @@
 
 // Test `@` patterns combined with `box` patterns.
 
-#![feature(bindings_after_at)]
 #![feature(box_patterns)]
 
 #[derive(Copy, Clone)]
index 07fac1d363133a809e11b83749745c56c92731a2..45aa65e67a9fa7449d2edda861567caf5a75eff0 100644 (file)
@@ -1,6 +1,5 @@
 // Test `@` patterns combined with `box` patterns.
 
-#![feature(bindings_after_at)]
 #![feature(box_patterns)]
 
 #[derive(Copy, Clone)]
index 83da16a72a7ba5d11b24dc91660015d4fd79d476..4b2048855ebb42ea383307b3044892872c6e85d0 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-at-and-box.rs:32:9
+  --> $DIR/borrowck-pat-at-and-box.rs:31:9
    |
 LL |     let ref a @ box b = Box::new(NC);
    |         -----^^^^^^^-
@@ -8,7 +8,7 @@ LL |     let ref a @ box b = Box::new(NC);
    |         value borrowed, by `a`, here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:35:9
+  --> $DIR/borrowck-pat-at-and-box.rs:34:9
    |
 LL |     let ref a @ box ref mut b = Box::new(nc());
    |         -----^^^^^^^---------
@@ -17,7 +17,7 @@ LL |     let ref a @ box ref mut b = Box::new(nc());
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:37:9
+  --> $DIR/borrowck-pat-at-and-box.rs:36:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -26,7 +26,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:39:9
+  --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -35,7 +35,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:43:9
+  --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -44,7 +44,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:49:9
+  --> $DIR/borrowck-pat-at-and-box.rs:48:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ---------^^^^^^^-----
@@ -53,7 +53,7 @@ LL |     let ref mut a @ box ref b = Box::new(NC);
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:63:9
+  --> $DIR/borrowck-pat-at-and-box.rs:62:9
    |
 LL |         ref mut a @ box ref b => {
    |         ---------^^^^^^^-----
@@ -62,7 +62,7 @@ LL |         ref mut a @ box ref b => {
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:55:11
+  --> $DIR/borrowck-pat-at-and-box.rs:54:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ---------^^^^^^^-----
@@ -71,7 +71,7 @@ LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           mutable borrow, by `a`, occurs here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:32:9
+  --> $DIR/borrowck-pat-at-and-box.rs:31:9
    |
 LL |     let ref a @ box b = Box::new(NC);
    |         ^^^^^^^^^^^^-
@@ -82,7 +82,7 @@ LL |     let ref a @ box b = Box::new(NC);
    = note: move occurs because value has type `NC`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:39:9
+  --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         ^^^^^^^^^^^^---------
@@ -94,7 +94,7 @@ LL |     *b = NC;
    |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:43:9
+  --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         ^^^^^^^^^^^^---------
@@ -106,7 +106,7 @@ LL |     *b = NC;
    |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:49:9
+  --> $DIR/borrowck-pat-at-and-box.rs:48:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ^^^^^^^^^^^^^^^^-----
@@ -118,7 +118,7 @@ LL |     drop(b);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:63:9
+  --> $DIR/borrowck-pat-at-and-box.rs:62:9
    |
 LL |         ref mut a @ box ref b => {
    |         ^^^^^^^^^^^^^^^^-----
@@ -130,7 +130,7 @@ LL |             drop(b);
    |                  - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:55:11
+  --> $DIR/borrowck-pat-at-and-box.rs:54:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ^^^^^^^^^^^^^^^^-----
index c4ce50c8b9a16313d92168477130159170043b9f..0108861cfce3ca09fb1e90a7dc031e226370f1b6 100644 (file)
@@ -2,8 +2,6 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
-#![feature(bindings_after_at)]
-
 #[derive(Copy, Clone)]
 struct C;
 
index a22d27763d261fee7cd722636194aeb82124eafe..82f16fca65fee6ec25381978db786161f0c941e4 100644 (file)
@@ -1,8 +1,6 @@
 // Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented even with promotion.
 // Currently this logic exists in THIR match checking as opposed to borrowck.
 
-#![feature(bindings_after_at)]
-
 fn main() {
     struct U;
     let a @ ref b = U; //~ ERROR borrow of moved value
index 0e09d478e3a1044d41350df40981db51b7ff0e17..be4e81c61aa626fb19ff70255e95c0251ceb9d61 100644 (file)
@@ -1,5 +1,5 @@
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:8:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:6:9
    |
 LL |     let a @ ref b = U;
    |         -^^^-----
index 8a574f880ed8d0b9c2a6f9f9e667fd4ace4aa53f..06dc6e1c4da1f2e04324aae7e87c09a75be56036 100644 (file)
@@ -1,7 +1,5 @@
 // Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented.
 
-#![feature(bindings_after_at)]
-
 fn main() {
     struct U;
 
index 79addf9d574b673f78cb18770d8de5573fc0a9ce..bc2c1625fd0ef7275da5b1526ff92d4da7d45b9c 100644 (file)
@@ -1,5 +1,5 @@
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:22:9
    |
 LL |     let a @ ref b = U;
    |         -^^^-----
@@ -9,7 +9,7 @@ LL |     let a @ ref b = U;
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:26:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         -^^^^^^^^^^^^---------^^^^^^-----^
@@ -20,7 +20,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:26:14
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |              -----^^^---------
@@ -30,7 +30,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:26:33
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |                                 -^^^-----
@@ -40,7 +40,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9
    |
 LL |     let a @ [ref mut b, ref c] = [U, U];
    |         -^^^^---------^^-----^
@@ -51,7 +51,7 @@ LL |     let a @ [ref mut b, ref c] = [U, U];
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
    |
 LL |     let a @ ref b = u();
    |         -^^^-----
@@ -61,7 +61,7 @@ LL |     let a @ ref b = u();
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:35:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         -^^^^^^^^^^^^---------^^^^^^-----^
@@ -72,7 +72,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:35:14
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |              -----^^^---------
@@ -82,7 +82,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:35:33
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |                                 -^^^-----
@@ -92,7 +92,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
    |
 LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         -^^^^---------^^-----^
@@ -103,7 +103,7 @@ LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9
    |
 LL |         a @ Some(ref b) => {}
    |         -^^^^^^^^-----^
@@ -113,7 +113,7 @@ LL |         a @ Some(ref b) => {}
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:49:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
@@ -124,7 +124,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:49:19
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   -----^^^---------
@@ -134,7 +134,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:49:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      -^^^-----
@@ -144,7 +144,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:57:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         -----^^^^^^^^^-----^^---------^^
@@ -155,7 +155,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:63:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
    |
 LL |         a @ Some(ref b) => {}
    |         -^^^^^^^^-----^
@@ -165,7 +165,7 @@ LL |         a @ Some(ref b) => {}
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:69:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
@@ -176,7 +176,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:69:19
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   -----^^^---------
@@ -186,7 +186,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:69:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      -^^^-----
@@ -196,7 +196,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         -----^^^^^^^^^-----^^---------^^
@@ -207,7 +207,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11
    |
 LL |     fn f1(a @ ref b: U) {}
    |           -^^^-----
@@ -217,7 +217,7 @@ LL |     fn f1(a @ ref b: U) {}
    |           move occurs because `a` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:16:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           -----^^^^^^^^-----^^^^^^^^^^-----^
@@ -228,7 +228,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:16:20
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                    -^^^-----
@@ -238,7 +238,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                    move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:16:31
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                               -----^^^-----
@@ -248,7 +248,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                               move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:21:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11
    |
 LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
    |           -^^^^---------^^-----^
@@ -259,7 +259,7 @@ LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
    |           move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:26:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^---------^
@@ -270,7 +270,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:35:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         ^^^^^^^^^^^^^^^^^^^^^^^^---------^
@@ -281,7 +281,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:49:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38
    |
 LL |     match Some((U, U)) {
    |           ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
@@ -292,7 +292,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:57:30
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30
    |
 LL |     match Some([U, U]) {
    |           ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
@@ -303,7 +303,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:63:18
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18
    |
 LL |     match Some(u()) {
    |           --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait
@@ -314,7 +314,7 @@ LL |         a @ Some(ref b) => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:69:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
    |
 LL |     match Some((u(), u())) {
    |           ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
@@ -325,7 +325,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:30
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30
    |
 LL |     match Some([u(), u()]) {
    |           ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
@@ -336,7 +336,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         value moved here
 
 error[E0382]: use of partially moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:16:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           ^^^^^^^^^^^^^^^^^^^^-------------^
index b9235eabd88f43dbd622e683a7b1a6554a269f6e..0b0a7801049fe588917fc5f8549f5ef0a4c6ec90 100644 (file)
@@ -1,7 +1,5 @@
 // Test that `ref mut? @ pat_with_by_move_bindings` is prevented.
 
-#![feature(bindings_after_at)]
-
 fn main() {
     struct U;
 
index 50b2f8929f2251794dbee3687f39704bef8cfd05..e6a1e5ef07ce41bc96b7d9c18d5dd4d637869e17 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:26:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:24:9
    |
 LL |     let ref a @ b = U;
    |         -----^^^-
@@ -8,7 +8,7 @@ LL |     let ref a @ b = U;
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:28:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:26:9
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |         -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@@ -18,7 +18,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:28:18
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:26:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                  -----^^^-----
@@ -27,7 +27,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                  value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:28:33
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:26:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                                 -----^^^-
@@ -36,7 +36,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                                 value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:32:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
    |
 LL |     let ref mut a @ [b, mut c] = [U, U];
    |         ---------^^^^-^^-----^
@@ -46,7 +46,7 @@ LL |     let ref mut a @ [b, mut c] = [U, U];
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:35:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
    |
 LL |     let ref a @ b = u();
    |         -----^^^-
@@ -55,7 +55,7 @@ LL |     let ref a @ b = u();
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:38:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:36:9
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |         -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@@ -65,7 +65,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:38:18
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                  -----^^^-----
@@ -74,7 +74,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                  value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:38:33
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                                 -----^^^-
@@ -83,7 +83,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                                 value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:44:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9
    |
 LL |     let ref mut a @ [b, mut c] = [u(), u()];
    |         ---------^^^^-^^-----^
@@ -93,7 +93,7 @@ LL |     let ref mut a @ [b, mut c] = [u(), u()];
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:49:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:47:9
    |
 LL |         ref a @ Some(b) => {}
    |         -----^^^^^^^^-^
@@ -102,7 +102,7 @@ LL |         ref a @ Some(b) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:54:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:52:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
@@ -112,7 +112,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:54:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:52:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       -----^^^-----
@@ -121,7 +121,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:54:38
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:52:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      -----^^^-
@@ -130,7 +130,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:61:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
    |         ---------^^^^^^^^^-^^-----^^
@@ -140,7 +140,7 @@ LL |         ref mut a @ Some([b, mut c]) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:66:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9
    |
 LL |         ref a @ Some(b) => {}
    |         -----^^^^^^^^-^
@@ -149,7 +149,7 @@ LL |         ref a @ Some(b) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
@@ -159,7 +159,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       -----^^^-----
@@ -168,7 +168,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      -----^^^-
@@ -177,7 +177,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
    |         ---------^^^^^^^^^-^^-----^^
@@ -187,7 +187,7 @@ LL |         ref mut a @ Some([b, mut c]) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:13:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
    |
 LL |     fn f1(ref a @ b: U) {}
    |           -----^^^-
@@ -196,7 +196,7 @@ LL |     fn f1(ref a @ b: U) {}
    |           value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |           -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@@ -206,7 +206,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |           value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:20
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                    -----^^^-----
@@ -215,7 +215,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                    value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:35
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                                   -----^^^-
@@ -224,7 +224,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                                   value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:22:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
    |
 LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
    |           ---------^^^^-^^-----^
@@ -234,7 +234,7 @@ LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
    |           value borrowed, by `a`, here
 
 error[E0382]: borrow of partially moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:32:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
    |
 LL |     let ref mut a @ [b, mut c] = [U, U];
    |         ^^^^^^^^^^^^^^^^-----^
@@ -245,7 +245,7 @@ LL |     let ref mut a @ [b, mut c] = [U, U];
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:35:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
    |
 LL |     let ref a @ b = u();
    |         ^^^^^^^^-   --- move occurs because value has type `U`, which does not implement the `Copy` trait
@@ -254,7 +254,7 @@ LL |     let ref a @ b = u();
    |         value borrowed here after move
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:38:18
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                  ^^^^^^^^-----
@@ -265,7 +265,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:38:33
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                                 ^^^^^^^^-
@@ -276,7 +276,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of partially moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:44:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9
    |
 LL |     let ref mut a @ [b, mut c] = [u(), u()];
    |         ^^^^^^^^^^^^^^^^-----^
@@ -287,7 +287,7 @@ LL |     let ref mut a @ [b, mut c] = [u(), u()];
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       ^^^^^^^^-----
@@ -302,7 +302,7 @@ LL |         ref a @ Some((ref b @ ref mut c, ref d @ e)) => {}
    |                               ^^^
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      ^^^^^^^^-
@@ -317,7 +317,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ ref e)) => {}
    |                                              ^^^
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:13:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
    |
 LL |     fn f1(ref a @ b: U) {}
    |           ^^^^^^^^-
@@ -327,7 +327,7 @@ LL |     fn f1(ref a @ b: U) {}
    |           move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:20
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                    ^^^^^^^^-----
@@ -338,7 +338,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:35
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                                   ^^^^^^^^-
@@ -349,7 +349,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of partially moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:22:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
    |
 LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
    |           ^^^^^^^^^^^^^^^^-----^
index fb243016a1185f6ae9112823240a42e77c73c124..df213f688c2825c7cb7fbf4a09a07ee657f3626a 100644 (file)
@@ -3,8 +3,6 @@
 // Test that `ref` patterns may be used on both sides
 // of an `@` pattern according to NLL borrowck.
 
-#![feature(bindings_after_at)]
-
 fn main() {
     struct U; // Not copy!
 
index 2d391cd7d0722ee97fcfc0f9bf31da76da4d57cf..6bc0d346c111a5e2905b836a1f079c2b40ea0fde 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(bindings_after_at)]
-
 enum Option<T> {
     None,
     Some(T),
index 13032c3838a926520f49d336867e19d83bb66b2b..2ae78d1084e0e4263eb423b8664cdb55b68f109d 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ---------^^^^^^^^^^^^^-----^
@@ -8,7 +8,7 @@ LL |         ref mut z @ &mut Some(ref a) => {
    |         mutable borrow, by `z`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:9
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         ---------^^^^-----------------^
@@ -18,7 +18,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:22
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      -----^^^---------
@@ -27,7 +27,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      immutable borrow, by `b`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -36,7 +36,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -45,7 +45,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -55,7 +55,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -65,7 +65,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9
    |
 LL |     let ref mut a @ ref b = u();
    |         ---------^^^-----
@@ -74,7 +74,7 @@ LL |     let ref mut a @ ref b = u();
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9
    |
 LL |     let ref a @ ref mut b = u();
    |         -----^^^---------
@@ -83,7 +83,7 @@ LL |     let ref a @ ref mut b = u();
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:57:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -92,7 +92,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:63:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:61:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -101,7 +101,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         ---------^^^^^^-----^
@@ -110,7 +110,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 ---------^^^^^^^-----^
@@ -119,7 +119,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----^^^^^^---------^
@@ -128,7 +128,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 -----^^^^^^^---------^
@@ -137,7 +137,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |         -----^^^^^^---------^
@@ -146,7 +146,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                 -----^^^^^^^---------^
@@ -155,7 +155,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |                                 immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |         ---------^^^^^^-----^
@@ -164,7 +164,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -173,7 +173,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |                                 mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |         -----^^^^^^---------^
@@ -182,7 +182,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                 -----^^^^^^^---------^
@@ -191,7 +191,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                 immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |         ---------^^^^^^-----^
@@ -200,7 +200,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -209,7 +209,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |                                 mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -219,7 +219,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:125:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -229,7 +229,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -239,7 +239,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:136:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -249,7 +249,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11
    |
 LL |     fn f1(ref a @ ref mut b: U) {}
    |           -----^^^---------
@@ -258,7 +258,7 @@ LL |     fn f1(ref a @ ref mut b: U) {}
    |           immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
    |
 LL |     fn f2(ref mut a @ ref b: U) {}
    |           ---------^^^-----
@@ -267,7 +267,7 @@ LL |     fn f2(ref mut a @ ref b: U) {}
    |           mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
    |
 LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           -----^^^^^^^^^^^----------------^^^^^^^^
@@ -276,7 +276,7 @@ LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                      -----^^^-------------
@@ -286,7 +286,7 @@ LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                      immutable borrow, by `a`, occurs here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:30
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                              ---------^^^-
@@ -295,7 +295,7 @@ LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                              value borrowed, by `b`, here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ----------------------^^^^^-
@@ -307,7 +307,7 @@ LL |             **z = None;
    |             ---------- mutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9
    |
 LL |     let ref mut a @ ref b = u();
    |         ^^^^^^^^^^^^-----
@@ -319,7 +319,7 @@ LL |     drop(b);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9
    |
 LL |     let ref a @ ref mut b = u();
    |         ^^^^^^^^---------
@@ -331,7 +331,7 @@ LL |     *b = u();
    |     -------- mutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----------^^^^^^^^^-
@@ -343,7 +343,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 ------------^^^^^^^^^-
@@ -355,7 +355,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                                             ^^^^^^ cannot assign
@@ -363,7 +363,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                                             ^^^^^^^^^^^ cannot assign
@@ -371,7 +371,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@@ -379,7 +379,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@@ -387,7 +387,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait
@@ -395,7 +395,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait
@@ -403,7 +403,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^^^^^---------^^^^^^^^^^^^
@@ -415,7 +415,7 @@ LL |     *b = U;
    |     ------ mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:125:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^^^^^---------^^^^^^^^^^^^
@@ -427,7 +427,7 @@ LL |     *b = U;
    |     ------ mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^^^^^---------^^^^^^^^^^^^
@@ -439,7 +439,7 @@ LL |     *b = U;
    |     ------ mutable borrow later used here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:30
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                      --------^^^^^^^^^^^^-
index 339814e1e3167278085f400ad4e74bec7897902d..99739c7bce0412091437e44209c35053875ca428 100644 (file)
@@ -1,7 +1,5 @@
 // Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
 
-#![feature(bindings_after_at)]
-
 fn main() {
     struct U;
 
index 0370037f24210d9765a25f95462621ef8c5e71b7..aa02230419b5e4956577a2b7cb0319c66a98feb8 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:26:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -8,7 +8,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -17,7 +17,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:33:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -26,7 +26,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:36:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -35,7 +35,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:41:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -44,7 +44,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:46:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:44:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -66,7 +66,7 @@ LL | |     ) = (U, [U, U, U]);
    | |_____^
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:56:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:54:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -88,7 +88,7 @@ LL | |         ) = (u(), [u(), u(), u()]);
    | |_________^
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:64:9
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         -^^^^---------^^---------^
@@ -99,7 +99,7 @@ LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:69:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         -^^^^-^^^-^^-^^
@@ -111,7 +111,7 @@ LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         -^^^^^^^^---------
@@ -121,7 +121,7 @@ LL |     let a @ &mut ref mut b = &mut U;
    |         move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         -^^^^^^^^^---------^^---------^
@@ -132,7 +132,7 @@ LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -141,7 +141,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:76:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -150,7 +150,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -159,7 +159,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -168,7 +168,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -177,7 +177,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -186,7 +186,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:101:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -195,7 +195,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:101:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -204,7 +204,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11
    |
 LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -213,7 +213,7 @@ LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
    |
 LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -222,7 +222,7 @@ LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9
    |
 LL |           ref mut a @ [
    |           ^--------
@@ -240,7 +240,7 @@ LL | |         ] : [[U; 4]; 5]
    | |_________^
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:23:22
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                      ---------^^^-------------
@@ -250,7 +250,7 @@ LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                      first mutable borrow, by `a`, occurs here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:23:34
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                                  ---------^^^-
@@ -259,7 +259,7 @@ LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                                  value borrowed, by `b`, here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ^^^^^^^^^^^^---------
@@ -271,7 +271,7 @@ LL |     drop(b);
    |          - first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:41:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ^^^^^^^^^^^^---------
@@ -283,7 +283,7 @@ LL |     *b = U;
    |     ------ first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -295,7 +295,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
@@ -307,7 +307,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -319,7 +319,7 @@ LL |             drop(a);
    |                  - first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
@@ -331,7 +331,7 @@ LL |             drop(a);
    |                  - first borrow later used here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:23:34
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                      ------------^^^^^^^^^^^^-
index ef9669a6b9e5ae9fca05f23ff0dea1f983269711..9db37253c5368f862d56853178d697c99fb98835 100644 (file)
@@ -2,7 +2,6 @@
 
 // run-pass
 
-#![feature(bindings_after_at)]
 #![feature(box_patterns)]
 
 #[derive(Debug, PartialEq)]
index f731aa2e96327415c53d730954aeb738925076e8..1e2c2968c4b7aef54066556d366c265d76492365 100644 (file)
@@ -1,7 +1,5 @@
 // Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
 
-#![feature(bindings_after_at)]
-
 #[derive(Copy, Clone)]
 struct C;
 
index 183a37176ec6c070ae994bb5afae8adaa754b851..d290144b6155a6fa9cbf449c530737a8460f3200 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of partially moved value
-  --> $DIR/copy-and-move-mixed.rs:14:9
+  --> $DIR/copy-and-move-mixed.rs:12:9
    |
 LL |     let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
    |         ^^^^^^^^^^------------^
index c15167e717592e82863764101ec4e3960a8928d1..dfd4d02854dac2b3ee0de1affbb5124055cd896e 100644 (file)
@@ -7,7 +7,6 @@
 // If `binding` is allowed to influence `subpat`,
 // this would create problems for the generalization aforementioned.
 
-#![feature(bindings_after_at)]
 
 fn main() {
     struct NotCopy;
index a41fec7a3f86d89fecb03f4310d21aa436c8f4a5..d78faa682b5078f5590a78e8743183de2597cd84 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:27:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:26:9
    |
 LL |     let ref a @ b = NotCopy;
    |         -----^^^-
@@ -8,7 +8,7 @@ LL |     let ref a @ b = NotCopy;
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:30:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:29:9
    |
 LL |     let ref mut a @ b = NotCopy;
    |         ---------^^^-
@@ -17,7 +17,7 @@ LL |     let ref mut a @ b = NotCopy;
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:35:12
+  --> $DIR/default-binding-modes-both-sides-independent.rs:34:12
    |
 LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |            -----^^^-
@@ -26,7 +26,7 @@ LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |            value borrowed, by `a`, here
 
 error: borrow of moved value
-  --> $DIR/default-binding-modes-both-sides-independent.rs:35:29
+  --> $DIR/default-binding-modes-both-sides-independent.rs:34:29
    |
 LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |                             -^^^-----
@@ -36,7 +36,7 @@ LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |                             move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:43:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:42:9
    |
 LL |         ref a @ b => {
    |         -----^^^-
@@ -45,7 +45,7 @@ LL |         ref a @ b => {
    |         value borrowed, by `a`, here
 
 error[E0382]: borrow of moved value
-  --> $DIR/default-binding-modes-both-sides-independent.rs:30:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:29:9
    |
 LL |     let ref mut a @ b = NotCopy;
    |         ^^^^^^^^^^^^-   ------- move occurs because value has type `NotCopy`, which does not implement the `Copy` trait
diff --git a/src/test/ui/pattern/bindings-after-at/feature-gate-bindings_after_at.rs b/src/test/ui/pattern/bindings-after-at/feature-gate-bindings_after_at.rs
deleted file mode 100644 (file)
index d655f15..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    let x @ y = 0; //~ ERROR pattern bindings after an `@` are unstable
-}
diff --git a/src/test/ui/pattern/bindings-after-at/feature-gate-bindings_after_at.stderr b/src/test/ui/pattern/bindings-after-at/feature-gate-bindings_after_at.stderr
deleted file mode 100644 (file)
index b976ef4..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: pattern bindings after an `@` are unstable
-  --> $DIR/feature-gate-bindings_after_at.rs:2:13
-   |
-LL |     let x @ y = 0;
-   |             ^
-   |
-   = note: see issue #65490 <https://github.com/rust-lang/rust/issues/65490> for more information
-   = help: add `#![feature(bindings_after_at)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index 497d94a3db0d9547a55d838637ca254846c233b3..fe7d1eba1d9f26577a2532a5c56aedd7adb6a04a 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 
-#![feature(bindings_after_at)]
 #![deny(unused_mut)]
 
 fn main() {
index 54f04117f7def61f7c772c2a04c8b3b0384e6cd4..e7d99534d6ab05c129f36ddc4d44cbb17dd454fa 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(bindings_after_at)]
-
 fn main() {
     let mut is_mut @ not_mut = 42;
     &mut is_mut;
index a8d5e4c4c69cc2b4d2a0bfeda57d01f60258dcbc..3180bd0afc10492fecd61808999343a6e57e4c58 100644 (file)
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable
-  --> $DIR/nested-binding-modes-mut.rs:6:5
+  --> $DIR/nested-binding-modes-mut.rs:4:5
    |
 LL |     let mut is_mut @ not_mut = 42;
    |                      ------- help: consider changing this to be mutable: `mut not_mut`
@@ -8,7 +8,7 @@ LL |     &mut not_mut;
    |     ^^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable
-  --> $DIR/nested-binding-modes-mut.rs:11:5
+  --> $DIR/nested-binding-modes-mut.rs:9:5
    |
 LL |     let not_mut @ mut is_mut = 42;
    |         -------------------- help: consider changing this to be mutable: `mut not_mut`
index d5086aec93ec3bd4e978fe6661002746716e3a76..adfb0387f46a24720cfebaf34300edad063b427d 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(bindings_after_at)]
-
 fn main() {
     let ref is_ref @ is_val = 42;
     *is_ref;
index 9cc928d214993b9d3d772266325fa05c205ada61..b378fe356ce102b8e339a3384245587cec3ce304 100644 (file)
@@ -1,11 +1,11 @@
 error[E0614]: type `{integer}` cannot be dereferenced
-  --> $DIR/nested-binding-modes-ref.rs:6:5
+  --> $DIR/nested-binding-modes-ref.rs:4:5
    |
 LL |     *is_val;
    |     ^^^^^^^
 
 error[E0614]: type `{integer}` cannot be dereferenced
-  --> $DIR/nested-binding-modes-ref.rs:11:5
+  --> $DIR/nested-binding-modes-ref.rs:9:5
    |
 LL |     *is_val;
    |     ^^^^^^^
index 6296652c112124e99980f1c5bb623ef95af68508..f06563d56cb06df497dd1279cb43b8272d70fb8f 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 
-#![feature(bindings_after_at)]
 
 struct A { a: u8, b: u8 }
 
index dbec2f135fbbe2967560750b2fabb5c10d131460..5c7769ce604cf6606e67192893f074dd1857b45f 100644 (file)
@@ -1,7 +1,6 @@
 // Here we check that type ascription is syntactically invalid when
 // not in the top position of a ascribing a let binding or function parameter.
 
-#![feature(bindings_after_at)]
 
 // This has no effect.
 // We include it to demonstrate that this is the case:
index 1e957ed06892c01bdc4cfd54fcaffef856a50947..27660ae406e291b5cd6a7c219cc507172ae9903d 100644 (file)
@@ -1,23 +1,23 @@
 error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@`
-  --> $DIR/nested-type-ascription-syntactically-invalid.rs:19:15
+  --> $DIR/nested-type-ascription-syntactically-invalid.rs:18:15
    |
 LL |     let a: u8 @ b = 0;
    |               ^ expected one of 7 possible tokens
 
 error: expected one of `)`, `,`, `@`, or `|`, found `:`
-  --> $DIR/nested-type-ascription-syntactically-invalid.rs:25:15
+  --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:15
    |
 LL |     let a @ (b: u8);
    |               ^ expected one of `)`, `,`, `@`, or `|`
 
 error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `)`
-  --> $DIR/nested-type-ascription-syntactically-invalid.rs:25:19
+  --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:19
    |
 LL |     let a @ (b: u8);
    |                   ^ expected one of 7 possible tokens
 
 error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@`
-  --> $DIR/nested-type-ascription-syntactically-invalid.rs:32:15
+  --> $DIR/nested-type-ascription-syntactically-invalid.rs:31:15
    |
 LL |     let a: T1 @ Outer(b: T2);
    |               ^ expected one of 7 possible tokens
index cffff80eead11d10f5ab37a14cc68c2563b45555..383e377a5ebbb45b8c0cfb8885d2fab99d1f5a9b 100644 (file)
@@ -2,7 +2,6 @@
 
 // run-pass
 
-#![feature(bindings_after_at)]
 #![feature(box_patterns)]
 
 #[derive(Debug, PartialEq)]
index a99ec0158f02df99016eb2325a755a432a460db9..d315f7ee3b68a60b0cd84b5ec192f7d27eea55f1 100644 (file)
@@ -2,7 +2,6 @@
 
 // run-pass
 
-#![feature(bindings_after_at)]
 
 #[derive(Debug, PartialEq)]
 enum MatchArm {
index caf6d91e0011b64ca175bdf5c9ea748d563a135c..fcc361489994fb29aad4a36bc08e69fe8de4f27b 100644 (file)
@@ -2,7 +2,6 @@
 
 // run-pass
 
-#![feature(bindings_after_at)]
 
 #[derive(Debug, PartialEq)]
 enum MatchArm {
index 09df15f754538a7b4d776ca095e009b5e6e2f6f5..f167a3952ee9c3885e50d7a7c0178bf56c4a2319 100644 (file)
@@ -1,7 +1,6 @@
 // Test that `binding @ subpat` acts as a product context with respect to duplicate binding names.
 // The code that is tested here lives in resolve (see `resolve_pattern_inner`).
 
-#![feature(bindings_after_at)]
 
 fn main() {
     fn f(a @ a @ a: ()) {}
index 77a493732243038031d5634e4c400f997e9dc7a8..a165549f6b436c85f97eac61aea7f2155e261fcb 100644 (file)
@@ -1,59 +1,59 @@
 error[E0415]: identifier `a` is bound more than once in this parameter list
-  --> $DIR/pat-at-same-name-both.rs:7:14
+  --> $DIR/pat-at-same-name-both.rs:6:14
    |
 LL |     fn f(a @ a @ a: ()) {}
    |              ^ used as parameter more than once
 
 error[E0415]: identifier `a` is bound more than once in this parameter list
-  --> $DIR/pat-at-same-name-both.rs:7:18
+  --> $DIR/pat-at-same-name-both.rs:6:18
    |
 LL |     fn f(a @ a @ a: ()) {}
    |                  ^ used as parameter more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:12:20
+  --> $DIR/pat-at-same-name-both.rs:11:20
    |
 LL |         Ok(a @ b @ a)
    |                    ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:14:23
+  --> $DIR/pat-at-same-name-both.rs:13:23
    |
 LL |         | Err(a @ b @ a)
    |                       ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:19:13
+  --> $DIR/pat-at-same-name-both.rs:18:13
    |
 LL |     let a @ a @ a = ();
    |             ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:19:17
+  --> $DIR/pat-at-same-name-both.rs:18:17
    |
 LL |     let a @ a @ a = ();
    |                 ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:22:21
+  --> $DIR/pat-at-same-name-both.rs:21:21
    |
 LL |     let ref a @ ref a = ();
    |                     ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:24:29
+  --> $DIR/pat-at-same-name-both.rs:23:29
    |
 LL |     let ref mut a @ ref mut a = ();
    |                             ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:27:17
+  --> $DIR/pat-at-same-name-both.rs:26:17
    |
 LL |     let a @ (Ok(a) | Err(a)) = Ok(());
    |                 ^ used in a pattern more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
-  --> $DIR/pat-at-same-name-both.rs:27:26
+  --> $DIR/pat-at-same-name-both.rs:26:26
    |
 LL |     let a @ (Ok(a) | Err(a)) = Ok(());
    |                          ^ used in a pattern more than once
index 7e50527af0b97b69b753112f4ca8aa150d638769..4f4c96e450b644b7e2a3a6ec5c969b9287b550ae 100644 (file)
@@ -2,7 +2,6 @@
 
 // run-pass
 
-#![feature(bindings_after_at)]
 
 #[derive(Debug, PartialEq)]
 enum MatchArm {
index 18663c3fe3f9681b8eb770b542d8dcbbf2013969..ff7b625a68e4a82eddfcdc9ec56cf8c267110a42 100644 (file)
@@ -4,8 +4,6 @@
 
 // check-pass
 
-#![feature(bindings_after_at)]
-
 fn main() {
     return;
 
index a7f0d509af52169e39a6c343bd1db2ba026bb89e..2e6064aeb00744f1e1c620fe8212fed9d3f28a04 100644 (file)
@@ -73,8 +73,7 @@ mod enum_inline {
     // general; this test is relying on that.)
     two_fifty_six_variant_enum!(Visible2, N8);
 
-    #[repr(no_niche)]
-    two_fifty_six_variant_enum!(Cloaked2, N8);
+    two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2, N8);
 }
 
 mod enum_param {
@@ -96,8 +95,7 @@ mod enum_param {
     // here as above (assuming `T` is instantiated with `NonZeroU8`).
     two_fifty_six_variant_enum!(Visible2<T>);
 
-    #[repr(no_niche)]
-    two_fifty_six_variant_enum!(Cloaked2<T>);
+    two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2<T>);
 }
 
 fn main() {
@@ -157,8 +155,8 @@ fn main() {
 }
 
 macro two_fifty_six_variant_enum {
-    ($name:ident<$param:ident>) => {
-        #[derive(Debug)]
+    ($(#[$attr:meta])* $name:ident<$param:ident>) => {
+        #[derive(Debug)] $(#[$attr])*
         pub enum $name<$param> {
             _V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param),
             _V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param),
@@ -242,8 +240,8 @@ pub enum $name<$param> {
         }
     },
 
-    ($name:ident, $param:ty) => {
-        #[derive(Debug)]
+    ($(#[$attr:meta])* $name:ident, $param:ty) => {
+        #[derive(Debug)] $(#[$attr])*
         pub enum $name {
             _V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param),
             _V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param),
index a678731934f6e0e75a75cb6fc6bd453a54dadc3a..e25c6363515be7d0ff556f1ad0e9af6ad6d96345 100644 (file)
@@ -1,8 +1,8 @@
 error: lifetime may not live long enough
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -                     ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+   |                          -          ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
    |                          |
    |                          let's call the lifetime of this reference `'1`
    |
index 5cb3a404037a718e74ef3ea2670ffb492591e9fa..18ba7254446b4768a133b98113bcfafb393113c0 100644 (file)
@@ -1,22 +1,3 @@
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9
-   |
-LL | struct X<T>(T);
-   |          - required by this bound in `X`
-...
-LL | struct Struct5<T: ?Sized>{
-   |                - this type parameter needs to be `std::marker::Sized`
-LL |     _t: X<T>,
-   |         ^^^^ doesn't have a size known at compile-time
-   |
-help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
-  --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
-   |
-LL | struct X<T>(T);
-   |          ^  - ...if indirection were used here: `Box<T>`
-   |          |
-   |          this could be changed to `T: ?Sized`...
-
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
   --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19
    |
@@ -92,6 +73,25 @@ help: consider relaxing the implicit `Sized` restriction
 LL | struct Struct4<T: ?Sized>{
    |                 ^^^^^^^^
 
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9
+   |
+LL | struct X<T>(T);
+   |          - required by this bound in `X`
+...
+LL | struct Struct5<T: ?Sized>{
+   |                - this type parameter needs to be `std::marker::Sized`
+LL |     _t: X<T>,
+   |         ^^^^ doesn't have a size known at compile-time
+   |
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+  --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
+   |
+LL | struct X<T>(T);
+   |          ^  - ...if indirection were used here: `Box<T>`
+   |          |
+   |          this could be changed to `T: ?Sized`...
+
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 797406f869fe6b6b149b6e228a5352638ec64499..f332b7213d8bcc6e5b13b6721308bca4383af306 100644 (file)
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/object-unsafe-trait-references-self.rs:6:11
+  --> $DIR/object-unsafe-trait-references-self.rs:6:12
    |
 LL | fn bar(x: &dyn Trait) {}
-   |           ^^^^^^^^^^ `Trait` cannot be made into an object
+   |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
    = help: consider moving `baz` to another trait
    = help: consider moving `bat` to another trait
@@ -17,10 +17,10 @@ LL |     fn bat(&self) -> Self {}
    |                      ^^^^ ...because method `bat` references the `Self` type in its return type
 
 error[E0038]: the trait `Other` cannot be made into an object
-  --> $DIR/object-unsafe-trait-references-self.rs:10:11
+  --> $DIR/object-unsafe-trait-references-self.rs:10:12
    |
 LL | fn foo(x: &dyn Other) {}
-   |           ^^^^^^^^^^ `Other` cannot be made into an object
+   |            ^^^^^^^^^ `Other` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-references-self.rs:8:14
index a2caf846cc5febe6a3a4e7ea5650b39a9a54ae1d..4a53706f9772e0a761fa57fd2c66bc7e1422e1cb 100644 (file)
@@ -1,8 +1,17 @@
+error[E0307]: invalid `self` parameter type: ()
+  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18
+   |
+LL |     fn bar(self: ()) {}
+   |                  ^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:11
+  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12
    |
 LL | fn bar(x: &dyn Trait) {}
-   |           ^^^^^^^^^^ `Trait` cannot be made into an object
+   |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8
@@ -26,15 +35,6 @@ help: consider changing method `bar`'s `self` parameter to be `&self`
 LL |     fn bar(self: &Self) {}
    |                  ^^^^^
 
-error[E0307]: invalid `self` parameter type: ()
-  --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18
-   |
-LL |     fn bar(self: ()) {}
-   |                  ^^
-   |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0307.
diff --git a/src/test/ui/traits/vtable/vtable-diamond.rs b/src/test/ui/traits/vtable/vtable-diamond.rs
new file mode 100644 (file)
index 0000000..f64ae95
--- /dev/null
@@ -0,0 +1,39 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+#[rustc_dump_vtable]
+trait A {
+    fn foo_a(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait B: A {
+    fn foo_b(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait C: A {
+    //~^ error Vtable
+    fn foo_c(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait D: B + C {
+    //~^ error Vtable
+    fn foo_d(&self) {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+impl C for S {}
+impl D for S {}
+
+fn foo(d: &dyn D) {
+    d.foo_d();
+}
+
+fn main() {
+    foo(&S);
+}
diff --git a/src/test/ui/traits/vtable/vtable-diamond.stderr b/src/test/ui/traits/vtable/vtable-diamond.stderr
new file mode 100644 (file)
index 0000000..92a7f29
--- /dev/null
@@ -0,0 +1,35 @@
+error: Vtable entries for `<S as D>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as A>::foo_a),
+    Method(<S as B>::foo_b),
+    Method(<S as C>::foo_c),
+    TraitVPtr(<S as C>),
+    Method(<S as D>::foo_d),
+]
+  --> $DIR/vtable-diamond.rs:21:1
+   |
+LL | / trait D: B + C {
+LL | |
+LL | |     fn foo_d(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as C>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as A>::foo_a),
+    Method(<S as C>::foo_c),
+]
+  --> $DIR/vtable-diamond.rs:15:1
+   |
+LL | / trait C: A {
+LL | |
+LL | |     fn foo_c(&self) {}
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/traits/vtable/vtable-multi-level.rs b/src/test/ui/traits/vtable/vtable-multi-level.rs
new file mode 100644 (file)
index 0000000..33112b4
--- /dev/null
@@ -0,0 +1,122 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+//   O --> G --> C --> A
+//     \     \     \-> B
+//     |     |-> F --> D
+//     |           \-> E
+//     |-> N --> J --> H
+//           \     \-> I
+//           |-> M --> K
+//                 \-> L
+
+#[rustc_dump_vtable]
+trait A {
+    fn foo_a(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait B {
+    //~^ error Vtable
+    fn foo_b(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait C: A + B {
+    fn foo_c(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait D {
+    //~^ error Vtable
+    fn foo_d(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait E {
+    //~^ error Vtable
+    fn foo_e(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait F: D + E {
+    //~^ error Vtable
+    fn foo_f(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait G: C + F {
+    fn foo_g(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait H {
+    //~^ error Vtable
+    fn foo_h(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait I {
+    //~^ error Vtable
+    fn foo_i(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait J: H + I {
+    //~^ error Vtable
+    fn foo_j(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait K {
+    //~^ error Vtable
+    fn foo_k(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait L {
+    //~^ error Vtable
+    fn foo_l(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait M: K + L {
+    //~^ error Vtable
+    fn foo_m(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait N: J + M {
+    //~^ error Vtable
+    fn foo_n(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait O: G + N {
+    //~^ error Vtable
+    fn foo_o(&self) {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+impl C for S {}
+impl D for S {}
+impl E for S {}
+impl F for S {}
+impl G for S {}
+impl H for S {}
+impl I for S {}
+impl J for S {}
+impl K for S {}
+impl L for S {}
+impl M for S {}
+impl N for S {}
+impl O for S {}
+
+fn foo(_: &dyn O) {}
+
+fn main() {
+    foo(&S);
+}
diff --git a/src/test/ui/traits/vtable/vtable-multi-level.stderr b/src/test/ui/traits/vtable/vtable-multi-level.stderr
new file mode 100644 (file)
index 0000000..7700db9
--- /dev/null
@@ -0,0 +1,214 @@
+error: Vtable entries for `<S as O>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as A>::foo_a),
+    Method(<S as B>::foo_b),
+    TraitVPtr(<S as B>),
+    Method(<S as C>::foo_c),
+    Method(<S as D>::foo_d),
+    TraitVPtr(<S as D>),
+    Method(<S as E>::foo_e),
+    TraitVPtr(<S as E>),
+    Method(<S as F>::foo_f),
+    TraitVPtr(<S as F>),
+    Method(<S as G>::foo_g),
+    Method(<S as H>::foo_h),
+    TraitVPtr(<S as H>),
+    Method(<S as I>::foo_i),
+    TraitVPtr(<S as I>),
+    Method(<S as J>::foo_j),
+    TraitVPtr(<S as J>),
+    Method(<S as K>::foo_k),
+    TraitVPtr(<S as K>),
+    Method(<S as L>::foo_l),
+    TraitVPtr(<S as L>),
+    Method(<S as M>::foo_m),
+    TraitVPtr(<S as M>),
+    Method(<S as N>::foo_n),
+    TraitVPtr(<S as N>),
+    Method(<S as O>::foo_o),
+]
+  --> $DIR/vtable-multi-level.rs:95:1
+   |
+LL | / trait O: G + N {
+LL | |
+LL | |     fn foo_o(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as B>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as B>::foo_b),
+]
+  --> $DIR/vtable-multi-level.rs:19:1
+   |
+LL | / trait B {
+LL | |
+LL | |     fn foo_b(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as D>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as D>::foo_d),
+]
+  --> $DIR/vtable-multi-level.rs:30:1
+   |
+LL | / trait D {
+LL | |
+LL | |     fn foo_d(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as E>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as E>::foo_e),
+]
+  --> $DIR/vtable-multi-level.rs:36:1
+   |
+LL | / trait E {
+LL | |
+LL | |     fn foo_e(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as F>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as D>::foo_d),
+    Method(<S as E>::foo_e),
+    TraitVPtr(<S as E>),
+    Method(<S as F>::foo_f),
+]
+  --> $DIR/vtable-multi-level.rs:42:1
+   |
+LL | / trait F: D + E {
+LL | |
+LL | |     fn foo_f(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as H>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as H>::foo_h),
+]
+  --> $DIR/vtable-multi-level.rs:53:1
+   |
+LL | / trait H {
+LL | |
+LL | |     fn foo_h(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as I>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as I>::foo_i),
+]
+  --> $DIR/vtable-multi-level.rs:59:1
+   |
+LL | / trait I {
+LL | |
+LL | |     fn foo_i(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as J>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as H>::foo_h),
+    Method(<S as I>::foo_i),
+    TraitVPtr(<S as I>),
+    Method(<S as J>::foo_j),
+]
+  --> $DIR/vtable-multi-level.rs:65:1
+   |
+LL | / trait J: H + I {
+LL | |
+LL | |     fn foo_j(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as K>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as K>::foo_k),
+]
+  --> $DIR/vtable-multi-level.rs:71:1
+   |
+LL | / trait K {
+LL | |
+LL | |     fn foo_k(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as L>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as L>::foo_l),
+]
+  --> $DIR/vtable-multi-level.rs:77:1
+   |
+LL | / trait L {
+LL | |
+LL | |     fn foo_l(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as M>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as K>::foo_k),
+    Method(<S as L>::foo_l),
+    TraitVPtr(<S as L>),
+    Method(<S as M>::foo_m),
+]
+  --> $DIR/vtable-multi-level.rs:83:1
+   |
+LL | / trait M: K + L {
+LL | |
+LL | |     fn foo_m(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as N>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as H>::foo_h),
+    Method(<S as I>::foo_i),
+    TraitVPtr(<S as I>),
+    Method(<S as J>::foo_j),
+    Method(<S as K>::foo_k),
+    TraitVPtr(<S as K>),
+    Method(<S as L>::foo_l),
+    TraitVPtr(<S as L>),
+    Method(<S as M>::foo_m),
+    TraitVPtr(<S as M>),
+    Method(<S as N>::foo_n),
+]
+  --> $DIR/vtable-multi-level.rs:89:1
+   |
+LL | / trait N: J + M {
+LL | |
+LL | |     fn foo_n(&self) {}
+LL | | }
+   | |_^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/traits/vtable/vtable-multiple.rs b/src/test/ui/traits/vtable/vtable-multiple.rs
new file mode 100644 (file)
index 0000000..cb0d0b7
--- /dev/null
@@ -0,0 +1,31 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+#[rustc_dump_vtable]
+trait A {
+    fn foo_a(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait B {
+    //~^ error Vtable
+    fn foo_b(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait C: A + B {
+    //~^ error Vtable
+    fn foo_c(&self) {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+impl C for S {}
+
+fn foo(c: &dyn C) {}
+
+fn main() {
+    foo(&S);
+}
diff --git a/src/test/ui/traits/vtable/vtable-multiple.stderr b/src/test/ui/traits/vtable/vtable-multiple.stderr
new file mode 100644 (file)
index 0000000..f51b083
--- /dev/null
@@ -0,0 +1,33 @@
+error: Vtable entries for `<S as C>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as A>::foo_a),
+    Method(<S as B>::foo_b),
+    TraitVPtr(<S as B>),
+    Method(<S as C>::foo_c),
+]
+  --> $DIR/vtable-multiple.rs:16:1
+   |
+LL | / trait C: A + B {
+LL | |
+LL | |     fn foo_c(&self) {}
+LL | | }
+   | |_^
+
+error: Vtable entries for `<S as B>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as B>::foo_b),
+]
+  --> $DIR/vtable-multiple.rs:10:1
+   |
+LL | / trait B {
+LL | |
+LL | |     fn foo_b(&self) {}
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/traits/vtable/vtable-vacant.rs b/src/test/ui/traits/vtable/vtable-vacant.rs
new file mode 100644 (file)
index 0000000..ebea941
--- /dev/null
@@ -0,0 +1,28 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+// B --> A
+
+#[rustc_dump_vtable]
+trait A {
+    fn foo_a1(&self) {}
+    fn foo_a2(&self) where Self: Sized {}
+}
+
+#[rustc_dump_vtable]
+trait B: A {
+    //~^ error Vtable
+    fn foo_b1(&self) {}
+    fn foo_b2() where Self: Sized {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+
+fn foo(_: &dyn B) {}
+
+fn main() {
+    foo(&S);
+}
diff --git a/src/test/ui/traits/vtable/vtable-vacant.stderr b/src/test/ui/traits/vtable/vtable-vacant.stderr
new file mode 100644 (file)
index 0000000..768cca5
--- /dev/null
@@ -0,0 +1,20 @@
+error: Vtable entries for `<S as B>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<S as A>::foo_a1),
+    Vacant,
+    Method(<S as B>::foo_b1),
+    Vacant,
+]
+  --> $DIR/vtable-vacant.rs:13:1
+   |
+LL | / trait B: A {
+LL | |
+LL | |     fn foo_b1(&self) {}
+LL | |     fn foo_b2() where Self: Sized {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index d0f3be336dccb2b36419e9b5a89dbd879676373e..28ac61a6b984a6165c820bedb20085eeacd6c7a1 100644 (file)
@@ -28,7 +28,7 @@ LL | type WrongGeneric<T> = impl 'static;
            found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:17:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:16:30
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                              ^^^^^^^^^^^^^^^
index 6394a1f8e8509f1f6b4780f217e46ae2dacab15b..90a753b5a6de16d58995cd5f7433fff64ab5d17a 100644 (file)
@@ -36,16 +36,7 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:24
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
index 7496d96fa2136aff302dae359aa353e11b8aa9fd..b8ca8e46079aad4c5db20b159b4fcd62da6f5be7 100644 (file)
@@ -19,7 +19,7 @@ LL | type WrongGeneric<T> = impl 'static;
            found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:17:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:16:30
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                              ^^^^^^^^^^^^^^^
index 49ead8b094c1977f95bcef33e12889ee18c5b28d..e50282201074ecb98c291816f2adac9d038e3d40 100644 (file)
@@ -27,16 +27,7 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:24
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
index 3dda34ff668ced241736e9bc2d45f0f54781a0ba..9f647d9e737fecbdb14fcf2a99fcaec1761e0e2a 100644 (file)
@@ -11,7 +11,6 @@ fn main() {
 
 type WrongGeneric<T> = impl 'static;
 //~^ ERROR the parameter type `T` may not live long enough
-//~| ERROR the parameter type `T` may not live long enough
 //~| ERROR: at least one trait must be specified
 
 fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
index 481d66dd8110f5400f6b65738d3fe26ffeebd63a..e2b8b19aeba1bb815d00c8be2e48a06d53cf09c6 100644 (file)
@@ -8,13 +8,13 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
@@ -28,7 +28,7 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
index d90f328708a7bdeb9a482a1a903952248437ad2f..61e8da91bbaa98d26c237bfd75488ec993c5297a 100644 (file)
@@ -16,52 +16,5 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0308`.
index 0343a769564af807e62b9dffdd9ce948138abca3..3a4d1d90c039731d4a1396e44dd4402a7922400b 100644 (file)
@@ -1,11 +1,11 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
@@ -19,7 +19,7 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
+  --> $DIR/issue-57611-trait-alias.rs:24:9
    |
 LL |         |x| x
    |         ^^^^^
index d019f40757eedf9cc8af457cb509f25af57ba602..f65e91e52c7132b90589e3c7e19b9cbefc222f4c 100644 (file)
@@ -7,52 +7,5 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'<empty> X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:28:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:20:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
index ccc727e0bf01b10349e95ac0a7378fdbeb2518ba..508ecdd88a482b4c2a7cb569228199459368ce6c 100644 (file)
@@ -19,10 +19,6 @@ trait Foo {
 impl Foo for X {
     type Bar = impl Baz<Self, Self>;
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR mismatched types
-    //~| ERROR mismatched types
 
     fn bar(&self) -> Self::Bar {
         |x| x
index b7c8a58a656290da2fabd82e5ca7133a2c586c55..cee5e5a01cc2a5aefc6fb6df8065ac87865bc863 100644 (file)
@@ -9,7 +9,6 @@ trait Bug {
 impl Bug for &() {
     type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable
     //~^ ERROR the trait bound `(): Bug` is not satisfied
-    //~^^ ERROR the trait bound `(): Bug` is not satisfied
 
     const FUN: fn() -> Self::Item = || ();
     //~^ ERROR type alias impl trait is not permitted here
index 4906ea9c2e261a6c0d58560992398052c880c7b0..a9df74689df295b76bb0c60c79771bf18817c75f 100644 (file)
@@ -8,7 +8,7 @@ LL |     type Item = impl Bug;
    = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: type alias impl trait is not permitted here
-  --> $DIR/issue-60371.rs:14:40
+  --> $DIR/issue-60371.rs:13:40
    |
 LL |     const FUN: fn() -> Self::Item = || ();
    |                                        ^
@@ -25,16 +25,7 @@ LL |     type Item = impl Bug;
    = help: the following implementations were found:
              <&() as Bug>
 
-error[E0277]: the trait bound `(): Bug` is not satisfied
-  --> $DIR/issue-60371.rs:10:17
-   |
-LL |     type Item = impl Bug;
-   |                 ^^^^^^^^ the trait `Bug` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <&() as Bug>
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0658.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.rs b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs
new file mode 100644 (file)
index 0000000..4b0f2af
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(member_constraints)]
+#![feature(type_alias_impl_trait)]
+//~^ WARN incomplete
+
+pub trait A {
+    type B;
+    fn f(&self) -> Self::B;
+}
+impl<'a, 'b> A for () {
+    //~^ ERROR the lifetime parameter `'a` is not constrained
+    //~| ERROR the lifetime parameter `'b` is not constrained
+    type B = impl core::fmt::Debug;
+    //~^ ERROR is unstable
+
+
+    fn f(&self) -> Self::B {}
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr
new file mode 100644 (file)
index 0000000..4506a6e
--- /dev/null
@@ -0,0 +1,34 @@
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/issue-74761-2.rs:12:14
+   |
+LL |     type B = impl core::fmt::Debug;
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable
+
+warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74761-2.rs:2:12
+   |
+LL | #![feature(type_alias_impl_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761-2.rs:9:6
+   |
+LL | impl<'a, 'b> A for () {
+   |      ^^ unconstrained lifetime parameter
+
+error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-74761-2.rs:9:10
+   |
+LL | impl<'a, 'b> A for () {
+   |          ^^ unconstrained lifetime parameter
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0207, E0658.
+For more information about an error, try `rustc --explain E0207`.
index 38aa18fe40ee71ab57da0c7d82945a0b14904b34..11756017ad846538f7dbdc74ec5760573655d71d 100644 (file)
@@ -5,9 +5,9 @@
 #![feature(min_type_alias_impl_trait)]
 
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
-//~^ ERROR could not find defining uses
 
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+    //~^ ERROR concrete type differs from previous defining opaque type
     (a.clone(), a)
 }
 
index c00973c0761b058c4410913294223756e8ec9e7f..52b0462de988c28d21c987efc822a0adbae587eb 100644 (file)
@@ -1,8 +1,14 @@
-error: could not find defining uses
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:7:52
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
    |
-LL | type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
-   |                                                    ^^^^^^^^^^^^^
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `B`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
+   |
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 17e900058113dd8283be89c3672611d5beb32af9..5f25365666c7f9d5b78a1d6899f3840dc5beafb6 100644 (file)
@@ -11,6 +11,7 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>)
 }
 
 fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+    //~^ ERROR concrete type differs from previous defining opaque type
     (a, b)
     //~^ ERROR mismatched types
 }
index bbe709dccab4eb6e9404d4b5cba860ad4a7a2592..3d943b77af57da8a7586a1d5a5ba97514ae8886c 100644 (file)
@@ -1,10 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9
    |
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
    |      |
    |      expected type parameter
+LL |
 LL |     (a, b)
    |         ^ expected type parameter `A`, found type parameter `B`
    |
@@ -13,6 +14,18 @@ LL |     (a, b)
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1
+   |
+LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
+   |
+LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-83693.rs b/src/test/ui/typeck/issue-83693.rs
new file mode 100644 (file)
index 0000000..a425582
--- /dev/null
@@ -0,0 +1,19 @@
+// Regression test for the ICE described in #83693.
+
+#![feature(fn_traits)]
+#![crate_type="lib"]
+
+impl F {
+//~^ ERROR: cannot find type `F` in this scope [E0412]
+    fn call() {
+        <Self as Fn(&TestResult)>::call
+        //~^ ERROR: cannot find type `TestResult` in this scope [E0412]
+        //~| associated type bindings are not allowed here [E0229]
+    }
+}
+
+fn call() {
+    <x as Fn(&usize)>::call
+    //~^ ERROR: cannot find type `x` in this scope [E0412]
+    //~| ERROR: associated type bindings are not allowed here [E0229]
+}
diff --git a/src/test/ui/typeck/issue-83693.stderr b/src/test/ui/typeck/issue-83693.stderr
new file mode 100644 (file)
index 0000000..e5ef0d0
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0412]: cannot find type `F` in this scope
+  --> $DIR/issue-83693.rs:6:6
+   |
+LL | impl F {
+   |      ^ help: a trait with a similar name exists: `Fn`
+   | 
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0412]: cannot find type `TestResult` in this scope
+  --> $DIR/issue-83693.rs:9:22
+   |
+LL |         <Self as Fn(&TestResult)>::call
+   |                      ^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `x` in this scope
+  --> $DIR/issue-83693.rs:16:6
+   |
+LL |     <x as Fn(&usize)>::call
+   |      ^ not found in this scope
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-83693.rs:9:18
+   |
+LL |         <Self as Fn(&TestResult)>::call
+   |                  ^^^^^^^^^^^^^^^ associated type not allowed here
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-83693.rs:16:11
+   |
+LL |     <x as Fn(&usize)>::call
+   |           ^^^^^^^^^^ associated type not allowed here
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0229, E0412.
+For more information about an error, try `rustc --explain E0229`.
diff --git a/src/test/ui/typeck/issue-84768.rs b/src/test/ui/typeck/issue-84768.rs
new file mode 100644 (file)
index 0000000..ffa9282
--- /dev/null
@@ -0,0 +1,10 @@
+// Regression test for the ICE described in #84768.
+
+#![feature(fn_traits)]
+#![crate_type="lib"]
+
+fn transform_mut<F>(f: F) where F: for<'b> FnOnce(&'b mut u8) {
+    <F as FnOnce(&mut u8)>::call_once(f, 1)
+    //~^ ERROR: associated type bindings are not allowed here [E0229]
+    //~| ERROR: mismatched types [E0308]
+}
diff --git a/src/test/ui/typeck/issue-84768.stderr b/src/test/ui/typeck/issue-84768.stderr
new file mode 100644 (file)
index 0000000..0a79d53
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-84768.rs:7:11
+   |
+LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
+   |           ^^^^^^^^^^^^^^^ associated type not allowed here
+
+error[E0308]: mismatched types
+  --> $DIR/issue-84768.rs:7:42
+   |
+LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
+   |                                          ^ expected tuple, found integer
+   |
+   = note: expected tuple `(&mut u8,)`
+               found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0229, E0308.
+For more information about an error, try `rustc --explain E0229`.
index e8414903d548fbd80e8e6efdbbaa3ff54694e041..3cb3a18cb7544cbfdab377adba0842e91d1ecfb1 100644 (file)
@@ -36,8 +36,8 @@ fn deref_union_field(mut u: URef) {
 
 fn assign_noncopy_union_field(mut u: URefCell) {
     // FIXME(thir-unsafeck)
-    u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping
-    u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping
+    u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping
+    u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping
     u.a.1 = 1; // OK
 }
 
index 51f19879c819550408bd3c295846f2ae1dcb696c..e88642b0ff7adbc8ef7894468689e74c90d6bf92 100644 (file)
@@ -6,6 +6,22 @@ LL |     *(u.p) = 13;
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:39:5
+   |
+LL |     u.a = (RefCell::new(0), 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:40:5
+   |
+LL |     u.a.0 = RefCell::new(0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
 error[E0133]: access to union field is unsafe and requires unsafe function or block
   --> $DIR/union-unsafe.rs:47:6
    |
@@ -70,6 +86,6 @@ LL |     *u3.a = String::from("new");
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 9 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
index a0eb7d10bd94a0ab61200d679765757bf4369659..f6b48938f9b04437bf699c469ca51c284f135498 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/wf-foreign-fn-decl-ret.rs:11:12
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:25
    |
+LL | pub trait Foo {
+   | ------------- required by this bound in `Foo`
+...
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
-   |            ^^^^^^^ the trait `Foo` is not implemented for `()`
+   |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
index 9687658feba43b50936900e63c938265b4957242..ca90e9222dea9c9f29773f7a5153a9cd4ddbc47b 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-arg.rs:10:14
+  --> $DIR/wf-in-fn-arg.rs:10:15
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL | fn bar<T>(_: &MustBeCopy<T>)
-   |              ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |               ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 33300b3964258e0b21571481625e282d13f942d4..20aa97707105e2156079225216800fd2bb60229f 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-type-arg.rs:9:8
+  --> $DIR/wf-in-fn-type-arg.rs:9:11
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL |     x: fn(MustBeCopy<T>)
-   |        ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |           ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 1ffc47e6d826c842603291ac253aa276562d6612..48af696c3a7527aac89b520c901bd24bc0c5ff98 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-fn-type-ret.rs:9:8
+  --> $DIR/wf-in-fn-type-ret.rs:9:16
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL |     x: fn() -> MustBeCopy<T>
-   |        ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |                ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 8606eabf59c146f0680c8112cae0db333d55102a..b3b919a569ed41fa0b08a79355bab4088a6dbb55 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/wf-in-obj-type-trait.rs:11:8
+  --> $DIR/wf-in-obj-type-trait.rs:11:19
    |
 LL | struct MustBeCopy<T:Copy> {
    |                     ---- required by this bound in `MustBeCopy`
 ...
 LL |     x: dyn Object<MustBeCopy<T>>
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |                   ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index c3d5d2b9669b80edd54c11e24b8ca3519e6d816a..2a129538f76333bbfb69cf8b829a255f8947227a 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-default-fn-arg.rs:11:22
+  --> $DIR/wf-trait-default-fn-arg.rs:11:23
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              -- required by this bound in `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>) {
-   |                      ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
+   |                       ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 4510f50feea58871f3e8bd03638732e613d85f36..7693aa6d2d583ed64a597ddc705a1488cea19216 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-fn-arg.rs:10:22
+  --> $DIR/wf-trait-fn-arg.rs:10:23
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              -- required by this bound in `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>);
-   |                      ^^^^^^^^^^ the trait `Eq` is not implemented for `Self`
+   |                       ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 27277d966b3cfa454d6dea7f724cb961c036251c..cebef2951ee69617852844894164b54ed478a7da 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 27277d966b3cfa454d6dea7f724cb961c036251c
+Subproject commit cebef2951ee69617852844894164b54ed478a7da
index a46a7407df0ceba21331d46cf938be5a0c8c2bc6..6ad702f8eafdf28a1130c4c9f6a8bea66313bb91 100644 (file)
@@ -106,7 +106,7 @@ fn exit_lint_attrs(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute])
 
     fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
         let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
-        self.check_missing_docs_attrs(cx, attrs, krate.item.inner, "the", "crate");
+        self.check_missing_docs_attrs(cx, attrs, krate.module().inner, "the", "crate");
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
index b59dbb3e76c6455ac99d678f4bba6cca14bd7fd6..c734051ccf320b086567185414793a707c50a379 100644 (file)
@@ -55,11 +55,11 @@ note: captured value is not `Send`
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
-note: captured value is not `Send`
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
   --> $DIR/future_not_send.rs:20:40
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`
+   |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
index 68e28795347e91f8515dbd1fd7871678b2a389dd..28089e85b55b493dbb3610e91f3f52ab9d930dfe 100644 (file)
@@ -98,7 +98,7 @@ pub struct TestProps {
     // a proc-macro and needs `#![crate_type = "proc-macro"]`. This ensures
     // that the aux file is compiled as a `proc-macro` and not as a `dylib`.
     pub no_prefer_dynamic: bool,
-    // Run --pretty expanded when running pretty printing tests
+    // Run -Zunpretty expanded when running pretty printing tests
     pub pretty_expanded: bool,
     // Which pretty mode are we testing with, default to 'normal'
     pub pretty_mode: String,
index 181ce0f2c3de5808f483e95249f9bd70c29ab577..dee1d315b3d0ee80746db2f132270dbbaf7637bf 100644 (file)
@@ -619,7 +619,7 @@ fn run_pretty_test(&self) {
             return;
         }
 
-        // additionally, run `--pretty expanded` and try to build it.
+        // additionally, run `-Zunpretty=expanded` and try to build it.
         let proc_res = self.print_source(ReadFrom::Path, "expanded");
         if !proc_res.status.success() {
             self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
index bf2830254e8190cfeff90f9fe2ca429ad7f2cc48..7bdf527d8842bbedba3da1795ea5a4bd8b57a165 100644 (file)
@@ -15,6 +15,11 @@ fn check_html_file(file: &Path) -> usize {
         "MISSING_ENDTAG_BEFORE",
         "INSERTING_TAG",
         "DISCARDING_UNEXPECTED",
+        // This error is caused by nesting the Notable Traits tooltip within an <h4> tag.
+        // The solution is to avoid doing that, but we need to have the <h4> tags for accessibility
+        // reasons, and we need the Notable Traits tooltip to help everyone understand the Iterator
+        // combinators
+        "TAG_NOT_ALLOWED_IN",
     ];
     let to_mute_s = to_mute.join(",");
     let mut command = Command::new("tidy");
index 517e9d62c095a04fa497d6b6d3c63b31696a88b4..a82a0527057eab59c24a0452add35ccb39584e80 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 517e9d62c095a04fa497d6b6d3c63b31696a88b4
+Subproject commit a82a0527057eab59c24a0452add35ccb39584e80
index fe00358888a24c64878abc15f09b0e60e16db9d6..ea105f9396a9dab68e71efb06016b7c76c83ba7c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fe00358888a24c64878abc15f09b0e60e16db9d6
+Subproject commit ea105f9396a9dab68e71efb06016b7c76c83ba7c
index 26d6081c8816b65a1ebb562585c9ef06e0441846..869245d5b9554935736d494abb9fea3409abf915 100644 (file)
@@ -17,12 +17,16 @@ path = "lib.rs"
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
 features = [
-  "aclapi",
   "accctrl",
+  "aclapi",
   "basetsd",
+  "cfg",
   "consoleapi",
   "errhandlingapi",
+  "evntrace",
   "fibersapi",
+  "in6addr",
+  "inaddr",
   "ioapiset",
   "jobapi",
   "jobapi2",
@@ -32,6 +36,8 @@ features = [
   "memoryapi",
   "minschannel",
   "minwinbase",
+  "mstcpip",
+  "mswsock",
   "namedpipeapi",
   "ntdef",
   "ntsecapi",
@@ -54,6 +60,8 @@ features = [
   "winbase",
   "wincon",
   "wincrypt",
+  "windef",
+  "winioctl",
   "winsock2",
   "ws2def",
   "ws2ipdef",
index 799d685ce5ca1844e698cd49f4d0726a93da3dd1..32660ae2aeeefd5b72a1865a4a6aed4d8bd2f585 100644 (file)
 const EXCEPTIONS: &[(&str, &str)] = &[
     ("mdbook", "MPL-2.0"),                                  // mdbook
     ("openssl", "Apache-2.0"),                              // cargo, mdbook
-    ("fuchsia-zircon-sys", "BSD-3-Clause"),                 // rustdoc, rustc, cargo
-    ("fuchsia-zircon", "BSD-3-Clause"), // rustdoc, rustc, cargo (jobserver & tempdir)
-    ("colored", "MPL-2.0"),             // rustfmt
-    ("ordslice", "Apache-2.0"),         // rls
-    ("ryu", "Apache-2.0 OR BSL-1.0"),   // rls/cargo/... (because of serde)
-    ("bytesize", "Apache-2.0"),         // cargo
-    ("im-rc", "MPL-2.0+"),              // cargo
-    ("sized-chunks", "MPL-2.0+"),       // cargo via im-rc
-    ("bitmaps", "MPL-2.0+"),            // cargo via im-rc
+    ("colored", "MPL-2.0"),                                 // rustfmt
+    ("ordslice", "Apache-2.0"),                             // rls
+    ("ryu", "Apache-2.0 OR BSL-1.0"),                       // rls/cargo/... (because of serde)
+    ("bytesize", "Apache-2.0"),                             // cargo
+    ("im-rc", "MPL-2.0+"),                                  // cargo
+    ("sized-chunks", "MPL-2.0+"),                           // cargo via im-rc
+    ("bitmaps", "MPL-2.0+"),                                // cargo via im-rc
     ("crossbeam-queue", "MIT/Apache-2.0 AND BSD-2-Clause"), // rls via rayon
-    ("instant", "BSD-3-Clause"),        // rustc_driver/tracing-subscriber/parking_lot
-    ("snap", "BSD-3-Clause"),           // rustc
+    ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
+    ("snap", "BSD-3-Clause"),    // rustc
     // FIXME: this dependency violates the documentation comment above:
     ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
 ];
     "fixedbitset",
     "flate2",
     "fortanix-sgx-abi",
-    "fuchsia-zircon",
-    "fuchsia-zircon-sys",
     "generic-array",
     "getopts",
     "getrandom",
     "itertools",
     "itoa",
     "jobserver",
-    "kernel32-sys",
     "lazy_static",
     "libc",
     "libz-sys",
     "version_check",
     "wasi",
     "winapi",
-    "winapi-build",
     "winapi-i686-pc-windows-gnu",
     "winapi-util",
     "winapi-x86_64-pc-windows-gnu",
index 094d6ad00ce785097b2113c238df3156bd57e871..3ebf789f5a8dfa4d1d653d65a125a99a50b3294c 100644 (file)
@@ -1 +1 @@
-1.55.0
+1.56.0
index bf30927448a8026d5ef0382283122a9f93ce2b6c..81c6719647fc1476ff7bf3d2bbc5ddb9e154f8aa 100644 (file)
@@ -112,6 +112,14 @@ message_on_add = """\
 """
 message_on_remove = "Issue #{number}'s nomination request has been removed."
 
+[notify-zulip."A-edition-2021"]
+required_labels = ["C-bug"]
+zulip_stream = 268952 # #edition 2021
+topic = "Edition Bugs"
+message_on_add = """\
+Issue #{number} "{title}" has been added.
+"""
+
 [github-releases]
 format = "rustc"
 project-name = "Rust"