]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #92917 - jackh726:issue-91762-2, r=nikomatsakis
authorMatthias Krüger <matthias.krueger@famsik.de>
Tue, 8 Feb 2022 15:40:48 +0000 (16:40 +0100)
committerGitHub <noreply@github.com>
Tue, 8 Feb 2022 15:40:48 +0000 (16:40 +0100)
Don't constrain projection predicates with inference vars in GAT substs

cc #91762

Not a fix, but a mitigation to prevent a backwards-compatible hazard where we normalize using a predicate only because it's the only one available, but shouldn't. This would constrain an inference variable which didn't really want. We already do this when selecting a projection candidate, which isn't always correct. But changing that is a problem for a different day.

Also found out that a suggestion for `await`ing a future was using the wrong substs.

r? ``@nikomatsakis``

517 files changed:
compiler/rustc_ast/src/util/comments.rs
compiler/rustc_ast/src/util/comments/tests.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_borrowck/src/type_check/input_output.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_borrowck/src/type_check/relate_tys.rs
compiler/rustc_borrowck/src/universal_regions.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/global_allocator.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_data_structures/src/vec_map.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_infer/src/infer/at.rs
compiler/rustc_infer/src/infer/canonical/query_response.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/equate.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
compiler/rustc_infer/src/infer/glb.rs
compiler/rustc_infer/src/infer/lattice.rs
compiler/rustc_infer/src/infer/lub.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/opaque_types/table.rs [new file with mode: 0644]
compiler/rustc_infer/src/infer/outlives/mod.rs
compiler/rustc_infer/src/infer/outlives/obligations.rs
compiler/rustc_infer/src/infer/sub.rs
compiler/rustc_infer/src/infer/undo_log.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_middle/src/infer/canonical.rs
compiler/rustc_middle/src/ty/_match.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/flags.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_query_system/src/dep_graph/serialized.rs
compiler/rustc_serialize/src/json.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/spec/abi.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/codegen.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/object_safety.rs
compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/chalk/mod.rs
compiler/rustc_traits/src/implied_outlives_bounds.rs
compiler/rustc_traits/src/normalize_erasing_regions.rs
compiler/rustc_type_ir/src/lib.rs
compiler/rustc_typeck/src/check/_match.rs
compiler/rustc_typeck/src/check/callee.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/closure.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/expectation.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fallback.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
compiler/rustc_typeck/src/check/inherited.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/explicit.rs
library/alloc/tests/lib.rs
library/alloc/tests/str.rs
library/core/src/num/mod.rs
library/core/src/num/wrapping.rs
library/core/src/str/mod.rs
library/core/src/str/validations.rs
library/std/src/ffi/c_str.rs
library/std/src/fs.rs
library/std/src/io/buffered/bufreader.rs
library/std/src/io/buffered/bufwriter.rs
library/std/src/io/cursor.rs
library/std/src/io/error.rs
library/std/src/io/error/repr_bitpacked.rs [new file with mode: 0644]
library/std/src/io/error/repr_unpacked.rs [new file with mode: 0644]
library/std/src/io/error/tests.rs
library/std/src/io/impls.rs
library/std/src/io/mod.rs
library/std/src/io/tests.rs
library/std/src/net/mod.rs
library/std/src/net/udp.rs
library/std/src/os/fd/owned.rs
library/std/src/os/unix/fs.rs
library/std/src/os/unix/net/addr.rs
library/std/src/os/wasi/fs.rs
library/std/src/os/windows/io/socket.rs
library/std/src/sys/hermit/fs.rs
library/std/src/sys/hermit/mod.rs
library/std/src/sys/hermit/net.rs
library/std/src/sys/hermit/stdio.rs
library/std/src/sys/hermit/thread.rs
library/std/src/sys/sgx/mod.rs
library/std/src/sys/sgx/net.rs
library/std/src/sys/solid/fs.rs
library/std/src/sys/solid/mod.rs
library/std/src/sys/solid/net.rs
library/std/src/sys/solid/os.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/l4re.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/net.rs
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/process/process_fuchsia.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/process/process_vxworks.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unsupported/common.rs
library/std/src/sys/unsupported/os.rs
library/std/src/sys/wasi/fs.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys/windows/mod.rs
library/std/src/sys/windows/net.rs
library/std/src/sys/windows/process.rs
library/std/src/sys/windows/stdio.rs
library/std/src/sys/windows/thread.rs
library/std/src/sys_common/fs.rs
library/std/src/sys_common/net.rs
library/test/src/console.rs
library/test/src/formatters/json.rs
library/test/src/formatters/junit.rs
library/test/src/formatters/pretty.rs
library/test/src/formatters/terse.rs
library/test/src/test_result.rs
library/test/src/tests.rs
library/test/src/types.rs
src/bootstrap/bin/main.rs
src/bootstrap/bin/rustc.rs
src/bootstrap/bootstrap.py
src/bootstrap/build.rs
src/bootstrap/lib.rs
src/bootstrap/setup.rs
src/doc/unstable-book/src/language-features/c-unwind.md
src/etc/natvis/libstd.natvis
src/etc/pre-commit.sh [deleted file]
src/etc/pre-push.sh [new file with mode: 0755]
src/librustdoc/clean/mod.rs
src/librustdoc/doctest.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/markdown/tests.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/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/html_tags.rs
src/librustdoc/scrape_examples.rs
src/test/codegen/unwind-abis/aapcs-unwind-abi.rs [new file with mode: 0644]
src/test/codegen/unwind-abis/cdecl-unwind-abi.rs [new file with mode: 0644]
src/test/codegen/unwind-abis/fastcall-unwind-abi.rs [new file with mode: 0644]
src/test/codegen/unwind-abis/sysv64-unwind-abi.rs [new file with mode: 0644]
src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs [new file with mode: 0644]
src/test/codegen/unwind-abis/win64-unwind-abi.rs [new file with mode: 0644]
src/test/incremental/hashes/function_interfaces.rs
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_crate.txt
src/test/run-make-fulldeps/coverage/no_cov_crate.rs
src/test/run-make-fulldeps/libtest-json/output-default.json
src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile [new file with mode: 0644]
src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs [new file with mode: 0644]
src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs [new file with mode: 0644]
src/test/rustdoc-gui/mobile.goml
src/test/rustdoc-gui/sidebar-mobile.goml
src/test/rustdoc-gui/sidebar.goml
src/test/rustdoc-gui/type-declation-overflow.goml
src/test/rustdoc-ui/block-doc-comment.rs [new file with mode: 0644]
src/test/rustdoc-ui/block-doc-comment.stdout [new file with mode: 0644]
src/test/rustdoc-ui/check-attr-test.rs
src/test/rustdoc-ui/check-attr-test.stderr
src/test/rustdoc-ui/check-attr.rs
src/test/rustdoc-ui/check-attr.stderr
src/test/rustdoc-ui/intra-doc/macro-rules.rs [new file with mode: 0644]
src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs [new file with mode: 0644]
src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr [new file with mode: 0644]
src/test/rustdoc-ui/suggestions/html-as-generics.fixed [new file with mode: 0644]
src/test/rustdoc-ui/suggestions/html-as-generics.rs [new file with mode: 0644]
src/test/rustdoc-ui/suggestions/html-as-generics.stderr [new file with mode: 0644]
src/test/rustdoc/strip-block-doc-comments-stars.rs
src/test/ui/allocator/not-an-allocator.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/impl-trait-return-missing-constraint.rs
src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
src/test/ui/async-await/issue-64130-4-async-move.rs
src/test/ui/async-await/issue-64130-4-async-move.stderr
src/test/ui/async-await/issue-70818.rs
src/test/ui/async-await/issue-70818.stderr
src/test/ui/async-await/issue-70935-complex-spans.rs
src/test/ui/async-await/issue-70935-complex-spans.stderr
src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
src/test/ui/async-await/no-const-async.rs
src/test/ui/async-await/no-const-async.stderr
src/test/ui/async-await/recursive-async-impl-trait-type.rs
src/test/ui/async-await/suggest-missing-await.rs
src/test/ui/async-await/suggest-missing-await.stderr
src/test/ui/cast/casts-differing-anon.rs
src/test/ui/cast/casts-differing-anon.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr
src/test/ui/codemap_tests/unicode.stderr
src/test/ui/conservative_impl_trait.stderr
src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs
src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
src/test/ui/consts/const-tup-index-span.stderr
src/test/ui/consts/const_fn_trait_bound.stock.stderr
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
src/test/ui/feature-gates/feature-gate-allow_fail.rs [deleted file]
src/test/ui/feature-gates/feature-gate-allow_fail.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr [deleted file]
src/test/ui/fmt/format-args-capture-issue-93378.rs [new file with mode: 0644]
src/test/ui/fmt/format-args-capture-issue-93378.stderr [new file with mode: 0644]
src/test/ui/fmt/format-args-capture.rs
src/test/ui/generator/issue-88653.rs
src/test/ui/generator/issue-88653.stderr
src/test/ui/generator/type-mismatch-signature-deduction.rs
src/test/ui/generator/type-mismatch-signature-deduction.stderr
src/test/ui/generic-associated-types/issue-87258_a.rs
src/test/ui/generic-associated-types/issue-87258_a.stderr
src/test/ui/generic-associated-types/issue-87258_b.rs
src/test/ui/generic-associated-types/issue-87258_b.stderr
src/test/ui/generic-associated-types/issue-88595.rs
src/test/ui/generic-associated-types/issue-88595.stderr
src/test/ui/generic-associated-types/issue-92096.migrate.stderr
src/test/ui/generic-associated-types/issue-92096.rs
src/test/ui/impl-trait/auto-trait-leak.rs
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/auto-trait.rs
src/test/ui/impl-trait/auto-trait.stderr
src/test/ui/impl-trait/bound-normalization-fail.rs
src/test/ui/impl-trait/bound-normalization-fail.stderr
src/test/ui/impl-trait/does-not-live-long-enough.stderr
src/test/ui/impl-trait/equality.rs
src/test/ui/impl-trait/equality.stderr
src/test/ui/impl-trait/equality2.stderr
src/test/ui/impl-trait/fallback.rs [new file with mode: 0644]
src/test/ui/impl-trait/hidden-lifetimes.rs
src/test/ui/impl-trait/hidden-lifetimes.stderr
src/test/ui/impl-trait/issue-55872-1.rs
src/test/ui/impl-trait/issue-55872-1.stderr
src/test/ui/impl-trait/issue-55872-2.rs
src/test/ui/impl-trait/issue-55872-2.stderr
src/test/ui/impl-trait/issue-55872-3.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-55872-3.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-55872.rs
src/test/ui/impl-trait/issue-55872.stderr
src/test/ui/impl-trait/issue-72911.rs
src/test/ui/impl-trait/issue-72911.stderr
src/test/ui/impl-trait/issues/issue-70877.rs
src/test/ui/impl-trait/issues/issue-70877.stderr
src/test/ui/impl-trait/issues/issue-78722.rs
src/test/ui/impl-trait/issues/issue-78722.stderr
src/test/ui/impl-trait/issues/issue-86201.rs
src/test/ui/impl-trait/issues/issue-86201.stderr [deleted file]
src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-88236-2.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-88236-2.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-88236.rs [new file with mode: 0644]
src/test/ui/impl-trait/lifetimes2.rs [new file with mode: 0644]
src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
src/test/ui/impl-trait/negative-reasoning.rs
src/test/ui/impl-trait/negative-reasoning.stderr
src/test/ui/impl-trait/nested_impl_trait.rs
src/test/ui/impl-trait/nested_impl_trait.stderr
src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
src/test/ui/impl-trait/question_mark.rs [new file with mode: 0644]
src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs
src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr [deleted file]
src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs
src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs [new file with mode: 0644]
src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr [new file with mode: 0644]
src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound.rs
src/test/ui/impl-trait/region-escape-via-bound.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.rs
src/test/ui/impl-trait/static-return-lifetime-infered.stderr
src/test/ui/impl-trait/two_tait_defining_each_other.rs [new file with mode: 0644]
src/test/ui/impl-trait/two_tait_defining_each_other.stderr [new file with mode: 0644]
src/test/ui/impl-trait/two_tait_defining_each_other2.rs [new file with mode: 0644]
src/test/ui/impl-trait/two_tait_defining_each_other2.stderr [new file with mode: 0644]
src/test/ui/impl-trait/two_tait_defining_each_other3.rs [new file with mode: 0644]
src/test/ui/impl-trait/two_tait_defining_each_other3.stderr [new file with mode: 0644]
src/test/ui/impl-trait/type_parameters_captured.nll.stderr
src/test/ui/impl-trait/type_parameters_captured.rs
src/test/ui/impl-trait/type_parameters_captured.stderr
src/test/ui/impl-trait/where-allowed-2.rs
src/test/ui/impl-trait/where-allowed-2.stderr [deleted file]
src/test/ui/inference/char-as-str-multi.rs
src/test/ui/inference/char-as-str-multi.stderr
src/test/ui/issues-71798.rs
src/test/ui/issues-71798.stderr
src/test/ui/lang-items/lang-item-missing-generator.stderr
src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs [new file with mode: 0644]
src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs [new file with mode: 0644]
src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs [new file with mode: 0644]
src/test/ui/lazy-type-alias-impl-trait/nested.rs [new file with mode: 0644]
src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs [new file with mode: 0644]
src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs [new file with mode: 0644]
src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
src/test/ui/lint/inline-trait-and-foreign-items.rs
src/test/ui/lint/inline-trait-and-foreign-items.stderr
src/test/ui/lint/lint-ctypes-73249-2.rs
src/test/ui/lint/lint-ctypes-73249-2.stderr
src/test/ui/lint/lint-ctypes-73249-3.rs
src/test/ui/lint/lint-ctypes-73249-3.stderr
src/test/ui/lint/lint-ctypes-73249-5.rs
src/test/ui/lint/lint-ctypes-73249-5.stderr
src/test/ui/lint/lint-ctypes-73251-1.rs
src/test/ui/lint/lint-ctypes-73251-1.stderr
src/test/ui/lint/lint-ctypes-73251-2.rs
src/test/ui/lint/lint-ctypes-73251-2.stderr
src/test/ui/lint/opaque-ty-ffi-unsafe.rs
src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
src/test/ui/never_type/feature-gate-never_type_fallback.rs
src/test/ui/never_type/feature-gate-never_type_fallback.stderr
src/test/ui/never_type/impl_trait_fallback.rs [new file with mode: 0644]
src/test/ui/never_type/impl_trait_fallback2.rs [new file with mode: 0644]
src/test/ui/never_type/impl_trait_fallback2.stderr [new file with mode: 0644]
src/test/ui/never_type/impl_trait_fallback3.rs [new file with mode: 0644]
src/test/ui/never_type/impl_trait_fallback3.stderr [new file with mode: 0644]
src/test/ui/never_type/impl_trait_fallback4.rs [new file with mode: 0644]
src/test/ui/never_type/impl_trait_fallback4.stderr [new file with mode: 0644]
src/test/ui/nll/issue-52113.rs
src/test/ui/nll/issue-52113.stderr
src/test/ui/nll/issue-55825-const-fn.stderr
src/test/ui/nll/issue-73159-rpit-static.rs
src/test/ui/nll/issue-73159-rpit-static.stderr
src/test/ui/nll/ty-outlives/impl-trait-captures.rs
src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
src/test/ui/parser/fn-header-semantic-fail.rs
src/test/ui/parser/fn-header-semantic-fail.stderr
src/test/ui/parser/issues/issue-8537.stderr
src/test/ui/polymorphization/generators.rs
src/test/ui/polymorphization/generators.stderr
src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
src/test/ui/save-analysis/issue-68621.rs
src/test/ui/save-analysis/issue-68621.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
src/test/ui/suggestions/args-instead-of-tuple-errors.rs
src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
src/test/ui/suggestions/args-instead-of-tuple.fixed
src/test/ui/suggestions/args-instead-of-tuple.rs
src/test/ui/suggestions/args-instead-of-tuple.stderr
src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
src/test/ui/suggestions/issue-81098.stderr
src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr
src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
src/test/ui/suggestions/match-prev-arm-needing-semi.rs
src/test/ui/suggestions/match-prev-arm-needing-semi.stderr
src/test/ui/suggestions/opaque-type-error.stderr
src/test/ui/test-attrs/test-allow-fail-attr.rs [deleted file]
src/test/ui/traits/alias/issue-83613.rs
src/test/ui/traits/alias/issue-83613.stderr
src/test/ui/type-alias-impl-trait/argument-types.rs
src/test/ui/type-alias-impl-trait/argument-types.stderr [deleted file]
src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
src/test/ui/type-alias-impl-trait/bound_reduction2.rs
src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
src/test/ui/type-alias-impl-trait/bounds-are-checked.rs
src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs
src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs
src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr [deleted file]
src/test/ui/type-alias-impl-trait/fallback.rs
src/test/ui/type-alias-impl-trait/field-types.rs
src/test/ui/type-alias-impl-trait/field-types.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
src/test/ui/type-alias-impl-trait/generic_not_used.rs
src/test/ui/type-alias-impl-trait/generic_not_used.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
src/test/ui/type-alias-impl-trait/inference-cycle.rs
src/test/ui/type-alias-impl-trait/inference-cycle.stderr
src/test/ui/type-alias-impl-trait/issue-53598.rs
src/test/ui/type-alias-impl-trait/issue-53598.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
src/test/ui/type-alias-impl-trait/issue-57700.rs
src/test/ui/type-alias-impl-trait/issue-57700.stderr
src/test/ui/type-alias-impl-trait/issue-58951-2.rs [new file with mode: 0644]
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-60564.rs
src/test/ui/type-alias-impl-trait/issue-60564.stderr
src/test/ui/type-alias-impl-trait/issue-63279.rs
src/test/ui/type-alias-impl-trait/issue-63279.stderr
src/test/ui/type-alias-impl-trait/issue-63355.rs
src/test/ui/type-alias-impl-trait/issue-63355.stderr [deleted file]
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
src/test/ui/type-alias-impl-trait/issue-74280.stderr
src/test/ui/type-alias-impl-trait/issue-77179.stderr
src/test/ui/type-alias-impl-trait/issue-89686.stderr
src/test/ui/type-alias-impl-trait/issue-93411.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
src/test/ui/type-alias-impl-trait/nested-tait-inference.rs
src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs
src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr
src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr [deleted file]
src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
src/test/ui/type-alias-impl-trait/self-referential-2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/self-referential-2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/self-referential-3.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/self-referential-4.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/self-referential-4.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/self-referential.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/self-referential.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/static-const-types.rs
src/test/ui/type-alias-impl-trait/static-const-types.stderr [deleted file]
src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
src/test/ui/type-alias-impl-trait/structural-match.rs
src/test/ui/type-alias-impl-trait/structural-match.stderr
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr [deleted file]
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs
src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs
src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/type_of_a_let.rs
src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
src/tools/compiletest/src/header.rs

index 612ee71f350f16e31b218607a8dabdd2bdbea7d4..f51b0086dc8b6d6be5b784c677f93c067505428c 100644 (file)
@@ -43,7 +43,7 @@ fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
         if i != 0 || j != lines.len() { Some((i, j)) } else { None }
     }
 
-    fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
+    fn get_horizontal_trim<'a>(lines: &'a [&str], kind: CommentKind) -> Option<String> {
         let mut i = usize::MAX;
         let mut first = true;
 
@@ -51,7 +51,8 @@ fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
         // present. However, we first need to strip the empty lines so they don't get in the middle
         // when we try to compute the "horizontal trim".
         let lines = if kind == CommentKind::Block {
-            let mut i = 0;
+            // Whatever happens, we skip the first line.
+            let mut i = if lines[0].trim_start().starts_with('*') { 0 } else { 1 };
             let mut j = lines.len();
 
             while i < j && lines[i].trim().is_empty() {
@@ -84,7 +85,7 @@ fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
                 return None;
             }
         }
-        Some(i)
+        if lines.is_empty() { None } else { Some(lines[0][..i].into()) }
     }
 
     let data_s = data.as_str();
@@ -102,8 +103,13 @@ fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
             changes = true;
             // remove a "[ \t]*\*" block from each line, if possible
             for line in lines.iter_mut() {
-                if horizontal + 1 < line.len() {
-                    *line = &line[horizontal + 1..];
+                if let Some(tmp) = line.strip_prefix(&horizontal) {
+                    *line = tmp;
+                    if kind == CommentKind::Block
+                        && (*line == "*" || line.starts_with("* ") || line.starts_with("**"))
+                    {
+                        *line = &line[1..];
+                    }
                 }
             }
         }
index 98f692a7724e2778b9410ff4e8d85ae8e59273dd..11d50603a1011fb84f483c82731bce45664789d8 100644 (file)
@@ -24,7 +24,7 @@ fn test_block_doc_comment_3() {
     create_default_session_globals_then(|| {
         let comment = "\n let a: *i32;\n *a = 5;\n";
         let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
-        assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
+        assert_eq!(stripped.as_str(), "let a: *i32;\n*a = 5;");
     })
 }
 
@@ -41,3 +41,21 @@ fn test_line_doc_comment() {
         assert_eq!(stripped.as_str(), "!test");
     })
 }
+
+#[test]
+fn test_doc_blocks() {
+    create_default_session_globals_then(|| {
+        let stripped =
+            beautify_doc_string(Symbol::intern(" # Returns\n     *\n     "), CommentKind::Block);
+        assert_eq!(stripped.as_str(), " # Returns\n\n");
+
+        let stripped = beautify_doc_string(
+            Symbol::intern("\n     * # Returns\n     *\n     "),
+            CommentKind::Block,
+        );
+        assert_eq!(stripped.as_str(), " # Returns\n\n");
+
+        let stripped = beautify_doc_string(Symbol::intern("\n *     a\n "), CommentKind::Block);
+        assert_eq!(stripped.as_str(), "     a\n");
+    })
+}
index a6ecfa4520608a42cf1425844db1171b84313733..0a96e60d4d3af58cd667412635663304faa98eb2 100644 (file)
@@ -196,6 +196,54 @@ fn check_abi(&self, abi: ast::StrLit) {
                     "thiscall-unwind ABI is experimental and subject to change"
                 );
             }
+            "cdecl-unwind" => {
+                gate_feature_post!(
+                    &self,
+                    c_unwind,
+                    span,
+                    "cdecl-unwind ABI is experimental and subject to change"
+                );
+            }
+            "fastcall-unwind" => {
+                gate_feature_post!(
+                    &self,
+                    c_unwind,
+                    span,
+                    "fastcall-unwind ABI is experimental and subject to change"
+                );
+            }
+            "vectorcall-unwind" => {
+                gate_feature_post!(
+                    &self,
+                    c_unwind,
+                    span,
+                    "vectorcall-unwind ABI is experimental and subject to change"
+                );
+            }
+            "aapcs-unwind" => {
+                gate_feature_post!(
+                    &self,
+                    c_unwind,
+                    span,
+                    "aapcs-unwind ABI is experimental and subject to change"
+                );
+            }
+            "win64-unwind" => {
+                gate_feature_post!(
+                    &self,
+                    c_unwind,
+                    span,
+                    "win64-unwind ABI is experimental and subject to change"
+                );
+            }
+            "sysv64-unwind" => {
+                gate_feature_post!(
+                    &self,
+                    c_unwind,
+                    span,
+                    "sysv64-unwind ABI is experimental and subject to change"
+                );
+            }
             "wasm" => {
                 gate_feature_post!(
                     &self,
index 5597a8b091554769adc7dd0f07be095b02ea8739..c318386f33b1333883ae3629ffa8a20e19e3d539 100644 (file)
@@ -124,8 +124,9 @@ fn mir_borrowck<'tcx>(
 ) -> &'tcx BorrowCheckResult<'tcx> {
     let (input_body, promoted) = tcx.mir_promoted(def);
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
+    let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
 
-    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
+    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
         let input_body: &Body<'_> = &input_body.borrow();
         let promoted: &IndexVec<_, _> = &promoted.borrow();
         do_mir_borrowck(&infcx, input_body, promoted, false).0
@@ -140,7 +141,7 @@ fn mir_borrowck<'tcx>(
 /// If `return_body_with_facts` is true, then return the body with non-erased
 /// region ids on which the borrow checking was performed together with Polonius
 /// facts.
-#[instrument(skip(infcx, input_body, input_promoted), level = "debug")]
+#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
 fn do_mir_borrowck<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     input_body: &Body<'tcx>,
index 76b3be7976c61e9b8def72466f0d6a39f95f8cfb..f24d88163992008e44136ff2c56dd7400f3bc9f1 100644 (file)
@@ -1,7 +1,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir::OpaqueTyOrigin;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
@@ -54,27 +53,44 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
-        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
+        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (Ty<'tcx>, Span, OpaqueTyOrigin)>,
         span: Span,
     ) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
         opaque_ty_decls
             .into_iter()
-            .filter_map(|(opaque_type_key, decl)| {
+            .map(|(opaque_type_key, (concrete_type, decl_span, origin))| {
                 let substs = opaque_type_key.substs;
-                let concrete_type = decl.concrete_ty;
+                // FIXME: why are the spans in decl_span often DUMMY_SP?
+                let span = decl_span.substitute_dummy(span);
                 debug!(?concrete_type, ?substs);
 
                 let mut subst_regions = vec![self.universal_regions.fr_static];
                 let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
-                    let vid = self.universal_regions.to_region_vid(region);
-                    subst_regions.push(vid);
-                    self.definitions[vid].external_name.unwrap_or_else(|| {
-                        infcx
-                            .tcx
-                            .sess
-                            .delay_span_bug(span, "opaque type with non-universal region substs");
-                        infcx.tcx.lifetimes.re_static
-                    })
+                    if let ty::RePlaceholder(..) = region {
+                        // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
+                        return region;
+                    }
+                    let vid = self.to_region_vid(region);
+                    trace!(?vid);
+                    let scc = self.constraint_sccs.scc(vid);
+                    trace!(?scc);
+                    match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| {
+                        self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?)
+                    }) {
+                        Some(region) => {
+                            let vid = self.universal_regions.to_region_vid(region);
+                            subst_regions.push(vid);
+                            region
+                        }
+                        None => {
+                            subst_regions.push(vid);
+                            infcx.tcx.sess.delay_span_bug(
+                                span,
+                                "opaque type with non-universal region substs",
+                            );
+                            infcx.tcx.lifetimes.re_static
+                        }
+                    }
                 });
 
                 subst_regions.sort();
@@ -100,12 +116,14 @@ pub(crate) fn infer_opaque_types(
                     span,
                 );
 
-                check_opaque_type_parameter_valid(
-                    infcx.tcx,
+                (
                     opaque_type_key,
-                    OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
+                    if check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) {
+                        remapped_type
+                    } else {
+                        infcx.tcx.ty_error()
+                    },
                 )
-                .then_some((opaque_type_key, remapped_type))
             })
             .collect()
     }
@@ -149,9 +167,10 @@ pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
 fn check_opaque_type_parameter_valid(
     tcx: TyCtxt<'_>,
     opaque_type_key: OpaqueTypeKey<'_>,
-    decl: OpaqueTypeDecl<'_>,
+    origin: OpaqueTyOrigin,
+    span: Span,
 ) -> bool {
-    match decl.origin {
+    match origin {
         // No need to check return position impl trait (RPIT)
         // because for type and const parameters they are correct
         // by construction: we convert
@@ -177,7 +196,6 @@ fn check_opaque_type_parameter_valid(
         // Check these
         OpaqueTyOrigin::TyAlias => {}
     }
-    let span = decl.definition_span;
     let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
     let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
     for (i, arg) in opaque_type_key.substs.iter().enumerate() {
index bc740de5150659cc48f1954c0a17b8036fec98a9..83c8ecba1f17aa78d86d2af0a8a8c76dbc69bf06 100644 (file)
@@ -147,9 +147,9 @@ pub(super) fn equate_inputs_and_outputs(
         // Return types are a bit more complex. They may contain opaque `impl Trait` types.
         let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
         let output_span = body.local_decls[RETURN_PLACE].source_info.span;
-        if let Err(terr) = self.eq_opaque_type_and_type(
-            mir_output_ty,
+        if let Err(terr) = self.eq_types(
             normalized_output_ty,
+            mir_output_ty,
             Locations::All(output_span),
             ConstraintCategory::BoringNoLocation,
         ) {
@@ -169,9 +169,9 @@ pub(super) fn equate_inputs_and_outputs(
             let user_provided_output_ty = user_provided_sig.output();
             let user_provided_output_ty =
                 self.normalize(user_provided_output_ty, Locations::All(output_span));
-            if let Err(err) = self.eq_opaque_type_and_type(
-                mir_output_ty,
+            if let Err(err) = self.eq_types(
                 user_provided_output_ty,
+                mir_output_ty,
                 Locations::All(output_span),
                 ConstraintCategory::BoringNoLocation,
             ) {
index 73103643e3e16f2253edb83e036f440c25aa8930..4647610b0033da4906f9b1686c66ab6ca58ddf70 100644 (file)
@@ -5,6 +5,7 @@
 
 use either::Either;
 
+use hir::OpaqueTyOrigin;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::vec_map::VecMap;
@@ -15,7 +16,6 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
@@ -41,7 +41,7 @@
 use rustc_trait_selection::traits::query::type_op;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::Fallible;
-use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
+use rustc_trait_selection::traits::{self, ObligationCause};
 
 use rustc_const_eval::transform::{
     check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
@@ -75,7 +75,7 @@ macro_rules! span_mirbug {
             $context.last_span,
             &format!(
                 "broken MIR in {:?} ({:?}): {}",
-                $context.body.source.def_id(),
+                $context.body().source.def_id(),
                 $elem,
                 format_args!($($message)*),
             ),
@@ -190,59 +190,44 @@ pub(crate) fn type_check<'mir, 'tcx>(
             liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
 
             translate_outlives_facts(&mut cx);
-            let opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types);
+            let opaque_type_values =
+                infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 
             opaque_type_values
                 .into_iter()
-                .filter_map(|(opaque_type_key, mut decl)| {
-                    decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
+                .map(|(opaque_type_key, decl)| {
+                    cx.fully_perform_op(
+                        Locations::All(body.span),
+                        ConstraintCategory::OpaqueType,
+                        CustomTypeOp::new(
+                            |infcx| {
+                                infcx.register_member_constraints(
+                                    param_env,
+                                    opaque_type_key,
+                                    decl.hidden_type.ty,
+                                    decl.hidden_type.span,
+                                );
+                                Ok(InferOk { value: (), obligations: vec![] })
+                            },
+                            || "opaque_type_map".to_string(),
+                        ),
+                    )
+                    .unwrap();
+                    let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type.ty);
                     trace!(
                         "finalized opaque type {:?} to {:#?}",
                         opaque_type_key,
-                        decl.concrete_ty.kind()
+                        hidden_type.kind()
                     );
-                    if decl.concrete_ty.has_infer_types_or_consts() {
+                    if hidden_type.has_infer_types_or_consts() {
                         infcx.tcx.sess.delay_span_bug(
-                            body.span,
-                            &format!("could not resolve {:#?}", decl.concrete_ty.kind()),
+                            decl.hidden_type.span,
+                            &format!("could not resolve {:#?}", hidden_type.kind()),
                         );
-                        decl.concrete_ty = infcx.tcx.ty_error();
+                        hidden_type = infcx.tcx.ty_error();
                     }
-                    let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_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,
-                        );
-                        None
-                    } else {
-                        Some((opaque_type_key, decl))
-                    }
+                    (opaque_type_key, (hidden_type, decl.hidden_type.span, decl.origin))
                 })
                 .collect()
         },
@@ -274,7 +259,7 @@ fn type_check_internal<'a, 'tcx, R>(
         borrowck_context,
     );
     let errors_reported = {
-        let mut verifier = TypeVerifier::new(&mut checker, body, promoted);
+        let mut verifier = TypeVerifier::new(&mut checker, promoted);
         verifier.visit_body(&body);
         verifier.errors_reported
     };
@@ -331,7 +316,6 @@ enum FieldAccessError {
 /// is a problem.
 struct TypeVerifier<'a, 'b, 'tcx> {
     cx: &'a mut TypeChecker<'b, 'tcx>,
-    body: &'b Body<'tcx>,
     promoted: &'b IndexVec<Promoted, Body<'tcx>>,
     last_span: Span,
     errors_reported: bool,
@@ -467,7 +451,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
-        let rval_ty = rvalue.ty(self.body, self.tcx());
+        let rval_ty = rvalue.ty(self.body(), self.tcx());
         self.sanitize_type(rvalue, rval_ty);
     }
 
@@ -526,10 +510,13 @@ fn visit_body(&mut self, body: &Body<'tcx>) {
 impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
     fn new(
         cx: &'a mut TypeChecker<'b, 'tcx>,
-        body: &'b Body<'tcx>,
         promoted: &'b IndexVec<Promoted, Body<'tcx>>,
     ) -> Self {
-        TypeVerifier { body, promoted, cx, last_span: body.span, errors_reported: false }
+        TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
+    }
+
+    fn body(&self) -> &Body<'tcx> {
+        self.cx.body
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -554,7 +541,7 @@ fn sanitize_place(
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
 
-        let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
+        let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
 
         for elem in place.projection.iter() {
             if place_ty.variant_index.is_none() {
@@ -599,7 +586,7 @@ fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Locatio
         // checker on the promoted MIR, then transfer the constraints back to
         // the main MIR, changing the locations to the provided location.
 
-        let parent_body = mem::replace(&mut self.body, promoted_body);
+        let parent_body = mem::replace(&mut self.cx.body, promoted_body);
 
         // Use new sets of constraints and closure bounds so that we can
         // modify their locations.
@@ -635,7 +622,7 @@ fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Locatio
             self.cx.typeck_mir(promoted_body);
         }
 
-        self.body = parent_body;
+        self.cx.body = parent_body;
         // Merge the outlives constraints back in, at the given location.
         swap_constraints(self);
 
@@ -697,7 +684,7 @@ fn sanitize_projection(
                 }))
             }
             ProjectionElem::Index(i) => {
-                let index_ty = Place::from(i).ty(self.body, tcx).ty;
+                let index_ty = Place::from(i).ty(self.body(), tcx).ty;
                 if index_ty != tcx.types.usize {
                     PlaceTy::from_ty(span_mirbug_and_err!(self, i, "index by non-usize {:?}", i))
                 } else {
@@ -906,7 +893,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
     crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
+    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, (Ty<'tcx>, Span, OpaqueTyOrigin)>,
 }
 
 /// A collection of region constraints that must be satisfied for the
@@ -1056,17 +1043,19 @@ fn new(
         checker
     }
 
+    fn body(&self) -> &Body<'tcx> {
+        self.body
+    }
+
     fn unsized_feature_enabled(&self) -> bool {
         let features = self.tcx().features();
         features.unsized_locals || features.unsized_fn_params
     }
 
     /// Equate the inferred type and the annotated type for user type annotations
+    #[instrument(skip(self), level = "debug")]
     fn check_user_type_annotations(&mut self) {
-        debug!(
-            "check_user_type_annotations: user_type_annotations={:?}",
-            self.user_type_annotations
-        );
+        debug!(?self.user_type_annotations);
         for user_annotation in self.user_type_annotations {
             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
             let inferred_ty = self.normalize(inferred_ty, Locations::All(span));
@@ -1207,131 +1196,6 @@ fn relate_type_and_user_type(
         Ok(())
     }
 
-    /// Equates a type `anon_ty` that may contain opaque types whose
-    /// values are to be inferred by the MIR.
-    ///
-    /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
-    /// hidden types for impl traits revealed.
-    ///
-    /// # Example
-    ///
-    /// Consider a piece of code like
-    ///
-    /// ```rust
-    /// type Foo<U> = impl Debug;
-    ///
-    /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
-    ///      Box::new((t, 22_u32))
-    /// }
-    /// ```
-    ///
-    /// Here, the function signature would be something like
-    /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
-    /// the type with the opaque type revealed, so `Box<(T, u32)>`.
-    ///
-    /// In terms of our function parameters:
-    ///
-    /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
-    ///   scoped to this function (note that it is parameterized by the
-    ///   generics of `foo`). Note that `anon_ty` is not just the opaque type,
-    ///   but the entire return type (which may contain opaque types within it).
-    /// * `revealed_ty` would be `Box<(T, u32)>`
-    #[instrument(skip(self), level = "debug")]
-    fn eq_opaque_type_and_type(
-        &mut self,
-        revealed_ty: Ty<'tcx>,
-        anon_ty: Ty<'tcx>,
-        locations: Locations,
-        category: ConstraintCategory,
-    ) -> Fallible<()> {
-        // Fast path for the common case.
-        if !anon_ty.has_opaque_types() {
-            if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) {
-                span_mirbug!(
-                    self,
-                    locations,
-                    "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`",
-                    revealed_ty,
-                    anon_ty,
-                    terr
-                );
-            }
-            return Ok(());
-        }
-
-        let param_env = self.param_env;
-        let body = self.body;
-        let mir_def_id = body.source.def_id().expect_local();
-
-        debug!(?mir_def_id);
-        self.fully_perform_op(
-            locations,
-            category,
-            CustomTypeOp::new(
-                |infcx| {
-                    let mut obligations = ObligationAccumulator::default();
-
-                    let dummy_body_id = hir::CRATE_HIR_ID;
-
-                    // Replace the opaque types defined by this function with
-                    // inference variables, creating a map. In our example above,
-                    // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
-                    // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
-                    // (Note that the key of the map is both the def-id of `Foo` along with
-                    // any generic parameters.)
-                    let output_ty = obligations.add(infcx.instantiate_opaque_types(
-                        dummy_body_id,
-                        param_env,
-                        anon_ty,
-                        locations.span(body),
-                    ));
-                    debug!(?output_ty, ?revealed_ty);
-
-                    // Make sure that the inferred types are well-formed. I'm
-                    // not entirely sure this is needed (the HIR type check
-                    // didn't do this) but it seems sensible to prevent opaque
-                    // types hiding ill-formed types.
-                    obligations.obligations.push(traits::Obligation::new(
-                        ObligationCause::dummy(),
-                        param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into()))
-                            .to_predicate(infcx.tcx),
-                    ));
-                    obligations.add(
-                        infcx
-                            .at(&ObligationCause::dummy(), param_env)
-                            .eq(output_ty, revealed_ty)?,
-                    );
-
-                    debug!("equated");
-
-                    Ok(InferOk { value: (), obligations: obligations.into_vec() })
-                },
-                || "input_output".to_string(),
-            ),
-        )?;
-
-        // Finally, if we instantiated the anon types successfully, we
-        // have to solve any bounds (e.g., `-> impl Iterator` needs to
-        // prove that `T: Iterator` where `T` is the type we
-        // instantiated it with).
-        let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone();
-        for (opaque_type_key, opaque_decl) in opaque_type_map {
-            self.fully_perform_op(
-                locations,
-                ConstraintCategory::OpaqueType,
-                CustomTypeOp::new(
-                    |infcx| {
-                        infcx.constrain_opaque_type(opaque_type_key, &opaque_decl);
-                        Ok(InferOk { value: (), obligations: vec![] })
-                    },
-                    || "opaque_type_map".to_string(),
-                ),
-            )?;
-        }
-        Ok(())
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
@@ -2773,20 +2637,3 @@ fn to_locations(self) -> Locations {
         Locations::Single(self)
     }
 }
-
-#[derive(Debug, Default)]
-struct ObligationAccumulator<'tcx> {
-    obligations: PredicateObligations<'tcx>,
-}
-
-impl<'tcx> ObligationAccumulator<'tcx> {
-    fn add<T>(&mut self, value: InferOk<'tcx, T>) -> T {
-        let InferOk { value, obligations } = value;
-        self.obligations.extend(obligations);
-        value
-    }
-
-    fn into_vec(self) -> PredicateObligations<'tcx> {
-        self.obligations
-    }
-}
index cc3fe0a123c55bc79803e994cddc189e71f13c85..aba1dd2bc548cc65beb4899134124dd4e93e3152 100644 (file)
@@ -1,13 +1,15 @@
 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
-use rustc_infer::infer::NllRegionVariableOrigin;
+use rustc_infer::infer::{InferOk, NllRegionVariableOrigin};
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Const, Ty};
+use rustc_span::Span;
 use rustc_trait_selection::traits::query::Fallible;
 
 use crate::constraints::OutlivesConstraint;
 use crate::diagnostics::UniverseInfo;
-use crate::type_check::{Locations, TypeChecker};
+use crate::type_check::{CustomTypeOp, Locations, TypeChecker};
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
@@ -63,6 +65,10 @@ fn new(
 }
 
 impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
+    fn span(&self) -> Span {
+        self.locations.span(self.type_checker.body)
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.type_checker.param_env
     }
@@ -117,6 +123,9 @@ fn push_outlives(
 
     // We don't have to worry about the equality of consts during borrow checking
     // as consts always have a static lifetime.
+    // FIXME(oli-obk): is this really true? We can at least have HKL and with
+    // inline consts we may have further lifetimes that may be unsound to treat as
+    // 'static.
     fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {}
 
     fn normalization() -> NormalizationStrategy {
@@ -126,4 +135,33 @@ fn normalization() -> NormalizationStrategy {
     fn forbid_inference_vars() -> bool {
         true
     }
+
+    fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) {
+        let param_env = self.param_env();
+        let span = self.span();
+        let def_id = self.type_checker.body.source.def_id().expect_local();
+        let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
+        let cause = ObligationCause::misc(span, body_id);
+        self.type_checker
+            .fully_perform_op(
+                self.locations,
+                self.category,
+                CustomTypeOp::new(
+                    |infcx| {
+                        Ok(InferOk {
+                            value: (),
+                            obligations: vec![infcx.opaque_ty_obligation(
+                                a,
+                                b,
+                                a_is_expected,
+                                param_env,
+                                cause,
+                            )],
+                        })
+                    },
+                    || "register_opaque_type".to_string(),
+                ),
+            )
+            .unwrap();
+    }
 }
index 16a903d5e593f75dd306d4859ee929aec251d94e..a944b2d87ac6d42ff850c260099ea3b0815a104e 100644 (file)
@@ -728,6 +728,7 @@ fn replace_free_regions_with_nll_infer_vars<T>(
         self.tcx.fold_regions(value, &mut false, |_region, _depth| self.next_nll_region_var(origin))
     }
 
+    #[instrument(level = "debug", skip(self, indices))]
     fn replace_bound_regions_with_nll_infer_vars<T>(
         &self,
         origin: NllRegionVariableOrigin,
@@ -738,22 +739,15 @@ fn replace_bound_regions_with_nll_infer_vars<T>(
     where
         T: TypeFoldable<'tcx>,
     {
-        debug!(
-            "replace_bound_regions_with_nll_infer_vars(value={:?}, all_outlive_scope={:?})",
-            value, all_outlive_scope,
-        );
         let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
-            debug!("replace_bound_regions_with_nll_infer_vars: br={:?}", br);
+            debug!(?br);
             let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
                 scope: all_outlive_scope.to_def_id(),
                 bound_region: br.kind,
             }));
             let region_vid = self.next_nll_region_var(origin);
             indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
-            debug!(
-                "replace_bound_regions_with_nll_infer_vars: liberated_region={:?} => {:?}",
-                liberated_region, region_vid
-            );
+            debug!(?liberated_region, ?region_vid);
             region_vid
         });
         value
@@ -768,6 +762,7 @@ fn replace_bound_regions_with_nll_infer_vars<T>(
     /// entries for them and store them in the indices map. This code iterates over the complete
     /// set of late-bound regions and checks for any that we have not yet seen, adding them to the
     /// inputs vector.
+    #[instrument(skip(self, indices))]
     fn replace_late_bound_regions_with_nll_infer_vars(
         &self,
         mir_def_id: LocalDefId,
@@ -779,6 +774,7 @@ fn replace_late_bound_regions_with_nll_infer_vars(
             debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = self.next_nll_region_var(FR);
+                debug!(?region_vid);
                 indices.insert_late_bound_region(r, region_vid.to_region_vid());
             }
         });
index 367a5aa732370a0dff03491b22f151322989206e..0ca7988ca152f6c48059a6c494fec820493bb688 100644 (file)
@@ -134,7 +134,7 @@ fn inject_impl_of_structural_trait(
 
     // Create the type of `self`.
     //
-    // in addition, remove defaults from type params (impls cannot have them).
+    // in addition, remove defaults from generic params (impls cannot have them).
     let self_params: Vec<_> = generics
         .params
         .iter_mut()
index aaa6580acc6f08543d8895009306d3fc29229f32..584fbd1b605cd7e4d2af62b1bc062e1e488ad0e6 100644 (file)
@@ -25,6 +25,7 @@ enum ArgumentType {
 
 enum Position {
     Exact(usize),
+    Capture(usize),
     Named(Symbol),
 }
 
@@ -49,6 +50,8 @@ struct Context<'a, 'b> {
     /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]`
     /// * `names` (in JSON): `{"foo": 2}`
     args: Vec<P<ast::Expr>>,
+    /// The number of arguments that were added by implicit capturing.
+    num_captured_args: usize,
     /// Placeholder slot numbers indexed by argument.
     arg_types: Vec<Vec<usize>>,
     /// Unique format specs seen for each argument.
@@ -231,6 +234,11 @@ fn parse_args<'a>(
 }
 
 impl<'a, 'b> Context<'a, 'b> {
+    /// The number of arguments that were explicitly given.
+    fn num_args(&self) -> usize {
+        self.args.len() - self.num_captured_args
+    }
+
     fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) {
         // NOTE: the `unwrap_or` branch is needed in case of invalid format
         // arguments, e.g., `format_args!("{foo}")`.
@@ -345,7 +353,7 @@ fn verify_count(&mut self, c: parse::Count) {
     }
 
     fn describe_num_args(&self) -> Cow<'_, str> {
-        match self.args.len() {
+        match self.num_args() {
             0 => "no arguments were given".into(),
             1 => "there is 1 argument".into(),
             x => format!("there are {} arguments", x).into(),
@@ -371,7 +379,7 @@ fn report_invalid_references(&self, numbered_position_args: bool) {
 
         let count = self.pieces.len()
             + self.arg_with_formatting.iter().filter(|fmt| fmt.precision_span.is_some()).count();
-        if self.names.is_empty() && !numbered_position_args && count != self.args.len() {
+        if self.names.is_empty() && !numbered_position_args && count != self.num_args() {
             e = self.ecx.struct_span_err(
                 sp,
                 &format!(
@@ -419,7 +427,7 @@ fn report_invalid_references(&self, numbered_position_args: bool) {
             if let Some(span) = fmt.precision_span {
                 let span = self.fmtsp.from_inner(span);
                 match fmt.precision {
-                    parse::CountIsParam(pos) if pos > self.args.len() => {
+                    parse::CountIsParam(pos) if pos > self.num_args() => {
                         e.span_label(
                             span,
                             &format!(
@@ -462,7 +470,7 @@ fn report_invalid_references(&self, numbered_position_args: bool) {
             if let Some(span) = fmt.width_span {
                 let span = self.fmtsp.from_inner(span);
                 match fmt.width {
-                    parse::CountIsParam(pos) if pos > self.args.len() => {
+                    parse::CountIsParam(pos) if pos > self.num_args() => {
                         e.span_label(
                             span,
                             &format!(
@@ -494,12 +502,15 @@ fn report_invalid_references(&self, numbered_position_args: bool) {
     /// Actually verifies and tracks a given format placeholder
     /// (a.k.a. argument).
     fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
+        if let Exact(arg) = arg {
+            if arg >= self.num_args() {
+                self.invalid_refs.push((arg, self.curpiece));
+                return;
+            }
+        }
+
         match arg {
-            Exact(arg) => {
-                if self.args.len() <= arg {
-                    self.invalid_refs.push((arg, self.curpiece));
-                    return;
-                }
+            Exact(arg) | Capture(arg) => {
                 match ty {
                     Placeholder(_) => {
                         // record every (position, type) combination only once
@@ -526,7 +537,7 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
                 match self.names.get(&name) {
                     Some(&idx) => {
                         // Treat as positional arg.
-                        self.verify_arg_type(Exact(idx), ty)
+                        self.verify_arg_type(Capture(idx), ty)
                     }
                     None => {
                         // For the moment capturing variables from format strings expanded from macros is
@@ -541,9 +552,10 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
                             } else {
                                 self.fmtsp
                             };
+                            self.num_captured_args += 1;
                             self.args.push(self.ecx.expr_ident(span, Ident::new(name, span)));
                             self.names.insert(name, idx);
-                            self.verify_arg_type(Exact(idx), ty)
+                            self.verify_arg_type(Capture(idx), ty)
                         } else {
                             let msg = format!("there is no argument named `{}`", name);
                             let sp = if self.is_literal {
@@ -1051,6 +1063,7 @@ pub fn expand_preparsed_format_args(
     let mut cx = Context {
         ecx,
         args,
+        num_captured_args: 0,
         arg_types,
         arg_unique_types,
         names,
index a433876147f8d903edbc8568485649f5eef0cf92..36cfbba45daccb2d521a5419b5c370e6e97293aa 100644 (file)
@@ -26,14 +26,14 @@ pub fn expand(
 
     // Allow using `#[global_allocator]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt) = match &item {
+    let (item, is_stmt, ty_span) = match &item {
         Annotatable::Item(item) => match item.kind {
-            ItemKind::Static(..) => (item, false),
+            ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)),
             _ => return not_static(),
         },
         Annotatable::Stmt(stmt) => match &stmt.kind {
             StmtKind::Item(item_) => match item_.kind {
-                ItemKind::Static(..) => (item_, true),
+                ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)),
                 _ => return not_static(),
             },
             _ => return not_static(),
@@ -43,13 +43,14 @@ pub fn expand(
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
-    let f = AllocFnFactory { span, kind: AllocatorKind::Global, global: item.ident, cx: ecx };
+    let f =
+        AllocFnFactory { span, ty_span, kind: AllocatorKind::Global, global: item.ident, cx: ecx };
 
     // Generate item statements for the allocator methods.
     let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
 
     // Generate anonymous constant serving as container for the allocator methods.
-    let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
+    let const_ty = ecx.ty(ty_span, TyKind::Tup(Vec::new()));
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
     let const_item = if is_stmt {
@@ -64,6 +65,7 @@ pub fn expand(
 
 struct AllocFnFactory<'a, 'b> {
     span: Span,
+    ty_span: Span,
     kind: AllocatorKind,
     global: Ident,
     cx: &'b ExtCtxt<'a>,
@@ -97,18 +99,18 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
             self.attrs(),
             kind,
         );
-        self.cx.stmt_item(self.span, item)
+        self.cx.stmt_item(self.ty_span, item)
     }
 
     fn call_allocator(&self, method: Symbol, mut args: Vec<P<Expr>>) -> P<Expr> {
         let method = self.cx.std_path(&[sym::alloc, sym::GlobalAlloc, method]);
-        let method = self.cx.expr_path(self.cx.path(self.span, method));
-        let allocator = self.cx.path_ident(self.span, self.global);
+        let method = self.cx.expr_path(self.cx.path(self.ty_span, method));
+        let allocator = self.cx.path_ident(self.ty_span, self.global);
         let allocator = self.cx.expr_path(allocator);
-        let allocator = self.cx.expr_addr_of(self.span, allocator);
+        let allocator = self.cx.expr_addr_of(self.ty_span, allocator);
         args.insert(0, allocator);
 
-        self.cx.expr_call(self.span, method, args)
+        self.cx.expr_call(self.ty_span, method, args)
     }
 
     fn attrs(&self) -> Vec<Attribute> {
index c08b141b557cae1db99280d915156929ab35d964..9459bb7047f5c64e2f45b53c7c8787431bd349e4 100644 (file)
@@ -252,11 +252,6 @@ pub fn expand_test_or_bench(
                                         "ignore",
                                         cx.expr_bool(sp, should_ignore(&cx.sess, &item)),
                                     ),
-                                    // allow_fail: true | false
-                                    field(
-                                        "allow_fail",
-                                        cx.expr_bool(sp, should_fail(&cx.sess, &item)),
-                                    ),
                                     // compile_fail: true | false
                                     field("compile_fail", cx.expr_bool(sp, false)),
                                     // no_run: true | false
@@ -359,10 +354,6 @@ fn should_ignore(sess: &Session, i: &ast::Item) -> bool {
     sess.contains_name(&i.attrs, sym::ignore)
 }
 
-fn should_fail(sess: &Session, i: &ast::Item) -> bool {
-    sess.contains_name(&i.attrs, sym::allow_fail)
-}
-
 fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
     match cx.sess.find_by_name(&i.attrs, sym::should_panic) {
         Some(attr) => {
index 6799514a4490db098206e2958dff72304158fb10..49a9b911f3a4b3894923ce206c50a14d7124ec8b 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
-use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
+use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
 use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
 use rustc_trait_selection::traits::SelectionContext;
@@ -46,7 +46,10 @@ pub fn needs_drop(
         location: Location,
     ) -> bool {
         let ty = ccx.body.local_decls[local].ty;
-        if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
+        // Peeking into opaque types causes cycles if the current function declares said opaque
+        // type. Thus we avoid short circuiting on the type and instead run the more expensive
+        // analysis that looks at the actual usage within this function
+        if !ty.has_opaque_types() && !NeedsDrop::in_any_value_of_ty(ccx, ty) {
             return false;
         }
 
@@ -100,7 +103,10 @@ pub fn has_mut_interior(
         location: Location,
     ) -> bool {
         let ty = ccx.body.local_decls[local].ty;
-        if !HasMutInterior::in_any_value_of_ty(ccx, ty) {
+        // Peeking into opaque types causes cycles if the current function declares said opaque
+        // type. Thus we avoid short circuiting on the type and instead run the more expensive
+        // analysis that looks at the actual usage within this function
+        if !ty.has_opaque_types() && !HasMutInterior::in_any_value_of_ty(ccx, ty) {
             return false;
         }
 
@@ -148,7 +154,12 @@ fn in_return_place(
 
             // 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,
+            // Opaque types do not participate in const generics or pattern matching, so we can safely count them out.
+            _ if ccx.body.return_ty().has_opaque_types()
+                || !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)
@@ -395,6 +406,7 @@ fn check_item_predicates(&mut self) {
                     | ty::PredicateKind::Projection(_)
                     | ty::PredicateKind::ConstEvaluatable(..)
                     | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::OpaqueType(..)
                     | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
                     ty::PredicateKind::ObjectSafe(_) => {
                         bug!("object safe predicate on function: {:#?}", predicate)
index cf15fc4ddc3a54fa3fe60f13453274462fbb6831..f8e5764878579ff780b285b6086f675cab48d1a0 100644 (file)
@@ -79,7 +79,6 @@ pub fn equal_up_to_regions<'tcx>(
     }
 
     // Normalize lifetimes away on both sides, then compare.
-    let param_env = param_env.with_reveal_all_normalized(tcx);
     let normalize = |ty: Ty<'tcx>| {
         tcx.normalize_erasing_regions(
             param_env,
@@ -171,9 +170,7 @@ fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
             return true;
         }
         // Normalize projections and things like that.
-        // FIXME: We need to reveal_all, as some optimizations change types in ways
-        // that require unfolding opaque types.
-        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
+        let param_env = self.param_env;
         let src = self.tcx.normalize_erasing_regions(param_env, src);
         let dest = self.tcx.normalize_erasing_regions(param_env, dest);
 
index cc7ec9432faed31803376bbc5113cebd642229ca..2f4b3844430e38afaf4ac523d09de47a10f59317 100644 (file)
@@ -30,6 +30,11 @@ pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         }
     }
 
+    /// Removes the entry from the map and returns the removed value
+    pub fn remove(&mut self, k: &K) -> Option<V> {
+        self.0.iter().position(|(k2, _)| k2 == k).map(|pos| self.0.remove(pos).1)
+    }
+
     /// Gets a reference to the value in the entry.
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
     where
@@ -39,6 +44,15 @@ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
         self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
     }
 
+    /// Gets a mutable reference to the value in the entry.
+    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
+    where
+        K: Borrow<Q>,
+        Q: Eq,
+    {
+        self.0.iter_mut().find(|(key, _)| k == key.borrow()).map(|elem| &mut elem.1)
+    }
+
     /// 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
@@ -58,7 +72,7 @@ pub fn get_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) ->
         // This should return just one element, otherwise it's a bug
         assert!(
             filter.next().is_none(),
-            "Collection {:?} should have just one matching element",
+            "Collection {:#?} should have just one matching element",
             self
         );
         Some(value)
index bfe2459dc8dc1cf259b2fd72243cbd5112adc7ca..e5232bf3dd0193a2789d7a58aa605644d594b127 100644 (file)
@@ -277,8 +277,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (incomplete, adt_const_params, "1.56.0", Some(44580), None),
     /// Allows defining an `#[alloc_error_handler]`.
     (active, alloc_error_handler, "1.29.0", Some(51540), None),
-    /// Allows a test to fail without failing the whole suite.
-    (active, allow_fail, "1.19.0", Some(46488), None),
     /// Allows explicit discriminants on non-unit enum variants.
     (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
     /// Allows trait methods with arbitrary self types.
@@ -332,7 +330,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using and casting function pointers in a `const fn`.
     (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None),
     /// Allows trait bounds in `const fn`.
-    (active, const_fn_trait_bound, "1.53.0", Some(57563), None),
+    (active, const_fn_trait_bound, "1.53.0", Some(93706), None),
     /// Allows `for _ in _` loops in const contexts.
     (active, const_for, "1.56.0", Some(87575), None),
     /// Allows argument and return position `impl Trait` in a `const fn`.
index 3933746c319ecc89d5e630ec15cdf48c478fe7d5..cb2562d09a5250e5c39c1ddf2944927c891e05bc 100644 (file)
@@ -403,7 +403,6 @@ pub struct BuiltinAttribute {
     },
 
     // Testing:
-    gated!(allow_fail, Normal, template!(Word), WarnFollowing, experimental!(allow_fail)),
     gated!(
         test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks,
         "custom test frameworks are an unstable feature",
index b9f3b5ad1b1fce8b5c6aebbf821dbcaa0306b5af..f5f944db5e90b23cbbd63a3a381beb997e566ff1 100644 (file)
@@ -48,6 +48,8 @@ macro_rules! declare_features {
     (removed, advanced_slice_patterns, "1.0.0", Some(62254), None,
      Some("merged into `#![feature(slice_patterns)]`")),
     (removed, allocator, "1.0.0", None, None, None),
+    /// Allows a test to fail without failing the whole suite.
+    (removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
     (removed, await_macro, "1.38.0", Some(50547), None,
      Some("subsumed by `.await` syntax")),
     /// Allows comparing raw pointers during const eval.
index 147061dafeb1ed555e543024173fe9ac92f79d8f..6515f948dd3bc873ff8e446a14c33eeda6c94489 100644 (file)
@@ -34,6 +34,12 @@ pub struct At<'a, 'tcx> {
     pub infcx: &'a InferCtxt<'a, 'tcx>,
     pub cause: &'a ObligationCause<'tcx>,
     pub param_env: ty::ParamEnv<'tcx>,
+    /// Whether we should define opaque types
+    /// or just treat them opaquely.
+    /// Currently only used to prevent predicate
+    /// matching from matching anything against opaque
+    /// types.
+    pub define_opaque_types: bool,
 }
 
 pub struct Trace<'a, 'tcx> {
@@ -49,7 +55,7 @@ pub fn at(
         cause: &'a ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> At<'a, 'tcx> {
-        At { infcx: self, cause, param_env }
+        At { infcx: self, cause, param_env, define_opaque_types: true }
     }
 }
 
@@ -64,6 +70,10 @@ fn to_trace(
 }
 
 impl<'a, 'tcx> At<'a, 'tcx> {
+    pub fn define_opaque_types(self, define_opaque_types: bool) -> Self {
+        Self { define_opaque_types, ..self }
+    }
+
     /// Hacky routine for equating two impl headers in coherence.
     pub fn eq_impl_headers(
         self,
@@ -194,7 +204,7 @@ pub fn sub<T>(self, a: T, b: T) -> InferResult<'tcx, ()>
     {
         let Trace { at, trace, a_is_expected } = self;
         at.infcx.commit_if_ok(|_| {
-            let mut fields = at.infcx.combine_fields(trace, at.param_env);
+            let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
             fields
                 .sub(a_is_expected)
                 .relate(a, b)
@@ -211,7 +221,7 @@ pub fn eq<T>(self, a: T, b: T) -> InferResult<'tcx, ()>
     {
         let Trace { at, trace, a_is_expected } = self;
         at.infcx.commit_if_ok(|_| {
-            let mut fields = at.infcx.combine_fields(trace, at.param_env);
+            let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
             fields
                 .equate(a_is_expected)
                 .relate(a, b)
@@ -226,7 +236,7 @@ pub fn lub<T>(self, a: T, b: T) -> InferResult<'tcx, T>
     {
         let Trace { at, trace, a_is_expected } = self;
         at.infcx.commit_if_ok(|_| {
-            let mut fields = at.infcx.combine_fields(trace, at.param_env);
+            let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
             fields
                 .lub(a_is_expected)
                 .relate(a, b)
@@ -241,7 +251,7 @@ pub fn glb<T>(self, a: T, b: T) -> InferResult<'tcx, T>
     {
         let Trace { at, trace, a_is_expected } = self;
         at.infcx.commit_if_ok(|_| {
-            let mut fields = at.infcx.combine_fields(trace, at.param_env);
+            let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
             fields
                 .glb(a_is_expected)
                 .relate(a, b)
@@ -258,7 +268,10 @@ fn to_trace(
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Types(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+        }
     }
 }
 
@@ -282,27 +295,22 @@ fn to_trace(
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Consts(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+        }
     }
 }
 
 impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
     fn to_trace(
-        tcx: TyCtxt<'tcx>,
+        _: TyCtxt<'tcx>,
         cause: &ObligationCause<'tcx>,
         a_is_expected: bool,
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        match (a, b) {
-            (ty::Term::Ty(a), ty::Term::Ty(b)) => {
-                ToTrace::to_trace(tcx, cause, a_is_expected, a, b)
-            }
-            (ty::Term::Const(a), ty::Term::Const(b)) => {
-                ToTrace::to_trace(tcx, cause, a_is_expected, a, b)
-            }
-            (_, _) => todo!(),
-        }
+        TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) }
     }
 }
 
@@ -348,7 +356,7 @@ fn to_trace(
         let b_ty = tcx.mk_projection(b.item_def_id, b.substs);
         TypeTrace {
             cause: cause.clone(),
-            values: Types(ExpectedFound::new(a_is_expected, a_ty, b_ty)),
+            values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())),
         }
     }
 }
index 5b4a9d9dfad456e43b201933ffe15107eb2f73d9..7d86f8a763c30349fb2b0d39261e142bb2b522d1 100644 (file)
@@ -26,6 +26,7 @@
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
+use rustc_span::Span;
 use std::fmt::Debug;
 use std::iter;
 
@@ -89,6 +90,7 @@ pub fn make_query_response_ignoring_pending_obligations<T>(
             var_values: inference_vars,
             region_constraints: QueryRegionConstraints::default(),
             certainty: Certainty::Proven, // Ambiguities are OK!
+            opaque_types: vec![],
             value: answer,
         })
     }
@@ -133,14 +135,27 @@ fn make_query_response<T>(
         let certainty =
             if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
 
+        let opaque_types = self.take_opaque_types_for_query_response();
+
         Ok(QueryResponse {
             var_values: inference_vars,
             region_constraints,
             certainty,
             value: answer,
+            opaque_types,
         })
     }
 
+    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+        self.inner
+            .borrow_mut()
+            .opaque_type_storage
+            .take_opaque_types()
+            .into_iter()
+            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id, k.substs), v.hidden_type.ty))
+            .collect()
+    }
+
     /// Given the (canonicalized) result to a canonical query,
     /// instantiates the result so it can be used, plugging in the
     /// values from the canonical query. (Note that the result may
@@ -223,13 +238,12 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
     where
         R: Debug + TypeFoldable<'tcx>,
     {
-        let result_subst =
-            self.query_response_substitution_guess(cause, original_values, query_response);
+        let InferOk { value: result_subst, mut obligations } = self
+            .query_response_substitution_guess(cause, param_env, original_values, query_response)?;
 
         // Compute `QueryOutlivesConstraint` values that unify each of
         // the original values `v_o` that was canonicalized into a
         // variable...
-        let mut obligations = vec![];
 
         for (index, original_value) in original_values.var_values.iter().enumerate() {
             // ...with the value `v_r` of that variable from the query.
@@ -344,20 +358,25 @@ fn query_response_substitution<R>(
             original_values, query_response,
         );
 
-        let result_subst =
-            self.query_response_substitution_guess(cause, original_values, query_response);
+        let mut value = self.query_response_substitution_guess(
+            cause,
+            param_env,
+            original_values,
+            query_response,
+        )?;
 
-        let obligations = self
-            .unify_query_response_substitution_guess(
+        value.obligations.extend(
+            self.unify_query_response_substitution_guess(
                 cause,
                 param_env,
                 original_values,
-                &result_subst,
+                &value.value,
                 query_response,
             )?
-            .into_obligations();
+            .into_obligations(),
+        );
 
-        Ok(InferOk { value: result_subst, obligations })
+        Ok(value)
     }
 
     /// Given the original values and the (canonicalized) result from
@@ -372,9 +391,10 @@ fn query_response_substitution<R>(
     fn query_response_substitution_guess<R>(
         &self,
         cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
         original_values: &OriginalQueryValues<'tcx>,
         query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
-    ) -> CanonicalVarValues<'tcx>
+    ) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
     where
         R: Debug + TypeFoldable<'tcx>,
     {
@@ -474,7 +494,16 @@ fn query_response_substitution_guess<R>(
                 .collect(),
         };
 
-        result_subst
+        let mut obligations = vec![];
+
+        // Carry all newly resolved opaque types to the caller's scope
+        for &(a, b) in &query_response.value.opaque_types {
+            let a = substitute_value(self.tcx, &result_subst, a);
+            let b = substitute_value(self.tcx, &result_subst, b);
+            obligations.extend(self.handle_opaque_type(a, b, cause, param_env)?.obligations);
+        }
+
+        Ok(InferOk { value: result_subst, obligations })
     }
 
     /// Given a "guess" at the values for the canonical variables in
@@ -631,6 +660,10 @@ struct QueryTypeRelatingDelegate<'a, 'tcx> {
 }
 
 impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
+    fn span(&self) -> Span {
+        self.cause.span
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
@@ -686,4 +719,14 @@ fn normalization() -> NormalizationStrategy {
     fn forbid_inference_vars() -> bool {
         true
     }
+
+    fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) {
+        self.obligations.push(self.infcx.opaque_ty_obligation(
+            a,
+            b,
+            a_is_expected,
+            self.param_env,
+            self.cause.clone(),
+        ));
+    }
 }
index a77fd8fae8d20d059cbfc110d90bda00580111d9..5668b6c10b000e97f6ac8831addb98b258ba1866 100644 (file)
@@ -51,6 +51,12 @@ pub struct CombineFields<'infcx, 'tcx> {
     pub cause: Option<ty::relate::Cause>,
     pub param_env: ty::ParamEnv<'tcx>,
     pub obligations: PredicateObligations<'tcx>,
+    /// Whether we should define opaque types
+    /// or just treat them opaquely.
+    /// Currently only used to prevent predicate
+    /// matching from matching anything against opaque
+    /// types.
+    pub define_opaque_types: bool,
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -322,6 +328,7 @@ pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'tcx> {
     /// will first instantiate `b_vid` with a *generalized* version
     /// of `a_ty`. Generalization introduces other inference
     /// variables wherever subtyping could occur.
+    #[instrument(skip(self), level = "debug")]
     pub fn instantiate(
         &mut self,
         a_ty: Ty<'tcx>,
@@ -334,8 +341,6 @@ pub fn instantiate(
         // Get the actual variable that b_vid has been inferred to
         debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
 
-        debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
-
         // Generalize type of `a_ty` appropriately depending on the
         // direction.  As an example, assume:
         //
@@ -348,10 +353,7 @@ pub fn instantiate(
         // variables. (Down below, we will relate `a_ty <: b_ty`,
         // adding constraints like `'x: '?2` and `?1 <: ?3`.)
         let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
-        debug!(
-            "instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
-            a_ty, dir, b_vid, b_ty
-        );
+        debug!(?b_ty);
         self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
 
         if needs_wf {
@@ -392,13 +394,13 @@ pub fn instantiate(
     /// Preconditions:
     ///
     /// - `for_vid` is a "root vid"
+    #[instrument(skip(self), level = "trace")]
     fn generalize(
         &self,
         ty: Ty<'tcx>,
         for_vid: ty::TyVid,
         dir: RelationDir,
     ) -> RelateResult<'tcx, Generalization<'tcx>> {
-        debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir);
         // Determine the ambient variance within which `ty` appears.
         // The surrounding equation is:
         //
@@ -412,7 +414,7 @@ fn generalize(
             RelationDir::SupertypeOf => ty::Contravariant,
         };
 
-        debug!("generalize: ambient_variance = {:?}", ambient_variance);
+        trace!(?ambient_variance);
 
         let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
             v @ TypeVariableValue::Known { .. } => {
@@ -421,8 +423,8 @@ fn generalize(
             TypeVariableValue::Unknown { universe } => universe,
         };
 
-        debug!("generalize: for_universe = {:?}", for_universe);
-        debug!("generalize: trace = {:?}", self.trace);
+        trace!(?for_universe);
+        trace!(?self.trace);
 
         let mut generalize = Generalizer {
             infcx: self.infcx,
@@ -439,12 +441,12 @@ fn generalize(
         let ty = match generalize.relate(ty, ty) {
             Ok(ty) => ty,
             Err(e) => {
-                debug!("generalize: failure {:?}", e);
+                debug!(?e, "failure");
                 return Err(e);
             }
         };
         let needs_wf = generalize.needs_wf;
-        debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf);
+        trace!(?ty, ?needs_wf, "success");
         Ok(Generalization { ty, needs_wf })
     }
 
index 90c0ff9226f7783618ff2219672a0965043cfa73..9f6c6d3184533c2f9fe674f35cb51d49d32ee007 100644 (file)
@@ -66,18 +66,19 @@ fn relate_with_variance<T: Relate<'tcx>>(
         self.relate(a, b)
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({:?}, {:?})", self.tag(), a, b);
         if a == b {
             return Ok(a);
         }
 
+        trace!(a = ?a.kind(), b = ?b.kind());
+
         let infcx = self.fields.infcx;
+
         let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
         let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
 
-        debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);
-
         match (a.kind(), b.kind()) {
             (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
                 infcx.inner.borrow_mut().type_variables().equate(a_id, b_id);
@@ -91,6 +92,21 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
             }
 
+            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+                self.fields.infcx.super_combine_tys(self, a, b)?;
+            }
+            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
+                if self.fields.define_opaque_types && did.is_local() =>
+            {
+                self.fields.obligations.push(infcx.opaque_ty_obligation(
+                    a,
+                    b,
+                    self.a_is_expected(),
+                    self.param_env(),
+                    self.fields.trace.cause.clone(),
+                ));
+            }
+
             _ => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
             }
index 1eb8190bd7d2fb5d5747640174ed1692fb6ba620..8d41497541a192d5e78ce58621cd9ddd0e33445c 100644 (file)
@@ -1582,18 +1582,18 @@ enum Mismatch<'a> {
             None => (None, Mismatch::Fixed("type"), false),
             Some(values) => {
                 let (is_simple_error, exp_found) = match values {
-                    ValuePairs::Types(exp_found) => {
-                        let is_simple_err =
-                            exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
-                        OpaqueTypesVisitor::visit_expected_found(
-                            self.tcx,
-                            exp_found.expected,
-                            exp_found.found,
-                            span,
-                        )
-                        .report(diag);
+                    ValuePairs::Terms(infer::ExpectedFound {
+                        expected: ty::Term::Ty(expected),
+                        found: ty::Term::Ty(found),
+                    }) => {
+                        let is_simple_err = expected.is_simple_text() && found.is_simple_text();
+                        OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span)
+                            .report(diag);
 
-                        (is_simple_err, Mismatch::Variable(exp_found))
+                        (
+                            is_simple_err,
+                            Mismatch::Variable(infer::ExpectedFound { expected, found }),
+                        )
                     }
                     ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
                     _ => (false, Mismatch::Fixed("type")),
@@ -1624,7 +1624,7 @@ enum Mismatch<'a> {
                 };
                 if let Some((sp, msg)) = secondary_span {
                     if swap_secondary_and_primary {
-                        let terr = if let Some(infer::ValuePairs::Types(infer::ExpectedFound {
+                        let terr = if let Some(infer::ValuePairs::Terms(infer::ExpectedFound {
                             expected,
                             ..
                         })) = values
@@ -2036,27 +2036,14 @@ pub fn report_and_explain_type_error(
             }
             FailureCode::Error0308(failure_str) => {
                 let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
-                if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) =
-                    trace.values
-                {
+                if let Some((expected, found)) = trace.values.ty() {
                     match (expected.kind(), found.kind()) {
                         (ty::Tuple(_), ty::Tuple(_)) => {}
                         // If a tuple of length one was expected and the found expression has
                         // parentheses around it, perhaps the user meant to write `(expr,)` to
                         // build a tuple (issue #86100)
-                        (ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => {
-                            if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
-                                if let Some(code) =
-                                    code.strip_prefix('(').and_then(|s| s.strip_suffix(')'))
-                                {
-                                    err.span_suggestion(
-                                        span,
-                                        "use a trailing comma to create a tuple with one element",
-                                        format!("({},)", code),
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                }
-                            }
+                        (ty::Tuple(_), _) => {
+                            self.emit_tuple_wrap_err(&mut err, span, found, expected)
                         }
                         // If a character was expected and the found expression is a string literal
                         // containing a single character, perhaps the user meant to write `'c'` to
@@ -2066,7 +2053,7 @@ pub fn report_and_explain_type_error(
                                 if let Some(code) =
                                     code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
                                 {
-                                    if code.chars().nth(1).is_none() {
+                                    if code.chars().count() == 1 {
                                         err.span_suggestion(
                                             span,
                                             "if you meant to write a `char` literal, use single quotes",
@@ -2119,14 +2106,48 @@ pub fn report_and_explain_type_error(
         diag
     }
 
+    fn emit_tuple_wrap_err(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        found: Ty<'tcx>,
+        expected: Ty<'tcx>,
+    ) {
+        let [expected_tup_elem] = &expected.tuple_fields().collect::<Vec<_>>()[..]
+            else { return };
+
+        if !same_type_modulo_infer(expected_tup_elem, found) {
+            return;
+        }
+
+        let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
+            else { return };
+
+        let msg = "use a trailing comma to create a tuple with one element";
+        if code.starts_with('(') && code.ends_with(')') {
+            let before_close = span.hi() - BytePos::from_u32(1);
+            err.span_suggestion(
+                span.with_hi(before_close).shrink_to_hi(),
+                msg,
+                ",".into(),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.multipart_suggestion(
+                msg,
+                vec![(span.shrink_to_lo(), "(".into()), (span.shrink_to_hi(), ",)".into())],
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     fn values_str(
         &self,
         values: ValuePairs<'tcx>,
     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
         match values {
-            infer::Types(exp_found) => self.expected_found_str_ty(exp_found),
             infer::Regions(exp_found) => self.expected_found_str(exp_found),
-            infer::Consts(exp_found) => self.expected_found_str(exp_found),
+            infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
             infer::TraitRefs(exp_found) => {
                 let pretty_exp_found = ty::error::ExpectedFound {
                     expected: exp_found.expected.print_only_trait_path(),
@@ -2154,16 +2175,22 @@ fn values_str(
         }
     }
 
-    fn expected_found_str_ty(
+    fn expected_found_str_term(
         &self,
-        exp_found: ty::error::ExpectedFound<Ty<'tcx>>,
+        exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
         }
 
-        Some(self.cmp(exp_found.expected, exp_found.found))
+        Some(match (exp_found.expected, exp_found.found) {
+            (ty::Term::Ty(expected), ty::Term::Ty(found)) => self.cmp(expected, found),
+            (expected, found) => (
+                DiagnosticStyledString::highlighted(expected.to_string()),
+                DiagnosticStyledString::highlighted(found.to_string()),
+            ),
+        })
     }
 
     /// Returns a string of the form "expected `{}`, found `{}`".
index bbea450a76973a868c48b05e169bd936b50944c2..a79ed20730b5cf014eff50d71b7ccc3ac8c528f8 100644 (file)
@@ -2,7 +2,7 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
+use crate::infer::{SubregionOrigin, Subtype};
 use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
@@ -34,16 +34,16 @@ pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorRepo
         {
             if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
                 if let (
-                    ValuePairs::Types(sub_expected_found),
-                    ValuePairs::Types(sup_expected_found),
+                    sub_expected_found @ Some((sub_expected, sub_found)),
+                    sup_expected_found @ Some(_),
                     CompareImplMethodObligation { trait_item_def_id, .. },
-                ) = (&sub_trace.values, &sup_trace.values, sub_trace.cause.code())
+                ) = (&sub_trace.values.ty(), &sup_trace.values.ty(), sub_trace.cause.code())
                 {
                     if sup_expected_found == sub_expected_found {
                         self.emit_err(
                             var_origin.span(),
-                            sub_expected_found.expected,
-                            sub_expected_found.found,
+                            sub_expected,
+                            sub_found,
                             *trait_item_def_id,
                         );
                         return Some(ErrorReported);
index 862f5a5fbb8c1805ca84a47bc2e1ff71f7c9d7d2..c4c4eab261e86de313bfc901c565ed3fd4853477 100644 (file)
@@ -4,7 +4,7 @@
 use super::Subtype;
 
 use crate::infer::combine::ConstEquateRelation;
-use crate::traits::ObligationCause;
+use crate::traits::{ObligationCause, PredicateObligation};
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -111,12 +111,20 @@ fn cause(&self) -> &ObligationCause<'tcx> {
         &self.fields.trace.cause
     }
 
+    fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
+        self.fields.obligations.extend(obligations)
+    }
+
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
         let mut sub = self.fields.sub(self.a_is_expected);
         sub.relate(v, a)?;
         sub.relate(v, b)?;
         Ok(())
     }
+
+    fn define_opaque_types(&self) -> bool {
+        self.fields.define_opaque_types
+    }
 }
 
 impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
index c47d476963772e2adda260bca51b6a4f3e1f1c97..6bda44f0ef256cad3a40d4a5f22ff1d22d26f90a 100644 (file)
@@ -22,7 +22,7 @@
 use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use super::InferCtxt;
 
-use crate::traits::ObligationCause;
+use crate::traits::{ObligationCause, PredicateObligation};
 use rustc_middle::ty::relate::{RelateResult, TypeRelation};
 use rustc_middle::ty::TyVar;
 use rustc_middle::ty::{self, Ty};
@@ -32,6 +32,10 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
 
     fn cause(&self) -> &ObligationCause<'tcx>;
 
+    fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
+
+    fn define_opaque_types(&self) -> bool;
+
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
     //
@@ -41,6 +45,7 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
 }
 
+#[instrument(skip(this), level = "debug")]
 pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
     this: &mut L,
     a: Ty<'tcx>,
@@ -49,15 +54,17 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
 where
     L: LatticeDir<'a, 'tcx>,
 {
-    debug!("{}.lattice_tys({:?}, {:?})", this.tag(), a, b);
+    debug!("{}", this.tag());
 
     if a == b {
         return Ok(a);
     }
 
     let infcx = this.infcx();
+
     let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
     let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
+
     match (a.kind(), b.kind()) {
         // If one side is known to be a variable and one is not,
         // create a variable (`v`) to represent the LUB. Make sure to
@@ -94,6 +101,22 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
             Ok(v)
         }
 
+        (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            infcx.super_combine_tys(this, a, b)
+        }
+        (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
+            if this.define_opaque_types() && did.is_local() =>
+        {
+            this.add_obligations(vec![infcx.opaque_ty_obligation(
+                a,
+                b,
+                this.a_is_expected(),
+                this.param_env(),
+                this.cause().clone(),
+            )]);
+            Ok(a)
+        }
+
         _ => infcx.super_combine_tys(this, a, b),
     }
 }
index 5191d1c1cc1008c8706a9fcc2d866affe976360a..bbd8e00146905e991e99051a11db70e329fef1af 100644 (file)
@@ -4,7 +4,7 @@
 use super::Subtype;
 
 use crate::infer::combine::ConstEquateRelation;
-use crate::traits::ObligationCause;
+use crate::traits::{ObligationCause, PredicateObligation};
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -117,10 +117,18 @@ fn cause(&self) -> &ObligationCause<'tcx> {
         &self.fields.trace.cause
     }
 
+    fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
+        self.fields.obligations.extend(obligations)
+    }
+
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
         let mut sub = self.fields.sub(self.a_is_expected);
         sub.relate(a, v)?;
         sub.relate(b, v)?;
         Ok(())
     }
+
+    fn define_opaque_types(&self) -> bool {
+        self.fields.define_opaque_types
+    }
 }
index d1b24b332bdcc65b2cef56a189b3f05cdeff0f53..08320a0ff1d4229aaec90255cca58204cbdf6d27 100644 (file)
@@ -5,7 +5,7 @@
 pub use self::SubregionOrigin::*;
 pub use self::ValuePairs::*;
 
-use self::opaque_types::OpaqueTypeMap;
+use self::opaque_types::OpaqueTypeStorage;
 pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
 
 use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
@@ -192,18 +192,8 @@ pub struct InferCtxtInner<'tcx> {
 
     undo_log: InferCtxtUndoLogs<'tcx>,
 
-    // Opaque types found in explicit return types and their
-    // associated fresh inference variable. Writeback resolves these
-    // variables to get the concrete type, which can be used to
-    // 'de-opaque' OpaqueTypeDecl outside of type inference.
-    pub opaque_types: OpaqueTypeMap<'tcx>,
-
-    /// A map from inference variables created from opaque
-    /// type instantiations (`ty::Infer`) to the actual opaque
-    /// type (`ty::Opaque`). Used during fallback to map unconstrained
-    /// opaque type inference variables to their corresponding
-    /// opaque type.
-    pub opaque_types_vars: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+    /// Caches for opaque type inference.
+    pub opaque_type_storage: OpaqueTypeStorage<'tcx>,
 }
 
 impl<'tcx> InferCtxtInner<'tcx> {
@@ -217,8 +207,7 @@ fn new() -> InferCtxtInner<'tcx> {
             float_unification_storage: ut::UnificationTableStorage::new(),
             region_constraint_storage: Some(RegionConstraintStorage::new()),
             region_obligations: vec![],
-            opaque_types: Default::default(),
-            opaque_types_vars: Default::default(),
+            opaque_type_storage: Default::default(),
         }
     }
 
@@ -237,6 +226,11 @@ fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> {
         self.type_variable_storage.with_log(&mut self.undo_log)
     }
 
+    #[inline]
+    pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
+        self.opaque_type_storage.with_log(&mut self.undo_log)
+    }
+
     #[inline]
     fn int_unification_table(
         &mut self,
@@ -297,6 +291,10 @@ pub struct InferCtxt<'a, 'tcx> {
     /// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
     pub defining_use_anchor: Option<LocalDefId>,
 
+    /// Used by WF-checking to not have to figure out hidden types itself, but
+    /// to just invoke type_of to get the already computed hidden type from typeck.
+    pub reveal_defining_opaque_types: bool,
+
     /// During type-checking/inference of a body, `in_progress_typeck_results`
     /// contains a reference to the typeck results being built up, which are
     /// used for reading closure kinds/signatures as they are inferred,
@@ -368,13 +366,26 @@ pub struct InferCtxt<'a, 'tcx> {
 /// See the `error_reporting` module for more details.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
 pub enum ValuePairs<'tcx> {
-    Types(ExpectedFound<Ty<'tcx>>),
     Regions(ExpectedFound<ty::Region<'tcx>>),
-    Consts(ExpectedFound<&'tcx ty::Const<'tcx>>),
+    Terms(ExpectedFound<ty::Term<'tcx>>),
     TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
     PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
 }
 
+impl<'tcx> ValuePairs<'tcx> {
+    pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
+        if let ValuePairs::Terms(ExpectedFound {
+            expected: ty::Term::Ty(expected),
+            found: ty::Term::Ty(found),
+        }) = self
+        {
+            Some((expected, found))
+        } else {
+            None
+        }
+    }
+}
+
 /// The trace designates the path through inference that we took to
 /// encounter an error or subtyping constraint.
 ///
@@ -552,6 +563,7 @@ pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
     fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
     defining_use_anchor: Option<LocalDefId>,
+    reveal_defining_opaque_types: bool,
 }
 
 pub trait TyCtxtInferExt<'tcx> {
@@ -560,7 +572,12 @@ pub trait TyCtxtInferExt<'tcx> {
 
 impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
     fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
-        InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None }
+        InferCtxtBuilder {
+            tcx: self,
+            defining_use_anchor: None,
+            fresh_typeck_results: None,
+            reveal_defining_opaque_types: false,
+        }
     }
 }
 
@@ -584,6 +601,13 @@ pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) ->
         self
     }
 
+    /// WF-checking doesn't need to recompute opaque types and can instead use
+    /// the type_of query to get them from typeck.
+    pub fn reveal_defining_opaque_types(mut self) -> Self {
+        self.reveal_defining_opaque_types = true;
+        self
+    }
+
     /// Given a canonical value `C` as a starting point, create an
     /// inference context that contains each of the bound values
     /// within instantiated as a fresh variable. The `f` closure is
@@ -608,11 +632,17 @@ pub fn enter_with_canonical<T, R>(
     }
 
     pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
-        let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
+        let InferCtxtBuilder {
+            tcx,
+            defining_use_anchor,
+            reveal_defining_opaque_types,
+            ref fresh_typeck_results,
+        } = *self;
         let in_progress_typeck_results = fresh_typeck_results.as_ref();
         f(InferCtxt {
             tcx,
             defining_use_anchor,
+            reveal_defining_opaque_types,
             in_progress_typeck_results,
             inner: RefCell::new(InferCtxtInner::new()),
             lexical_region_resolutions: RefCell::new(None),
@@ -734,6 +764,7 @@ fn combine_fields(
         &'a self,
         trace: TypeTrace<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
+        define_opaque_types: bool,
     ) -> CombineFields<'a, 'tcx> {
         CombineFields {
             infcx: self,
@@ -741,6 +772,7 @@ fn combine_fields(
             cause: None,
             param_env,
             obligations: PredicateObligations::new(),
+            define_opaque_types,
         }
     }
 
@@ -1056,12 +1088,20 @@ pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
         self.tcx.mk_ty_var(self.next_ty_var_id(origin))
     }
 
+    pub fn next_ty_var_id_in_universe(
+        &self,
+        origin: TypeVariableOrigin,
+        universe: ty::UniverseIndex,
+    ) -> TyVid {
+        self.inner.borrow_mut().type_variables().new_var(universe, origin)
+    }
+
     pub fn next_ty_var_in_universe(
         &self,
         origin: TypeVariableOrigin,
         universe: ty::UniverseIndex,
     ) -> Ty<'tcx> {
-        let vid = self.inner.borrow_mut().type_variables().new_var(universe, origin);
+        let vid = self.next_ty_var_id_in_universe(origin, universe);
         self.tcx.mk_ty_var(vid)
     }
 
@@ -1790,7 +1830,10 @@ pub fn types(
         a: Ty<'tcx>,
         b: Ty<'tcx>,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Types(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+        }
     }
 
     pub fn consts(
@@ -1799,7 +1842,10 @@ pub fn consts(
         a: &'tcx ty::Const<'tcx>,
         b: &'tcx ty::Const<'tcx>,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Consts(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+        }
     }
 }
 
index 0a210ed053ce4ec7f61c9bbc0aa4ea3e0e13c6e5..3a288516664e380ad1371902797a273d161b3601 100644 (file)
 use crate::infer::combine::ConstEquateRelation;
 use crate::infer::InferCtxt;
 use crate::infer::{ConstVarValue, ConstVariableValue};
+use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
+use rustc_span::Span;
 use std::fmt::Debug;
 use std::ops::ControlFlow;
 
@@ -75,6 +77,7 @@ pub struct TypeRelating<'me, 'tcx, D>
 
 pub trait TypeRelatingDelegate<'tcx> {
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
+    fn span(&self) -> Span;
 
     /// Push a constraint `sup: sub` -- this constraint must be
     /// satisfied for the two types to be related. `sub` and `sup` may
@@ -87,6 +90,8 @@ fn push_outlives(
         info: ty::VarianceDiagInfo<'tcx>,
     );
 
+    fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool);
+
     fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>);
 
     /// Creates a new universe index. Used when instantiating placeholders.
@@ -277,7 +282,6 @@ fn relate_projection_ty(
         projection_ty: ty::ProjectionTy<'tcx>,
         value_ty: Ty<'tcx>,
     ) -> Ty<'tcx> {
-        use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
         use rustc_span::DUMMY_SP;
 
         match *value_ty.kind() {
@@ -286,6 +290,8 @@ fn relate_projection_ty(
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
                 });
+                // FIXME(lazy-normalization): This will always ICE, because the recursive
+                // call will end up in the _ arm below.
                 self.relate_projection_ty(projection_ty, var);
                 self.relate_projection_ty(other_projection_ty, var);
                 var
@@ -531,6 +537,8 @@ fn relate_with_variance<T: Relate<'tcx>>(
 
     #[instrument(skip(self), level = "debug")]
     fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        let infcx = self.infcx;
+
         let a = self.infcx.shallow_resolve(a);
 
         if !D::forbid_inference_vars() {
@@ -559,6 +567,35 @@ fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>
 
             (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
 
+            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+                self.infcx.super_combine_tys(self, a, b)
+            }
+            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
+                let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
+                let mut generalize = |ty, ty_is_expected| {
+                    let var = infcx.next_ty_var_id_in_universe(
+                        TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::MiscVariable,
+                            span: self.delegate.span(),
+                        },
+                        ty::UniverseIndex::ROOT,
+                    );
+                    if ty_is_expected {
+                        self.relate_ty_var((ty, var))
+                    } else {
+                        self.relate_ty_var((var, ty))
+                    }
+                };
+                let (a, b) = match (a.kind(), b.kind()) {
+                    (&ty::Opaque(..), _) => (a, generalize(b, false)?),
+                    (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
+                    _ => unreachable!(),
+                };
+                self.delegate.register_opaque_type(a, b, true);
+                trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
+                Ok(a)
+            }
+
             (&ty::Projection(projection_ty), _)
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
index e7dca94806cb740243e7ab0af2c141a84635e2ce..46420fbe0c305c5afe04e6c8c2240790e2416f81 100644 (file)
@@ -1,10 +1,11 @@
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{InferCtxt, InferOk};
-use crate::traits;
+use crate::traits::{self, PredicateObligation};
+use hir::def_id::{DefId, LocalDefId};
+use hir::OpaqueTyOrigin;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 
 pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
 
+mod table;
+
+pub use table::{OpaqueTypeStorage, OpaqueTypeTable};
+
+use super::InferResult;
+
 /// Information about the opaque types whose values we
 /// are inferring in this function (these are the `impl Trait` that
 /// appear in the return type).
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
 pub struct OpaqueTypeDecl<'tcx> {
-    /// The opaque type (`ty::Opaque`) for this declaration.
-    pub opaque_type: Ty<'tcx>,
+    /// The hidden types that have been inferred for this opaque type.
+    /// There can be multiple, but they are all `lub`ed together at the end
+    /// to obtain the canonical hidden type.
+    pub hidden_type: OpaqueHiddenType<'tcx>,
+
+    /// The origin of the opaque type.
+    pub origin: hir::OpaqueTyOrigin,
+}
 
+#[derive(Copy, Clone, Debug, TypeFoldable)]
+pub struct OpaqueHiddenType<'tcx> {
     /// The span of this particular definition of the opaque type. So
     /// for example:
     ///
@@ -35,7 +50,7 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// In cases where the fn returns `(impl Trait, impl Trait)` or
     /// other such combinations, the result is currently
     /// over-approximated, but better than nothing.
-    pub definition_span: Span,
+    pub span: Span,
 
     /// The type variable that represents the value of the opaque type
     /// that we require. In other words, after we compile this function,
@@ -49,54 +64,132 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// those that are arguments to `Foo` in the constraint above. (In
     /// other words, `?C` should not include `'b`, even though it's a
     /// lifetime parameter on `foo`.)
-    pub concrete_ty: Ty<'tcx>,
-
-    /// The origin of the opaque type.
-    pub origin: hir::OpaqueTyOrigin,
+    pub ty: Ty<'tcx>,
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    /// Replaces all opaque types in `value` with fresh inference variables
-    /// and creates appropriate obligations. For example, given the input:
-    ///
-    ///     impl Iterator<Item = impl Debug>
-    ///
-    /// this method would create two type variables, `?0` and `?1`. It would
-    /// return the type `?0` but also the obligations:
-    ///
-    ///     ?0: Iterator<Item = ?1>
-    ///     ?1: Debug
-    ///
-    /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to
-    /// info about the `impl Iterator<..>` type and `?1` to info about
-    /// the `impl Debug` type.
-    ///
-    /// # Parameters
-    ///
-    /// - `parent_def_id` -- the `DefId` of the function in which the opaque type
-    ///   is defined
-    /// - `body_id` -- the body-id with which the resulting obligations should
-    ///   be associated
-    /// - `param_env` -- the in-scope parameter environment to be used for
-    ///   obligations
-    /// - `value` -- the value within which we are instantiating opaque types
-    /// - `value_span` -- the span where the value came from, used in error reporting
-    pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
+    pub fn handle_opaque_type(
         &self,
-        body_id: hir::HirId,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
+        cause: &ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        value: T,
-        value_span: Span,
-    ) -> InferOk<'tcx, T> {
-        debug!(
-            "instantiate_opaque_types(value={:?}, body_id={:?}, \
-             param_env={:?}, value_span={:?})",
-            value, body_id, param_env, value_span,
-        );
-        let mut instantiator =
-            Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] };
-        let value = instantiator.instantiate_opaque_types_in_map(value);
-        InferOk { value, obligations: instantiator.obligations }
+    ) -> InferResult<'tcx, ()> {
+        if a.references_error() || b.references_error() {
+            return Ok(InferOk { value: (), obligations: vec![] });
+        }
+        if self.defining_use_anchor.is_some() {
+            let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
+                ty::Opaque(def_id, substs) => {
+                    if let ty::Opaque(did2, _) = *b.kind() {
+                        // We could accept this, but there are various ways to handle this situation, and we don't
+                        // want to make a decision on it right now. Likely this case is so super rare anyway, that
+                        // no one encounters it in practice.
+                        // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
+                        // where it is of no concern, so we only check for TAITs.
+                        if let Some(OpaqueTyOrigin::TyAlias) =
+                            self.opaque_type_origin(did2, cause.span)
+                        {
+                            self.tcx
+                                .sess
+                                .struct_span_err(
+                                    cause.span,
+                                    "opaque type's hidden type cannot be another opaque type from the same scope",
+                                )
+                                .span_label(cause.span, "one of the two opaque types used here has to be outside its defining scope")
+                                .span_note(
+                                    self.tcx.def_span(def_id),
+                                    "opaque type whose hidden type is being assigned",
+                                )
+                                .span_note(
+                                    self.tcx.def_span(did2),
+                                    "opaque type being used as hidden type",
+                                )
+                                .emit();
+                        }
+                    }
+                    Some(self.register_hidden_type(
+                        OpaqueTypeKey { def_id, substs },
+                        cause.clone(),
+                        param_env,
+                        b,
+                        // Check that this is `impl Trait` type is
+                        // declared by `parent_def_id` -- i.e., one whose
+                        // value we are inferring.  At present, this is
+                        // always true during the first phase of
+                        // type-check, but not always true later on during
+                        // NLL. Once we support named opaque types more fully,
+                        // this same scenario will be able to arise during all phases.
+                        //
+                        // Here is an example using type alias `impl Trait`
+                        // that indicates the distinction we are checking for:
+                        //
+                        // ```rust
+                        // mod a {
+                        //   pub type Foo = impl Iterator;
+                        //   pub fn make_foo() -> Foo { .. }
+                        // }
+                        //
+                        // mod b {
+                        //   fn foo() -> a::Foo { a::make_foo() }
+                        // }
+                        // ```
+                        //
+                        // Here, the return type of `foo` references an
+                        // `Opaque` indeed, but not one whose value is
+                        // presently being inferred. You can get into a
+                        // similar situation with closure return types
+                        // today:
+                        //
+                        // ```rust
+                        // fn foo() -> impl Iterator { .. }
+                        // fn bar() {
+                        //     let x = || foo(); // returns the Opaque assoc with `foo`
+                        // }
+                        // ```
+                        self.opaque_type_origin(def_id, cause.span)?,
+                    ))
+                }
+                _ => None,
+            };
+            if let Some(res) = process(a, b) {
+                res
+            } else if let Some(res) = process(b, a) {
+                res
+            } else {
+                // Rerun equality check, but this time error out due to
+                // different types.
+                match self.at(cause, param_env).define_opaque_types(false).eq(a, b) {
+                    Ok(_) => span_bug!(
+                        cause.span,
+                        "opaque types are never equal to anything but themselves: {:#?}",
+                        (a, b)
+                    ),
+                    Err(e) => Err(e),
+                }
+            }
+        } else {
+            let (opaque_type, hidden_ty) = match (a.kind(), b.kind()) {
+                (ty::Opaque(..), _) => (a, b),
+                (_, ty::Opaque(..)) => (b, a),
+                types => span_bug!(
+                    cause.span,
+                    "opaque type obligations only work for opaque types: {:#?}",
+                    types
+                ),
+            };
+            let key = opaque_type.expect_opaque_type();
+            let origin = self.opaque_ty_origin_unchecked(key.def_id, cause.span);
+            let prev = self.inner.borrow_mut().opaque_types().register(
+                key,
+                OpaqueHiddenType { ty: hidden_ty, span: cause.span },
+                origin,
+            );
+            match prev {
+                Some(prev) => self.at(cause, param_env).eq(prev, hidden_ty),
+                None => Ok(InferOk { value: (), obligations: vec![] }),
+            }
+        }
     }
 
     /// Given the map `opaque_types` containing the opaque
@@ -231,51 +324,23 @@ pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
     /// but this is not necessary, because the opaque type we
     /// create will be allowed to reference `T`. So we only generate a
     /// constraint that `'0: 'a`.
-    ///
-    /// # The `free_region_relations` parameter
-    ///
-    /// The `free_region_relations` argument is used to find the
-    /// "minimum" of the regions supplied to a given opaque type.
-    /// It must be a relation that can answer whether `'a <= 'b`,
-    /// where `'a` and `'b` are regions that appear in the "substs"
-    /// for the opaque type references (the `<'a>` in `Foo1<'a>`).
-    ///
-    /// Note that we do not impose the constraints based on the
-    /// generic regions from the `Foo1` definition (e.g., `'x`). This
-    /// is because the constraints we are imposing here is basically
-    /// the concern of the one generating the constraining type C1,
-    /// which is the current function. It also means that we can
-    /// take "implied bounds" into account in some cases:
-    ///
-    /// ```text
-    /// trait SomeTrait<'a, 'b> { }
-    /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
-    /// ```
-    ///
-    /// Here, the fact that `'b: 'a` is known only because of the
-    /// implied bounds from the `&'a &'b u32` parameter, and is not
-    /// "inherent" to the opaque type definition.
-    ///
-    /// # Parameters
-    ///
-    /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
-    /// - `free_region_relations` -- something that can be used to relate
-    ///   the free regions (`'a`) that appear in the impl trait.
     #[instrument(level = "debug", skip(self))]
-    pub fn constrain_opaque_type(
+    pub fn register_member_constraints(
         &self,
+        param_env: ty::ParamEnv<'tcx>,
         opaque_type_key: OpaqueTypeKey<'tcx>,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        concrete_ty: Ty<'tcx>,
+        span: Span,
     ) {
         let def_id = opaque_type_key.def_id;
 
         let tcx = self.tcx;
 
-        let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
+        let concrete_ty = self.resolve_vars_if_possible(concrete_ty);
 
         debug!(?concrete_ty);
 
-        let first_own_region = match opaque_defn.origin {
+        let first_own_region = match self.opaque_ty_origin_unchecked(def_id, span) {
             hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
                 // We lower
                 //
@@ -319,7 +384,7 @@ pub fn constrain_opaque_type(
             op: |r| {
                 self.member_constraint(
                     opaque_type_key.def_id,
-                    opaque_defn.definition_span,
+                    span,
                     concrete_ty,
                     r,
                     &choice_regions,
@@ -328,15 +393,34 @@ pub fn constrain_opaque_type(
         });
     }
 
-    fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<hir::OpaqueTyOrigin> {
-        let tcx = self.tcx;
-        let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+    pub fn opaque_ty_obligation(
+        &self,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
+        a_is_expected: bool,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: ObligationCause<'tcx>,
+    ) -> PredicateObligation<'tcx> {
+        let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
+        PredicateObligation::new(
+            cause,
+            param_env,
+            self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::OpaqueType(a, b))),
+        )
+    }
+
+    #[instrument(skip(self), level = "trace")]
+    pub fn opaque_type_origin(&self, opaque_def_id: DefId, span: Span) -> Option<OpaqueTyOrigin> {
+        let def_id = opaque_def_id.as_local()?;
+        let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let parent_def_id = self.defining_use_anchor?;
-        let item_kind = &tcx.hir().expect_item(def_id).kind;
+        let item_kind = &self.tcx.hir().expect_item(def_id).kind;
+
         let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, ..  }) = item_kind else {
             span_bug!(
-                tcx.def_span(def_id),
-                "weird opaque type: {:#?}",
+                span,
+                "weird opaque type: {:#?}, {:#?}",
+                opaque_def_id,
                 item_kind
             )
         };
@@ -347,11 +431,29 @@ fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<hir::OpaqueTyOrigin>
             hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
             // Named `type Foo = impl Bar;`
             hir::OpaqueTyOrigin::TyAlias => {
-                may_define_opaque_type(tcx, parent_def_id, opaque_hir_id)
+                may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
             }
         };
+        trace!(?origin);
         in_definition_scope.then_some(*origin)
     }
+
+    #[instrument(skip(self), level = "trace")]
+    fn opaque_ty_origin_unchecked(&self, opaque_def_id: DefId, span: Span) -> OpaqueTyOrigin {
+        let def_id = opaque_def_id.as_local().unwrap();
+        let origin = match self.tcx.hir().expect_item(def_id).kind {
+            hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
+            ref itemkind => {
+                span_bug!(span, "weird opaque type: {:?}, {:#?}", opaque_def_id, itemkind)
+            }
+        };
+        trace!(?origin);
+        origin
+    }
+
+    pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> {
+        self.inner.borrow().opaque_type_storage.opaque_types()
+    }
 }
 
 // Visitor that requires that (almost) all regions in the type visited outlive
@@ -426,180 +528,93 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 }
 
-struct Instantiator<'a, 'tcx> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    body_id: hir::HirId,
-    param_env: ty::ParamEnv<'tcx>,
-    value_span: Span,
-    obligations: Vec<traits::PredicateObligation<'tcx>>,
+pub enum UseKind {
+    DefiningUse,
+    OpaqueUse,
 }
 
-impl<'a, 'tcx> Instantiator<'a, 'tcx> {
-    fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
-        let tcx = self.infcx.tcx;
-        value.fold_with(&mut BottomUpFolder {
-            tcx,
-            ty_op: |ty| {
-                if ty.references_error() {
-                    return tcx.ty_error();
-                } else if let ty::Opaque(def_id, substs) = ty.kind() {
-                    // Check that this is `impl Trait` type is
-                    // declared by `parent_def_id` -- i.e., one whose
-                    // value we are inferring.  At present, this is
-                    // always true during the first phase of
-                    // type-check, but not always true later on during
-                    // NLL. Once we support named opaque types more fully,
-                    // this same scenario will be able to arise during all phases.
-                    //
-                    // Here is an example using type alias `impl Trait`
-                    // that indicates the distinction we are checking for:
-                    //
-                    // ```rust
-                    // mod a {
-                    //   pub type Foo = impl Iterator;
-                    //   pub fn make_foo() -> Foo { .. }
-                    // }
-                    //
-                    // mod b {
-                    //   fn foo() -> a::Foo { a::make_foo() }
-                    // }
-                    // ```
-                    //
-                    // Here, the return type of `foo` references an
-                    // `Opaque` indeed, but not one whose value is
-                    // presently being inferred. You can get into a
-                    // similar situation with closure return types
-                    // today:
-                    //
-                    // ```rust
-                    // fn foo() -> impl Iterator { .. }
-                    // fn bar() {
-                    //     let x = || foo(); // returns the Opaque assoc with `foo`
-                    // }
-                    // ```
-                    if let Some(def_id) = def_id.as_local() {
-                        if let Some(origin) = self.infcx.opaque_type_origin(def_id) {
-                            let opaque_type_key =
-                                OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
-                            return self.fold_opaque_ty(ty, opaque_type_key, origin);
-                        }
-
-                        debug!(
-                            "instantiate_opaque_types_in_map: \
-                             encountered opaque outside its definition scope \
-                             def_id={:?}",
-                            def_id,
-                        );
-                    }
-                }
-
-                ty
-            },
-            lt_op: |lt| lt,
-            ct_op: |ct| ct,
-        })
+impl UseKind {
+    pub fn is_defining(self) -> bool {
+        match self {
+            UseKind::DefiningUse => true,
+            UseKind::OpaqueUse => false,
+        }
     }
+}
 
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
-    fn fold_opaque_ty(
-        &mut self,
-        ty: Ty<'tcx>,
+    fn register_hidden_type(
+        &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        hidden_ty: Ty<'tcx>,
         origin: hir::OpaqueTyOrigin,
-    ) -> Ty<'tcx> {
-        let infcx = self.infcx;
-        let tcx = infcx.tcx;
+    ) -> InferResult<'tcx, ()> {
+        let tcx = self.tcx;
         let OpaqueTypeKey { def_id, substs } = opaque_type_key;
 
-        // Use the same type variable if the exact same opaque type appears more
-        // than once in the return type (e.g., if it's passed to a type alias).
-        if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
-            debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
-            return opaque_defn.concrete_ty;
-        }
-
-        let ty_var = infcx.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::TypeInference,
-            span: self.value_span,
-        });
-
         // Ideally, we'd get the span where *this specific `ty` came
         // from*, but right now we just use the span from the overall
         // value being folded. In simple cases like `-> impl Foo`,
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
-        let definition_span = self.value_span;
+        let span = cause.span;
 
-        {
-            let mut infcx = self.infcx.inner.borrow_mut();
-            infcx.opaque_types.insert(
-                OpaqueTypeKey { def_id, substs },
-                OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin },
-            );
-            infcx.opaque_types_vars.insert(ty_var, ty);
+        let mut obligations = vec![];
+        let prev = self.inner.borrow_mut().opaque_types().register(
+            OpaqueTypeKey { def_id, substs },
+            OpaqueHiddenType { ty: hidden_ty, span },
+            origin,
+        );
+        if let Some(prev) = prev {
+            obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations;
         }
 
-        debug!("generated new type inference var {:?}", ty_var.kind());
-
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
-        self.obligations.reserve(item_bounds.len());
         for (predicate, _) in item_bounds {
             debug!(?predicate);
             let predicate = predicate.subst(tcx, substs);
-            debug!(?predicate);
 
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
                 ty_op: |ty| match *ty.kind() {
-                    // Replace all other mentions of the same opaque type with the hidden type,
-                    // as the bounds must hold on the hidden type after all.
-                    ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => {
-                        ty_var
-                    }
-                    // Instantiate nested instances of `impl Trait`.
-                    ty::Opaque(..) => self.instantiate_opaque_types_in_map(ty),
-                    _ => ty,
-                },
-                lt_op: |lt| lt,
-                ct_op: |ct| ct,
-            });
-
-            // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
-            let predicate = predicate.fold_with(&mut BottomUpFolder {
-                tcx,
-                ty_op: |ty| match ty.kind() {
+                    // We can't normalize associated types from `rustc_infer`,
+                    // but we can eagerly register inference variables for them.
                     ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
-                        infcx.infer_projection(
-                            self.param_env,
-                            *projection_ty,
-                            traits::ObligationCause::misc(self.value_span, self.body_id),
+                        self.infer_projection(
+                            param_env,
+                            projection_ty,
+                            cause.clone(),
                             0,
-                            &mut self.obligations,
+                            &mut obligations,
                         )
                     }
+                    // Replace all other mentions of the same opaque type with the hidden type,
+                    // as the bounds must hold on the hidden type after all.
+                    ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => {
+                        hidden_ty
+                    }
                     _ => ty,
                 },
                 lt_op: |lt| lt,
                 ct_op: |ct| ct,
             });
-            debug!(?predicate);
 
             if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
                 if projection.term.references_error() {
-                    return tcx.ty_error();
+                    // No point on adding these obligations since there's a type error involved.
+                    return Ok(InferOk { value: (), obligations: vec![] });
                 }
+                trace!("{:#?}", projection.term);
             }
-
-            let cause =
-                traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
-
             // Require that the predicate holds for the concrete type.
             debug!(?predicate);
-            self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
+            obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate));
         }
-
-        ty_var
+        Ok(InferOk { value: (), obligations })
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
new file mode 100644 (file)
index 0000000..9b8f225
--- /dev/null
@@ -0,0 +1,88 @@
+use rustc_data_structures::undo_log::UndoLogs;
+use rustc_hir::OpaqueTyOrigin;
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty};
+use rustc_span::DUMMY_SP;
+
+use crate::infer::{InferCtxtUndoLogs, UndoLog};
+
+use super::{OpaqueHiddenType, OpaqueTypeDecl, OpaqueTypeMap};
+
+#[derive(Default, Debug)]
+pub struct OpaqueTypeStorage<'tcx> {
+    // Opaque types found in explicit return types and their
+    // associated fresh inference variable. Writeback resolves these
+    // variables to get the concrete type, which can be used to
+    // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
+    pub opaque_types: OpaqueTypeMap<'tcx>,
+}
+
+impl<'tcx> OpaqueTypeStorage<'tcx> {
+    #[instrument(level = "debug")]
+    pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
+        if let Some(idx) = idx {
+            self.opaque_types.get_mut(&key).unwrap().hidden_type = idx;
+        } else {
+            match self.opaque_types.remove(&key) {
+                None => bug!("reverted opaque type inference that was never registered: {:?}", key),
+                Some(_) => {}
+            }
+        }
+    }
+
+    pub fn get_decl(&self, key: &OpaqueTypeKey<'tcx>) -> Option<&OpaqueTypeDecl<'tcx>> {
+        self.opaque_types.get(key)
+    }
+
+    pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> {
+        self.opaque_types.clone()
+    }
+
+    #[instrument(level = "debug")]
+    pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> {
+        std::mem::take(&mut self.opaque_types)
+    }
+
+    #[inline]
+    pub(crate) fn with_log<'a>(
+        &'a mut self,
+        undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
+    ) -> OpaqueTypeTable<'a, 'tcx> {
+        OpaqueTypeTable { storage: self, undo_log }
+    }
+}
+
+impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
+    fn drop(&mut self) {
+        if !self.opaque_types.is_empty() {
+            ty::tls::with(|tcx| {
+                tcx.sess.delay_span_bug(DUMMY_SP, &format!("{:?}", self.opaque_types))
+            });
+        }
+    }
+}
+
+pub struct OpaqueTypeTable<'a, 'tcx> {
+    storage: &'a mut OpaqueTypeStorage<'tcx>,
+
+    undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
+}
+
+impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
+    #[instrument(skip(self), level = "debug")]
+    pub fn register(
+        &mut self,
+        key: OpaqueTypeKey<'tcx>,
+        hidden_type: OpaqueHiddenType<'tcx>,
+        origin: OpaqueTyOrigin,
+    ) -> Option<Ty<'tcx>> {
+        if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
+            let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
+            self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
+            return Some(prev.ty);
+        }
+        let decl = OpaqueTypeDecl { hidden_type, origin };
+        self.storage.opaque_types.insert(key, decl);
+        self.undo_log.push(UndoLog::OpaqueTypes(key, None));
+        None
+    }
+}
index 03d6c45a653459220fe75c4fbffe369549a44678..b60ffc1878be44a38f776b0d48e8a1c14ea648b3 100644 (file)
@@ -28,6 +28,7 @@ pub fn explicit_outlives_bounds<'tcx>(
             | ty::PredicateKind::TypeOutlives(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::OpaqueType(..)
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
             ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
                 Some(OutlivesBound::RegionSubRegion(r_b, r_a))
index a5276afc5bfa7ed03b59fd2cc5ccecaa4378a70c..d554d7d935c52c570d7873e9d321a2c12bb405ae 100644 (file)
@@ -153,6 +153,7 @@ pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionOblig
     /// This function may have to perform normalizations, and hence it
     /// returns an `InferOk` with subobligations that must be
     /// processed.
+    #[instrument(level = "debug", skip(self, region_bound_pairs_map))]
     pub fn process_registered_region_obligations(
         &self,
         region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
@@ -164,8 +165,6 @@ pub fn process_registered_region_obligations(
             "cannot process registered region obligations in a snapshot"
         );
 
-        debug!(?param_env, "process_registered_region_obligations()");
-
         let my_region_obligations = self.take_registered_region_obligations();
 
         for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations {
index ccac0efd6c9eec22084e869b9073afeb97aae04a..e0a8219beede1804189c126ae68242efb65707ec 100644 (file)
@@ -2,6 +2,7 @@
 use super::SubregionOrigin;
 
 use crate::infer::combine::ConstEquateRelation;
+use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::traits::Obligation;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
@@ -74,9 +75,8 @@ fn relate_with_variance<T: Relate<'tcx>>(
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({:?}, {:?})", self.tag(), a, b);
-
         if a == b {
             return Ok(a);
         }
@@ -84,6 +84,7 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         let infcx = self.fields.infcx;
         let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
         let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
+
         match (a.kind(), b.kind()) {
             (&ty::Infer(TyVar(_)), &ty::Infer(TyVar(_))) => {
                 // Shouldn't have any LBR here, so we can safely put
@@ -121,6 +122,40 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 Ok(self.tcx().ty_error())
             }
 
+            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+                self.fields.infcx.super_combine_tys(self, a, b)?;
+                Ok(a)
+            }
+            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
+                if self.fields.define_opaque_types && did.is_local() =>
+            {
+                let mut generalize = |ty, ty_is_expected| {
+                    let var = infcx.next_ty_var_id_in_universe(
+                        TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::MiscVariable,
+                            span: self.fields.trace.cause.span,
+                        },
+                        ty::UniverseIndex::ROOT,
+                    );
+                    self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?;
+                    Ok(infcx.tcx.mk_ty_var(var))
+                };
+                let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) };
+                let (a, b) = match (a.kind(), b.kind()) {
+                    (&ty::Opaque(..), _) => (a, generalize(b, true)?),
+                    (_, &ty::Opaque(..)) => (generalize(a, false)?, b),
+                    _ => unreachable!(),
+                };
+                self.fields.obligations.push(infcx.opaque_ty_obligation(
+                    a,
+                    b,
+                    true,
+                    self.param_env(),
+                    self.fields.trace.cause.clone(),
+                ));
+                Ok(a)
+            }
+
             _ => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
                 Ok(a)
index 89db8f464b4e7c7e41c2c003a4ab7def776c3341..02b15baf8fb2dba45fc4221e23271b3fd76a1644 100644 (file)
@@ -4,13 +4,15 @@
 use rustc_data_structures::undo_log::{Rollback, UndoLogs};
 use rustc_data_structures::unify as ut;
 use rustc_middle::infer::unify_key::RegionVidKey;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, OpaqueTypeKey};
 
 use crate::{
     infer::{region_constraints, type_variable, InferCtxtInner},
     traits,
 };
 
+use super::opaque_types::OpaqueHiddenType;
+
 pub struct Snapshot<'tcx> {
     pub(crate) undo_len: usize,
     _marker: PhantomData<&'tcx ()>,
@@ -18,6 +20,7 @@ pub struct Snapshot<'tcx> {
 
 /// Records the "undo" data for a single operation that affects some form of inference variable.
 pub(crate) enum UndoLog<'tcx> {
+    OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
     TypeVariables(type_variable::UndoLog<'tcx>),
     ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
     IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
@@ -64,6 +67,7 @@ fn from(x: $ty) -> Self {
 impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
     fn reverse(&mut self, undo: UndoLog<'tcx>) {
         match undo {
+            UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx),
             UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo),
             UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
             UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo),
index 674c75fdee56113bb3b1b29067d7b7ecb235d549..6600d5e4d0279a3f3303ab0eeada9d47f9e11f71 100644 (file)
@@ -167,6 +167,9 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                 // Currently, we do not elaborate WF predicates,
                 // although we easily could.
             }
+            ty::PredicateKind::OpaqueType(..) => {
+                todo!("{:#?}", obligation)
+            }
             ty::PredicateKind::ObjectSafe(..) => {
                 // Currently, we do not elaborate object-safe
                 // predicates.
index 734b32bb92f1e88d4233b44de19690cc1769bbc1..44e3da11826cd00c08d92f99a97c907dcf8bd72e 100644 (file)
@@ -1654,6 +1654,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                     Coerce(..) |
                     ConstEvaluatable(..) |
                     ConstEquate(..) |
+                    OpaqueType(..) |
                     TypeWellFormedFromEnv(..) => continue,
                 };
                 if predicate.is_global() {
index 13cd8e4a046b03ba3d8a84da0ad655868ff83fde..88292a4422419774019d3a1db67a7b384d1ce27a 100644 (file)
@@ -404,11 +404,13 @@ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
     fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
         let calling_convention = if self.tcx.sess.target.arch == "x86" {
             match abi {
-                Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
+                Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
                 Abi::Stdcall { .. } | Abi::System { .. } => {
                     DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
                 }
-                Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)),
+                Abi::Fastcall { .. } => {
+                    DllCallingConvention::Fastcall(self.i686_arg_list_size(item))
+                }
                 // Vectorcall is intentionally not supported at this time.
                 _ => {
                     self.tcx.sess.span_fatal(
@@ -419,7 +421,7 @@ fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
             }
         } else {
             match abi {
-                Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C,
+                Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
                 _ => {
                     self.tcx.sess.span_fatal(
                         item.span,
index 28217aeab13ee51d91d752fcfc5802b5d167cc49..2fc901bdbff34db5a8c4411b511f842a1cbe36f2 100644 (file)
@@ -178,6 +178,12 @@ pub struct QueryResponse<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
     pub region_constraints: QueryRegionConstraints<'tcx>,
     pub certainty: Certainty,
+    /// List of opaque types which we tried to compare to another type.
+    /// Inside the query we don't know yet whether the opaque type actually
+    /// should get its hidden type inferred. So we bubble the opaque type
+    /// and the type it was compared against upwards and let the query caller
+    /// handle it.
+    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
     pub value: R,
 }
 
index e0e3febe6b3109b0c23cefe3b98f3cccffc95ca0..2642bddb9a4d33509467e6151330a203107e4a45 100644 (file)
@@ -53,17 +53,17 @@ fn relate_with_variance<T: Relate<'tcx>>(
         self.relate(a, b)
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn regions(
         &mut self,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
         Ok(a)
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({:?}, {:?})", self.tag(), a, b);
         if a == b {
             return Ok(a);
         }
index 5dae4b9e4c9712808aeab34febf4ad5b90ea1abb..694b7d2b817cfc4ff8407f4fd179bcaad32bac7f 100644 (file)
@@ -30,6 +30,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
+use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -464,9 +465,13 @@ pub struct TypeckResults<'tcx> {
     /// this field will be set to `Some(ErrorReported)`.
     pub tainted_by_errors: Option<ErrorReported>,
 
-    /// All the opaque types that are restricted to concrete types
-    /// by this function.
-    pub concrete_opaque_types: FxHashSet<DefId>,
+    /// All the opaque types that have hidden types set
+    /// by this function. For return-position-impl-trait we also store the
+    /// type here, so that mir-borrowck can figure out hidden types,
+    /// even if they are only set in dead code (which doesn't show up in MIR).
+    /// For type-alias-impl-trait, this map is only used to prevent query cycles,
+    /// so the hidden types are all `None`.
+    pub concrete_opaque_types: VecMap<DefId, Option<Ty<'tcx>>>,
 
     /// Tracks the minimum captures required for a closure;
     /// see `MinCaptureInformationMap` for more details.
index f06a1b09cd82ab236553403b81ba572fd2d65dc6..7394bc5b2d8dd45c8382748b95d4096a2094aef7 100644 (file)
@@ -265,6 +265,10 @@ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 self.add_ty(ty);
             }
+            ty::PredicateKind::OpaqueType(opaque, ty) => {
+                self.add_ty(opaque);
+                self.add_ty(ty);
+            }
         }
     }
 
index 3133cdfdd7a7211222a0e9336aa4240a798e0121..2fd0ca423cc944ff4de0ad0b6c59e0cc0e515d96 100644 (file)
@@ -1207,15 +1207,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     type BreakTy = FoundFlags;
 
     #[inline]
-    #[instrument(level = "trace")]
-    fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
-        debug!(
-            "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
-            t,
-            t.flags(),
-            self.flags
-        );
-        if t.flags().intersects(self.flags) {
+    #[instrument(skip(self), level = "trace")]
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        let flags = t.flags();
+        trace!(t.flags=?t.flags());
+        if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
             ControlFlow::CONTINUE
@@ -1235,7 +1231,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 
     #[inline]
-    #[instrument(level = "trace")]
+    #[instrument(skip(self), level = "trace")]
     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = FlagComputation::for_const(c);
         trace!(r.flags=?flags);
index ad817e185a3cfd5abe10610c5f3d06a4c681557e..87965b06435dd6a265a844f8b50251daed631894 100644 (file)
@@ -2776,17 +2776,20 @@ pub fn fn_can_unwind<'tcx>(
     // [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
     use SpecAbi::*;
     match abi {
-        C { unwind } | Stdcall { unwind } | System { unwind } | Thiscall { unwind } => {
+        C { unwind }
+        | System { unwind }
+        | Cdecl { unwind }
+        | Stdcall { unwind }
+        | Fastcall { unwind }
+        | Vectorcall { unwind }
+        | Thiscall { unwind }
+        | Aapcs { unwind }
+        | Win64 { unwind }
+        | SysV64 { unwind } => {
             unwind
                 || (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind)
         }
-        Cdecl
-        | Fastcall
-        | Vectorcall
-        | Aapcs
-        | Win64
-        | SysV64
-        | PtxKernel
+        PtxKernel
         | Msp430Interrupt
         | X86Interrupt
         | AmdGpuKernel
@@ -2813,14 +2816,14 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
         EfiApi => bug!("eficall abi should be selected elsewhere"),
 
         Stdcall { .. } => Conv::X86Stdcall,
-        Fastcall => Conv::X86Fastcall,
-        Vectorcall => Conv::X86VectorCall,
+        Fastcall { .. } => Conv::X86Fastcall,
+        Vectorcall { .. } => Conv::X86VectorCall,
         Thiscall { .. } => Conv::X86ThisCall,
         C { .. } => Conv::C,
         Unadjusted => Conv::C,
-        Win64 => Conv::X86_64Win64,
-        SysV64 => Conv::X86_64SysV,
-        Aapcs => Conv::ArmAapcs,
+        Win64 { .. } => Conv::X86_64Win64,
+        SysV64 { .. } => Conv::X86_64SysV,
+        Aapcs { .. } => Conv::ArmAapcs,
         CCmseNonSecureCall => Conv::CCmseNonSecureCall,
         PtxKernel => Conv::PtxKernel,
         Msp430Interrupt => Conv::Msp430Intr,
@@ -2831,7 +2834,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
         Wasm => Conv::C,
 
         // These API constants ought to be more specific...
-        Cdecl => Conv::C,
+        Cdecl { .. } => Conv::C,
     }
 }
 
index 8eb2793cc34e3b7fe6f636d6a64af2ed2897c6f4..8bf760179e680e6188827e3f8ada18ddc8c0bfbc 100644 (file)
@@ -627,6 +627,11 @@ pub enum PredicateKind<'tcx> {
     ///
     /// Only used for Chalk.
     TypeWellFormedFromEnv(Ty<'tcx>),
+
+    /// Represents a hidden type assignment for an opaque type.
+    /// Such obligations get processed by checking whether the item currently being
+    /// type-checked may acually define it.
+    OpaqueType(Ty<'tcx>, Ty<'tcx>),
 }
 
 /// The crate outlives map is computed during typeck and contains the
@@ -986,6 +991,7 @@ pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
             | PredicateKind::TypeOutlives(..)
             | PredicateKind::ConstEvaluatable(..)
             | PredicateKind::ConstEquate(..)
+            | PredicateKind::OpaqueType(..)
             | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
@@ -1004,6 +1010,7 @@ pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
             | PredicateKind::ClosureKind(..)
             | PredicateKind::ConstEvaluatable(..)
             | PredicateKind::ConstEquate(..)
+            | PredicateKind::OpaqueType(..)
             | PredicateKind::TypeWellFormedFromEnv(..) => None,
         }
     }
@@ -1044,7 +1051,18 @@ pub fn is_empty(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)]
+#[derive(
+    Copy,
+    Clone,
+    Debug,
+    PartialEq,
+    Eq,
+    HashStable,
+    TyEncodable,
+    TyDecodable,
+    TypeFoldable,
+    Lift
+)]
 pub struct OpaqueTypeKey<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
index ddcc8680d835269bd4f34257bccb79f01db361c6..6521957ec944c36b9b26a7fdbe31fa530666a5c0 100644 (file)
@@ -644,20 +644,23 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                     return Ok(self);
                 }
 
-                return with_no_queries(|| {
-                    let def_key = self.tcx().def_key(def_id);
-                    if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
-                        p!(write("{}", name));
-                        // FIXME(eddyb) print this with `print_def_path`.
-                        if !substs.is_empty() {
-                            p!("::");
-                            p!(generic_delimiters(|cx| cx.comma_sep(substs.iter())));
+                let parent = self.tcx().parent(def_id).expect("opaque types always have a parent");
+                match self.tcx().def_kind(parent) {
+                    DefKind::TyAlias | DefKind::AssocTy => {
+                        if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
+                            if d == def_id {
+                                // If the type alias directly starts with the `impl` of the
+                                // opaque type we're printing, then skip the `::{opaque#1}`.
+                                p!(print_def_path(parent, substs));
+                                return Ok(self);
+                            }
                         }
+                        // Complex opaque type, e.g. `type Foo = (i32, impl Debug);`
+                        p!(print_def_path(def_id, substs));
                         return Ok(self);
                     }
-
-                    self.pretty_print_opaque_impl_type(def_id, substs)
-                });
+                    _ => return self.pretty_print_opaque_impl_type(def_id, substs),
+                }
             }
             ty::Str => p!("str"),
             ty::Generator(did, substs, movability) => {
@@ -2607,6 +2610,9 @@ pub fn print_modifiers_and_trait_path(
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 p!("the type `", print(ty), "` is found in the environment")
             }
+            ty::PredicateKind::OpaqueType(a, b) => {
+                p!("opaque type assigment with `", print(a), "` == `", print(b) ,"`")
+            }
         }
     }
 
index 1c5bc7860db2de7280f0446399e3f3ec796fa051..ef54832791d41a23558edad81edd6606442b39a8 100644 (file)
@@ -191,6 +191,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 write!(f, "TypeWellFormedFromEnv({:?})", ty)
             }
+            ty::PredicateKind::OpaqueType(a, b) => {
+                write!(f, "OpaqueType({:?}, {:?})", a.kind(), b.kind())
+            }
         }
     }
 }
@@ -463,6 +466,9 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                 tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv)
             }
+            ty::PredicateKind::OpaqueType(opaque, ty) => {
+                Some(ty::PredicateKind::OpaqueType(tcx.lift(opaque)?, tcx.lift(ty)?))
+            }
         }
     }
 }
index 7d4af6cfa405257088c8e41bb3c1ed5cc89151b7..6b187f7da4c6d2f18781748fc0fe1abcb849c71b 100644 (file)
@@ -152,6 +152,7 @@ pub enum TyKind<'tcx> {
 
     /// The anonymous type of a closure. Used to represent the type of
     /// `|a| a`.
+    /// For the order of the substs see the `ClosureSubsts` type's documentation.
     Closure(DefId, SubstsRef<'tcx>),
 
     /// The anonymous type of a generator. Used to represent the type of
@@ -1815,6 +1816,13 @@ pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         }
     }
 
+    pub fn expect_opaque_type(&self) -> ty::OpaqueTypeKey<'tcx> {
+        match *self.kind() {
+            Opaque(def_id, substs) => ty::OpaqueTypeKey { def_id, substs },
+            _ => bug!("`expect_opaque_type` called on non-opaque type: {}", self),
+        }
+    }
+
     pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
         match self.kind() {
             Adt(def, substs) => {
index df71379c1d88643c50813a1329565cc9c401bc90..8cb19baa29230d15652b48fe8ec33a076b795c05 100644 (file)
@@ -1,8 +1,8 @@
 use crate::build::matches::ArmHasGuard;
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
-use rustc_middle::mir::*;
 use rustc_middle::thir::*;
+use rustc_middle::{mir::*, ty};
 use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
 use rustc_session::lint::Level;
 use rustc_span::Span;
@@ -192,7 +192,9 @@ fn ast_block_stmts(
             // This return type is usually `()`, unless the block is diverging, in which case the
             // return type is `!`. For the unit type, we need to actually return the unit, but in
             // the case of `!`, no return value is required, as the block will never return.
-            if destination_ty.is_unit() {
+            // Opaque types of empty bodies also need this unit assignment, in order to infer that their
+            // type is actually unit. Otherwise there will be no defining use found in the MIR.
+            if destination_ty.is_unit() || matches!(destination_ty.kind(), ty::Opaque(..)) {
                 // We only want to assign an implicit `()` as the return value of the block if the
                 // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
                 this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
index c95dff13d6615ffe71097d8f480fad6097a7f9c6..36f2a80773ea3af84b3a2384c600119d44e4178a 100644 (file)
@@ -186,7 +186,6 @@ fn new(encoder: FileEncoder, record_stats: bool) -> Self {
         }
     }
 
-    #[instrument(level = "debug", skip(self, record_graph))]
     fn encode_node(
         &mut self,
         node: &NodeInfo<K>,
@@ -213,7 +212,6 @@ fn encode_node(
             stat.edge_counter += edge_count as u64;
         }
 
-        debug!(?index, ?node);
         let encoder = &mut self.encoder;
         if self.result.is_ok() {
             self.result = node.encode(encoder);
index 044de8e4e24839eedd178a8dd92d56819cb26255..6a3985492412262d382a0160922ddd24b94d5f3e 100644 (file)
 
 use std::borrow::Cow;
 use std::collections::{BTreeMap, HashMap};
-use std::io;
-use std::io::prelude::*;
 use std::mem::swap;
 use std::num::FpCategory as Fp;
 use std::ops::Index;
@@ -250,7 +248,6 @@ pub enum ErrorCode {
 pub enum ParserError {
     /// msg, line, col
     SyntaxError(ErrorCode, usize, usize),
-    IoError(io::ErrorKind, String),
 }
 
 // Builder and Parser have the same errors.
@@ -329,10 +326,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-fn io_error_to_error(io: io::Error) -> ParserError {
-    IoError(io.kind(), io.to_string())
-}
-
 impl fmt::Display for ParserError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // FIXME this should be a nicer error
@@ -2163,21 +2156,6 @@ fn build_object(&mut self) -> Result<Json, BuilderError> {
     }
 }
 
-/// Decodes a json value from an `&mut io::Read`
-pub fn from_reader(rdr: &mut dyn Read) -> Result<Json, BuilderError> {
-    let mut contents = Vec::new();
-    match rdr.read_to_end(&mut contents) {
-        Ok(c) => c,
-        Err(e) => return Err(io_error_to_error(e)),
-    };
-    let s = match str::from_utf8(&contents).ok() {
-        Some(s) => s,
-        _ => return Err(SyntaxError(NotUtf8, 0, 0)),
-    };
-    let mut builder = Builder::new(s.chars());
-    builder.build()
-}
-
 /// Decodes a json value from a string
 pub fn from_str(s: &str) -> Result<Json, BuilderError> {
     let mut builder = Builder::new(s.chars());
index 735b7e76e3862a5ceaf792d0226c9f4fa7e71625..43eb7ab05e0bf24a524a430f238503b4e1fbc660 100644 (file)
@@ -658,22 +658,24 @@ pub fn adjust_for_foreign_abi<C>(
 
         match &cx.target_spec().arch[..] {
             "x86" => {
-                let flavor = if abi == spec::abi::Abi::Fastcall {
+                let flavor = if let spec::abi::Abi::Fastcall { .. } = abi {
                     x86::Flavor::Fastcall
                 } else {
                     x86::Flavor::General
                 };
                 x86::compute_abi_info(cx, self, flavor);
             }
-            "x86_64" => {
-                if abi == spec::abi::Abi::SysV64 {
-                    x86_64::compute_abi_info(cx, self);
-                } else if abi == spec::abi::Abi::Win64 || cx.target_spec().is_like_windows {
-                    x86_win64::compute_abi_info(self);
-                } else {
-                    x86_64::compute_abi_info(cx, self);
+            "x86_64" => match abi {
+                spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
+                spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self),
+                _ => {
+                    if cx.target_spec().is_like_windows {
+                        x86_win64::compute_abi_info(self)
+                    } else {
+                        x86_64::compute_abi_info(cx, self)
+                    }
                 }
-            }
+            },
             "aarch64" => aarch64::compute_abi_info(cx, self),
             "amdgpu" => amdgpu::compute_abi_info(cx, self),
             "arm" => arm::compute_abi_info(cx, self),
index e3a2226eb9d152a4a64f4d36da1be0b930b62849..d9e571c72e53a946de00bb350475071640e1d77e 100644 (file)
@@ -13,14 +13,14 @@ pub enum Abi {
     // churn. The specific values are meaningless.
     Rust,
     C { unwind: bool },
-    Cdecl,
+    Cdecl { unwind: bool },
     Stdcall { unwind: bool },
-    Fastcall,
-    Vectorcall,
+    Fastcall { unwind: bool },
+    Vectorcall { unwind: bool },
     Thiscall { unwind: bool },
-    Aapcs,
-    Win64,
-    SysV64,
+    Aapcs { unwind: bool },
+    Win64 { unwind: bool },
+    SysV64 { unwind: bool },
     PtxKernel,
     Msp430Interrupt,
     X86Interrupt,
@@ -50,16 +50,22 @@ pub struct AbiData {
     AbiData { abi: Abi::Rust, name: "Rust" },
     AbiData { abi: Abi::C { unwind: false }, name: "C" },
     AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
-    AbiData { abi: Abi::Cdecl, name: "cdecl" },
+    AbiData { abi: Abi::Cdecl { unwind: false }, name: "cdecl" },
+    AbiData { abi: Abi::Cdecl { unwind: true }, name: "cdecl-unwind" },
     AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" },
     AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
-    AbiData { abi: Abi::Fastcall, name: "fastcall" },
-    AbiData { abi: Abi::Vectorcall, name: "vectorcall" },
+    AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" },
+    AbiData { abi: Abi::Fastcall { unwind: true }, name: "fastcall-unwind" },
+    AbiData { abi: Abi::Vectorcall { unwind: false }, name: "vectorcall" },
+    AbiData { abi: Abi::Vectorcall { unwind: true }, name: "vectorcall-unwind" },
     AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" },
     AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
-    AbiData { abi: Abi::Aapcs, name: "aapcs" },
-    AbiData { abi: Abi::Win64, name: "win64" },
-    AbiData { abi: Abi::SysV64, name: "sysv64" },
+    AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" },
+    AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" },
+    AbiData { abi: Abi::Win64 { unwind: false }, name: "win64" },
+    AbiData { abi: Abi::Win64 { unwind: true }, name: "win64-unwind" },
+    AbiData { abi: Abi::SysV64 { unwind: false }, name: "sysv64" },
+    AbiData { abi: Abi::SysV64 { unwind: true }, name: "sysv64-unwind" },
     AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" },
     AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
     AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
@@ -101,32 +107,38 @@ pub fn index(self) -> usize {
             C { unwind: false } => 1,
             C { unwind: true } => 2,
             // Platform-specific ABIs
-            Cdecl => 3,
-            Stdcall { unwind: false } => 4,
-            Stdcall { unwind: true } => 5,
-            Fastcall => 6,
-            Vectorcall => 7,
-            Thiscall { unwind: false } => 8,
-            Thiscall { unwind: true } => 9,
-            Aapcs => 10,
-            Win64 => 11,
-            SysV64 => 12,
-            PtxKernel => 13,
-            Msp430Interrupt => 14,
-            X86Interrupt => 15,
-            AmdGpuKernel => 16,
-            EfiApi => 17,
-            AvrInterrupt => 18,
-            AvrNonBlockingInterrupt => 19,
-            CCmseNonSecureCall => 20,
-            Wasm => 21,
+            Cdecl { unwind: false } => 3,
+            Cdecl { unwind: true } => 4,
+            Stdcall { unwind: false } => 5,
+            Stdcall { unwind: true } => 6,
+            Fastcall { unwind: false } => 7,
+            Fastcall { unwind: true } => 8,
+            Vectorcall { unwind: false } => 9,
+            Vectorcall { unwind: true } => 10,
+            Thiscall { unwind: false } => 11,
+            Thiscall { unwind: true } => 12,
+            Aapcs { unwind: false } => 13,
+            Aapcs { unwind: true } => 14,
+            Win64 { unwind: false } => 15,
+            Win64 { unwind: true } => 16,
+            SysV64 { unwind: false } => 17,
+            SysV64 { unwind: true } => 18,
+            PtxKernel => 19,
+            Msp430Interrupt => 20,
+            X86Interrupt => 21,
+            AmdGpuKernel => 22,
+            EfiApi => 23,
+            AvrInterrupt => 24,
+            AvrNonBlockingInterrupt => 25,
+            CCmseNonSecureCall => 26,
+            Wasm => 27,
             // Cross-platform ABIs
-            System { unwind: false } => 22,
-            System { unwind: true } => 23,
-            RustIntrinsic => 24,
-            RustCall => 25,
-            PlatformIntrinsic => 26,
-            Unadjusted => 27,
+            System { unwind: false } => 28,
+            System { unwind: true } => 29,
+            RustIntrinsic => 30,
+            RustCall => 31,
+            PlatformIntrinsic => 32,
+            Unadjusted => 33,
         };
         debug_assert!(
             AbiDatas
index 92ee3fd294bdf748ff65fd41b9ce59d0d8706e55..4407f22b9059923dcfa25b7843f708c0953efb3f 100644 (file)
@@ -1559,15 +1559,15 @@ pub fn adjust_abi(&self, abi: Abi) -> Abi {
                 Abi::Stdcall { unwind }
             }
             Abi::System { unwind } => Abi::C { unwind },
-            Abi::EfiApi if self.arch == "x86_64" => Abi::Win64,
+            Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false },
             Abi::EfiApi => Abi::C { unwind: false },
 
             // See commentary in `is_abi_supported`.
             Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
             Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
-            Abi::Fastcall if self.arch == "x86" => abi,
-            Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
-            Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false },
+            Abi::Fastcall { .. } if self.arch == "x86" => abi,
+            Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
+            Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind },
 
             abi => abi,
         }
@@ -1584,12 +1584,12 @@ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
             | RustCall
             | PlatformIntrinsic
             | Unadjusted
-            | Cdecl
+            | Cdecl { .. }
             | EfiApi => true,
             X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
-            Aapcs => "arm" == self.arch,
+            Aapcs { .. } => "arm" == self.arch,
             CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
-            Win64 | SysV64 => self.arch == "x86_64",
+            Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
             AmdGpuKernel => self.arch == "amdgcn",
@@ -1626,13 +1626,13 @@ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
             // > convention is used.
             //
             // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
-            Stdcall { .. } | Fastcall | Vectorcall if self.is_like_windows => true,
+            Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
             // Outside of Windows we want to only support these calling conventions for the
             // architectures for which these calling conventions are actually well defined.
-            Stdcall { .. } | Fastcall if self.arch == "x86" => true,
-            Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
+            Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
+            Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
             // Return a `None` for other cases so that we know to emit a future compat lint.
-            Stdcall { .. } | Fastcall | Vectorcall => return None,
+            Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => return None,
         })
     }
 
@@ -2148,8 +2148,8 @@ pub fn search(
         use std::fs;
 
         fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
-            let contents = fs::read(path).map_err(|e| e.to_string())?;
-            let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?;
+            let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
+            let obj = json::from_str(&contents).map_err(|e| e.to_string())?;
             Target::from_json(obj)
         }
 
index ea0ac6318bc9a71ff736d9d986b1825010a89eb6..cd12430a2a249c5e0579a6c20b2fc2f67701c91a 100644 (file)
@@ -33,7 +33,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     /// purpose of this function is to do that translation.
     ///
     /// (*) C1 and C2 were introduced in the comments on
-    /// `constrain_opaque_type`. Read that comment for more context.
+    /// `register_member_constraints`. Read that comment for more context.
     ///
     /// # Parameters
     ///
@@ -48,6 +48,10 @@ fn infer_opaque_definition_from_instantiation(
         instantiated_ty: Ty<'tcx>,
         span: Span,
     ) -> Ty<'tcx> {
+        if self.is_tainted_by_errors() {
+            return self.tcx.ty_error();
+        }
+
         let OpaqueTypeKey { def_id, substs } = opaque_type_key;
 
         // Use substs to build up a reverse map from regions to their
@@ -67,7 +71,6 @@ fn infer_opaque_definition_from_instantiation(
         // after producing an error for each of them.
         let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
             self.tcx,
-            self.is_tainted_by_errors(),
             def_id,
             map,
             instantiated_ty,
@@ -82,10 +85,6 @@ fn infer_opaque_definition_from_instantiation(
 struct ReverseMapper<'tcx> {
     tcx: TyCtxt<'tcx>,
 
-    /// If errors have already been reported in this fn, we suppress
-    /// our own errors because they are sometimes derivative.
-    tainted_by_errors: bool,
-
     opaque_type_def_id: DefId,
     map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
     map_missing_regions_to_empty: bool,
@@ -100,7 +99,6 @@ struct ReverseMapper<'tcx> {
 impl<'tcx> ReverseMapper<'tcx> {
     fn new(
         tcx: TyCtxt<'tcx>,
-        tainted_by_errors: bool,
         opaque_type_def_id: DefId,
         map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
         hidden_ty: Ty<'tcx>,
@@ -108,7 +106,6 @@ fn new(
     ) -> Self {
         Self {
             tcx,
-            tainted_by_errors,
             opaque_type_def_id,
             map,
             map_missing_regions_to_empty: false,
@@ -167,9 +164,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match self.map.get(&r.into()).map(|k| k.unpack()) {
             Some(GenericArgKind::Lifetime(r1)) => r1,
             Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
-            None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
-                self.tcx.lifetimes.re_root_empty
-            }
+            None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
             None if generics.parent.is_some() => {
                 if let Some(hidden_ty) = self.hidden_ty.take() {
                     unexpected_hidden_region_diagnostic(
@@ -359,6 +354,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                 | ty::PredicateKind::RegionOutlives(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::OpaqueType(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
                 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
                     // Search for a bound of the form `erased_self_ty
index f2ed5ae26a3c268569cf3174c25ef9d77e04407a..da04fb2cd2104241d99dc0ae180a2fb774c39baf 100644 (file)
@@ -853,6 +853,7 @@ fn evaluate_nested_obligations(
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::Coerce(..)
+                | ty::PredicateKind::OpaqueType(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
             };
         }
index 759bc696981676162f708c376ee9f0406f649c1f..04a7da06063ba03098efd7a6e17a74d5d95cb817 100644 (file)
@@ -90,6 +90,11 @@ pub fn codegen_fulfill_obligation<'tcx>(
         });
         let impl_source = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, impl_source);
 
+        // We may constrain the hidden types of opaque types in this query, but this is
+        // not information our callers need, as all that information is handled by borrowck
+        // and typeck.
+        drop(infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types());
+
         debug!("Cache miss: {:?} => {:?}", trait_ref, impl_source);
         Ok(impl_source)
     })
index 6cb19416cd769be512516716938bf2e57bd0e1ed..2cb2ac8666120badcc5549f629bef290ac9ce684 100644 (file)
@@ -775,6 +775,10 @@ fn report_selection_error(
                         span,
                         "TypeWellFormedFromEnv predicate should only exist in the environment"
                     ),
+
+                    ty::PredicateKind::OpaqueType(..) => {
+                        todo!("{:#?}", obligation);
+                    }
                 }
             }
 
@@ -1378,26 +1382,11 @@ fn report_projection_error(
                     normalized_ty,
                     data.term,
                 ) {
-                    values = Some(match (normalized_ty, data.term) {
-                        (ty::Term::Ty(normalized_ty), ty::Term::Ty(ty)) => {
-                            infer::ValuePairs::Types(ExpectedFound::new(
-                                is_normalized_ty_expected,
-                                normalized_ty,
-                                ty,
-                            ))
-                        }
-                        (ty::Term::Const(normalized_ct), ty::Term::Const(ct)) => {
-                            infer::ValuePairs::Consts(ExpectedFound::new(
-                                is_normalized_ty_expected,
-                                normalized_ct,
-                                ct,
-                            ))
-                        }
-                        (_, _) => span_bug!(
-                            obligation.cause.span,
-                            "found const or type where other expected"
-                        ),
-                    });
+                    values = Some(infer::ValuePairs::Terms(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        data.term,
+                    )));
                     err_buf = error;
                     err = &err_buf;
                 }
index b594723aa0bd2790ffa768ee570d1bc92856000a..65a18897b39157f5150ddfcf286424219b144422 100644 (file)
@@ -1328,6 +1328,7 @@ fn report_closure_arg_mismatch(
             ty::Generator(..) => "generator",
             _ => "function",
         };
+        let span = self.tcx.sess.source_map().guess_head_span(span);
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
@@ -1680,6 +1681,7 @@ fn note_obligation_cause_for_async_await(
             ));
 
             let original_span = err.span.primary_span().unwrap();
+            let original_span = self.tcx.sess.source_map().guess_head_span(original_span);
             let mut span = MultiSpan::from_span(original_span);
 
             let message = outer_generator
index e7897887df7063896245eacb455be83a41d75f81..274f8a3ef79fa138d4c84caa74495b87f5d3539c 100644 (file)
@@ -397,6 +397,9 @@ fn progress_changed_obligations(
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
                 }
+                ty::PredicateKind::OpaqueType(..) => {
+                    todo!("{:#?}", obligation);
+                }
             },
             Some(pred) => match pred {
                 ty::PredicateKind::Trait(data) => {
@@ -642,6 +645,20 @@ fn progress_changed_obligations(
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
                 }
+                ty::PredicateKind::OpaqueType(a, b) => {
+                    match self.selcx.infcx().handle_opaque_type(
+                        a,
+                        b,
+                        &obligation.cause,
+                        obligation.param_env,
+                    ) {
+                        Ok(value) => ProcessResult::Changed(mk_pending(value.obligations)),
+                        Err(err) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
+                            ExpectedFound::new(true, a, b),
+                            err,
+                        )),
+                    }
+                }
             },
         }
     }
index 7818053218decef33c5f9a848dc26cd8c9d884c6..cd6f381333ad0c4c21da8b6e5e892a3c3eb7a5d7 100644 (file)
@@ -313,6 +313,7 @@ fn predicate_references_self<'tcx>(
         | ty::PredicateKind::Coerce(..)
         | ty::PredicateKind::ConstEvaluatable(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::OpaqueType(..)
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
     }
 }
@@ -347,6 +348,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
             | ty::PredicateKind::TypeOutlives(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::OpaqueType(..)
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
         }
     })
index 0a85676f4315e36a88893a759201e899d87b0754..3aa5ee366f78fa23d4f7284fcd2f2225a35cea5d 100644 (file)
@@ -3,7 +3,7 @@
 use crate::traits::engine::TraitEngineExt as _;
 use crate::traits::query::type_op::TypeOpOutput;
 use crate::traits::query::Fallible;
-use crate::traits::{ObligationCause, TraitEngine};
+use crate::traits::TraitEngine;
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::DUMMY_SP;
 
@@ -60,7 +60,6 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
 ) -> Fallible<TypeOpOutput<'tcx, Op>> {
     let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-    let dummy_body_id = ObligationCause::dummy().body_id;
 
     // During NLL, we expect that nobody will register region
     // obligations **except** as part of a custom type op (and, at the
@@ -75,7 +74,6 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     );
 
     let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
-    debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
     fulfill_cx.register_predicate_obligations(infcx, obligations);
     let errors = fulfill_cx.select_all_or_error(infcx);
     if !errors.is_empty() {
index db86041f6180b5efdc49a71aebda28ba7a8d2020..0c5d764e79d0cb25a472294b607a3dbb71ce5e48 100644 (file)
@@ -254,6 +254,7 @@ pub(super) fn assemble_candidates<'o>(
         };
 
         if obligation.predicate.skip_binder().self_ty().is_ty_var() {
+            debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type");
             // Self is a type variable (e.g., `_: AsRef<str>`).
             //
             // This is somewhat problematic, as the current scheme can't really
index 47427395b93b36adff83c8dda2f9034cc12346bf..a183a20a2fed0b5458f5b6ee74325d290057de1a 100644 (file)
@@ -37,6 +37,7 @@
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
+use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
@@ -697,6 +698,19 @@ fn evaluate_predicate_recursively<'o>(
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for chalk")
                 }
+                ty::PredicateKind::OpaqueType(a, b) => {
+                    match self.infcx().handle_opaque_type(
+                        a,
+                        b,
+                        &obligation.cause,
+                        obligation.param_env,
+                    ) {
+                        Ok(res) => {
+                            self.evaluate_predicates_recursively(previous_stack, res.obligations)
+                        }
+                        Err(_) => Ok(EvaluatedToErr),
+                    }
+                }
             }
         });
 
@@ -1337,6 +1351,7 @@ fn can_cache_candidate(
         }
     }
 
+    #[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")]
     fn insert_candidate_cache(
         &mut self,
         mut param_env: ty::ParamEnv<'tcx>,
@@ -1377,6 +1392,7 @@ fn insert_candidate_cache(
     /// a projection, look at the bounds of `T::Bar`, see if we can find a
     /// `Baz` bound. We return indexes into the list returned by
     /// `tcx.item_bounds` for any applicable bounds.
+    #[instrument(level = "debug", skip(self))]
     fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -1384,10 +1400,7 @@ fn match_projection_obligation_against_definition_bounds(
         let poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate);
         let placeholder_trait_predicate =
             self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate);
-        debug!(
-            ?placeholder_trait_predicate,
-            "match_projection_obligation_against_definition_bounds"
-        );
+        debug!(?placeholder_trait_predicate);
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
@@ -1438,7 +1451,7 @@ fn match_projection_obligation_against_definition_bounds(
             })
             .collect();
 
-        debug!(?matching_bounds, "match_projection_obligation_against_definition_bounds");
+        debug!(?matching_bounds);
         matching_bounds
     }
 
@@ -1468,6 +1481,7 @@ fn match_normalize_trait_ref(
         });
         self.infcx
             .at(&obligation.cause, obligation.param_env)
+            .define_opaque_types(false)
             .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
             .map(|InferOk { obligations: _, value: () }| {
                 // This method is called within a probe, so we can't have
@@ -1523,6 +1537,7 @@ pub(super) fn match_projection_projections(
 
         self.infcx
             .at(&obligation.cause, obligation.param_env)
+            .define_opaque_types(false)
             .sup(obligation.predicate, infer_projection)
             .map_or(false, |InferOk { obligations, value: () }| {
                 self.evaluate_predicates_recursively(
@@ -2081,11 +2096,22 @@ fn rematch_impl(
         match self.match_impl(impl_def_id, obligation) {
             Ok(substs) => substs,
             Err(()) => {
-                bug!(
-                    "Impl {:?} was matchable against {:?} but now is not",
-                    impl_def_id,
-                    obligation
+                self.infcx.tcx.sess.delay_span_bug(
+                    obligation.cause.span,
+                    &format!(
+                        "Impl {:?} was matchable against {:?} but now is not",
+                        impl_def_id, obligation
+                    ),
                 );
+                let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
+                let err = self.tcx().ty_error();
+                let value = value.fold_with(&mut BottomUpFolder {
+                    tcx: self.tcx(),
+                    ty_op: |_| err,
+                    lt_op: |l| l,
+                    ct_op: |c| c,
+                });
+                Normalized { value, obligations: vec![] }
             }
         }
     }
@@ -2222,6 +2248,11 @@ fn match_poly_trait_ref(
     ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
         self.infcx
             .at(&obligation.cause, obligation.param_env)
+            // We don't want predicates for opaque types to just match all other types,
+            // if there is an obligation on the opaque type, then that obligation must be met
+            // opaquely. Otherwise we'd match any obligation to the opaque type and then error
+            // out later.
+            .define_opaque_types(false)
             .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
             .map(|InferOk { obligations, .. }| obligations)
             .map_err(|_| ())
index 493cb199f114485d544538a14e22f1e8dbd7d41e..68707fee44f99635bfbfe455034e8e61b03e56bb 100644 (file)
@@ -146,6 +146,10 @@ pub fn predicate_obligations<'a, 'tcx>(
             wf.compute(c1.into());
             wf.compute(c2.into());
         }
+        ty::PredicateKind::OpaqueType(opaque, ty) => {
+            wf.compute(opaque.into());
+            wf.compute(ty.into());
+        }
         ty::PredicateKind::TypeWellFormedFromEnv(..) => {
             bug!("TypeWellFormedFromEnv is only used for Chalk")
         }
index 67d0ba39667d31127bb910d1283bace99b87356c..71ea77dc3791088caadda56d5db0e77fa79abb9f 100644 (file)
@@ -110,6 +110,7 @@ fn lower_into(
                 | ty::PredicateKind::ClosureKind(..)
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
+                | ty::PredicateKind::OpaqueType(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
             };
@@ -196,6 +197,7 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GoalData<RustInte
             | ty::PredicateKind::Subtype(..)
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
+            | ty::PredicateKind::OpaqueType(..)
             | ty::PredicateKind::ConstEquate(..) => {
                 chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
             }
@@ -610,6 +612,7 @@ fn lower_into(
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::OpaqueType(..)
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 bug!("unexpected predicate {}", &self)
             }
@@ -739,6 +742,7 @@ fn lower_into(
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::OpaqueType(..)
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                 bug!("unexpected predicate {}", &self)
             }
index 09bfdabf4737357871a7fad22d2bfdd7f6f8577b..287538e0764d3d577d7726262f69d6107c01a75f 100644 (file)
                 var_values: CanonicalVarValues { var_values },
                 region_constraints: QueryRegionConstraints::default(),
                 certainty: Certainty::Proven,
+                opaque_types: vec![],
                 value: (),
             },
         };
                                     .make_identity(tcx),
                                 region_constraints: QueryRegionConstraints::default(),
                                 certainty: Certainty::Ambiguous,
+                                opaque_types: vec![],
                                 value: (),
                             },
                         };
index 90c698db8fb542eb212b88623332213d1ab8e7f6..1535a46a01b475b89dac7b17f678aeb5f482fc09 100644 (file)
@@ -105,6 +105,7 @@ fn compute_implied_outlives_bounds<'tcx>(
                     | ty::PredicateKind::ObjectSafe(..)
                     | ty::PredicateKind::ConstEvaluatable(..)
                     | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::OpaqueType(..)
                     | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
                     ty::PredicateKind::WellFormed(arg) => {
                         wf_args.push(arg);
index 46c2f7e4cf2ed2ada9587a72a69ff03ec8b77f54..c64e97074a6e02451066ff441eb2d7bc7d34f567 100644 (file)
@@ -69,6 +69,7 @@ fn not_outlives_predicate<'tcx>(p: &ty::Predicate<'tcx>) -> bool {
         | ty::PredicateKind::Coerce(..)
         | ty::PredicateKind::ConstEvaluatable(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::OpaqueType(..)
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
     }
 }
index ec6fb622d32aa40c9f7d097115ed143fd1b609e3..741438b3d29cc773f02f9725fa7b78df3fc3ab6e 100644 (file)
@@ -61,6 +61,14 @@ pub struct TypeFlags: u32 {
                                           | TypeFlags::HAS_CT_INFER.bits
                                           | TypeFlags::HAS_TY_PLACEHOLDER.bits
                                           | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                          // The `evaluate_obligation` query does not return further
+                                          // obligations. If it evaluates an obligation with an opaque
+                                          // type, that opaque type may get compared to another type,
+                                          // constraining it. We would lose this information.
+                                          // FIXME: differentiate between crate-local opaque types
+                                          // and opaque types from other crates, as only opaque types
+                                          // from the local crate can possibly be a local name
+                                          | TypeFlags::HAS_TY_OPAQUE.bits
                                           // We consider 'freshened' types and constants
                                           // to depend on a particular fn.
                                           // The freshening process throws away information,
index 405e4e8594a3ac60bd3d3210a49f57b73b35a4dc..195fbd7752065298138b1d24f917366d03ea2880 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::Obligation;
-use rustc_middle::ty::{self, ToPredicate, Ty, TyS};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyS, TypeFoldable};
 use rustc_span::{MultiSpan, Span};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
@@ -98,8 +98,7 @@ pub fn check_match(
             let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
             all_arms_diverge &= self.diverges.get();
 
-            let opt_suggest_box_span =
-                self.opt_suggest_box_span(arm.body.span, arm_ty, orig_expected);
+            let opt_suggest_box_span = self.opt_suggest_box_span(arm_ty, orig_expected);
 
             let (arm_span, semi_span) =
                 self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty);
@@ -504,20 +503,15 @@ fn find_block_span(
     // provide a structured suggestion in that case.
     pub(crate) fn opt_suggest_box_span(
         &self,
-        span: Span,
         outer_ty: &'tcx TyS<'tcx>,
         orig_expected: Expectation<'tcx>,
     ) -> Option<Span> {
-        match (orig_expected, self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty))) {
-            (Expectation::ExpectHasType(expected), Some((_id, ty)))
-                if self.in_tail_expr && self.can_coerce(outer_ty, expected) =>
+        match orig_expected {
+            Expectation::ExpectHasType(expected)
+                if self.in_tail_expr
+                    && self.ret_coercion.as_ref()?.borrow().merged_ty().has_opaque_types()
+                    && self.can_coerce(outer_ty, expected) =>
             {
-                let impl_trait_ret_ty =
-                    self.infcx.instantiate_opaque_types(self.body_id, self.param_env, ty, span);
-                assert!(
-                    impl_trait_ret_ty.obligations.is_empty(),
-                    "we should never get new obligations here"
-                );
                 let obligations = self.fulfillment_cx.borrow().pending_obligations();
                 let mut suggest_box = !obligations.is_empty();
                 for o in obligations {
index 0fea0afb572c9368f41cda8b8ccd6d1427c44b16..19c3f00ed9357c155fbbbd1539aa8eef7e26f5cf 100644 (file)
@@ -545,7 +545,7 @@ fn confirm_deferred_closure_call(
         expected: Expectation<'tcx>,
         fn_sig: ty::FnSig<'tcx>,
     ) -> Ty<'tcx> {
-        // `fn_sig` is the *signature* of the cosure being called. We
+        // `fn_sig` is the *signature* of the closure being called. We
         // don't know the full details yet (`Fn` vs `FnMut` etc), but we
         // do know the types expected for each argument and the return
         // type.
index 18a0a8767d45bf786d6ace91f4db58fd06d12465..d10d3e43b5b18fc8f58941bcb16cf742baa53e85 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_middle::ty::layout::MAX_SIMD_LANES;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, MultiSpan, Span};
@@ -81,8 +81,6 @@ pub(super) fn check_fn<'a, 'tcx>(
     can_be_generator: Option<hir::Movability>,
     return_type_pre_known: bool,
 ) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
-    let mut fn_sig = fn_sig;
-
     // Create the function context. This is either derived from scratch or,
     // in the case of closures, based on the outer context.
     let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
@@ -95,21 +93,8 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     let declared_ret_ty = fn_sig.output();
 
-    let revealed_ret_ty =
-        fcx.instantiate_opaque_types_from_value(declared_ret_ty, decl.output.span());
-    debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
-    fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
+    fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(declared_ret_ty)));
     fcx.ret_type_span = Some(decl.output.span());
-    if let ty::Opaque(..) = declared_ret_ty.kind() {
-        fcx.ret_coercion_impl_trait = Some(declared_ret_ty);
-    }
-    fn_sig = tcx.mk_fn_sig(
-        fn_sig.inputs().iter().cloned(),
-        revealed_ret_ty,
-        fn_sig.c_variadic,
-        fn_sig.unsafety,
-        fn_sig.abi,
-    );
 
     let span = body.value.span;
 
@@ -251,7 +236,7 @@ pub(super) fn check_fn<'a, 'tcx>(
             fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
         debug!("actual_return_ty replaced with {:?}", actual_return_ty);
     }
-    fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
+    fcx.demand_suptype(span, declared_ret_ty, actual_return_ty);
 
     // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
     if let Some(panic_impl_did) = tcx.lang_items().panic_impl() {
@@ -629,6 +614,8 @@ fn check_opaque_meets_bounds<'tcx>(
     span: Span,
     origin: &hir::OpaqueTyOrigin,
 ) {
+    let hidden_type = tcx.type_of(def_id).subst(tcx, substs);
+
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let defining_use_anchor = match *origin {
         hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
@@ -643,24 +630,12 @@ fn check_opaque_meets_bounds<'tcx>(
 
         let misc_cause = traits::ObligationCause::misc(span, hir_id);
 
-        let _ = inh.register_infer_ok_obligations(
-            infcx.instantiate_opaque_types(hir_id, param_env, opaque_ty, span),
-        );
-
-        let opaque_type_map = infcx.inner.borrow().opaque_types.clone();
-        for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map {
-            let hidden_type = tcx.type_of(def_id).subst(tcx, substs);
-            trace!(?hidden_type);
-            match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) {
-                Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
-                Err(ty_err) => tcx.sess.delay_span_bug(
-                    span,
-                    &format!(
-                        "could not check bounds on revealed type `{}`:\n{}",
-                        hidden_type, ty_err,
-                    ),
-                ),
-            }
+        match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
+            Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
+            Err(ty_err) => tcx.sess.delay_span_bug(
+                span,
+                &format!("could not unify `{}` with revealed type:\n{}", hidden_type, ty_err,),
+            ),
         }
 
         // Check that all obligations are satisfied by the implementation's
@@ -672,7 +647,7 @@ fn check_opaque_meets_bounds<'tcx>(
 
         match origin {
             // Checked when type checking the function containing them.
-            hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return,
+            hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
             // Can have different predicates to their defining use
             hir::OpaqueTyOrigin::TyAlias => {
                 // Finally, resolve all regions. This catches wily misuses of
@@ -681,6 +656,9 @@ fn check_opaque_meets_bounds<'tcx>(
                 fcx.regionck_item(hir_id, span, FxHashSet::default());
             }
         }
+
+        // Clean up after ourselves
+        let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
     });
 }
 
index e88099afa03539ce855f6e40d2320a40c968677c..d4336563b96037bf7c8ff948b4b6b8a1c3f05483 100644 (file)
@@ -3,16 +3,20 @@
 use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
 
 use crate::astconv::AstConv;
+use crate::rustc_middle::ty::subst::Subst;
+use hir::OpaqueTyOrigin;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_infer::infer::{InferOk, InferResult};
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Span;
+use rustc_span::DUMMY_SP;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::ArgKind;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
@@ -172,6 +176,29 @@ fn deduce_expectations_from_expected_type(
         expected_ty: Ty<'tcx>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
+            ty::Opaque(def_id, substs) => {
+                let bounds = self.tcx.explicit_item_bounds(def_id);
+                let sig = bounds.iter().find_map(|(pred, span)| match pred.kind().skip_binder() {
+                    ty::PredicateKind::Projection(proj_predicate) => self
+                        .deduce_sig_from_projection(
+                            Some(*span),
+                            pred.kind().rebind(proj_predicate.subst(self.tcx, substs)),
+                        ),
+                    _ => None,
+                });
+
+                let kind = bounds
+                    .iter()
+                    .filter_map(|(pred, _)| match pred.kind().skip_binder() {
+                        ty::PredicateKind::Trait(tp) => {
+                            self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
+                        }
+                        _ => None,
+                    })
+                    .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
+                trace!(?sig, ?kind);
+                (sig, kind)
+            }
             ty::Dynamic(ref object_type, ..) => {
                 let sig = object_type.projection_bounds().find_map(|pb| {
                     let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@@ -197,10 +224,7 @@ fn deduce_expectations_from_obligations(
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         let expected_sig =
             self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| {
-                debug!(
-                    "deduce_expectations_from_obligations: obligation.predicate={:?}",
-                    obligation.predicate
-                );
+                debug!(?obligation.predicate);
 
                 let bound_predicate = obligation.predicate.kind();
                 if let ty::PredicateKind::Projection(proj_predicate) =
@@ -401,9 +425,14 @@ fn sig_of_closure_with_expectation(
         // in this binder we are creating.
         assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
         let bound_sig = expected_sig.sig.map_bound(|sig| {
+            let output = self.hide_parent_opaque_types(
+                sig.output(),
+                expected_sig.cause_span.unwrap_or(DUMMY_SP),
+                body.id().hir_id,
+            );
             self.tcx.mk_fn_sig(
                 sig.inputs().iter().cloned(),
-                sig.output(),
+                output,
                 sig.c_variadic,
                 hir::Unsafety::Normal,
                 Abi::RustCall,
@@ -590,6 +619,8 @@ fn supplied_sig_of_closure(
                 _ => astconv.ty_infer(None, decl.output.span()),
             },
         };
+        let supplied_return =
+            self.hide_parent_opaque_types(supplied_return, decl.output.span(), body.id().hir_id);
 
         let result = ty::Binder::bind_with_vars(
             self.tcx.mk_fn_sig(
@@ -610,27 +641,57 @@ fn supplied_sig_of_closure(
         result
     }
 
+    fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
+        ty.fold_with(&mut ty::fold::BottomUpFolder {
+            tcx: self.infcx.tcx,
+            lt_op: |lt| lt,
+            ct_op: |ct| ct,
+            ty_op: |ty| match *ty.kind() {
+                // Closures can't create hidden types for opaque types of their parent, as they
+                // do not have all the outlives information available. Also `type_of` looks for
+                // hidden types in the owner (so the closure's parent), so it would not find these
+                // definitions.
+                ty::Opaque(def_id, _substs)
+                    if matches!(
+                        self.infcx.opaque_type_origin(def_id, DUMMY_SP),
+                        Some(OpaqueTyOrigin::FnReturn(..))
+                    ) =>
+                {
+                    let ty_var = self.next_ty_var(TypeVariableOrigin {
+                        kind: TypeVariableOriginKind::TypeInference,
+                        span,
+                    });
+                    let cause = ObligationCause::misc(span, body_id);
+                    self.register_predicates(vec![self.infcx.opaque_ty_obligation(
+                        ty,
+                        ty_var,
+                        true,
+                        self.param_env,
+                        cause,
+                    )]);
+                    ty_var
+                }
+                _ => ty,
+            },
+        })
+    }
+
     /// Invoked when we are translating the generator that results
     /// from desugaring an `async fn`. Returns the "sugared" return
     /// type of the `async fn` -- that is, the return type that the
     /// user specified. The "desugared" return type is an `impl
     /// Future<Output = T>`, so we do this by searching through the
     /// obligations to extract the `T`.
+    #[instrument(skip(self), level = "debug")]
     fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> {
-        debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id);
-
         let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
             span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
         });
 
-        // In practice, the return type of the surrounding function is
-        // always a (not yet resolved) inference variable, because it
-        // is the hidden type for an `impl Trait` that we are going to
-        // be inferring.
         let ret_ty = ret_coercion.borrow().expected_ty();
         let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
-        let ret_vid = match *ret_ty.kind() {
-            ty::Infer(ty::TyVar(ret_vid)) => ret_vid,
+        let (def_id, substs) = match *ret_ty.kind() {
+            ty::Opaque(def_id, substs) => (def_id, substs),
             ty::Error(_) => return None,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
@@ -638,17 +699,19 @@ fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty
             ),
         };
 
+        let item_bounds = self.tcx.explicit_item_bounds(def_id);
+
         // Search for a pending obligation like
         //
         // `<R as Future>::Output = T`
         //
         // where R is the return type we are expecting. This type `T`
         // will be our output.
-        let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
-            let bound_predicate = obligation.predicate.kind();
+        let output_ty = item_bounds.iter().find_map(|&(predicate, span)| {
+            let bound_predicate = predicate.subst(self.tcx, substs).kind();
             if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
                 self.deduce_future_output_from_projection(
-                    obligation.cause.span,
+                    span,
                     bound_predicate.rebind(proj_predicate),
                 )
             } else {
index 3668ecd234c64e1c8b216af4f6d07e653ba8038b..8204a25e9112b71d99cea21425fefa753227178c 100644 (file)
@@ -1275,7 +1275,7 @@ pub fn expected_ty(&self) -> Ty<'tcx> {
 
     /// Returns the current "merged type", representing our best-guess
     /// at the LUB of the expressions we've seen so far (if any). This
-    /// isn't *final* until you call `self.final()`, which will return
+    /// isn't *final* until you call `self.complete()`, which will return
     /// the merged type.
     pub fn merged_ty(&self) -> Ty<'tcx> {
         self.final_ty.unwrap_or(self.expected_ty)
index 74910234b7edcbe1215fbe6973a636acad8f00bc..5bb528458c59e07941570607ad8e0fcabb32d45f 100644 (file)
@@ -377,9 +377,9 @@ fn compare_predicate_entailment<'tcx>(
                 &mut diag,
                 &cause,
                 trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
-                Some(infer::ValuePairs::Types(ExpectedFound {
-                    expected: trait_fty,
-                    found: impl_fty,
+                Some(infer::ValuePairs::Terms(ExpectedFound {
+                    expected: trait_fty.into(),
+                    found: impl_fty.into(),
                 })),
                 &terr,
                 false,
@@ -1068,9 +1068,9 @@ fn compare_const_param_types<'tcx>(
                 &mut diag,
                 &cause,
                 trait_c_span.map(|span| (span, "type in trait".to_owned())),
-                Some(infer::ValuePairs::Types(ExpectedFound {
-                    expected: trait_ty,
-                    found: impl_ty,
+                Some(infer::ValuePairs::Terms(ExpectedFound {
+                    expected: trait_ty.into(),
+                    found: impl_ty.into(),
                 })),
                 &terr,
                 false,
index e9e810344776b963d52a0eeb85fbd6ecbcc8c376..9e1a70b7dfb929382497d1cdcbb5c15da3195694 100644 (file)
@@ -1,5 +1,6 @@
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::ty::{self, Ty};
+use rustc_span::DUMMY_SP;
 use rustc_span::{self, Span};
 
 use super::Expectation::*;
@@ -43,7 +44,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
     // when checking the 'then' block which are incompatible with the
     // 'else' branch.
     pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
-        match *self {
+        match self.strip_opaque(fcx) {
             ExpectHasType(ety) => {
                 let ety = fcx.shallow_resolve(ety);
                 if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
@@ -104,14 +105,35 @@ pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
     /// for the program to type-check). `only_has_type` will return
     /// such a constraint, if it exists.
     pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
-        match self {
-            ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)),
+        match self.strip_opaque(fcx) {
+            ExpectHasType(ty) => Some(ty),
             NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => {
                 None
             }
         }
     }
 
+    /// We must not treat opaque types as expected types in their defining scope, as that
+    /// will break `fn foo() -> impl Trait { if cond { a } else { b } }` if `a` and `b` are
+    /// only "equal" if they coerce to a common target, like two different function items
+    /// coercing to a function pointer if they have the same signature.
+    fn strip_opaque(self, fcx: &FnCtxt<'a, 'tcx>) -> Self {
+        match self {
+            ExpectHasType(ty) => {
+                let ty = fcx.resolve_vars_if_possible(ty);
+                match *ty.kind() {
+                    ty::Opaque(def_id, _)
+                        if fcx.infcx.opaque_type_origin(def_id, DUMMY_SP).is_some() =>
+                    {
+                        NoExpectation
+                    }
+                    _ => self,
+                }
+            }
+            _ => self,
+        }
+    }
+
     /// Like `only_has_type`, but instead of returning `None` if no
     /// hard constraint exists, creates a fresh type variable.
     pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
index 0347b6a4ab82f7da77d9b7c719e3661ba7d3fd3f..74341fef38e27ee0760f68f46fad146547c8cb61 100644 (file)
@@ -956,8 +956,7 @@ fn check_then_else(
             };
             let else_diverges = self.diverges.get();
 
-            let opt_suggest_box_span =
-                self.opt_suggest_box_span(else_expr.span, else_ty, orig_expected);
+            let opt_suggest_box_span = self.opt_suggest_box_span(else_ty, orig_expected);
             let if_cause =
                 self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span);
 
index e5da33d113e7c48e95ab6e626d4e0dc8ff0711f8..85132317824076160bf8b538e3d2f0ab582625fc 100644 (file)
@@ -24,7 +24,7 @@ pub(super) fn type_inference_fallback(&self) -> bool {
             self.fulfillment_cx.borrow_mut().pending_obligations()
         );
 
-        // Check if we have any unsolved varibales. If not, no need for fallback.
+        // Check if we have any unsolved variables. If not, no need for fallback.
         let unsolved_variables = self.unsolved_variables();
         if unsolved_variables.is_empty() {
             return false;
@@ -66,16 +66,6 @@ pub(super) fn type_inference_fallback(&self) -> bool {
         // refer to opaque types.
         self.select_obligations_where_possible(fallback_has_occurred, |_| {});
 
-        // We now run fallback again, but this time we allow it to replace
-        // unconstrained opaque type variables, in addition to performing
-        // other kinds of fallback.
-        for ty in &self.unsolved_variables() {
-            fallback_has_occurred |= self.fallback_opaque_type_vars(ty);
-        }
-
-        // See if we can make any more progress.
-        self.select_obligations_where_possible(fallback_has_occurred, |_| {});
-
         fallback_has_occurred
     }
 
@@ -136,59 +126,6 @@ fn fallback_if_possible(
         true
     }
 
-    /// Second round of fallback: Unconstrained type variables created
-    /// from the instantiation of an opaque type fall back to the
-    /// opaque type itself. This is a somewhat incomplete attempt to
-    /// manage "identity passthrough" for `impl Trait` types.
-    ///
-    /// For example, in this code:
-    ///
-    ///```
-    /// type MyType = impl Copy;
-    /// fn defining_use() -> MyType { true }
-    /// fn other_use() -> MyType { defining_use() }
-    /// ```
-    ///
-    /// `defining_use` will constrain the instantiated inference
-    /// variable to `bool`, while `other_use` will constrain
-    /// the instantiated inference variable to `MyType`.
-    ///
-    /// When we process opaque types during writeback, we
-    /// will handle cases like `other_use`, and not count
-    /// them as defining usages
-    ///
-    /// However, we also need to handle cases like this:
-    ///
-    /// ```rust
-    /// pub type Foo = impl Copy;
-    /// fn produce() -> Option<Foo> {
-    ///     None
-    ///  }
-    ///  ```
-    ///
-    /// In the above snippet, the inference variable created by
-    /// instantiating `Option<Foo>` will be completely unconstrained.
-    /// We treat this as a non-defining use by making the inference
-    /// variable fall back to the opaque type itself.
-    fn fallback_opaque_type_vars(&self, ty: Ty<'tcx>) -> bool {
-        let span = self
-            .infcx
-            .type_var_origin(ty)
-            .map(|origin| origin.span)
-            .unwrap_or(rustc_span::DUMMY_SP);
-        let oty = self.inner.borrow().opaque_types_vars.get(ty).copied();
-        if let Some(opaque_ty) = oty {
-            debug!(
-                "fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}",
-                ty, opaque_ty
-            );
-            self.demand_eqtype(span, ty, opaque_ty);
-            true
-        } else {
-            return false;
-        }
-    }
-
     /// The "diverging fallback" system is rather complicated. This is
     /// a result of our need to balance 'do the right thing' with
     /// backwards compatibility.
index 0f9803b969fb74521feef9aefcbfe1b950845721..e60893a658b3dc31b1211ebca0e5f1d9dda7de9d 100644 (file)
@@ -367,23 +367,6 @@ pub(in super::super) fn instantiate_bounds(
         (result, spans)
     }
 
-    /// Replaces the opaque types from the given value with type variables,
-    /// and records the `OpaqueTypeMap` for later use during writeback. See
-    /// `InferCtxt::instantiate_opaque_types` for more details.
-    #[instrument(skip(self, value_span), level = "debug")]
-    pub(in super::super) fn instantiate_opaque_types_from_value<T: TypeFoldable<'tcx>>(
-        &self,
-        value: T,
-        value_span: Span,
-    ) -> T {
-        self.register_infer_ok_obligations(self.instantiate_opaque_types(
-            self.body_id,
-            self.param_env,
-            value,
-            value_span,
-        ))
-    }
-
     /// Convenience method which tracks extra diagnostic information for normalization
     /// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item
     /// whose type is being wf-checked - this is used to construct a more precise span if
@@ -720,6 +703,7 @@ pub(in super::super) fn obligations_for_self_ty<'b>(
                     // inference variable.
                     ty::PredicateKind::ClosureKind(..) => None,
                     ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+                    ty::PredicateKind::OpaqueType(..) => None,
                 }
             })
             .filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root))
index 3a81af03162862f8c8d99024fd92681fd8cb7acb..234775ab45269c7845443fd67a7e9c34003ab841 100644 (file)
@@ -57,8 +57,6 @@ pub struct FnCtxt<'a, 'tcx> {
     /// any).
     pub(super) ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
 
-    pub(super) ret_coercion_impl_trait: Option<Ty<'tcx>>,
-
     pub(super) ret_type_span: Option<Span>,
 
     /// Used exclusively to reduce cost of advanced evaluation used for
@@ -130,7 +128,6 @@ pub fn new(
             param_env,
             err_count_on_creation: inh.tcx.sess.err_count(),
             ret_coercion: None,
-            ret_coercion_impl_trait: None,
             ret_type_span: None,
             in_tail_expr: false,
             ret_coercion_span: Cell::new(None),
index beb6b371b2bb8de1dba246009a5569c74f96a412..b775f24f8efd85f506b0b10cb01e720d0716873e 100644 (file)
@@ -95,6 +95,13 @@ pub fn enter<F, R>(&mut self, f: F) -> R
         let def_id = self.def_id;
         self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
     }
+
+    /// WF-checking doesn't need to recompute opaque types and can instead use
+    /// the type_of query to get them from typeck.
+    pub fn reveal_defining_opaque_types(mut self) -> Self {
+        self.infcx = self.infcx.reveal_defining_opaque_types();
+        self
+    }
 }
 
 impl<'a, 'tcx> Inherited<'a, 'tcx> {
@@ -119,8 +126,8 @@ pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
-        debug!("register_predicate({:?})", obligation);
         if obligation.has_escaping_bound_vars() {
             span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation);
         }
index 3815fd1992bf318b6806873052bfc84a554df097..b8a45133fd7ea8361c896ef16db507e6d8c80542 100644 (file)
@@ -858,6 +858,7 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
                 | ty::PredicateKind::TypeOutlives(..)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::OpaqueType(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
             }
         });
@@ -1477,6 +1478,7 @@ fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> Ca
             TraitCandidate(trait_ref) => self.probe(|_| {
                 let _ = self
                     .at(&ObligationCause::dummy(), self.param_env)
+                    .define_opaque_types(false)
                     .sup(candidate.xform_self_ty, self_ty);
                 match self.select_trait_candidate(trait_ref) {
                     Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
@@ -1506,6 +1508,7 @@ fn consider_probe(
             // First check that the self type can be related.
             let sub_obligations = match self
                 .at(&ObligationCause::dummy(), self.param_env)
+                .define_opaque_types(false)
                 .sup(probe.xform_self_ty, self_ty)
             {
                 Ok(InferOk { obligations, value: () }) => obligations,
@@ -1653,6 +1656,7 @@ fn consider_probe(
                     );
                     if self
                         .at(&ObligationCause::dummy(), self.param_env)
+                        .define_opaque_types(false)
                         .sup(return_ty, xform_ret_ty)
                         .is_err()
                     {
index 6e0b902a00bda1014c19a4f0771d17fee2a9e0a2..d4be3889a7ae7e1dcee977a2f19324fdd4feba24 100644 (file)
@@ -341,6 +341,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
     typeck_with_fallback(tcx, def_id, fallback)
 }
 
+#[instrument(skip(tcx, fallback))]
 fn typeck_with_fallback<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
index becae6c9dc920ad7ee67dcdcf406cebc18326b36..0482e8b895b5684711a42d5a1d5500d4f546d5df 100644 (file)
@@ -335,11 +335,6 @@ fn analyze_closure(
 
     // Returns a list of `Ty`s for each upvar.
     fn final_upvar_tys(&self, closure_id: DefId) -> Vec<Ty<'tcx>> {
-        // Presently an unboxed closure type cannot "escape" out of a
-        // function, so we will only encounter ones that originated in the
-        // local crate or were inlined into it along with some function.
-        // This may change if abstract return types of some sort are
-        // implemented.
         self.typeck_results
             .borrow()
             .closure_min_captures_flattened(closure_id)
index 71f45320e49520192185a5a885662a2c8a09e4bf..c0fa673774ffdb3e125e9510c47a6767ffd40d55 100644 (file)
@@ -895,7 +895,7 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<
 
 fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> {
     CheckWfFcxBuilder {
-        inherited: Inherited::build(tcx, def_id),
+        inherited: Inherited::build(tcx, def_id).reveal_defining_opaque_types(),
         id: hir::HirId::make_owner(def_id),
         span,
         param_env: tcx.param_env(def_id),
index ec88bdf4a370f8a8508d9da6f24e7e827aebdbeb..e04c1423cdac81f567c8b41f119778c221c766a2 100644 (file)
@@ -18,7 +18,6 @@
 use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_trait_selection::opaque_types::InferCtxtExt;
 
 use std::mem;
 
@@ -65,7 +64,7 @@ pub fn resolve_type_vars_in_body(
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
         wbcx.visit_fru_field_types();
-        wbcx.visit_opaque_types(body.value.span);
+        wbcx.visit_opaque_types();
         wbcx.visit_coercion_casts();
         wbcx.visit_user_provided_tys();
         wbcx.visit_user_provided_sigs();
@@ -496,64 +495,18 @@ fn visit_generator_interior_types(&mut self) {
             fcx_typeck_results.generator_interior_types.clone();
     }
 
-    #[instrument(skip(self, span), level = "debug")]
-    fn visit_opaque_types(&mut self, span: Span) {
-        let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone();
-        for (opaque_type_key, opaque_defn) in opaque_types {
-            let hir_id =
-                self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local());
-            let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id);
-
-            debug_assert!(!instantiated_ty.has_escaping_bound_vars());
-
-            let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap();
-
-            // Prevent:
-            // * `fn foo<T>() -> Foo<T>`
-            // * `fn foo<T: Bound + Other>() -> Foo<T>`
-            // from being defining.
-
-            // Also replace all generic params with the ones from the opaque type
-            // definition so that
-            // ```rust
-            // type Foo<T> = impl Baz + 'static;
-            // fn foo<U>() -> Foo<U> { .. }
-            // ```
-            // figures out the concrete type with `U`, but the stored type is with `T`.
-
-            // FIXME: why are we calling this here? This seems too early, and duplicated.
-            let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
-                opaque_type_key,
-                instantiated_ty,
-                span,
-            );
-
-            let mut skip_add = false;
-
-            if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() {
-                if opaque_defn.origin == hir::OpaqueTyOrigin::TyAlias {
-                    if opaque_type_key.def_id == definition_ty_def_id {
-                        debug!(
-                            "skipping adding concrete definition for opaque type {:?} {:?}",
-                            opaque_defn, opaque_type_key.def_id
-                        );
-                        skip_add = true;
-                    }
+    #[instrument(skip(self), level = "debug")]
+    fn visit_opaque_types(&mut self) {
+        let opaque_types =
+            self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+        for (opaque_type_key, decl) in opaque_types {
+            let hidden_type = match decl.origin {
+                hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
+                    Some(self.resolve(decl.hidden_type.ty, &decl.hidden_type.span))
                 }
-            }
-
-            if opaque_type_key.substs.needs_infer() {
-                span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs)
-            }
-
-            // We only want to add an entry into `concrete_opaque_types`
-            // if we actually found a defining usage of this opaque type.
-            // Otherwise, we do nothing - we'll either find a defining usage
-            // in some other location, or we'll end up emitting an error due
-            // to the lack of defining usage
-            if !skip_add {
-                self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id);
-            }
+                hir::OpaqueTyOrigin::TyAlias => None,
+            };
+            self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
         }
     }
 
index 5cb0d309ff4ee020073f606b143ecaf103f37844..912a16ffb8a13aca0efe3895f26fcbeb0ed49a73 100644 (file)
@@ -389,28 +389,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
                         .copied()
                         .unwrap_or_else(|| {
-                            tcx.sess.delay_span_bug(
-                                DUMMY_SP,
-                                &format!(
-                                    "owner {:?} has no opaque type for {:?} in its typeck results",
-                                    owner, def_id,
-                                ),
-                            );
-                            if let Some(ErrorReported) =
-                                tcx.typeck(owner).tainted_by_errors
-                            {
+                            let table = tcx.typeck(owner);
+                            if let Some(ErrorReported) = table.tainted_by_errors {
                                 // Some error in the
                                 // owner fn prevented us from populating
                                 // the `concrete_opaque_types` table.
                                 tcx.ty_error()
                             } else {
-                                // We failed to resolve the opaque type or it
-                                // resolves to itself. Return the non-revealed
-                                // type, which should result in E0720.
-                                tcx.mk_opaque(
-                                    def_id.to_def_id(),
-                                    InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
-                                )
+                                table.concrete_opaque_types.get(&def_id.to_def_id()).copied().unwrap_or_else(|| {
+                                    // We failed to resolve the opaque type or it
+                                    // resolves to itself. We interpret this as the
+                                    // no values of the hidden type ever being constructed,
+                                    // so we can just make the hidden type be `!`.
+                                    // For backwards compatibility reasons, we fall back to
+                                    // `()` until we the diverging default is changed.
+                                    Some(tcx.mk_diverging_default())
+                                }).expect("RPIT always have a hidden type from typeck")
                             }
                         });
                     debug!("concrete_ty = {:?}", concrete_ty);
@@ -604,7 +598,21 @@ fn check(&mut self, def_id: LocalDefId) {
             }
             // Calling `mir_borrowck` can lead to cycle errors through
             // const-checking, avoid calling it if we don't have to.
-            if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
+            // ```rust
+            // type Foo = impl Fn() -> usize; // when computing type for this
+            // const fn bar() -> Foo {
+            //     || 0usize
+            // }
+            // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
+            // // because we again need to reveal `Foo` so we can check whether the
+            // // constant does not contain interior mutability.
+            // ```
+            let tables = self.tcx.typeck(def_id);
+            if let Some(_) = tables.tainted_by_errors {
+                self.found = Some((DUMMY_SP, self.tcx.ty_error()));
+                return;
+            }
+            if tables.concrete_opaque_types.get(&self.def_id).is_none() {
                 debug!("no constraints in typeck results");
                 return;
             }
@@ -658,7 +666,7 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
             intravisit::walk_expr(self, ex);
         }
         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
-            debug!("find_existential_constraints: visiting {:?}", it);
+            trace!(?it.def_id);
             // The opaque type itself or its children are not within its reveal scope.
             if it.def_id.to_def_id() != self.def_id {
                 self.check(it.def_id);
@@ -666,7 +674,7 @@ fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
             }
         }
         fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
-            debug!("find_existential_constraints: visiting {:?}", it);
+            trace!(?it.def_id);
             // The opaque type itself or its children are not within its reveal scope.
             if it.def_id.to_def_id() != self.def_id {
                 self.check(it.def_id);
@@ -674,7 +682,7 @@ fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
             }
         }
         fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
-            debug!("find_existential_constraints: visiting {:?}", it);
+            trace!(?it.def_id);
             self.check(it.def_id);
             intravisit::walk_trait_item(self, it);
         }
@@ -684,12 +692,12 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
     let scope = tcx.hir().get_defining_scope(hir_id);
     let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
 
-    debug!("find_opaque_ty_constraints: scope={:?}", scope);
+    debug!(?scope);
 
     if scope == hir::CRATE_HIR_ID {
         tcx.hir().walk_toplevel_module(&mut locator);
     } else {
-        debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
+        trace!("scope={:#?}", tcx.hir().get(scope));
         match tcx.hir().get(scope) {
             // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
             // This allows our visitor to process the defining item itself, causing
@@ -716,7 +724,12 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
         Some((_, ty)) => ty,
         None => {
             let span = tcx.def_span(def_id);
-            tcx.sess.span_err(span, "could not find defining uses");
+            let name = tcx.item_name(tcx.parent(def_id.to_def_id()).unwrap());
+            let label = format!(
+                "`{}` must be used in combination with a concrete type within the same module",
+                name
+            );
+            tcx.sess.struct_span_err(span, "unconstrained opaque type").note(&label).emit();
             tcx.ty_error()
         }
     }
index d87e670a8fb5a7bf912ea64031a9b1a5d70e4944..4227ed6ab3ad58af53068ef42a51ab51d20f74f0 100644 (file)
@@ -427,6 +427,7 @@ fn trait_predicate_kind<'tcx>(
         | ty::PredicateKind::ClosureKind(..)
         | ty::PredicateKind::ConstEvaluatable(..)
         | ty::PredicateKind::ConstEquate(..)
+        | ty::PredicateKind::OpaqueType(..)
         | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
     }
 }
index 7b004fa086bf3a1bbda36fd1793663d073245f79..d415e37ff0116435c67d6a0acf30a6c5d762c9d1 100644 (file)
 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
     match (decl.c_variadic, abi) {
         // The function has the correct calling convention, or isn't a "C-variadic" function.
-        (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl) => {}
+        (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {}
         // The function is a "C-variadic" function with an incorrect calling convention.
         (true, _) => {
             let mut err = struct_span_err!(
index bbf31de527eb3fb7205507ee6707981b3ec8859f..7839ce5e4ff48e51739b2b23808eec60eab27c14 100644 (file)
@@ -59,6 +59,7 @@ pub fn explicit_predicates_of(
                     | ty::PredicateKind::Coerce(..)
                     | ty::PredicateKind::ConstEvaluatable(..)
                     | ty::PredicateKind::ConstEquate(..)
+                    | ty::PredicateKind::OpaqueType(..)
                     | ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
                 }
             }
index dcf51e3142a617924590b0f19b8739439c7fe10b..cbb86265233b0bdcc4578ffb210396b135d1f405 100644 (file)
@@ -29,6 +29,7 @@
 #![feature(binary_heap_as_slice)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
+#![feature(round_char_boundary)]
 #![feature(slice_group_by)]
 #![feature(slice_partition_dedup)]
 #![feature(string_remove_matches)]
index 7b07821ab1d31de590cb9e38ab45f6bf40bc90f3..6b8be2506b64e5bc8d179eaae03798c003ce42f9 100644 (file)
@@ -2272,3 +2272,95 @@ fn utf8_char_counts() {
         }
     }
 }
+
+#[test]
+fn floor_char_boundary() {
+    fn check_many(s: &str, arg: impl IntoIterator<Item = usize>, ret: usize) {
+        for idx in arg {
+            assert_eq!(
+                s.floor_char_boundary(idx),
+                ret,
+                "{:?}.floor_char_boundary({:?}) != {:?}",
+                s,
+                idx,
+                ret
+            );
+        }
+    }
+
+    // edge case
+    check_many("", [0, 1, isize::MAX as usize, usize::MAX], 0);
+
+    // basic check
+    check_many("x", [0], 0);
+    check_many("x", [1, isize::MAX as usize, usize::MAX], 1);
+
+    // 1-byte chars
+    check_many("jp", [0], 0);
+    check_many("jp", [1], 1);
+    check_many("jp", 2..4, 2);
+
+    // 2-byte chars
+    check_many("ĵƥ", 0..2, 0);
+    check_many("ĵƥ", 2..4, 2);
+    check_many("ĵƥ", 4..6, 4);
+
+    // 3-byte chars
+    check_many("日本", 0..3, 0);
+    check_many("日本", 3..6, 3);
+    check_many("日本", 6..8, 6);
+
+    // 4-byte chars
+    check_many("🇯🇵", 0..4, 0);
+    check_many("🇯🇵", 4..8, 4);
+    check_many("🇯🇵", 8..10, 8);
+}
+
+#[test]
+fn ceil_char_boundary() {
+    fn check_many(s: &str, arg: impl IntoIterator<Item = usize>, ret: usize) {
+        for idx in arg {
+            assert_eq!(
+                s.ceil_char_boundary(idx),
+                ret,
+                "{:?}.ceil_char_boundary({:?}) != {:?}",
+                s,
+                idx,
+                ret
+            );
+        }
+    }
+
+    // edge case
+    check_many("", [0], 0);
+
+    // basic check
+    check_many("x", [0], 0);
+    check_many("x", [1], 1);
+
+    // 1-byte chars
+    check_many("jp", [0], 0);
+    check_many("jp", [1], 1);
+    check_many("jp", [2], 2);
+
+    // 2-byte chars
+    check_many("ĵƥ", 0..=0, 0);
+    check_many("ĵƥ", 1..=2, 2);
+    check_many("ĵƥ", 3..=4, 4);
+
+    // 3-byte chars
+    check_many("日本", 0..=0, 0);
+    check_many("日本", 1..=3, 3);
+    check_many("日本", 4..=6, 6);
+
+    // 4-byte chars
+    check_many("🇯🇵", 0..=0, 0);
+    check_many("🇯🇵", 1..=4, 4);
+    check_many("🇯🇵", 5..=8, 8);
+}
+
+#[test]
+#[should_panic]
+fn ceil_char_boundary_above_len_panic() {
+    let _ = "x".ceil_char_boundary(2);
+}
index 721c030b410aec548ecbd15e73630e8bd65ba6f5..864a253299f6e28b00a58691006b3ccc2f84ada4 100644 (file)
@@ -809,6 +809,11 @@ pub const fn is_ascii_control(&self) -> bool {
     pub fn escape_ascii(&self) -> ascii::EscapeDefault {
         ascii::escape_default(*self)
     }
+
+    pub(crate) fn is_utf8_char_boundary(self) -> bool {
+        // This is bit magic equivalent to: b < 128 || b >= 192
+        (self as i8) >= -0x40
+    }
 }
 
 #[lang = "u16"]
index a0e42c51e4517a8091baa59893d90752983cac9b..5353d900e76629a33ef568ef1ecbe13291b81a50 100644 (file)
@@ -239,6 +239,16 @@ fn add_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const AddAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn add_assign(&mut self, other: $t) {
+                *self = *self + Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const AddAssign, add_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const Sub for Wrapping<$t> {
@@ -262,6 +272,16 @@ fn sub_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const SubAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn sub_assign(&mut self, other: $t) {
+                *self = *self - Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const SubAssign, sub_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const Mul for Wrapping<$t> {
@@ -285,6 +305,16 @@ fn mul_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const MulAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn mul_assign(&mut self, other: $t) {
+                *self = *self * Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const MulAssign, mul_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "wrapping_div", since = "1.3.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const Div for Wrapping<$t> {
@@ -308,6 +338,16 @@ fn div_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const DivAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn div_assign(&mut self, other: $t) {
+                *self = *self / Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const DivAssign, div_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "wrapping_impls", since = "1.7.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const Rem for Wrapping<$t> {
@@ -331,6 +371,16 @@ fn rem_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const RemAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn rem_assign(&mut self, other: $t) {
+                *self = *self % Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const RemAssign, rem_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const Not for Wrapping<$t> {
@@ -367,6 +417,16 @@ fn bitxor_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitXorAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn bitxor_assign(&mut self, other: $t) {
+                *self = *self ^ Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const BitOr for Wrapping<$t> {
@@ -390,6 +450,16 @@ fn bitor_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitOrAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn bitor_assign(&mut self, other: $t) {
+                *self = *self | Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const BitAnd for Wrapping<$t> {
@@ -413,6 +483,16 @@ fn bitand_assign(&mut self, other: Wrapping<$t>) {
         }
         forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> }
 
+        #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")]
+        #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
+        impl const BitAndAssign<$t> for Wrapping<$t> {
+            #[inline]
+            fn bitand_assign(&mut self, other: $t) {
+                *self = *self & Wrapping(other);
+            }
+        }
+        forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for Wrapping<$t>, $t }
+
         #[stable(feature = "wrapping_neg", since = "1.10.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "90080")]
         impl const Neg for Wrapping<$t> {
index fceea2366da54d8cc2fe7ddfe26ef8cf875d8a28..09709dc3cf6dfbd187f2ecfe020ad0a6a07fbe33 100644 (file)
 use iter::SplitInternal;
 use iter::{MatchesInternal, SplitNInternal};
 
-use validations::truncate_to_char_boundary;
-
 #[inline(never)]
 #[cold]
 #[track_caller]
 fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
     const MAX_DISPLAY_LENGTH: usize = 256;
-    let (truncated, s_trunc) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH);
-    let ellipsis = if truncated { "[...]" } else { "" };
+    let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH);
+    let s_trunc = &s[..trunc_len];
+    let ellipsis = if trunc_len < s.len() { "[...]" } else { "" };
 
     // 1. out of bounds
     if begin > s.len() || end > s.len() {
@@ -105,10 +104,7 @@ fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
     // 3. character boundary
     let index = if !s.is_char_boundary(begin) { begin } else { end };
     // find the character
-    let mut char_start = index;
-    while !s.is_char_boundary(char_start) {
-        char_start -= 1;
-    }
+    let char_start = s.floor_char_boundary(index);
     // `char_start` must be less than len and a char boundary
     let ch = s[char_start..].chars().next().unwrap();
     let char_range = char_start..char_start + ch.len_utf8();
@@ -215,8 +211,80 @@ pub fn is_char_boundary(&self, index: usize) -> bool {
             // code on higher opt-levels. See PR #84751 for more details.
             None => index == self.len(),
 
-            // This is bit magic equivalent to: b < 128 || b >= 192
-            Some(&b) => (b as i8) >= -0x40,
+            Some(&b) => b.is_utf8_char_boundary(),
+        }
+    }
+
+    /// Finds the closest `x` not exceeding `index` where `is_char_boundary(x)` is `true`.
+    ///
+    /// This method can help you truncate a string so that it's still valid UTF-8, but doesn't
+    /// exceed a given number of bytes. Note that this is done purely at the character level
+    /// and can still visually split graphemes, even though the underlying characters aren't
+    /// split. For example, the emoji 🧑‍🔬 (scientist) could be split so that the string only
+    /// includes 🧑 (person) instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(round_char_boundary)]
+    /// let s = "❤️🧡💛💚💙💜";
+    /// assert_eq!(s.len(), 26);
+    /// assert!(!s.is_char_boundary(13));
+    ///
+    /// let closest = s.floor_char_boundary(13);
+    /// assert_eq!(closest, 10);
+    /// assert_eq!(&s[..closest], "❤️🧡");
+    /// ```
+    #[unstable(feature = "round_char_boundary", issue = "93743")]
+    #[inline]
+    pub fn floor_char_boundary(&self, index: usize) -> usize {
+        if index >= self.len() {
+            self.len()
+        } else {
+            let lower_bound = index.saturating_sub(3);
+            let new_index = self.as_bytes()[lower_bound..=index]
+                .iter()
+                .rposition(|b| b.is_utf8_char_boundary());
+
+            // SAFETY: we know that the character boundary will be within four bytes
+            unsafe { lower_bound + new_index.unwrap_unchecked() }
+        }
+    }
+
+    /// Finds the closest `x` not below `index` where `is_char_boundary(x)` is `true`.
+    ///
+    /// This method is the natural complement to [`floor_char_boundary`]. See that method
+    /// for more details.
+    ///
+    /// [`floor_char_boundary`]: str::floor_char_boundary
+    ///
+    /// # Panics
+    ///
+    /// Panics if `index > self.len()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(round_char_boundary)]
+    /// let s = "❤️🧡💛💚💙💜";
+    /// assert_eq!(s.len(), 26);
+    /// assert!(!s.is_char_boundary(13));
+    ///
+    /// let closest = s.ceil_char_boundary(13);
+    /// assert_eq!(closest, 14);
+    /// assert_eq!(&s[..closest], "❤️🧡💛");
+    /// ```
+    #[unstable(feature = "round_char_boundary", issue = "93743")]
+    #[inline]
+    pub fn ceil_char_boundary(&self, index: usize) -> usize {
+        if index > self.len() {
+            slice_error_fail(self, index, index)
+        } else {
+            let upper_bound = Ord::min(index + 4, self.len());
+            self.as_bytes()[index..upper_bound]
+                .iter()
+                .position(|b| b.is_utf8_char_boundary())
+                .map_or(upper_bound, |pos| pos + index)
         }
     }
 
index b2ea86d699aa6bf6f88c4dce209189e830ae241e..0d3dc856be577c44669176a29cb182c6cdc95316 100644 (file)
@@ -273,16 +273,3 @@ pub const fn utf8_char_width(b: u8) -> usize {
 
 /// Mask of the value bits of a continuation byte.
 const CONT_MASK: u8 = 0b0011_1111;
-
-// truncate `&str` to length at most equal to `max`
-// return `true` if it were truncated, and the new str.
-pub(super) fn truncate_to_char_boundary(s: &str, mut max: usize) -> (bool, &str) {
-    if max >= s.len() {
-        (false, s)
-    } else {
-        while !s.is_char_boundary(max) {
-            max -= 1;
-        }
-        (true, &s[..max])
-    }
-}
index 66fee2fe548374dbd02eaaf7d62fd5f5a7f34282..c3f024026efad027534fa69de42ec34e28b16ee9 100644 (file)
@@ -1077,7 +1077,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl From<NulError> for io::Error {
     /// Converts a [`NulError`] into a [`io::Error`].
     fn from(_: NulError) -> io::Error {
-        io::Error::new_const(io::ErrorKind::InvalidInput, &"data provided contains a nul byte")
+        io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
     }
 }
 
@@ -1252,15 +1252,16 @@ pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
     /// assert!(cstr.is_err());
     /// ```
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-    pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
+    pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
         let nul_pos = memchr::memchr(0, bytes);
-        if let Some(nul_pos) = nul_pos {
-            if nul_pos + 1 != bytes.len() {
-                return Err(FromBytesWithNulError::interior_nul(nul_pos));
+        match nul_pos {
+            Some(nul_pos) if nul_pos + 1 == bytes.len() => {
+                // SAFETY: We know there is only one nul byte, at the end
+                // of the byte slice.
+                Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
             }
-            Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) })
-        } else {
-            Err(FromBytesWithNulError::not_nul_terminated())
+            Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
+            None => Err(FromBytesWithNulError::not_nul_terminated()),
         }
     }
 
index 7ca64c38e5d3a211e3ea1192cf7bf6dea7a1ac84..95e9064442634b53b510ee545b69b5df11e89850 100644 (file)
@@ -2263,9 +2263,9 @@ fn create_dir_all(&self, path: &Path) -> io::Result<()> {
         match path.parent() {
             Some(p) => self.create_dir_all(p)?,
             None => {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::Uncategorized,
-                    &"failed to create whole tree",
+                    "failed to create whole tree",
                 ));
             }
         }
index b56dc65f0b2f30f7e711b21c018ffd9992f92f4a..e7eee4436249b5073e76038d84c1f7be60ba27b9 100644 (file)
@@ -357,9 +357,9 @@ fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
             let mut bytes = Vec::new();
             self.read_to_end(&mut bytes)?;
             let string = crate::str::from_utf8(&bytes).map_err(|_| {
-                io::Error::new_const(
+                io::const_io_error!(
                     io::ErrorKind::InvalidData,
-                    &"stream did not contain valid UTF-8",
+                    "stream did not contain valid UTF-8",
                 )
             })?;
             *buf += string;
index c7423e4d92a896c359743285a3e76f2d47ab3ed6..2d3a0f37b4c2a56cf1bf56784e0252a1823cb9bf 100644 (file)
@@ -1,7 +1,7 @@
 use crate::error;
 use crate::fmt;
 use crate::io::{
-    self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
+    self, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
 };
 use crate::mem;
 use crate::ptr;
@@ -168,9 +168,9 @@ fn drop(&mut self) {
 
             match r {
                 Ok(0) => {
-                    return Err(Error::new_const(
+                    return Err(io::const_io_error!(
                         ErrorKind::WriteZero,
-                        &"failed to write the buffered data",
+                        "failed to write the buffered data",
                     ));
                 }
                 Ok(n) => guard.consume(n),
index 416cc906e65a56d0162dd13a639cb010675f8235..fc19704becee2e53d01c5d28ff742412a126a39a 100644 (file)
@@ -4,7 +4,7 @@
 use crate::io::prelude::*;
 
 use crate::cmp;
-use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
+use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
 
 use core::convert::TryInto;
 
@@ -297,9 +297,9 @@ fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
                 self.pos = n;
                 Ok(self.pos)
             }
-            None => Err(Error::new_const(
+            None => Err(io::const_io_error!(
                 ErrorKind::InvalidInput,
-                &"invalid seek to a negative or overflowing position",
+                "invalid seek to a negative or overflowing position",
             )),
         }
     }
@@ -400,9 +400,9 @@ fn slice_write_vectored(
 // Resizing write implementation
 fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
     let pos: usize = (*pos_mut).try_into().map_err(|_| {
-        Error::new_const(
+        io::const_io_error!(
             ErrorKind::InvalidInput,
-            &"cursor position exceeds maximum possible vector length",
+            "cursor position exceeds maximum possible vector length",
         )
     })?;
     // Make sure the internal buffer is as least as big as where we
index 074d693b83155dcfddf0808d7751b17b0ac3c31d..4b55324a2424cf45d424e44154b291db5ed3bd20 100644 (file)
@@ -1,6 +1,16 @@
 #[cfg(test)]
 mod tests;
 
+#[cfg(target_pointer_width = "64")]
+mod repr_bitpacked;
+#[cfg(target_pointer_width = "64")]
+use repr_bitpacked::Repr;
+
+#[cfg(not(target_pointer_width = "64"))]
+mod repr_unpacked;
+#[cfg(not(target_pointer_width = "64"))]
+use repr_unpacked::Repr;
+
 use crate::convert::From;
 use crate::error;
 use crate::fmt;
@@ -66,15 +76,58 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-enum Repr {
+// Only derive debug in tests, to make sure it
+// doesn't accidentally get printed.
+#[cfg_attr(test, derive(Debug))]
+enum ErrorData<C> {
     Os(i32),
     Simple(ErrorKind),
-    // &str is a fat pointer, but &&str is a thin pointer.
-    SimpleMessage(ErrorKind, &'static &'static str),
-    Custom(Box<Custom>),
+    SimpleMessage(&'static SimpleMessage),
+    Custom(C),
 }
 
+// `#[repr(align(4))]` is probably redundant, it should have that value or
+// higher already. We include it just because repr_bitpacked.rs's encoding
+// requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the
+// alignment required by the struct, only increase it).
+//
+// If we add more variants to ErrorData, this can be increased to 8, but it
+// should probably be behind `#[cfg_attr(target_pointer_width = "64", ...)]` or
+// whatever cfg we're using to enable the `repr_bitpacked` code, since only the
+// that version needs the alignment, and 8 is higher than the alignment we'll
+// have on 32 bit platforms.
+//
+// (For the sake of being explicit: the alignment requirement here only matters
+// if `error/repr_bitpacked.rs` is in use — for the unpacked repr it doesn't
+// matter at all)
+#[repr(align(4))]
 #[derive(Debug)]
+pub(crate) struct SimpleMessage {
+    kind: ErrorKind,
+    message: &'static str,
+}
+
+impl SimpleMessage {
+    pub(crate) const fn new(kind: ErrorKind, message: &'static str) -> Self {
+        Self { kind, message }
+    }
+}
+
+/// Create and return an `io::Error` for a given `ErrorKind` and constant
+/// message. This doesn't allocate.
+pub(crate) macro const_io_error($kind:expr, $message:expr $(,)?) {
+    $crate::io::error::Error::from_static_message({
+        const MESSAGE_DATA: $crate::io::error::SimpleMessage =
+            $crate::io::error::SimpleMessage::new($kind, $message);
+        &MESSAGE_DATA
+    })
+}
+
+// As with `SimpleMessage`: `#[repr(align(4))]` here is just because
+// repr_bitpacked's encoding requires it. In practice it almost certainly be
+// already be this high or higher.
+#[derive(Debug)]
+#[repr(align(4))]
 struct Custom {
     kind: ErrorKind,
     error: Box<dyn error::Error + Send + Sync>,
@@ -396,7 +449,7 @@ impl From<ErrorKind> for Error {
     /// ```
     #[inline]
     fn from(kind: ErrorKind) -> Error {
-        Error { repr: Repr::Simple(kind) }
+        Error { repr: Repr::new_simple(kind) }
     }
 }
 
@@ -461,20 +514,22 @@ pub fn other<E>(error: E) -> Error
     }
 
     fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
-        Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
+        Error { repr: Repr::new_custom(Box::new(Custom { kind, error })) }
     }
 
-    /// Creates a new I/O error from a known kind of error as well as a
-    /// constant message.
+    /// Creates a new I/O error from a known kind of error as well as a constant
+    /// message.
     ///
     /// This function does not allocate.
     ///
-    /// This function should maybe change to
-    /// `new_const<const MSG: &'static str>(kind: ErrorKind)`
-    /// in the future, when const generics allow that.
+    /// You should not use this directly, and instead use the `const_io_error!`
+    /// macro: `io::const_io_error!(ErrorKind::Something, "some_message")`.
+    ///
+    /// This function should maybe change to `from_static_message<const MSG: &'static
+    /// str>(kind: ErrorKind)` in the future, when const generics allow that.
     #[inline]
-    pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error {
-        Self { repr: Repr::SimpleMessage(kind, message) }
+    pub(crate) const fn from_static_message(msg: &'static SimpleMessage) -> Error {
+        Self { repr: Repr::new_simple_message(msg) }
     }
 
     /// Returns an error representing the last OS error which occurred.
@@ -532,7 +587,7 @@ pub fn last_os_error() -> Error {
     #[must_use]
     #[inline]
     pub fn from_raw_os_error(code: i32) -> Error {
-        Error { repr: Repr::Os(code) }
+        Error { repr: Repr::new_os(code) }
     }
 
     /// Returns the OS error that this error represents (if any).
@@ -568,11 +623,11 @@ pub fn from_raw_os_error(code: i32) -> Error {
     #[must_use]
     #[inline]
     pub fn raw_os_error(&self) -> Option<i32> {
-        match self.repr {
-            Repr::Os(i) => Some(i),
-            Repr::Custom(..) => None,
-            Repr::Simple(..) => None,
-            Repr::SimpleMessage(..) => None,
+        match self.repr.data() {
+            ErrorData::Os(i) => Some(i),
+            ErrorData::Custom(..) => None,
+            ErrorData::Simple(..) => None,
+            ErrorData::SimpleMessage(..) => None,
         }
     }
 
@@ -607,11 +662,11 @@ pub fn raw_os_error(&self) -> Option<i32> {
     #[must_use]
     #[inline]
     pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
-        match self.repr {
-            Repr::Os(..) => None,
-            Repr::Simple(..) => None,
-            Repr::SimpleMessage(..) => None,
-            Repr::Custom(ref c) => Some(&*c.error),
+        match self.repr.data() {
+            ErrorData::Os(..) => None,
+            ErrorData::Simple(..) => None,
+            ErrorData::SimpleMessage(..) => None,
+            ErrorData::Custom(c) => Some(&*c.error),
         }
     }
 
@@ -681,11 +736,11 @@ pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
     #[must_use]
     #[inline]
     pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
-        match self.repr {
-            Repr::Os(..) => None,
-            Repr::Simple(..) => None,
-            Repr::SimpleMessage(..) => None,
-            Repr::Custom(ref mut c) => Some(&mut *c.error),
+        match self.repr.data_mut() {
+            ErrorData::Os(..) => None,
+            ErrorData::Simple(..) => None,
+            ErrorData::SimpleMessage(..) => None,
+            ErrorData::Custom(c) => Some(&mut *c.error),
         }
     }
 
@@ -720,11 +775,11 @@ pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'stat
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
-        match self.repr {
-            Repr::Os(..) => None,
-            Repr::Simple(..) => None,
-            Repr::SimpleMessage(..) => None,
-            Repr::Custom(c) => Some(c.error),
+        match self.repr.into_data() {
+            ErrorData::Os(..) => None,
+            ErrorData::Simple(..) => None,
+            ErrorData::SimpleMessage(..) => None,
+            ErrorData::Custom(c) => Some(c.error),
         }
     }
 
@@ -750,29 +805,31 @@ pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
     #[must_use]
     #[inline]
     pub fn kind(&self) -> ErrorKind {
-        match self.repr {
-            Repr::Os(code) => sys::decode_error_kind(code),
-            Repr::Custom(ref c) => c.kind,
-            Repr::Simple(kind) => kind,
-            Repr::SimpleMessage(kind, _) => kind,
+        match self.repr.data() {
+            ErrorData::Os(code) => sys::decode_error_kind(code),
+            ErrorData::Custom(c) => c.kind,
+            ErrorData::Simple(kind) => kind,
+            ErrorData::SimpleMessage(m) => m.kind,
         }
     }
 }
 
 impl fmt::Debug for Repr {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Repr::Os(code) => fmt
+        match self.data() {
+            ErrorData::Os(code) => fmt
                 .debug_struct("Os")
                 .field("code", &code)
                 .field("kind", &sys::decode_error_kind(code))
                 .field("message", &sys::os::error_string(code))
                 .finish(),
-            Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
-            Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
-            Repr::SimpleMessage(kind, &message) => {
-                fmt.debug_struct("Error").field("kind", &kind).field("message", &message).finish()
-            }
+            ErrorData::Custom(c) => fmt::Debug::fmt(&c, fmt),
+            ErrorData::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
+            ErrorData::SimpleMessage(msg) => fmt
+                .debug_struct("Error")
+                .field("kind", &msg.kind)
+                .field("message", &msg.message)
+                .finish(),
         }
     }
 }
@@ -780,14 +837,14 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Error {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.repr {
-            Repr::Os(code) => {
+        match self.repr.data() {
+            ErrorData::Os(code) => {
                 let detail = sys::os::error_string(code);
                 write!(fmt, "{} (os error {})", detail, code)
             }
-            Repr::Custom(ref c) => c.error.fmt(fmt),
-            Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
-            Repr::SimpleMessage(_, &msg) => msg.fmt(fmt),
+            ErrorData::Custom(ref c) => c.error.fmt(fmt),
+            ErrorData::Simple(kind) => write!(fmt, "{}", kind.as_str()),
+            ErrorData::SimpleMessage(msg) => msg.message.fmt(fmt),
         }
     }
 }
@@ -796,29 +853,29 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl error::Error for Error {
     #[allow(deprecated, deprecated_in_future)]
     fn description(&self) -> &str {
-        match self.repr {
-            Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
-            Repr::SimpleMessage(_, &msg) => msg,
-            Repr::Custom(ref c) => c.error.description(),
+        match self.repr.data() {
+            ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(),
+            ErrorData::SimpleMessage(msg) => msg.message,
+            ErrorData::Custom(c) => c.error.description(),
         }
     }
 
     #[allow(deprecated)]
     fn cause(&self) -> Option<&dyn error::Error> {
-        match self.repr {
-            Repr::Os(..) => None,
-            Repr::Simple(..) => None,
-            Repr::SimpleMessage(..) => None,
-            Repr::Custom(ref c) => c.error.cause(),
+        match self.repr.data() {
+            ErrorData::Os(..) => None,
+            ErrorData::Simple(..) => None,
+            ErrorData::SimpleMessage(..) => None,
+            ErrorData::Custom(c) => c.error.cause(),
         }
     }
 
     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
-        match self.repr {
-            Repr::Os(..) => None,
-            Repr::Simple(..) => None,
-            Repr::SimpleMessage(..) => None,
-            Repr::Custom(ref c) => c.error.source(),
+        match self.repr.data() {
+            ErrorData::Os(..) => None,
+            ErrorData::Simple(..) => None,
+            ErrorData::SimpleMessage(..) => None,
+            ErrorData::Custom(c) => c.error.source(),
         }
     }
 }
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
new file mode 100644 (file)
index 0000000..f317368
--- /dev/null
@@ -0,0 +1,391 @@
+//! This is a densely packed error representation which is used on targets with
+//! 64-bit pointers.
+//!
+//! (Note that `bitpacked` vs `unpacked` here has no relationship to
+//! `#[repr(packed)]`, it just refers to attempting to use any available bits in
+//! a more clever manner than `rustc`'s default layout algorithm would).
+//!
+//! Conceptually, it stores the same data as the "unpacked" equivalent we use on
+//! other targets. Specifically, you can imagine it as an optimized version of
+//! the following enum (which is roughly equivalent to what's stored by
+//! `repr_unpacked::Repr`, e.g. `super::ErrorData<Box<Custom>>`):
+//!
+//! ```ignore (exposition-only)
+//! enum ErrorData {
+//!    Os(i32),
+//!    Simple(ErrorKind),
+//!    SimpleMessage(&'static SimpleMessage),
+//!    Custom(Box<Custom>),
+//! }
+//! ```
+//!
+//! However, it packs this data into a 64bit non-zero value.
+//!
+//! This optimization not only allows `io::Error` to occupy a single pointer,
+//! but improves `io::Result` as well, especially for situations like
+//! `io::Result<()>` (which is now 64 bits) or `io::Result<u64>` (which is now
+//! 128 bits), which are quite common.
+//!
+//! # Layout
+//! Tagged values are 64 bits, with the 2 least significant bits used for the
+//! tag. This means there are there are 4 "variants":
+//!
+//! - **Tag 0b00**: The first variant is equivalent to
+//!   `ErrorData::SimpleMessage`, and holds a `&'static SimpleMessage` directly.
+//!
+//!   `SimpleMessage` has an alignment >= 4 (which is requested with
+//!   `#[repr(align)]` and checked statically at the bottom of this file), which
+//!   means every `&'static SimpleMessage` should have the both tag bits as 0,
+//!   meaning its tagged and untagged representation are equivalent.
+//!
+//!   This means we can skip tagging it, which is necessary as this variant can
+//!   be constructed from a `const fn`, which probably cannot tag pointers (or
+//!   at least it would be difficult).
+//!
+//! - **Tag 0b01**: The other pointer variant holds the data for
+//!   `ErrorData::Custom` and the remaining 62 bits are used to store a
+//!   `Box<Custom>`. `Custom` also has alignment >= 4, so the bottom two bits
+//!   are free to use for the tag.
+//!
+//!   The only important thing to note is that `ptr::wrapping_add` and
+//!   `ptr::wrapping_sub` are used to tag the pointer, rather than bitwise
+//!   operations. This should preserve the pointer's provenance, which would
+//!   otherwise be lost.
+//!
+//! - **Tag 0b10**: Holds the data for `ErrorData::Os(i32)`. We store the `i32`
+//!   in the pointer's most significant 32 bits, and don't use the bits `2..32`
+//!   for anything. Using the top 32 bits is just to let us easily recover the
+//!   `i32` code with the correct sign.
+//!
+//! - **Tag 0b11**: Holds the data for `ErrorData::Simple(ErrorKind)`. This
+//!   stores the `ErrorKind` in the top 32 bits as well, although it doesn't
+//!   occupy nearly that many. Most of the bits are unused here, but it's not
+//!   like we need them for anything else yet.
+//!
+//! # Use of `NonNull<()>`
+//!
+//! Everything is stored in a `NonNull<()>`, which is odd, but actually serves a
+//! purpose.
+//!
+//! Conceptually you might think of this more like:
+//!
+//! ```ignore (exposition-only)
+//! union Repr {
+//!     // holds integer (Simple/Os) variants, and
+//!     // provides access to the tag bits.
+//!     bits: NonZeroU64,
+//!     // Tag is 0, so this is stored untagged.
+//!     msg: &'static SimpleMessage,
+//!     // Tagged (offset) `Box<Custom>` pointer.
+//!     tagged_custom: NonNull<()>,
+//! }
+//! ```
+//!
+//! But there are a few problems with this:
+//!
+//! 1. Union access is equivalent to a transmute, so this representation would
+//!    require we transmute between integers and pointers in at least one
+//!    direction, which may be UB (and even if not, it is likely harder for a
+//!    compiler to reason about than explicit ptr->int operations).
+//!
+//! 2. Even if all fields of a union have a niche, the union itself doesn't,
+//!    although this may change in the future. This would make things like
+//!    `io::Result<()>` and `io::Result<usize>` larger, which defeats part of
+//!    the motivation of this bitpacking.
+//!
+//! Storing everything in a `NonZeroUsize` (or some other integer) would be a
+//! bit more traditional for pointer tagging, but it would lose provenance
+//! information, couldn't be constructed from a `const fn`, and would probably
+//! run into other issues as well.
+//!
+//! The `NonNull<()>` seems like the only alternative, even if it's fairly odd
+//! to use a pointer type to store something that may hold an integer, some of
+//! the time.
+
+use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
+use alloc::boxed::Box;
+use core::mem::{align_of, size_of};
+use core::ptr::NonNull;
+
+// The 2 least-significant bits are used as tag.
+const TAG_MASK: usize = 0b11;
+const TAG_SIMPLE_MESSAGE: usize = 0b00;
+const TAG_CUSTOM: usize = 0b01;
+const TAG_OS: usize = 0b10;
+const TAG_SIMPLE: usize = 0b11;
+
+#[repr(transparent)]
+pub(super) struct Repr(NonNull<()>);
+
+// All the types `Repr` stores internally are Send + Sync, and so is it.
+unsafe impl Send for Repr {}
+unsafe impl Sync for Repr {}
+
+impl Repr {
+    pub(super) fn new_custom(b: Box<Custom>) -> Self {
+        let p = Box::into_raw(b).cast::<u8>();
+        // Should only be possible if an allocator handed out a pointer with
+        // wrong alignment.
+        debug_assert_eq!((p as usize & TAG_MASK), 0);
+        // Note: We know `TAG_CUSTOM <= size_of::<Custom>()` (static_assert at
+        // end of file), and both the start and end of the expression must be
+        // valid without address space wraparound due to `Box`'s semantics.
+        //
+        // This means it would be correct to implement this using `ptr::add`
+        // (rather than `ptr::wrapping_add`), but it's unclear this would give
+        // any benefit, so we just use `wrapping_add` instead.
+        let tagged = p.wrapping_add(TAG_CUSTOM).cast::<()>();
+        // Safety: `TAG_CUSTOM + p` is the same as `TAG_CUSTOM | p`,
+        // because `p`'s alignment means it isn't allowed to have any of the
+        // `TAG_BITS` set (you can verify that addition and bitwise-or are the
+        // same when the operands have no bits in common using a truth table).
+        //
+        // Then, `TAG_CUSTOM | p` is not zero, as that would require
+        // `TAG_CUSTOM` and `p` both be zero, and neither is (as `p` came from a
+        // box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore,
+        // `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the
+        // `new_unchecked` is safe.
+        let res = Self(unsafe { NonNull::new_unchecked(tagged) });
+        // quickly smoke-check we encoded the right thing (This generally will
+        // only run in libstd's tests, unless the user uses -Zbuild-std)
+        debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed");
+        res
+    }
+
+    #[inline]
+    pub(super) fn new_os(code: i32) -> Self {
+        let utagged = ((code as usize) << 32) | TAG_OS;
+        // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
+        let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
+        // quickly smoke-check we encoded the right thing (This generally will
+        // only run in libstd's tests, unless the user uses -Zbuild-std)
+        debug_assert!(
+            matches!(res.data(), ErrorData::Os(c) if c == code),
+            "repr(os) encoding failed for {}",
+            code,
+        );
+        res
+    }
+
+    #[inline]
+    pub(super) fn new_simple(kind: ErrorKind) -> Self {
+        let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
+        // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
+        let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
+        // quickly smoke-check we encoded the right thing (This generally will
+        // only run in libstd's tests, unless the user uses -Zbuild-std)
+        debug_assert!(
+            matches!(res.data(), ErrorData::Simple(k) if k == kind),
+            "repr(simple) encoding failed {:?}",
+            kind,
+        );
+        res
+    }
+
+    #[inline]
+    pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self {
+        // Safety: References are never null.
+        Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) })
+    }
+
+    #[inline]
+    pub(super) fn data(&self) -> ErrorData<&Custom> {
+        // Safety: We're a Repr, decode_repr is fine.
+        unsafe { decode_repr(self.0, |c| &*c) }
+    }
+
+    #[inline]
+    pub(super) fn data_mut(&mut self) -> ErrorData<&mut Custom> {
+        // Safety: We're a Repr, decode_repr is fine.
+        unsafe { decode_repr(self.0, |c| &mut *c) }
+    }
+
+    #[inline]
+    pub(super) fn into_data(self) -> ErrorData<Box<Custom>> {
+        let this = core::mem::ManuallyDrop::new(self);
+        // Safety: We're a Repr, decode_repr is fine. The `Box::from_raw` is
+        // safe because we prevent double-drop using `ManuallyDrop`.
+        unsafe { decode_repr(this.0, |p| Box::from_raw(p)) }
+    }
+}
+
+impl Drop for Repr {
+    #[inline]
+    fn drop(&mut self) {
+        // Safety: We're a Repr, decode_repr is fine. The `Box::from_raw` is
+        // safe because we're being dropped.
+        unsafe {
+            let _ = decode_repr(self.0, |p| Box::<Custom>::from_raw(p));
+        }
+    }
+}
+
+// Shared helper to decode a `Repr`'s internal pointer into an ErrorData.
+//
+// Safety: `ptr`'s bits should be encoded as described in the document at the
+// top (it should `some_repr.0`)
+#[inline]
+unsafe fn decode_repr<C, F>(ptr: NonNull<()>, make_custom: F) -> ErrorData<C>
+where
+    F: FnOnce(*mut Custom) -> C,
+{
+    let bits = ptr.as_ptr() as usize;
+    match bits & TAG_MASK {
+        TAG_OS => {
+            let code = ((bits as i64) >> 32) as i32;
+            ErrorData::Os(code)
+        }
+        TAG_SIMPLE => {
+            let kind_bits = (bits >> 32) as u32;
+            let kind = kind_from_prim(kind_bits).unwrap_or_else(|| {
+                debug_assert!(false, "Invalid io::error::Repr bits: `Repr({:#018x})`", bits);
+                // This means the `ptr` passed in was not valid, which violates
+                // the unsafe contract of `decode_repr`.
+                //
+                // Using this rather than unwrap meaningfully improves the code
+                // for callers which only care about one variant (usually
+                // `Custom`)
+                core::hint::unreachable_unchecked();
+            });
+            ErrorData::Simple(kind)
+        }
+        TAG_SIMPLE_MESSAGE => ErrorData::SimpleMessage(&*ptr.cast::<SimpleMessage>().as_ptr()),
+        TAG_CUSTOM => {
+            // It would be correct for us to use `ptr::sub` here (see the
+            // comment above the `wrapping_add` call in `new_custom` for why),
+            // but it isn't clear that it makes a difference, so we don't.
+            let custom = ptr.as_ptr().cast::<u8>().wrapping_sub(TAG_CUSTOM).cast::<Custom>();
+            ErrorData::Custom(make_custom(custom))
+        }
+        _ => {
+            // Can't happen, and compiler can tell
+            unreachable!();
+        }
+    }
+}
+
+// This compiles to the same code as the check+transmute, but doesn't require
+// unsafe, or to hard-code max ErrorKind or its size in a way the compiler
+// couldn't verify.
+#[inline]
+fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
+    macro_rules! from_prim {
+        ($prim:expr => $Enum:ident { $($Variant:ident),* $(,)? }) => {{
+            // Force a compile error if the list gets out of date.
+            const _: fn(e: $Enum) = |e: $Enum| match e {
+                $($Enum::$Variant => ()),*
+            };
+            match $prim {
+                $(v if v == ($Enum::$Variant as _) => Some($Enum::$Variant),)*
+                _ => None,
+            }
+        }}
+    }
+    from_prim!(ek => ErrorKind {
+        NotFound,
+        PermissionDenied,
+        ConnectionRefused,
+        ConnectionReset,
+        HostUnreachable,
+        NetworkUnreachable,
+        ConnectionAborted,
+        NotConnected,
+        AddrInUse,
+        AddrNotAvailable,
+        NetworkDown,
+        BrokenPipe,
+        AlreadyExists,
+        WouldBlock,
+        NotADirectory,
+        IsADirectory,
+        DirectoryNotEmpty,
+        ReadOnlyFilesystem,
+        FilesystemLoop,
+        StaleNetworkFileHandle,
+        InvalidInput,
+        InvalidData,
+        TimedOut,
+        WriteZero,
+        StorageFull,
+        NotSeekable,
+        FilesystemQuotaExceeded,
+        FileTooLarge,
+        ResourceBusy,
+        ExecutableFileBusy,
+        Deadlock,
+        CrossesDevices,
+        TooManyLinks,
+        FilenameTooLong,
+        ArgumentListTooLong,
+        Interrupted,
+        Other,
+        UnexpectedEof,
+        Unsupported,
+        OutOfMemory,
+        Uncategorized,
+    })
+}
+
+// Some static checking to alert us if a change breaks any of the assumptions
+// that our encoding relies on for correctness and soundness. (Some of these are
+// a bit overly thorough/cautious, admittedly)
+//
+// If any of these are hit on a platform that libstd supports, we should likely
+// just use `repr_unpacked.rs` there instead (unless the fix is easy).
+macro_rules! static_assert {
+    ($condition:expr) => {
+        const _: () = assert!($condition);
+    };
+    (@usize_eq: $lhs:expr, $rhs:expr) => {
+        const _: [(); $lhs] = [(); $rhs];
+    };
+}
+
+// The bitpacking we use requires pointers be exactly 64 bits.
+static_assert!(@usize_eq: size_of::<NonNull<()>>(), 8);
+
+// We also require pointers and usize be the same size.
+static_assert!(@usize_eq: size_of::<NonNull<()>>(), size_of::<usize>());
+
+// `Custom` and `SimpleMessage` need to be thin pointers.
+static_assert!(@usize_eq: size_of::<&'static SimpleMessage>(), 8);
+static_assert!(@usize_eq: size_of::<Box<Custom>>(), 8);
+
+static_assert!((TAG_MASK + 1).is_power_of_two());
+// And they must have sufficient alignment.
+static_assert!(align_of::<SimpleMessage>() >= TAG_MASK + 1);
+static_assert!(align_of::<Custom>() >= TAG_MASK + 1);
+
+static_assert!(@usize_eq: (TAG_MASK & TAG_SIMPLE_MESSAGE), TAG_SIMPLE_MESSAGE);
+static_assert!(@usize_eq: (TAG_MASK & TAG_CUSTOM), TAG_CUSTOM);
+static_assert!(@usize_eq: (TAG_MASK & TAG_OS), TAG_OS);
+static_assert!(@usize_eq: (TAG_MASK & TAG_SIMPLE), TAG_SIMPLE);
+
+// This is obviously true (`TAG_CUSTOM` is `0b01`), but in `Repr::new_custom` we
+// offset a pointer by this value, and expect it to both be within the same
+// object, and to not wrap around the address space. See the comment in that
+// function for further details.
+//
+// Actually, at the moment we use `ptr::wrapping_add`, not `ptr::add`, so this
+// check isn't needed for that one, although the assertion that we don't
+// actually wrap around in that wrapping_add does simplify the safety reasoning
+// elsewhere considerably.
+static_assert!(size_of::<Custom>() >= TAG_CUSTOM);
+
+// These two store a payload which is allowed to be zero, so they must be
+// non-zero to preserve the `NonNull`'s range invariant.
+static_assert!(TAG_OS != 0);
+static_assert!(TAG_SIMPLE != 0);
+// We can't tag `SimpleMessage`s, the tag must be 0.
+static_assert!(@usize_eq: TAG_SIMPLE_MESSAGE, 0);
+
+// Check that the point of all of this still holds.
+//
+// We'd check against `io::Error`, but *technically* it's allowed to vary,
+// as it's not `#[repr(transparent)]`/`#[repr(C)]`. We could add that, but
+// the `#[repr()]` would show up in rustdoc, which might be seen as a stable
+// commitment.
+static_assert!(@usize_eq: size_of::<Repr>(), 8);
+static_assert!(@usize_eq: size_of::<Option<Repr>>(), 8);
+static_assert!(@usize_eq: size_of::<Result<(), Repr>>(), 8);
+static_assert!(@usize_eq: size_of::<Result<usize, Repr>>(), 16);
diff --git a/library/std/src/io/error/repr_unpacked.rs b/library/std/src/io/error/repr_unpacked.rs
new file mode 100644 (file)
index 0000000..3729c03
--- /dev/null
@@ -0,0 +1,50 @@
+//! This is a fairly simple unpacked error representation that's used on
+//! non-64bit targets, where the packed 64 bit representation wouldn't work, and
+//! would have no benefit.
+
+use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
+use alloc::boxed::Box;
+
+type Inner = ErrorData<Box<Custom>>;
+
+pub(super) struct Repr(Inner);
+
+impl Repr {
+    pub(super) fn new_custom(b: Box<Custom>) -> Self {
+        Self(Inner::Custom(b))
+    }
+    #[inline]
+    pub(super) fn new_os(code: i32) -> Self {
+        Self(Inner::Os(code))
+    }
+    #[inline]
+    pub(super) fn new_simple(kind: ErrorKind) -> Self {
+        Self(Inner::Simple(kind))
+    }
+    #[inline]
+    pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self {
+        Self(Inner::SimpleMessage(m))
+    }
+    #[inline]
+    pub(super) fn into_data(self) -> ErrorData<Box<Custom>> {
+        self.0
+    }
+    #[inline]
+    pub(super) fn data(&self) -> ErrorData<&Custom> {
+        match &self.0 {
+            Inner::Os(c) => ErrorData::Os(*c),
+            Inner::Simple(k) => ErrorData::Simple(*k),
+            Inner::SimpleMessage(m) => ErrorData::SimpleMessage(*m),
+            Inner::Custom(m) => ErrorData::Custom(&*m),
+        }
+    }
+    #[inline]
+    pub(super) fn data_mut(&mut self) -> ErrorData<&mut Custom> {
+        match &mut self.0 {
+            Inner::Os(c) => ErrorData::Os(*c),
+            Inner::Simple(k) => ErrorData::Simple(*k),
+            Inner::SimpleMessage(m) => ErrorData::SimpleMessage(*m),
+            Inner::Custom(m) => ErrorData::Custom(&mut *m),
+        }
+    }
+}
index 5098a46313de39c22385f5b08cde895f5fe6ecae..c2c51553b208c25253eff217e4891d2f9b2f5dce 100644 (file)
@@ -1,4 +1,5 @@
-use super::{Custom, Error, ErrorKind, Repr};
+use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr};
+use crate::assert_matches::assert_matches;
 use crate::error;
 use crate::fmt;
 use crate::mem::size_of;
@@ -16,9 +17,9 @@ fn test_debug_error() {
     let msg = error_string(code);
     let kind = decode_error_kind(code);
     let err = Error {
-        repr: Repr::Custom(box Custom {
+        repr: Repr::new_custom(box Custom {
             kind: ErrorKind::InvalidInput,
-            error: box Error { repr: super::Repr::Os(code) },
+            error: box Error { repr: super::Repr::new_os(code) },
         }),
     };
     let expected = format!(
@@ -60,10 +61,83 @@ impl error::Error for TestError {}
 
 #[test]
 fn test_const() {
-    const E: Error = Error::new_const(ErrorKind::NotFound, &"hello");
+    const E: Error = const_io_error!(ErrorKind::NotFound, "hello");
 
     assert_eq!(E.kind(), ErrorKind::NotFound);
     assert_eq!(E.to_string(), "hello");
     assert!(format!("{:?}", E).contains("\"hello\""));
     assert!(format!("{:?}", E).contains("NotFound"));
 }
+
+#[test]
+fn test_os_packing() {
+    for code in -20i32..20i32 {
+        let e = Error::from_raw_os_error(code);
+        assert_eq!(e.raw_os_error(), Some(code));
+        assert_matches!(
+            e.repr.data(),
+            ErrorData::Os(c) if c == code,
+        );
+    }
+}
+
+#[test]
+fn test_errorkind_packing() {
+    assert_eq!(Error::from(ErrorKind::NotFound).kind(), ErrorKind::NotFound);
+    assert_eq!(Error::from(ErrorKind::PermissionDenied).kind(), ErrorKind::PermissionDenied);
+    assert_eq!(Error::from(ErrorKind::Uncategorized).kind(), ErrorKind::Uncategorized);
+    // Check that the innards look like like what we want.
+    assert_matches!(
+        Error::from(ErrorKind::OutOfMemory).repr.data(),
+        ErrorData::Simple(ErrorKind::OutOfMemory),
+    );
+}
+
+#[test]
+fn test_simple_message_packing() {
+    use super::{ErrorKind::*, SimpleMessage};
+    macro_rules! check_simple_msg {
+        ($err:expr, $kind:ident, $msg:literal) => {{
+            let e = &$err;
+            // Check that the public api is right.
+            assert_eq!(e.kind(), $kind);
+            assert!(format!("{:?}", e).contains($msg));
+            // and we got what we expected
+            assert_matches!(
+                e.repr.data(),
+                ErrorData::SimpleMessage(SimpleMessage { kind: $kind, message: $msg })
+            );
+        }};
+    }
+
+    let not_static = const_io_error!(Uncategorized, "not a constant!");
+    check_simple_msg!(not_static, Uncategorized, "not a constant!");
+
+    const CONST: Error = const_io_error!(NotFound, "definitely a constant!");
+    check_simple_msg!(CONST, NotFound, "definitely a constant!");
+
+    static STATIC: Error = const_io_error!(BrokenPipe, "a constant, sort of!");
+    check_simple_msg!(STATIC, BrokenPipe, "a constant, sort of!");
+}
+
+#[derive(Debug, PartialEq)]
+struct Bojji(bool);
+impl error::Error for Bojji {}
+impl fmt::Display for Bojji {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "ah! {:?}", self)
+    }
+}
+
+#[test]
+fn test_custom_error_packing() {
+    use super::Custom;
+    let test = Error::new(ErrorKind::Uncategorized, Bojji(true));
+    assert_matches!(
+        test.repr.data(),
+        ErrorData::Custom(Custom {
+            kind: ErrorKind::Uncategorized,
+            error,
+        }) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)),
+    );
+}
index 23201f9fc5c94deeaee0516f0fdc99bb5ea03e81..64d2457bce1596b28c2d619e3ca40b2fb142f93b 100644 (file)
@@ -5,7 +5,7 @@
 use crate::cmp;
 use crate::fmt;
 use crate::io::{
-    self, BufRead, Error, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write,
+    self, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write,
 };
 use crate::mem;
 
@@ -279,7 +279,10 @@ fn is_read_vectored(&self) -> bool {
     #[inline]
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
         if buf.len() > self.len() {
-            return Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer"));
+            return Err(io::const_io_error!(
+                ErrorKind::UnexpectedEof,
+                "failed to fill whole buffer"
+            ));
         }
         let (a, b) = self.split_at(buf.len());
 
@@ -361,7 +364,7 @@ fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
         if self.write(data)? == data.len() {
             Ok(())
         } else {
-            Err(Error::new_const(ErrorKind::WriteZero, &"failed to write whole buffer"))
+            Err(io::const_io_error!(ErrorKind::WriteZero, "failed to write whole buffer"))
         }
     }
 
index 824938ce38e68b430e5f45cd8ca53b62c2e35f27..71a59fb58032115e17e61ff233003068ad7887da 100644 (file)
 
 #[unstable(feature = "read_buf", issue = "78485")]
 pub use self::readbuf::ReadBuf;
+pub(crate) use error::const_io_error;
 
 mod buffered;
 pub(crate) mod copy;
@@ -337,7 +338,10 @@ pub(crate) unsafe fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize
     let ret = f(g.buf);
     if str::from_utf8(&g.buf[g.len..]).is_err() {
         ret.and_then(|_| {
-            Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8"))
+            Err(error::const_io_error!(
+                ErrorKind::InvalidData,
+                "stream did not contain valid UTF-8"
+            ))
         })
     } else {
         g.len = g.buf.len();
@@ -454,7 +458,7 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
         }
     }
     if !buf.is_empty() {
-        Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
+        Err(error::const_io_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
     } else {
         Ok(())
     }
@@ -1512,9 +1516,9 @@ fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
         while !buf.is_empty() {
             match self.write(buf) {
                 Ok(0) => {
-                    return Err(Error::new_const(
+                    return Err(error::const_io_error!(
                         ErrorKind::WriteZero,
-                        &"failed to write whole buffer",
+                        "failed to write whole buffer",
                     ));
                 }
                 Ok(n) => buf = &buf[n..],
@@ -1580,9 +1584,9 @@ fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> {
         while !bufs.is_empty() {
             match self.write_vectored(bufs) {
                 Ok(0) => {
-                    return Err(Error::new_const(
+                    return Err(error::const_io_error!(
                         ErrorKind::WriteZero,
-                        &"failed to write whole buffer",
+                        "failed to write whole buffer",
                     ));
                 }
                 Ok(n) => IoSlice::advance_slices(&mut bufs, n),
@@ -1657,7 +1661,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
                 if output.error.is_err() {
                     output.error
                 } else {
-                    Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error"))
+                    Err(error::const_io_error!(ErrorKind::Uncategorized, "formatter error"))
                 }
             }
         }
index ea49bfe3421d1beb6a83f64b211c947c67536887..eb62634856462aa874bc26ab64a9d3381df7a116 100644 (file)
@@ -185,12 +185,12 @@ fn take_eof() {
 
     impl Read for R {
         fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
-            Err(io::Error::new_const(io::ErrorKind::Other, &""))
+            Err(io::const_io_error!(io::ErrorKind::Other, ""))
         }
     }
     impl BufRead for R {
         fn fill_buf(&mut self) -> io::Result<&[u8]> {
-            Err(io::Error::new_const(io::ErrorKind::Other, &""))
+            Err(io::const_io_error!(io::ErrorKind::Other, ""))
         }
         fn consume(&mut self, _amt: usize) {}
     }
index 2669f4dbf3068b9603f58098dc7c07efedffccb1..f676e0a04f000883760a3a141da84018273b1b18 100644 (file)
@@ -17,7 +17,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::io::{self, Error, ErrorKind};
+use crate::io::{self, ErrorKind};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
@@ -90,6 +90,6 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
         }
     }
     Err(last_err.unwrap_or_else(|| {
-        Error::new_const(ErrorKind::InvalidInput, &"could not resolve to any addresses")
+        io::const_io_error!(ErrorKind::InvalidInput, "could not resolve to any addresses")
     }))
 }
index 6354752e64e766c97517bce6f845a994ad1e1228..11a696e92c82565725411e01b018e8d1bf61c5fd 100644 (file)
@@ -2,7 +2,7 @@
 mod tests;
 
 use crate::fmt;
-use crate::io::{self, Error, ErrorKind};
+use crate::io::{self, ErrorKind};
 use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
 use crate::sys_common::net as net_imp;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -175,7 +175,9 @@ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
     pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
         match addr.to_socket_addrs()?.next() {
             Some(addr) => self.0.send_to(buf, &addr),
-            None => Err(Error::new_const(ErrorKind::InvalidInput, &"no addresses to send data to")),
+            None => {
+                Err(io::const_io_error!(ErrorKind::InvalidInput, "no addresses to send data to"))
+            }
         }
     }
 
index 0b6588db92c83102b30fb5fe7a17de01c82a4acf..b53c3e79b0fe6e7a9046a434ef3623ec313baa31 100644 (file)
@@ -93,9 +93,9 @@ pub fn try_clone(&self) -> crate::io::Result<Self> {
 
     #[cfg(target_os = "wasi")]
     pub fn try_clone(&self) -> crate::io::Result<Self> {
-        Err(crate::io::Error::new_const(
+        Err(crate::io::const_io_error!(
             crate::io::ErrorKind::Unsupported,
-            &"operation not supported on WASI yet",
+            "operation not supported on WASI yet",
         ))
     }
 }
index 0284a428b5d749b8695257d575592cd4f8298672..db7edcd057432563b925d1118690ab7a5817b459 100644 (file)
@@ -114,7 +114,7 @@ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
             }
         }
         if !buf.is_empty() {
-            Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
+            Err(io::const_io_error!(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer",))
         } else {
             Ok(())
         }
@@ -196,9 +196,9 @@ fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
         while !buf.is_empty() {
             match self.write_at(buf, offset) {
                 Ok(0) => {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::WriteZero,
-                        &"failed to write whole buffer",
+                        "failed to write whole buffer",
                     ));
                 }
                 Ok(n) => {
index 9dbd4548bc92d02240e64b20a7bf24b9380ce0e5..034fa301ba1ead4c434edf14adb9a41886f22844 100644 (file)
@@ -30,16 +30,16 @@ pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::s
     let bytes = path.as_os_str().as_bytes();
 
     if bytes.contains(&0) {
-        return Err(io::Error::new_const(
+        return Err(io::const_io_error!(
             io::ErrorKind::InvalidInput,
-            &"paths must not contain interior null bytes",
+            "paths must not contain interior null bytes",
         ));
     }
 
     if bytes.len() >= addr.sun_path.len() {
-        return Err(io::Error::new_const(
+        return Err(io::const_io_error!(
             io::ErrorKind::InvalidInput,
-            &"path must be shorter than SUN_LEN",
+            "path must be shorter than SUN_LEN",
         ));
     }
     // SAFETY: `bytes` and `addr.sun_path` are not overlapping and
@@ -121,9 +121,9 @@ pub(super) fn from_parts(
             // linux returns zero bytes of address
             len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address
         } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
-                &"file descriptor did not correspond to a Unix socket",
+                "file descriptor did not correspond to a Unix socket",
             ));
         }
 
@@ -323,9 +323,9 @@ pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result<SocketAddr> {
             addr.sun_family = libc::AF_UNIX as libc::sa_family_t;
 
             if namespace.len() + 1 > addr.sun_path.len() {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidInput,
-                    &"namespace must be shorter than SUN_LEN",
+                    "namespace must be shorter than SUN_LEN",
                 ));
             }
 
index 37126069f942b218d0f1f8bef319d8bab01f7b34..160c8f1eca251a01fe4286ed7a23269226c8e6ae 100644 (file)
@@ -87,7 +87,7 @@ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
             }
         }
         if !buf.is_empty() {
-            Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
+            Err(io::const_io_error!(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
         } else {
             Ok(())
         }
@@ -153,9 +153,9 @@ fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
         while !buf.is_empty() {
             match self.write_at(buf, offset) {
                 Ok(0) => {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::WriteZero,
-                        &"failed to write whole buffer",
+                        "failed to write whole buffer",
                     ));
                 }
                 Ok(n) => {
@@ -258,9 +258,9 @@ fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()> {
             a if a == wasi::ADVICE_DONTNEED.raw() => wasi::ADVICE_DONTNEED,
             a if a == wasi::ADVICE_NOREUSE.raw() => wasi::ADVICE_NOREUSE,
             _ => {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidInput,
-                    &"invalid parameter 'advice'",
+                    "invalid parameter 'advice'",
                 ));
             }
         };
@@ -554,5 +554,5 @@ pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) ->
 
 fn osstr2str(f: &OsStr) -> io::Result<&str> {
     f.to_str()
-        .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8"))
+        .ok_or_else(|| io::const_io_error!(io::ErrorKind::Uncategorized, "input must be utf-8"))
 }
index 26b569bcdd3625f3f1c0ecaa75eb6c183113e6d3..d3a5b6dcc76c6847125ac630d2e04a036e928b21 100644 (file)
@@ -135,7 +135,7 @@ pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
 
     #[cfg(target_vendor = "uwp")]
     pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
-        Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Unavailable on UWP"))
+        Err(io::const_io_error!(io::ErrorKind::Unsupported, "Unavailable on UWP"))
     }
 }
 
index 974c44eb8dd5eda540d3eca293b17d4f2142f0a9..fa9a7fb19e4631fcab9c7d99de57a78857256559 100644 (file)
@@ -226,7 +226,7 @@ fn get_access_mode(&self) -> io::Result<i32> {
             (false, _, true) => Ok(O_WRONLY | O_APPEND),
             (true, _, true) => Ok(O_RDWR | O_APPEND),
             (false, false, false) => {
-                Err(io::Error::new_const(ErrorKind::InvalidInput, &"invalid access mode"))
+                Err(io::const_io_error!(ErrorKind::InvalidInput, "invalid access mode"))
             }
         }
     }
@@ -236,17 +236,17 @@ fn get_creation_mode(&self) -> io::Result<i32> {
             (true, false) => {}
             (false, false) => {
                 if self.truncate || self.create || self.create_new {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         ErrorKind::InvalidInput,
-                        &"invalid creation mode",
+                        "invalid creation mode",
                     ));
                 }
             }
             (_, true) => {
                 if self.truncate && !self.create_new {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         ErrorKind::InvalidInput,
-                        &"invalid creation mode",
+                        "invalid creation mode",
                     ));
                 }
             }
index 185b68c0a7803598107d1ac5acfdc5cd548d56d3..b798c97448b8f541aa68c19076e7736d0b6217ce 100644 (file)
@@ -58,9 +58,9 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
 }
 
 pub fn unsupported_err() -> crate::io::Error {
-    crate::io::Error::new_const(
+    crate::io::const_io_error!(
         crate::io::ErrorKind::Unsupported,
-        &"operation not supported on HermitCore yet",
+        "operation not supported on HermitCore yet",
     )
 }
 
index 1a6b3bc63e6def5868ab4015a8f021a3560cf40c..f65fd8e53bdc999a26998c5093124b0b2bba7ee6 100644 (file)
@@ -14,9 +14,9 @@
 /// if not, starts it.
 pub fn init() -> io::Result<()> {
     if abi::network_init() < 0 {
-        return Err(io::Error::new_const(
+        return Err(io::const_io_error!(
             ErrorKind::Uncategorized,
-            &"Unable to initialize network interface",
+            "Unable to initialize network interface",
         ));
     }
 
@@ -50,9 +50,9 @@ pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
 
         match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
             Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
-            _ => Err(io::Error::new_const(
+            _ => Err(io::const_io_error!(
                 ErrorKind::Uncategorized,
-                &"Unable to initiate a connection on a socket",
+                "Unable to initiate a connection on a socket",
             )),
         }
     }
@@ -64,9 +64,9 @@ pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result<Tcp
             Some(duration.as_millis() as u64),
         ) {
             Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
-            _ => Err(io::Error::new_const(
+            _ => Err(io::const_io_error!(
                 ErrorKind::Uncategorized,
-                &"Unable to initiate a connection on a socket",
+                "Unable to initiate a connection on a socket",
             )),
         }
     }
@@ -74,7 +74,7 @@ pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result<Tcp
     pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
         abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
             .map_err(|_| {
-                io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value")
+                io::const_io_error!(ErrorKind::Uncategorized, "Unable to set timeout value")
             })
     }
 
@@ -83,12 +83,12 @@ pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
             *self.0.as_inner(),
             duration.map(|d| d.as_millis() as u64),
         )
-        .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value"))
+        .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "Unable to set timeout value"))
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
         let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| {
-            io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value")
+            io::const_io_error!(ErrorKind::Uncategorized, "Unable to determine timeout value")
         })?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
@@ -96,7 +96,7 @@ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
         let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| {
-            io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value")
+            io::const_io_error!(ErrorKind::Uncategorized, "Unable to determine timeout value")
         })?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
@@ -104,7 +104,7 @@ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
 
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
         abi::tcpstream::peek(*self.0.as_inner(), buf)
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peek failed"))
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "peek failed"))
     }
 
     pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> {
@@ -116,7 +116,7 @@ pub fn read_vectored(&self, ioslice: &mut [IoSliceMut<'_>]) -> io::Result<usize>
 
         for i in ioslice.iter_mut() {
             let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| {
-                io::Error::new_const(ErrorKind::Uncategorized, &"Unable to read on socket")
+                io::const_io_error!(ErrorKind::Uncategorized, "Unable to read on socket")
             })?;
 
             if ret != 0 {
@@ -141,7 +141,7 @@ pub fn write_vectored(&self, ioslice: &[IoSlice<'_>]) -> io::Result<usize> {
 
         for i in ioslice.iter() {
             size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| {
-                io::Error::new_const(ErrorKind::Uncategorized, &"Unable to write on socket")
+                io::const_io_error!(ErrorKind::Uncategorized, "Unable to write on socket")
             })?;
         }
 
@@ -155,13 +155,13 @@ pub fn is_write_vectored(&self) -> bool {
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"))?;
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "peer_addr failed"))?;
 
         let saddr = match ipaddr {
             Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
             Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
             _ => {
-                return Err(io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"));
+                return Err(io::const_io_error!(ErrorKind::Uncategorized, "peer_addr failed"));
             }
         };
 
@@ -173,9 +173,8 @@ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        abi::tcpstream::shutdown(*self.0.as_inner(), how as i32).map_err(|_| {
-            io::Error::new_const(ErrorKind::Uncategorized, &"unable to shutdown socket")
-        })
+        abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to shutdown socket"))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
@@ -192,22 +191,22 @@ pub fn linger(&self) -> io::Result<Option<Duration>> {
 
     pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
         abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "set_nodelay failed"))
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
         abi::tcpstream::nodelay(*self.0.as_inner())
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"nodelay failed"))
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "nodelay failed"))
     }
 
     pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
         abi::tcpstream::set_tll(*self.0.as_inner(), tll)
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to set TTL"))
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to set TTL"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
         abi::tcpstream::get_tll(*self.0.as_inner())
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to get TTL"))
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to get TTL"))
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
@@ -216,7 +215,7 @@ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
 
     pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
         abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| {
-            io::Error::new_const(ErrorKind::Uncategorized, &"unable to set blocking mode")
+            io::const_io_error!(ErrorKind::Uncategorized, "unable to set blocking mode")
         })
     }
 }
@@ -243,12 +242,12 @@ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
         let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
-            .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"))?;
+            .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "accept failed"))?;
         let saddr = match ipaddr {
             Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
             Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
             _ => {
-                return Err(io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"));
+                return Err(io::const_io_error!(ErrorKind::Uncategorized, "accept failed"));
             }
         };
 
index 33b8390431f6d5327fa57abf590016ca4713dc78..514de1df6f9c33bc32f0ca34b0bd29ee6523c6c8 100644 (file)
@@ -40,7 +40,7 @@ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print"))
+            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -52,7 +52,7 @@ fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
         unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print"))
+            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -81,7 +81,7 @@ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print"))
+            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -93,7 +93,7 @@ fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
         unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print"))
+            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
         } else {
             Ok(len as usize)
         }
index 81b21fbbb1656c8758ffd982f153a85e7de04486..e53a1fea6a0dca8b4a6e49aeecd49839e6efbe25 100644 (file)
@@ -39,7 +39,7 @@ pub unsafe fn new_with_coreid(
             // The thread failed to start and as a result p was not consumed. Therefore, it is
             // safe to reconstruct the box so that it gets deallocated.
             drop(Box::from_raw(p));
-            Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Unable to create thread!"))
+            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Unable to create thread!"))
         } else {
             Ok(Thread { tid: tid })
         };
index a2a763c2b4e0f3f3c12e94525dcc3555fea9ad54..158c92e7a77d42ccf08c79e23ca576852885967d 100644 (file)
@@ -58,7 +58,7 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
 }
 
 pub fn unsupported_err() -> crate::io::Error {
-    crate::io::Error::new_const(ErrorKind::Unsupported, &"operation not supported on SGX yet")
+    crate::io::const_io_error!(ErrorKind::Unsupported, "operation not supported on SGX yet")
 }
 
 /// This function is used to implement various functions that doesn't exist,
@@ -69,9 +69,9 @@ pub fn unsupported_err() -> crate::io::Error {
 pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
     static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
     if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
-        Err(crate::io::Error::new_const(
+        Err(crate::io::const_io_error!(
             ErrorKind::Uncategorized,
-            &"operation can't be trusted to have any effect on SGX",
+            "operation can't be trusted to have any effect on SGX",
         ))
     } else {
         Ok(v)
index 89c5af6124f201bfdb8225a5306b494a4080099b..d14990c6877af6384dfc4385d2bd2c4702523109 100644 (file)
@@ -97,9 +97,9 @@ pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
 
     pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
         if dur == Duration::default() {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
-                &"cannot set a 0 duration timeout",
+                "cannot set a 0 duration timeout",
             ));
         }
         Self::connect(Ok(addr)) // FIXME: ignoring timeout
@@ -108,9 +108,9 @@ pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         match dur {
             Some(dur) if dur == Duration::default() => {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidInput,
-                    &"cannot set a 0 duration timeout",
+                    "cannot set a 0 duration timeout",
                 ));
             }
             _ => sgx_ineffective(()),
@@ -120,9 +120,9 @@ pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         match dur {
             Some(dur) if dur == Duration::default() => {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidInput,
-                    &"cannot set a 0 duration timeout",
+                    "cannot set a 0 duration timeout",
                 ));
             }
             _ => sgx_ineffective(()),
index 8a0eeff0c4d75f3e56d1078fbf9dece5197ee409..a6ed10f7789d26ffdd1e90a55c24243d7106b47b 100644 (file)
@@ -461,7 +461,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 pub fn unlink(p: &Path) -> io::Result<()> {
     if stat(p)?.file_type().is_dir() {
-        Err(io::Error::new_const(io::ErrorKind::IsADirectory, &"is a directory"))
+        Err(io::const_io_error!(io::ErrorKind::IsADirectory, "is a directory"))
     } else {
         error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(cstr(p)?.as_ptr()) })
             .map_err(|e| e.as_io_error())?;
@@ -491,7 +491,7 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
             .map_err(|e| e.as_io_error())?;
         Ok(())
     } else {
-        Err(io::Error::new_const(io::ErrorKind::NotADirectory, &"not a directory"))
+        Err(io::const_io_error!(io::ErrorKind::NotADirectory, "not a directory"))
     }
 }
 
@@ -511,7 +511,7 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     // This target doesn't support symlinks
     stat(p)?;
-    Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"not a symbolic link"))
+    Err(io::const_io_error!(io::ErrorKind::InvalidInput, "not a symbolic link"))
 }
 
 pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
index 211b8d7de31f5dd80e9664217720b2c3565b9a15..2082c9401535e8d1f4dd67a535f03eda626286bf 100644 (file)
@@ -57,9 +57,9 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
 }
 
 pub fn unsupported_err() -> crate::io::Error {
-    crate::io::Error::new_const(
+    crate::io::const_io_error!(
         crate::io::ErrorKind::Unsupported,
-        &"operation not supported on this platform",
+        "operation not supported on this platform",
     )
 }
 
index c91ecce4d728b70acd91b977c8084643ba8910d1..a43407bd0f8652a767cef42a221a33c83d26fd13 100644 (file)
@@ -243,9 +243,9 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
         }
 
         if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
-                &"cannot set a 0 duration timeout",
+                "cannot set a 0 duration timeout",
             ));
         }
 
@@ -271,7 +271,7 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
         };
 
         match n {
-            0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")),
+            0 => Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out")),
             _ => {
                 let can_write = writefds.num_fds != 0;
                 if !can_write {
@@ -364,9 +364,9 @@ pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()>
         let timeout = match dur {
             Some(dur) => {
                 if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::InvalidInput,
-                        &"cannot set a 0 duration timeout",
+                        "cannot set a 0 duration timeout",
                     ));
                 }
 
index 82542d81e6709c18792cf52c457be681798685e6..22239e1fa8ebc1944be2e0ae43e8f13b92b90a34 100644 (file)
@@ -173,11 +173,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
 /// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this
 /// function just returns a generic error.
 fn cvt_env(t: c_int) -> io::Result<c_int> {
-    if t == -1 {
-        Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"failure"))
-    } else {
-        Ok(t)
-    }
+    if t == -1 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) }
 }
 
 pub fn temp_dir() -> PathBuf {
index 878796065c8f17b906c6e3fb4f2db996e1440cd5..8bd0b9b14afedb4cb14c7b23eb1abee90ffecaf2 100644 (file)
@@ -387,17 +387,17 @@ pub fn created(&self) -> io::Result<SystemTime> {
                         tv_nsec: ext.stx_btime.tv_nsec as _,
                     }))
                 } else {
-                    Err(io::Error::new_const(
+                    Err(io::const_io_error!(
                         io::ErrorKind::Uncategorized,
-                        &"creation time is not available for the filesystem",
+                        "creation time is not available for the filesystem",
                     ))
                 };
             }
         }
 
-        Err(io::Error::new_const(
+        Err(io::const_io_error!(
             io::ErrorKind::Unsupported,
-            &"creation time is not available on this platform \
+            "creation time is not available on this platform \
                             currently",
         ))
     }
index ba63b41534c1a4f55deca27ad7c99d67ec85158d..d13e1ecbbfed4c8627a1f9ecf2ae91a5878c0a14 100644 (file)
@@ -1,8 +1,8 @@
 macro_rules! unimpl {
     () => {
-        return Err(io::Error::new_const(
+        return Err(io::const_io_error!(
             io::ErrorKind::Unsupported,
-            &"No networking available on L4Re.",
+            "No networking available on L4Re.",
         ));
     };
 }
index 2ba6c8d830ede552890c37898353615bf2a69dc8..6382354eb6ebd050e218a059eb786d24a807020b 100644 (file)
@@ -322,9 +322,6 @@ pub fn unsupported<T>() -> io::Result<T> {
     }
 
     pub fn unsupported_err() -> io::Error {
-        io::Error::new_const(
-            io::ErrorKind::Unsupported,
-            &"operation not supported on this platform",
-        )
+        io::const_io_error!(io::ErrorKind::Unsupported, "operation not supported on this platform",)
     }
 }
index a82a0172126d4fa51066b4b5313712cb61ffe812..61c15ecd85de3ce0a80355126d86fa899671cdb3 100644 (file)
@@ -154,9 +154,9 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
         let mut pollfd = libc::pollfd { fd: self.as_raw_fd(), events: libc::POLLOUT, revents: 0 };
 
         if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
-                &"cannot set a 0 duration timeout",
+                "cannot set a 0 duration timeout",
             ));
         }
 
@@ -165,7 +165,7 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
         loop {
             let elapsed = start.elapsed();
             if elapsed >= timeout {
-                return Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out"));
+                return Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out"));
             }
 
             let timeout = timeout - elapsed;
@@ -192,9 +192,9 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
                     // for POLLHUP rather than read readiness
                     if pollfd.revents & libc::POLLHUP != 0 {
                         let e = self.take_error()?.unwrap_or_else(|| {
-                            io::Error::new_const(
+                            io::const_io_error!(
                                 io::ErrorKind::Uncategorized,
-                                &"no error set after POLLHUP",
+                                "no error set after POLLHUP",
                             )
                         });
                         return Err(e);
@@ -338,9 +338,9 @@ pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Resul
         let timeout = match dur {
             Some(dur) => {
                 if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::InvalidInput,
-                        &"cannot set a 0 duration timeout",
+                        "cannot set a 0 duration timeout",
                     ));
                 }
 
index 7466c77356c7c40a35a5b1d23359e7ba9f7e799d..b268ef5c36400ba3c2aa97cc97f61792d2e83c4c 100644 (file)
@@ -294,9 +294,9 @@ fn sysctl() -> io::Result<PathBuf> {
                 0,
             ))?;
             if path_len <= 1 {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::Uncategorized,
-                    &"KERN_PROC_PATHNAME sysctl returned zero-length string",
+                    "KERN_PROC_PATHNAME sysctl returned zero-length string",
                 ));
             }
             let mut path: Vec<u8> = Vec::with_capacity(path_len);
@@ -317,9 +317,9 @@ fn procfs() -> io::Result<PathBuf> {
         if curproc_exe.is_file() {
             return crate::fs::read_link(curproc_exe);
         }
-        Err(io::Error::new_const(
+        Err(io::const_io_error!(
             io::ErrorKind::Uncategorized,
-            &"/proc/curproc/exe doesn't point to regular file.",
+            "/proc/curproc/exe doesn't point to regular file.",
         ))
     }
     sysctl().or_else(|_| procfs())
@@ -336,9 +336,9 @@ pub fn current_exe() -> io::Result<PathBuf> {
         cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?;
         argv.set_len(argv_len as usize);
         if argv[0].is_null() {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::Uncategorized,
-                &"no current exe available",
+                "no current exe available",
             ));
         }
         let argv0 = CStr::from_ptr(argv[0]).to_bytes();
@@ -353,9 +353,9 @@ pub fn current_exe() -> io::Result<PathBuf> {
 #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     match crate::fs::read_link("/proc/self/exe") {
-        Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const(
+        Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::const_io_error!(
             io::ErrorKind::Uncategorized,
-            &"no /proc/self/exe available. Is /proc mounted?",
+            "no /proc/self/exe available. Is /proc mounted?",
         )),
         other => other,
     }
@@ -417,7 +417,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
         );
         if result != 0 {
             use crate::io::ErrorKind;
-            Err(io::Error::new_const(ErrorKind::Uncategorized, &"Error getting executable path"))
+            Err(io::const_io_error!(ErrorKind::Uncategorized, "Error getting executable path"))
         } else {
             let name = CStr::from_ptr((*info.as_ptr()).name.as_ptr()).to_bytes();
             Ok(PathBuf::from(OsStr::from_bytes(name)))
@@ -433,7 +433,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 #[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use crate::io::ErrorKind;
-    Err(io::Error::new_const(ErrorKind::Unsupported, &"Not yet implemented!"))
+    Err(io::const_io_error!(ErrorKind::Unsupported, "Not yet implemented!"))
 }
 
 #[cfg(target_os = "vxworks")]
index ce77c210a6220c28ae2e8f22727b2adeab3c6f33..09bfd9680f5b2c50841d9ee9b9267c1a62e6e7a7 100644 (file)
@@ -23,9 +23,9 @@ pub fn spawn(
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
-                &"nul byte found in provided data",
+                "nul byte found in provided data",
             ));
         }
 
@@ -38,9 +38,9 @@ pub fn spawn(
 
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         if self.saw_nul() {
-            return io::Error::new_const(
+            return io::const_io_error!(
                 io::ErrorKind::InvalidInput,
-                &"nul byte found in provided data",
+                "nul byte found in provided data",
             );
         }
 
@@ -186,9 +186,9 @@ pub fn wait(&mut self) -> io::Result<ExitStatus> {
             ))?;
         }
         if actual != 1 {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidData,
-                &"Failed to get exit status of process",
+                "Failed to get exit status of process",
             ));
         }
         Ok(ExitStatus(proc_info.return_code))
@@ -224,9 +224,9 @@ pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
             ))?;
         }
         if actual != 1 {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidData,
-                &"Failed to get exit status of process",
+                "Failed to get exit status of process",
             ));
         }
         Ok(Some(ExitStatus(proc_info.return_code)))
index bce35b380e677075da4f2f2a43024787b5d6b378..9fc2d9fce4dc41b5df8c5fe2b0a5762a03b1bb24 100644 (file)
@@ -44,9 +44,9 @@ pub fn spawn(
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 ErrorKind::InvalidInput,
-                &"nul byte found in provided data",
+                "nul byte found in provided data",
             ));
         }
 
@@ -222,10 +222,7 @@ pub fn exec(&mut self, default: Stdio) -> io::Error {
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return io::Error::new_const(
-                ErrorKind::InvalidInput,
-                &"nul byte found in provided data",
-            );
+            return io::const_io_error!(ErrorKind::InvalidInput, "nul byte found in provided data",);
         }
 
         match self.setup_io(default, true) {
@@ -581,9 +578,9 @@ pub fn kill(&mut self) -> io::Result<()> {
         // and used for another process, and we probably shouldn't be killing
         // random processes, so just return an error.
         if self.status.is_some() {
-            Err(Error::new_const(
+            Err(io::const_io_error!(
                 ErrorKind::InvalidInput,
-                &"invalid argument: can't kill an exited process",
+                "invalid argument: can't kill an exited process",
             ))
         } else {
             cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
index c17822f51253266d1e66d3cbde32b88b9809fc1b..c6714d3aae246ffb8d640b8cb34106dfcfc31d8b 100644 (file)
@@ -24,9 +24,9 @@ pub fn spawn(
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 ErrorKind::InvalidInput,
-                &"nul byte found in provided data",
+                "nul byte found in provided data",
             ));
         }
         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
@@ -142,9 +142,9 @@ pub fn kill(&mut self) -> io::Result<()> {
         // and used for another process, and we probably shouldn't be killing
         // random processes, so just return an error.
         if self.status.is_some() {
-            Err(Error::new_const(
+            Err(io::const_io_error!(
                 ErrorKind::InvalidInput,
-                &"invalid argument: can't kill an exited process",
+                "invalid argument: can't kill an exited process",
             ))
         } else {
             cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
index 9e02966b57c0d1066486eca3c1fadd507055a364..cf8cf5ad49f73d03f3122f7a81a318928d8e23d5 100644 (file)
@@ -287,7 +287,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             }
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
                 -1 => Err(io::Error::last_os_error()),
-                0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
+                0 => Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")),
                 cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }),
             }
         } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] {
@@ -318,7 +318,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
                 if res == -1 {
                     return Err(io::Error::last_os_error());
                 } else if cpus == 0 {
-                    return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
+                    return Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"));
                 }
             }
             Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
@@ -344,7 +344,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             if res == -1 {
                 return Err(io::Error::last_os_error());
             } else if cpus == 0 {
-                return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
+                return Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"));
             }
 
             Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
@@ -356,14 +356,14 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
                 let res = libc::get_system_info(&mut sinfo);
 
                 if res != libc::B_OK {
-                    return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
+                    return Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"));
                 }
 
                 Ok(NonZeroUsize::new_unchecked(sinfo.cpu_count as usize))
             }
         } else {
             // FIXME: implement on vxWorks, Redox, l4re
-            Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform"))
+            Err(io::const_io_error!(io::ErrorKind::Unsupported, "Getting the number of hardware threads is not supported on the target platform"))
         }
     }
 }
index a06b44e96a923ae6fbe6940151d706edda592fb6..5274f53a7dbdb5be7fdcf270c4526d269885b681 100644 (file)
@@ -21,9 +21,9 @@ pub fn unsupported<T>() -> std_io::Result<T> {
 }
 
 pub fn unsupported_err() -> std_io::Error {
-    std_io::Error::new_const(
+    std_io::const_io_error!(
         std_io::ErrorKind::Unsupported,
-        &"operation not supported on this platform",
+        "operation not supported on this platform",
     )
 }
 
index 2886ec1180e54fab37ec126c6e0da7e0ac096092..e150ae143ad99b271338186ba51110a55e2cfd97 100644 (file)
@@ -81,11 +81,11 @@ pub fn getenv(_: &OsStr) -> Option<OsString> {
 }
 
 pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::Error::new_const(io::ErrorKind::Unsupported, &"cannot set env vars on this platform"))
+    Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
 }
 
 pub fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::Error::new_const(io::ErrorKind::Unsupported, &"cannot unset env vars on this platform"))
+    Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
 }
 
 pub fn temp_dir() -> PathBuf {
index 5924789d12ba40bb75ef46e06d0efd187b380712..cd6815bfc2136786e36a73b6225852782535453d 100644 (file)
@@ -711,7 +711,7 @@ pub fn __wasilibc_find_relpath(
 
 pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
     f.to_str()
-        .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8"))
+        .ok_or_else(|| io::const_io_error!(io::ErrorKind::Uncategorized, "input must be utf-8"))
 }
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
@@ -757,7 +757,7 @@ fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> {
     for entry in ReadDir::new(fd, dummy_root) {
         let entry = entry?;
         let path = crate::str::from_utf8(&entry.name).map_err(|_| {
-            io::Error::new_const(io::ErrorKind::Uncategorized, &"invalid utf-8 file name found")
+            io::const_io_error!(io::ErrorKind::Uncategorized, "invalid utf-8 file name found")
         })?;
 
         if entry.file_type()?.is_dir() {
index 028b6b30099dd7a7146b694b5c2ca1cbd32afd6e..fed655af87e635070d077b36734205205c98d40e 100644 (file)
@@ -511,9 +511,9 @@ fn readlink(&self) -> io::Result<PathBuf> {
                     )
                 }
                 _ => {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::Uncategorized,
-                        &"Unsupported reparse point type",
+                        "Unsupported reparse point type",
                     ));
                 }
             };
@@ -1124,9 +1124,9 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
 
 #[cfg(target_vendor = "uwp")]
 pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
-    return Err(io::Error::new_const(
+    return Err(io::const_io_error!(
         io::ErrorKind::Unsupported,
-        &"hard link are not supported on UWP",
+        "hard link are not supported on UWP",
     ));
 }
 
index ad4492f9d1f92a8c5e74eb1fa393758ef85ab585..c70f254cf39f8d734354a11c5400f864bb117f4d 100644 (file)
@@ -160,9 +160,9 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
     fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
         let mut maybe_result: Vec<u16> = s.encode_wide().collect();
         if unrolled_find_u16s(0, &maybe_result).is_some() {
-            return Err(crate::io::Error::new_const(
+            return Err(crate::io::const_io_error!(
                 ErrorKind::InvalidInput,
-                &"strings passed to WinAPI cannot contain NULs",
+                "strings passed to WinAPI cannot contain NULs",
             ));
         }
         maybe_result.push(0);
index 14d5f15d2024822585ad8b3c6cf3e6c4f9d0076a..aa6400aeefa0ddb2cb186c36f8e3ef3c636b2c5e 100644 (file)
@@ -152,9 +152,9 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
         match result {
             Err(ref error) if error.kind() == io::ErrorKind::WouldBlock => {
                 if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::InvalidInput,
-                        &"cannot set a 0 duration timeout",
+                        "cannot set a 0 duration timeout",
                     ));
                 }
 
@@ -185,9 +185,7 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
                 };
 
                 match count {
-                    0 => {
-                        Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out"))
-                    }
+                    0 => Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out")),
                     _ => {
                         if writefds.fd_count != 1 {
                             if let Some(e) = self.take_error()? {
@@ -353,9 +351,9 @@ pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()>
             Some(dur) => {
                 let timeout = sys::dur2timeout(dur);
                 if timeout == 0 {
-                    return Err(io::Error::new_const(
+                    return Err(io::const_io_error!(
                         io::ErrorKind::InvalidInput,
-                        &"cannot set a 0 duration timeout",
+                        "cannot set a 0 duration timeout",
                     ));
                 }
                 timeout
index 5ad570427978e5244b0d8d9f4af8c9ae3488d77b..c6f641d0932bf4bb0aeaa514c8d718a4176b6d7c 100644 (file)
@@ -149,7 +149,7 @@ fn as_ref(&self) -> &OsStr {
 
 fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> {
     if str.as_ref().encode_wide().any(|b| b == 0) {
-        Err(io::Error::new_const(ErrorKind::InvalidInput, &"nul byte found in provided data"))
+        Err(io::const_io_error!(ErrorKind::InvalidInput, "nul byte found in provided data"))
     } else {
         Ok(str)
     }
@@ -369,9 +369,9 @@ fn resolve_exe<'a>(
 ) -> io::Result<PathBuf> {
     // Early return if there is no filename.
     if exe_path.is_empty() || path::has_trailing_slash(exe_path) {
-        return Err(io::Error::new_const(
+        return Err(io::const_io_error!(
             io::ErrorKind::InvalidInput,
-            &"program path has no file name",
+            "program path has no file name",
         ));
     }
     // Test if the file name has the `exe` extension.
@@ -422,7 +422,7 @@ fn resolve_exe<'a>(
         }
     }
     // If we get here then the executable cannot be found.
-    Err(io::Error::new_const(io::ErrorKind::NotFound, &"program not found"))
+    Err(io::const_io_error!(io::ErrorKind::NotFound, "program not found"))
 }
 
 // Calls `f` for every path that should be used to find an executable.
index 684b8e3155e84b1a6554424e5bf5afb45748373e..a001d6b9858234a79bce1044e4d8c7e49bcf02b6 100644 (file)
@@ -110,9 +110,9 @@ fn write(
         if data[0] >> 6 != 0b10 {
             // not a continuation byte - reject
             incomplete_utf8.len = 0;
-            return Err(io::Error::new_const(
+            return Err(io::const_io_error!(
                 io::ErrorKind::InvalidData,
-                &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+                "Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
             ));
         }
         incomplete_utf8.bytes[incomplete_utf8.len as usize] = data[0];
@@ -132,9 +132,9 @@ fn write(
                 return Ok(1);
             }
             Err(_) => {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidData,
-                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+                    "Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                 ));
             }
         }
@@ -156,9 +156,9 @@ fn write(
                 incomplete_utf8.len = 1;
                 return Ok(1);
             } else {
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidData,
-                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+                    "Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                 ));
             }
         }
@@ -364,9 +364,9 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
             }
             Err(_) => {
                 // We can't really do any better than forget all data and return an error.
-                return Err(io::Error::new_const(
+                return Err(io::const_io_error!(
                     io::ErrorKind::InvalidData,
-                    &"Windows stdin in console mode does not support non-UTF-16 input; \
+                    "Windows stdin in console mode does not support non-UTF-16 input; \
                      encountered unpaired surrogate",
                 ));
             }
index 75f70c2076ee13efc9578ad91804aa82adc8d756..e4bba9255d23e774849196a88f09ee882638be2c 100644 (file)
@@ -107,9 +107,9 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
         sysinfo.dwNumberOfProcessors as usize
     };
     match res {
-        0 => Err(io::Error::new_const(
+        0 => Err(io::const_io_error!(
             io::ErrorKind::NotFound,
-            &"The number of hardware threads is not known for the target platform",
+            "The number of hardware threads is not known for the target platform",
         )),
         cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }),
     }
index 309f5483874e00c7b8d16b582905a78edfce3862..617ac52e51ca81aeb24b4ddcc289cc31acacbcee 100644 (file)
@@ -4,9 +4,9 @@
 use crate::io::{self, Error, ErrorKind};
 use crate::path::Path;
 
-pub(crate) const NOT_FILE_ERROR: Error = Error::new_const(
+pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!(
     ErrorKind::InvalidInput,
-    &"the source path is neither a regular file nor a symlink to a regular file",
+    "the source path is neither a regular file nor a symlink to a regular file",
 );
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
index c5c3df361f34bf86066eee932b74817ae83f2a43..70b29d4a92ed56f64b837474229fd208ee577d52 100644 (file)
@@ -5,7 +5,7 @@
 use crate::convert::{TryFrom, TryInto};
 use crate::ffi::CString;
 use crate::fmt;
-use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut};
+use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
 use crate::ptr;
@@ -102,7 +102,7 @@ pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result
                 *(storage as *const _ as *const c::sockaddr_in6)
             })))
         }
-        _ => Err(Error::new_const(ErrorKind::InvalidInput, &"invalid argument")),
+        _ => Err(io::const_io_error!(ErrorKind::InvalidInput, "invalid argument")),
     }
 }
 
@@ -165,7 +165,7 @@ macro_rules! try_opt {
             ($e:expr, $msg:expr) => {
                 match $e {
                     Some(r) => r,
-                    None => return Err(io::Error::new_const(io::ErrorKind::InvalidInput, &$msg)),
+                    None => return Err(io::const_io_error!(io::ErrorKind::InvalidInput, $msg)),
                 }
             };
         }
index 9c261e8cc8effcc707744698bf64f9bb10977d84..920f55ad251a651ca3f484c6d8f2fc1eb2c0d2c2 100644 (file)
@@ -47,7 +47,6 @@ pub struct ConsoleTestState {
     pub passed: usize,
     pub failed: usize,
     pub ignored: usize,
-    pub allowed_fail: usize,
     pub filtered_out: usize,
     pub measured: usize,
     pub exec_time: Option<TestSuiteExecTime>,
@@ -71,7 +70,6 @@ pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> {
             passed: 0,
             failed: 0,
             ignored: 0,
-            allowed_fail: 0,
             filtered_out: 0,
             measured: 0,
             exec_time: None,
@@ -112,7 +110,6 @@ pub fn write_log_result(
                     TestResult::TrFailed => "failed".to_owned(),
                     TestResult::TrFailedMsg(ref msg) => format!("failed: {}", msg),
                     TestResult::TrIgnored => "ignored".to_owned(),
-                    TestResult::TrAllowedFail => "failed (allowed)".to_owned(),
                     TestResult::TrBench(ref bs) => fmt_bench_samples(bs),
                     TestResult::TrTimedFail => "failed (time limit exceeded)".to_owned(),
                 },
@@ -126,7 +123,7 @@ pub fn write_log_result(
     }
 
     fn current_test_count(&self) -> usize {
-        self.passed + self.failed + self.ignored + self.measured + self.allowed_fail
+        self.passed + self.failed + self.ignored + self.measured
     }
 }
 
@@ -191,7 +188,6 @@ fn handle_test_result(st: &mut ConsoleTestState, completed_test: CompletedTest)
             st.not_failures.push((test, stdout));
         }
         TestResult::TrIgnored => st.ignored += 1,
-        TestResult::TrAllowedFail => st.allowed_fail += 1,
         TestResult::TrBench(bs) => {
             st.metrics.insert_metric(
                 test.name.as_slice(),
index 424d3ef7b4106fd29139f73563a31e4a4b36cb9f..c089bfc4791b5e2bf9b8162c1e72b9bba4ff9d75 100644 (file)
@@ -124,15 +124,6 @@ fn write_result(
                 self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None)
             }
 
-            TestResult::TrAllowedFail => self.write_event(
-                "test",
-                desc.name.as_slice(),
-                "allowed_failure",
-                exec_time,
-                stdout,
-                None,
-            ),
-
             TestResult::TrBench(ref bs) => {
                 let median = bs.ns_iter_summ.median as usize;
                 let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
@@ -172,14 +163,12 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
              \"event\": \"{}\", \
              \"passed\": {}, \
              \"failed\": {}, \
-             \"allowed_fail\": {}, \
              \"ignored\": {}, \
              \"measured\": {}, \
              \"filtered_out\": {}",
             if state.failed == 0 { "ok" } else { "failed" },
             state.passed,
-            state.failed + state.allowed_fail,
-            state.allowed_fail,
+            state.failed,
             state.ignored,
             state.measured,
             state.filtered_out,
index f940a9ff8f1d918f41547d0c42c59e47a951439f..54e9860ab548779173d623709d5a33fe4c98eb9e 100644 (file)
@@ -121,7 +121,7 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
                     ))?;
                 }
 
-                TestResult::TrOk | TestResult::TrAllowedFail => {
+                TestResult::TrOk => {
                     self.write_message(&*format!(
                         "<testcase classname=\"{}\" \
                          name=\"{}\" time=\"{}\"/>",
index 4a03b4b9147605c392fe76e4d7fa725fb37f9b49..4726ae864df7733a34551e7c4181426231dcc87f 100644 (file)
@@ -49,10 +49,6 @@ pub fn write_ignored(&mut self) -> io::Result<()> {
         self.write_short_result("ignored", term::color::YELLOW)
     }
 
-    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
-        self.write_short_result("FAILED (allowed)", term::color::YELLOW)
-    }
-
     pub fn write_time_failed(&mut self) -> io::Result<()> {
         self.write_short_result("FAILED (time limit exceeded)", term::color::RED)
     }
@@ -219,7 +215,6 @@ fn write_result(
             TestResult::TrOk => self.write_ok()?,
             TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?,
             TestResult::TrIgnored => self.write_ignored()?,
-            TestResult::TrAllowedFail => self.write_allowed_fail()?,
             TestResult::TrBench(ref bs) => {
                 self.write_bench()?;
                 self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
@@ -263,22 +258,10 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
             self.write_pretty("FAILED", term::color::RED)?;
         }
 
-        let s = if state.allowed_fail > 0 {
-            format!(
-                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out",
-                state.passed,
-                state.failed + state.allowed_fail,
-                state.allowed_fail,
-                state.ignored,
-                state.measured,
-                state.filtered_out
-            )
-        } else {
-            format!(
-                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out",
-                state.passed, state.failed, state.ignored, state.measured, state.filtered_out
-            )
-        };
+        let s = format!(
+            ". {} passed; {} failed; {} ignored; {} measured; {} filtered out",
+            state.passed, state.failed, state.ignored, state.measured, state.filtered_out
+        );
 
         self.write_plain(&s)?;
 
index 1f2c410cd96f3902493d9a17eab2fc5bc95a466c..12aca7cd9a42dd7af12b5cea216bd1e164a751a4 100644 (file)
@@ -54,10 +54,6 @@ pub fn write_ignored(&mut self) -> io::Result<()> {
         self.write_short_result("i", term::color::YELLOW)
     }
 
-    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
-        self.write_short_result("a", term::color::YELLOW)
-    }
-
     pub fn write_bench(&mut self) -> io::Result<()> {
         self.write_pretty("bench", term::color::CYAN)
     }
@@ -207,7 +203,6 @@ fn write_result(
                 self.write_failed()
             }
             TestResult::TrIgnored => self.write_ignored(),
-            TestResult::TrAllowedFail => self.write_allowed_fail(),
             TestResult::TrBench(ref bs) => {
                 if self.is_multithreaded {
                     self.write_test_name(desc)?;
@@ -244,22 +239,10 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
             self.write_pretty("FAILED", term::color::RED)?;
         }
 
-        let s = if state.allowed_fail > 0 {
-            format!(
-                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out",
-                state.passed,
-                state.failed + state.allowed_fail,
-                state.allowed_fail,
-                state.ignored,
-                state.measured,
-                state.filtered_out
-            )
-        } else {
-            format!(
-                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out",
-                state.passed, state.failed, state.ignored, state.measured, state.filtered_out
-            )
-        };
+        let s = format!(
+            ". {} passed; {} failed; {} ignored; {} measured; {} filtered out",
+            state.passed, state.failed, state.ignored, state.measured, state.filtered_out
+        );
 
         self.write_plain(&s)?;
 
index c5c56ca9c7ff9c57305d49946bdf6fec0b3aaa12..8c216a1e0e70e2d40206073610ac6b7be29a1cf1 100644 (file)
@@ -19,7 +19,6 @@ pub enum TestResult {
     TrFailed,
     TrFailedMsg(String),
     TrIgnored,
-    TrAllowedFail,
     TrBench(BenchSamples),
     TrTimedFail,
 }
@@ -42,8 +41,6 @@ pub fn calc_result<'a>(
 
             if maybe_panic_str.map(|e| e.contains(msg)).unwrap_or(false) {
                 TestResult::TrOk
-            } else if desc.allow_fail {
-                TestResult::TrAllowedFail
             } else if let Some(panic_str) = maybe_panic_str {
                 TestResult::TrFailedMsg(format!(
                     r#"panic did not contain expected string
@@ -64,7 +61,6 @@ pub fn calc_result<'a>(
         (&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => {
             TestResult::TrFailedMsg("test did not panic as expected".to_string())
         }
-        _ if desc.allow_fail => TestResult::TrAllowedFail,
         _ => TestResult::TrFailed,
     };
 
@@ -90,11 +86,10 @@ pub fn get_result_from_exit_code(
     time_opts: &Option<time::TestTimeOptions>,
     exec_time: &Option<time::TestExecTime>,
 ) -> TestResult {
-    let result = match (desc.allow_fail, code) {
-        (_, TR_OK) => TestResult::TrOk,
-        (true, TR_FAILED) => TestResult::TrAllowedFail,
-        (false, TR_FAILED) => TestResult::TrFailed,
-        (_, _) => TestResult::TrFailedMsg(format!("got unexpected return code {}", code)),
+    let result = match code {
+        TR_OK => TestResult::TrOk,
+        TR_FAILED => TestResult::TrFailed,
+        _ => TestResult::TrFailedMsg(format!("got unexpected return code {}", code)),
     };
 
     // If test is already failed (or allowed to fail), do not change the result.
index 7f0b6193d09acc311d81842ceb9b7a6f7ee5e0c9..9b9c5205686629cc1c6105117d4955de54208dd7 100644 (file)
@@ -62,10 +62,11 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 name: StaticTestName("1"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
-                allow_fail: false,
                 compile_fail: false,
                 no_run: false,
                 test_type: TestType::Unknown,
+                #[cfg(bootstrap)]
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move || {})),
         },
@@ -74,10 +75,11 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 name: StaticTestName("2"),
                 ignore: false,
                 should_panic: ShouldPanic::No,
-                allow_fail: false,
                 compile_fail: false,
                 no_run: false,
                 test_type: TestType::Unknown,
+                #[cfg(bootstrap)]
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move || {})),
         },
@@ -94,10 +96,11 @@ fn f() {
             name: StaticTestName("whatever"),
             ignore: true,
             should_panic: ShouldPanic::No,
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -115,10 +118,11 @@ fn f() {}
             name: StaticTestName("whatever"),
             ignore: true,
             should_panic: ShouldPanic::No,
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -140,10 +144,11 @@ fn f() {
             name: StaticTestName("whatever"),
             ignore: false,
             should_panic: ShouldPanic::Yes,
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -165,10 +170,11 @@ fn f() {
             name: StaticTestName("whatever"),
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage("error message"),
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -195,10 +201,11 @@ fn f() {
             name: StaticTestName("whatever"),
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -229,10 +236,11 @@ fn f() {
             name: StaticTestName("whatever"),
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -255,10 +263,11 @@ fn f() {}
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic,
-                allow_fail: false,
                 compile_fail: false,
                 no_run: false,
                 test_type: TestType::Unknown,
+                #[cfg(bootstrap)]
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(f)),
         };
@@ -289,10 +298,11 @@ fn f() {}
             name: StaticTestName("whatever"),
             ignore: false,
             should_panic: ShouldPanic::No,
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -324,10 +334,11 @@ fn f() {}
             name: StaticTestName("whatever"),
             ignore: false,
             should_panic: ShouldPanic::No,
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(f)),
     };
@@ -363,10 +374,11 @@ fn typed_test_desc(test_type: TestType) -> TestDesc {
         name: StaticTestName("whatever"),
         ignore: false,
         should_panic: ShouldPanic::No,
-        allow_fail: false,
         compile_fail: false,
         no_run: false,
         test_type,
+        #[cfg(bootstrap)]
+        allow_fail: false,
     }
 }
 
@@ -476,10 +488,11 @@ pub fn exclude_should_panic_option() {
             name: StaticTestName("3"),
             ignore: false,
             should_panic: ShouldPanic::Yes,
-            allow_fail: false,
             compile_fail: false,
             no_run: false,
             test_type: TestType::Unknown,
+            #[cfg(bootstrap)]
+            allow_fail: false,
         },
         testfn: DynTestFn(Box::new(move || {})),
     });
@@ -500,10 +513,11 @@ fn tests() -> Vec<TestDescAndFn> {
                     name: StaticTestName(name),
                     ignore: false,
                     should_panic: ShouldPanic::No,
-                    allow_fail: false,
                     compile_fail: false,
                     no_run: false,
                     test_type: TestType::Unknown,
+                    #[cfg(bootstrap)]
+                    allow_fail: false,
                 },
                 testfn: DynTestFn(Box::new(move || {})),
             })
@@ -589,10 +603,11 @@ fn testfn() {}
                 name: DynTestName((*name).clone()),
                 ignore: false,
                 should_panic: ShouldPanic::No,
-                allow_fail: false,
                 compile_fail: false,
                 no_run: false,
                 test_type: TestType::Unknown,
+                #[cfg(bootstrap)]
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(testfn)),
         };
@@ -740,10 +755,11 @@ fn f(_: &mut Bencher) {}
         name: StaticTestName("f"),
         ignore: false,
         should_panic: ShouldPanic::No,
-        allow_fail: false,
         compile_fail: false,
         no_run: false,
         test_type: TestType::Unknown,
+        #[cfg(bootstrap)]
+        allow_fail: false,
     };
 
     crate::bench::benchmark(TestId(0), desc, tx, true, f);
@@ -762,10 +778,11 @@ fn f(b: &mut Bencher) {
         name: StaticTestName("f"),
         ignore: false,
         should_panic: ShouldPanic::No,
-        allow_fail: false,
         compile_fail: false,
         no_run: false,
         test_type: TestType::Unknown,
+        #[cfg(bootstrap)]
+        allow_fail: false,
     };
 
     crate::bench::benchmark(TestId(0), desc, tx, true, f);
@@ -778,20 +795,22 @@ fn should_sort_failures_before_printing_them() {
         name: StaticTestName("a"),
         ignore: false,
         should_panic: ShouldPanic::No,
-        allow_fail: false,
         compile_fail: false,
         no_run: false,
         test_type: TestType::Unknown,
+        #[cfg(bootstrap)]
+        allow_fail: false,
     };
 
     let test_b = TestDesc {
         name: StaticTestName("b"),
         ignore: false,
         should_panic: ShouldPanic::No,
-        allow_fail: false,
         compile_fail: false,
         no_run: false,
         test_type: TestType::Unknown,
+        #[cfg(bootstrap)]
+        allow_fail: false,
     };
 
     let mut out = PrettyFormatter::new(OutputLocation::Raw(Vec::new()), false, 10, false, None);
@@ -802,7 +821,6 @@ fn should_sort_failures_before_printing_them() {
         passed: 0,
         failed: 0,
         ignored: 0,
-        allowed_fail: 0,
         filtered_out: 0,
         measured: 0,
         exec_time: None,
index 37bb38fb0df4efb64d557d31d515e83cd2a7183d..43e5a10ebbe95a02f6184410fb9368e7556a1f1f 100644 (file)
@@ -118,10 +118,11 @@ pub struct TestDesc {
     pub name: TestName,
     pub ignore: bool,
     pub should_panic: options::ShouldPanic,
-    pub allow_fail: bool,
     pub compile_fail: bool,
     pub no_run: bool,
     pub test_type: TestType,
+    #[cfg(bootstrap)]
+    pub allow_fail: bool,
 }
 
 impl TestDesc {
@@ -150,9 +151,6 @@ pub fn test_mode(&self) -> Option<&'static str> {
             }
             options::ShouldPanic::No => {}
         }
-        if self.allow_fail {
-            return Some("allow fail");
-        }
         if self.compile_fail {
             return Some("compile fail");
         }
index e730a2557e0bf38fd1f7a961b059c25c34c85a9b..9c41ab69c8be3784e4e07f12acc9c06d60b03844 100644 (file)
@@ -30,6 +30,7 @@ fn main() {
         println!("{}", suggestion);
     }
 
+    let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
     Build::new(config).build();
 
     if suggest_setup {
@@ -42,6 +43,19 @@ fn main() {
         println!("{}", suggestion);
     }
 
+    // Give a warning if the pre-commit script is in pre-commit and not pre-push.
+    // HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not.
+    // We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime.
+    // Instead, look for this comment, which is almost certainly not in any custom hook.
+    if std::fs::read_to_string(pre_commit).map_or(false, |contents| {
+        contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
+    }) {
+        println!(
+            "warning: You have the pre-push script installed to .git/hooks/pre-commit. \
+                  Consider moving it to .git/hooks/pre-push instead, which runs less often."
+        );
+    }
+
     if suggest_setup || changelog_suggestion.is_some() {
         println!("note: this message was printed twice to make it more likely to be seen");
     }
index 7105a2457e282329ebee43f59d269ffcd50bc635..d9467e8fd6bc13f86c3c043f5d1f8bfdec1627df 100644 (file)
@@ -147,6 +147,12 @@ fn main() {
         cmd.arg("-Z").arg("force-unstable-if-unmarked");
     }
 
+    if let Ok(flags) = env::var("MAGIC_EXTRA_RUSTFLAGS") {
+        for flag in flags.split(' ') {
+            cmd.arg(flag);
+        }
+    }
+
     let is_test = args.iter().any(|a| a == "--test");
     if verbose > 2 {
         let rust_env_vars =
index 6d7ab15326c5fc194fd94670d26c5e692cb27d7a..86115a90294654fff30c570e0e92801cf035ee3d 100644 (file)
@@ -1221,9 +1221,9 @@ def bootstrap(help_triggered):
     build.verbose = args.verbose
     build.clean = args.clean
 
-    # Read from `RUST_BOOTSTRAP_CONFIG`, then `--config`, then fallback to `config.toml` (if it
+    # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then fallback to `config.toml` (if it
     # exists).
-    toml_path = os.getenv('RUST_BOOTSTRAP_CONFIG') or args.config
+    toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG')
     if not toml_path and os.path.exists('config.toml'):
         toml_path = 'config.toml'
 
index d40b924e0ff5fbde6ce732d9abd81c9a5fdb830e..6e39ea00f808c20ae34cf367a0b01f8b4b0cdc70 100644 (file)
@@ -3,6 +3,8 @@
 
 fn main() {
     println!("cargo:rerun-if-changed=build.rs");
+    println!("cargo:rerun-if-env-changed=RUSTC");
+    println!("cargo:rerun-if-env-changed=PATH");
     println!("cargo:rustc-env=BUILD_TRIPLE={}", env::var("HOST").unwrap());
 
     // This may not be a canonicalized path.
index e5f84d417bf0b24f558889ec45cf5b0746677f7a..1a42d25c352d3eaa041807697e35b3c22db88242 100644 (file)
@@ -527,7 +527,7 @@ fn dir_is_empty(dir: &Path) -> bool {
         // Try passing `--progress` to start, then run git again without if that fails.
         let update = |progress: bool| {
             let mut git = Command::new("git");
-            git.args(&["submodule", "update", "--init", "--recursive"]);
+            git.args(&["submodule", "update", "--init", "--recursive", "--depth=1"]);
             if progress {
                 git.arg("--progress");
             }
index 5bc0a505bf6954602f44fb94b872126e09c15467..9a9ef0b76955d503127bc64bd7b6be057b575be7 100644 (file)
@@ -1,7 +1,9 @@
 use crate::TargetSelection;
 use crate::{t, VERSION};
+use std::env::consts::EXE_SUFFIX;
 use std::fmt::Write as _;
-use std::path::{Path, PathBuf};
+use std::fs::File;
+use std::path::{Path, PathBuf, MAIN_SEPARATOR};
 use std::process::Command;
 use std::str::FromStr;
 use std::{
@@ -109,7 +111,8 @@ pub fn setup(src_path: &Path, profile: Profile) {
     println!("`x.py` will now use the configuration at {}", include_path.display());
 
     let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
-    let stage_path = ["build", build.rustc_target_arg(), "stage1"].join("/");
+    let stage_path =
+        ["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
 
     println!();
 
@@ -171,6 +174,13 @@ fn attempt_toolchain_link(stage_path: &str) {
         return;
     }
 
+    if !ensure_stage1_toolchain_placeholder_exists(stage_path) {
+        println!(
+            "Failed to create a template for stage 1 toolchain or confirm that it already exists"
+        );
+        return;
+    }
+
     if try_link_toolchain(&stage_path[..]) {
         println!(
             "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
@@ -219,6 +229,33 @@ fn try_link_toolchain(stage_path: &str) -> bool {
         .map_or(false, |output| output.status.success())
 }
 
+fn ensure_stage1_toolchain_placeholder_exists(stage_path: &str) -> bool {
+    let pathbuf = PathBuf::from(stage_path);
+
+    if fs::create_dir_all(pathbuf.join("lib")).is_err() {
+        return false;
+    };
+
+    let pathbuf = pathbuf.join("bin");
+    if fs::create_dir_all(&pathbuf).is_err() {
+        return false;
+    };
+
+    let pathbuf = pathbuf.join(format!("rustc{}", EXE_SUFFIX));
+
+    if pathbuf.exists() {
+        return true;
+    }
+
+    // Take care not to overwrite the file
+    let result = File::options().append(true).create(true).open(&pathbuf);
+    if result.is_err() {
+        return false;
+    }
+
+    return true;
+}
+
 // Used to get the path for `Subcommand::Setup`
 pub fn interactive_path() -> io::Result<Profile> {
     fn abbrev_all() -> impl Iterator<Item = ((String, String), Profile)> {
@@ -271,9 +308,9 @@ fn install_git_hook_maybe(src_path: &Path) -> io::Result<()> {
     let mut input = String::new();
     println!(
         "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
-If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` on each commit
-to ensure your code is up to par. If you decide later that this behavior is undesirable,
-simply delete the `pre-commit` file from .git/hooks."
+If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
+pushing your code to ensure your code is up to par. If you decide later that this behavior is
+undesirable, simply delete the `pre-push` file from .git/hooks."
     );
 
     let should_install = loop {
@@ -293,21 +330,21 @@ fn install_git_hook_maybe(src_path: &Path) -> io::Result<()> {
     };
 
     if should_install {
-        let src = src_path.join("src").join("etc").join("pre-commit.sh");
+        let src = src_path.join("src").join("etc").join("pre-push.sh");
         let git = t!(Command::new("git").args(&["rev-parse", "--git-common-dir"]).output().map(
             |output| {
                 assert!(output.status.success(), "failed to run `git`");
                 PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
             }
         ));
-        let dst = git.join("hooks").join("pre-commit");
+        let dst = git.join("hooks").join("pre-push");
         match fs::hard_link(src, &dst) {
             Err(e) => println!(
                 "error: could not create hook {}: do you already have the git hook installed?\n{}",
                 dst.display(),
                 e
             ),
-            Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"),
+            Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-push`"),
         };
     } else {
         println!("Ok, skipping installation!");
index 2801d9b5e7778314a4e1c59a43d99053093ec84b..fb32918d5e439450e1ec61a14e5b83f63259ddf2 100644 (file)
@@ -6,9 +6,20 @@ The tracking issue for this feature is: [#74990]
 
 ------------------------
 
-Introduces four new ABI strings: "C-unwind", "stdcall-unwind",
-"thiscall-unwind", and "system-unwind". These enable unwinding from other
-languages (such as C++) into Rust frames and from Rust into other languages.
+Introduces new ABI strings:
+- "C-unwind"
+- "cdecl-unwind"
+- "stdcall-unwind"
+- "fastcall-unwind"
+- "vectorcall-unwind"
+- "thiscall-unwind"
+- "aapcs-unwind"
+- "win64-unwind"
+- "sysv64-unwind"
+- "system-unwind"
+
+These enable unwinding from other languages (such as C++) into Rust frames and
+from Rust into other languages.
 
 See [RFC 2945] for more information.
 
index c7be0167de9fdb8233f84cb35333688c3e0e36de..eb2b9c848aa6f419870e9424428b03119963585f 100644 (file)
@@ -41,7 +41,7 @@
           <If Condition="(base.table.table.ctrl.pointer[i] &amp; 0x80) == 0">
             <!-- Bucket is populated -->
             <Exec>n--</Exec>
-            <Item Name="{((tuple$&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$&lt;$T1, $T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
+            <Item Name="{((tuple$&lt;$T1,$T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$&lt;$T1,$T2&gt;*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item>
           </If>
           <Exec>i++</Exec>
         </Loop>
diff --git a/src/etc/pre-commit.sh b/src/etc/pre-commit.sh
deleted file mode 100755 (executable)
index 9045adb..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env bash
-#
-# Call `tidy --bless` before each commit
-# Copy this script to .git/hooks to activate,
-# and remove it from .git/hooks to deactivate.
-#
-
-set -Eeuo pipefail
-
-# https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570
-unset GIT_DIR
-ROOT_DIR="$(git rev-parse --show-toplevel)"
-COMMAND="$ROOT_DIR/x.py test tidy --bless"
-
-if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
-  COMMAND="python $COMMAND"
-fi
-
-echo "Running pre-commit script '$COMMAND'"
-
-cd "$ROOT_DIR"
-
-$COMMAND
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
new file mode 100755 (executable)
index 0000000..a78725f
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+#
+# Call `tidy --bless` before each commit
+# Copy this script to .git/hooks to activate,
+# and remove it from .git/hooks to deactivate.
+#
+
+set -Eeuo pipefail
+
+# https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570
+unset GIT_DIR
+ROOT_DIR="$(git rev-parse --show-toplevel)"
+COMMAND="$ROOT_DIR/x.py test tidy --bless"
+
+if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
+  COMMAND="python $COMMAND"
+fi
+
+echo "Running pre-push script '$COMMAND'"
+
+cd "$ROOT_DIR"
+
+$COMMAND
index cfdd119377f17669e44777185dc17f3988c3d30c..66cbf884a027b735aa697ccf7a723f5b96c04a83 100644 (file)
@@ -297,6 +297,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
             | ty::PredicateKind::ObjectSafe(..)
             | ty::PredicateKind::ClosureKind(..)
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::OpaqueType(..)
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
         }
     }
index d16383723f56373a8f12a80ef75996e281e5438a..6c55721c0dd9422dcd6f03ad8de6c9ca7841662d 100644 (file)
@@ -951,10 +951,11 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) {
                 },
                 // compiler failures are test failures
                 should_panic: test::ShouldPanic::No,
-                allow_fail: config.allow_fail,
                 compile_fail: config.compile_fail,
                 no_run,
                 test_type: test::TestType::DocTest,
+                #[cfg(bootstrap)]
+                allow_fail: false,
             },
             testfn: test::DynTestFn(box move || {
                 let report_unused_externs = |uext| {
index a9a3a0af276b11205f8bf6767fe8bb8570d9c48c..a40181352f6c03a19fc955b8ff8c21c85c2586e7 100644 (file)
@@ -847,7 +847,6 @@ fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
     crate test_harness: bool,
     crate compile_fail: bool,
     crate error_codes: Vec<String>,
-    crate allow_fail: bool,
     crate edition: Option<Edition>,
 }
 
@@ -869,7 +868,6 @@ fn default() -> Self {
             test_harness: false,
             compile_fail: false,
             error_codes: Vec::new(),
-            allow_fail: false,
             edition: None,
         }
     }
@@ -943,10 +941,6 @@ fn parse(
                         seen_rust_tags = !seen_other_tags;
                     }
                 }
-                "allow_fail" => {
-                    data.allow_fail = true;
-                    seen_rust_tags = !seen_other_tags;
-                }
                 "rust" => {
                     data.rust = true;
                     seen_rust_tags = true;
@@ -994,12 +988,6 @@ fn parse(
                             "the code block will either not be tested if not marked as a rust one \
                              or will be run (which you might not want)",
                         ))
-                    } else if s == "allow-fail" || s == "allow_fail" || s == "allowfail" {
-                        Some((
-                            "allow_fail",
-                            "the code block will either not be tested if not marked as a rust one \
-                             or will be run (which you might not want)",
-                        ))
                     } else if s == "test-harness" || s == "test_harness" || s == "testharness" {
                         Some((
                             "test_harness",
index d4af3663b624af5b7cded2b37ffe2ab5242914ac..ea6575d179d86716a10891c598c41b9ca20a2e8a 100644 (file)
@@ -70,7 +70,6 @@ fn t(lg: LangString) {
         compile_fail: true,
         ..Default::default()
     });
-    t(LangString { original: "allow_fail".into(), allow_fail: true, ..Default::default() });
     t(LangString { original: "no_run,example".into(), no_run: true, ..Default::default() });
     t(LangString {
         original: "sh,should_panic".into(),
index 38ececf5e78f838cfa086bf86319ca1fd36093f3..6d94c70eadee6455d27aa344e8d37439326c8f5a 100644 (file)
@@ -463,22 +463,21 @@ nav.sub {
 .location a:first-of-type {
        font-weight: 500;
 }
-.location a:hover {
-       text-decoration: underline;
-}
 
 .block {
        padding: 0;
 }
 .block ul, .block li {
        padding: 0;
+       margin: 0;
        list-style: none;
 }
 
-.block a {
+.block a,
+h2.location a {
        display: block;
-       padding: 0.3em;
-       margin-left: -0.3em;
+       padding: 0.3rem;
+       margin-left: -0.3rem;
 
        text-overflow: ellipsis;
        overflow: hidden;
@@ -493,8 +492,8 @@ nav.sub {
        font-weight: 500;
        padding: 0;
        margin: 0;
-       margin-top: 1rem;
-       margin-bottom: 1rem;
+       margin-top: 0.7rem;
+       margin-bottom: 0.7rem;
 }
 
 .sidebar h3 {
@@ -502,8 +501,6 @@ nav.sub {
        font-weight: 500;
        padding: 0;
        margin: 0;
-       margin-top: 0.5rem;
-       margin-bottom: 0.25rem;
 }
 
 .sidebar-links,
@@ -1813,10 +1810,7 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 
        .mobile-topbar .location {
                border: none;
-               margin: 0;
-               margin-left: auto;
-               padding: 0.3em;
-               padding-right: 0.6em;
+               margin: auto 0.5em auto auto;
                text-overflow: ellipsis;
                overflow: hidden;
                white-space: nowrap;
index 0aaf4f78c34ef1ae18ce79f1c1669749558199a9..e402b3583f3996db04ceac724326a98bc2f2a20d 100644 (file)
@@ -91,7 +91,8 @@ pre, .rustdoc.source .example-wrap {
        background-color: #5c6773;
 }
 
-.sidebar .current {
+.sidebar .current,
+.sidebar a:hover {
        background-color: transparent;
        color: #ffb44c;
 }
@@ -104,15 +105,6 @@ pre, .rustdoc.source .example-wrap {
        color: #ff7733;
 }
 
-.sidebar-elems .location a {
-       color: #fff;
-}
-
-.block a:hover {
-       background: transparent;
-       color: #ffb44c;
-}
-
 .line-numbers span { color: #5c6773; }
 .line-numbers .line-highlighted {
        color: #708090;
@@ -220,6 +212,10 @@ pre.rust a,
 .in-band a {
        color: #c5c5c5;
 }
+.sidebar h2 a,
+.sidebar h3 a {
+       color: white;
+}
 .search-results a {
        color: #0096cf;
 }
index 4fad2359ff0eb66bbc5aa883fa2df8ecbbe5a8d3..0a56055b8cbf67367ff32262c74aefe88b8f29ea 100644 (file)
@@ -61,18 +61,15 @@ pre, .rustdoc.source .example-wrap {
        background-color: rgba(32, 34, 37, .6);
 }
 
-.sidebar .current {
-       background-color: #333;
+.sidebar .current,
+.sidebar a:hover {
+       background: #444;
 }
 
 .source .sidebar {
        background-color: #565656;
 }
 
-.block a:hover {
-       background: #444;
-}
-
 .line-numbers span { color: #3B91E2; }
 .line-numbers .line-highlighted {
        background-color: #0a042f !important;
index 16a777b7e672a58ef807ccbd5cc2ed0833e042c2..dc1715b2a78f33116cc183b8fef0b3683d224dd8 100644 (file)
@@ -63,7 +63,8 @@ pre, .rustdoc.source .example-wrap {
        background-color: rgba(36, 37, 39, 0.6);
 }
 
-.sidebar .current {
+.sidebar .current,
+.sidebar a:hover {
        background-color: #fff;
 }
 
@@ -71,10 +72,6 @@ pre, .rustdoc.source .example-wrap {
        background-color: #f1f1f1;
 }
 
-.block a:hover {
-       background: #F5F5F5;
-}
-
 .line-numbers span { color: #c67e2d; }
 .line-numbers .line-highlighted {
        background-color: #FDFFD3 !important;
index cab3c28342dab5df73e0c6d258eff3ae3d083f3e..8e1919f75d671512149b1efdba9247121f2984ec 100644 (file)
@@ -559,7 +559,15 @@ function hideThemeButtonState() {
             others.appendChild(div);
         }
 
-        function block(shortty, longty) {
+        /**
+         * Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
+         *
+         * @param {string} shortty - A short type name, like "primitive", "mod", or "macro"
+         * @param {string} id - The HTML id of the corresponding section on the module page.
+         * @param {string} longty - A long, capitalized, plural name, like "Primitive Types",
+         *                          "Modules", or "Macros".
+         */
+        function block(shortty, id, longty) {
             var filtered = items[shortty];
             if (!filtered) {
                 return;
@@ -568,7 +576,7 @@ function hideThemeButtonState() {
             var div = document.createElement("div");
             div.className = "block " + shortty;
             var h3 = document.createElement("h3");
-            h3.textContent = longty;
+            h3.innerHTML = `<a href="index.html#${id}">${longty}</a>`;
             div.appendChild(h3);
             var ul = document.createElement("ul");
 
@@ -607,20 +615,20 @@ function hideThemeButtonState() {
 
             var isModule = hasClass(document.body, "mod");
             if (!isModule) {
-                block("primitive", "Primitive Types");
-                block("mod", "Modules");
-                block("macro", "Macros");
-                block("struct", "Structs");
-                block("enum", "Enums");
-                block("union", "Unions");
-                block("constant", "Constants");
-                block("static", "Statics");
-                block("trait", "Traits");
-                block("fn", "Functions");
-                block("type", "Type Definitions");
-                block("foreigntype", "Foreign Types");
-                block("keyword", "Keywords");
-                block("traitalias", "Trait Aliases");
+                block("primitive", "primitives", "Primitive Types");
+                block("mod", "modules", "Modules");
+                block("macro", "macros", "Macros");
+                block("struct", "structs", "Structs");
+                block("enum", "enums", "Enums");
+                block("union", "unions", "Unions");
+                block("constant", "constants", "Constants");
+                block("static", "static", "Statics");
+                block("trait", "traits", "Traits");
+                block("fn", "functions", "Functions");
+                block("type", "types", "Type Definitions");
+                block("foreigntype", "foreign-types", "Foreign Types");
+                block("keyword", "keywords", "Keywords");
+                block("traitalias", "trait-aliases", "Trait Aliases");
             }
 
             // `crates{version}.js` should always be loaded before this script, so we can use
index a7c3c0bb606102532413f59fe416c3c59d0cf9c3..68028604fa463d36ad980268ec5462f71214b891 100644 (file)
@@ -5,6 +5,7 @@
 #![feature(rustc_private)]
 #![feature(array_methods)]
 #![feature(assert_matches)]
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
index 86662ebaaca215505d5baaddb3de1bd8b7a45306..8621fe6ba1b93a0a19a5bd90ff8edf4791e56d54 100644 (file)
@@ -2,10 +2,8 @@
 //!
 //! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
 
-use rustc_ast as ast;
 use rustc_data_structures::{fx::FxHashMap, stable_set::FxHashSet};
 use rustc_errors::{Applicability, DiagnosticBuilder};
-use rustc_expand::base::SyntaxExtensionKind;
 use rustc_hir::def::{
     DefKind,
     Namespace::{self, *},
@@ -14,7 +12,6 @@
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID};
 use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug, ty};
-use rustc_resolve::ParentScope;
 use rustc_session::lint::Lint;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -486,23 +483,9 @@ fn resolve_macro(
         path_str: &'a str,
         module_id: DefId,
     ) -> Result<Res, ResolutionFailure<'a>> {
-        let path = ast::Path::from_ident(Ident::from_str(path_str));
         self.cx.enter_resolver(|resolver| {
-            // FIXME(jynelson): does this really need 3 separate lookups?
-            if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
-                &path,
-                None,
-                &ParentScope::module(resolver.graph_root(), resolver),
-                false,
-                false,
-            ) {
-                if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
-                    return Ok(res.try_into().unwrap());
-                }
-            }
-            if let Some(&res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
-                return Ok(res.try_into().unwrap());
-            }
+            // NOTE: this needs 2 separate lookups because `resolve_str_path_error` doesn't take
+            // lexical scope into account (it ignores all macros not defined at the mod-level)
             debug!("resolving {} as a macro in the module {:?}", path_str, module_id);
             if let Ok((_, res)) =
                 resolver.resolve_str_path_error(DUMMY_SP, path_str, MacroNS, module_id)
@@ -512,6 +495,9 @@ fn resolve_macro(
                     return Ok(res);
                 }
             }
+            if let Some(&res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
+                return Ok(res.try_into().unwrap());
+            }
             Err(ResolutionFailure::NotResolved {
                 module_id,
                 partial_res: None,
index f7a9a0899e390281e1f9faf705bec3da84c5fe8f..9caadef3dec7c92c371a3600fed3c9fc4eeaaadd 100644 (file)
@@ -38,7 +38,7 @@ fn drop_tag(
     tags: &mut Vec<(String, Range<usize>)>,
     tag_name: String,
     range: Range<usize>,
-    f: &impl Fn(&str, &Range<usize>),
+    f: &impl Fn(&str, &Range<usize>, bool),
 ) {
     let tag_name_low = tag_name.to_lowercase();
     if let Some(pos) = tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
@@ -59,14 +59,42 @@ fn drop_tag(
             // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
             // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
             // have `h3`, meaning the tag wasn't closed as it should have.
-            f(&format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span);
+            f(&format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span, true);
         }
         // Remove the `tag_name` that was originally closed
         tags.pop();
     } else {
         // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
         // but it helps for the visualization).
-        f(&format!("unopened HTML tag `{}`", tag_name), &range);
+        f(&format!("unopened HTML tag `{}`", tag_name), &range, false);
+    }
+}
+
+fn extract_path_backwards(text: &str, end_pos: usize) -> Option<usize> {
+    use rustc_lexer::{is_id_continue, is_id_start};
+    let mut current_pos = end_pos;
+    loop {
+        if current_pos >= 2 && text[..current_pos].ends_with("::") {
+            current_pos -= 2;
+        }
+        let new_pos = text[..current_pos]
+            .char_indices()
+            .rev()
+            .take_while(|(_, c)| is_id_start(*c) || is_id_continue(*c))
+            .reduce(|_accum, item| item)
+            .and_then(|(new_pos, c)| is_id_start(c).then_some(new_pos));
+        if let Some(new_pos) = new_pos {
+            if current_pos != new_pos {
+                current_pos = new_pos;
+                continue;
+            }
+        }
+        break;
+    }
+    if current_pos == end_pos {
+        return None;
+    } else {
+        return Some(current_pos);
     }
 }
 
@@ -76,7 +104,7 @@ fn extract_html_tag(
     range: &Range<usize>,
     start_pos: usize,
     iter: &mut Peekable<CharIndices<'_>>,
-    f: &impl Fn(&str, &Range<usize>),
+    f: &impl Fn(&str, &Range<usize>, bool),
 ) {
     let mut tag_name = String::new();
     let mut is_closing = false;
@@ -140,7 +168,7 @@ fn extract_tags(
     text: &str,
     range: Range<usize>,
     is_in_comment: &mut Option<Range<usize>>,
-    f: &impl Fn(&str, &Range<usize>),
+    f: &impl Fn(&str, &Range<usize>, bool),
 ) {
     let mut iter = text.char_indices().peekable();
 
@@ -178,14 +206,42 @@ fn visit_item(&mut self, item: &Item) {
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
         if !dox.is_empty() {
-            let report_diag = |msg: &str, range: &Range<usize>| {
+            let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
                 let sp = match super::source_span_for_markdown_range(tcx, &dox, range, &item.attrs)
                 {
                     Some(sp) => sp,
                     None => item.attr_span(tcx),
                 };
                 tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
-                    lint.build(msg).emit()
+                    use rustc_lint_defs::Applicability;
+                    let mut diag = lint.build(msg);
+                    // If a tag looks like `<this>`, it might actually be a generic.
+                    // We don't try to detect stuff `<like, this>` because that's not valid HTML,
+                    // and we don't try to detect stuff `<like this>` because that's not valid Rust.
+                    if let Some(Some(generics_start)) = (is_open_tag
+                        && dox[..range.end].ends_with(">"))
+                    .then(|| extract_path_backwards(&dox, range.start))
+                    {
+                        let generics_sp = match super::source_span_for_markdown_range(
+                            tcx,
+                            &dox,
+                            &(generics_start..range.end),
+                            &item.attrs,
+                        ) {
+                            Some(sp) => sp,
+                            None => item.attr_span(tcx),
+                        };
+                        // multipart form is chosen here because ``Vec<i32>`` would be confusing.
+                        diag.multipart_suggestion(
+                            "try marking as source code",
+                            vec![
+                                (generics_sp.shrink_to_lo(), String::from("`")),
+                                (generics_sp.shrink_to_hi(), String::from("`")),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    diag.emit()
                 });
             };
 
@@ -210,11 +266,11 @@ fn visit_item(&mut self, item: &Item) {
                 let t = t.to_lowercase();
                 !ALLOWED_UNCLOSED.contains(&t.as_str())
             }) {
-                report_diag(&format!("unclosed HTML tag `{}`", tag), range);
+                report_diag(&format!("unclosed HTML tag `{}`", tag), range, true);
             }
 
             if let Some(range) = is_in_comment {
-                report_diag("Unclosed HTML comment", &range);
+                report_diag("Unclosed HTML comment", &range, false);
             }
         }
 
index 93292efdcb629cfc4751647a84f4c6fdaa8dbcd1..16882cf83d09cdd058873d0cb5688ce9b7e981de 100644 (file)
@@ -196,7 +196,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                 return;
             }
 
-            let file = tcx.sess.source_map().lookup_char_pos(span.lo()).file;
+            let source_map = tcx.sess.source_map();
+            let file = source_map.lookup_char_pos(span.lo()).file;
             let file_path = match file.name.clone() {
                 FileName::Real(real_filename) => real_filename.into_local_path(),
                 _ => None,
@@ -217,6 +218,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                 let fn_entries = self.calls.entry(fn_key).or_default();
 
                 trace!("Including expr: {:?}", span);
+                let enclosing_item_span =
+                    source_map.span_extend_to_prev_char(enclosing_item_span, '\n', false);
                 let location = CallLocation::new(span, enclosing_item_span, &file);
                 fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
             }
diff --git a/src/test/codegen/unwind-abis/aapcs-unwind-abi.rs b/src/test/codegen/unwind-abis/aapcs-unwind-abi.rs
new file mode 100644 (file)
index 0000000..1fe0480
--- /dev/null
@@ -0,0 +1,31 @@
+// needs-llvm-components: arm
+// compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` atributes are correctly applied to exported `aapcs` and
+// `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "aapcs" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "aapcs-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/src/test/codegen/unwind-abis/cdecl-unwind-abi.rs b/src/test/codegen/unwind-abis/cdecl-unwind-abi.rs
new file mode 100644 (file)
index 0000000..52e0d2d
--- /dev/null
@@ -0,0 +1,29 @@
+// compile-flags: -C opt-level=0
+
+// Test that `nounwind` atributes are correctly applied to exported `cdecl` and
+// `cdecl-unwind` extern functions. `cdecl-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "cdecl" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "cdecl-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/src/test/codegen/unwind-abis/fastcall-unwind-abi.rs b/src/test/codegen/unwind-abis/fastcall-unwind-abi.rs
new file mode 100644 (file)
index 0000000..ed23235
--- /dev/null
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` atributes are correctly applied to exported `fastcall` and
+// `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "fastcall" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "fastcall-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/src/test/codegen/unwind-abis/sysv64-unwind-abi.rs b/src/test/codegen/unwind-abis/sysv64-unwind-abi.rs
new file mode 100644 (file)
index 0000000..a38736f
--- /dev/null
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` atributes are correctly applied to exported `sysv64` and
+// `sysv64-unwind` extern functions. `sysv64-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "sysv64" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "sysv64-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs b/src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs
new file mode 100644 (file)
index 0000000..0fb9612
--- /dev/null
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind, abi_vectorcall)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` atributes are correctly applied to exported `vectorcall` and
+// `vectorcall-unwind` extern functions. `vectorcall-unwind` functions MUST NOT have this attribute.
+// We disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "vectorcall" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/src/test/codegen/unwind-abis/win64-unwind-abi.rs b/src/test/codegen/unwind-abis/win64-unwind-abi.rs
new file mode 100644 (file)
index 0000000..5d8482d
--- /dev/null
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` atributes are correctly applied to exported `win64` and
+// `win64-unwind` extern functions. `win64-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "win64" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "win64-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
index 4124eada188e862e990fc5e3d930c084ba8855c0..31564a0cbd5c64a059d7d412301b2e493a9382ba 100644 (file)
@@ -305,7 +305,7 @@ pub fn return_impl_trait() -> i32        {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
 #[rustc_clean(cfg = "cfail3")]
 #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
 #[rustc_clean(cfg = "cfail6")]
index 324b9138c4d9c10271c007767fbc080d9f061fb1..83a9204136f7c15d82a676c84c9c461e55e297db 100644 (file)
@@ -6,8 +6,8 @@
     6|       |    println!("called but not covered");
     7|       |}
     8|       |
-    9|       |#[no_coverage]
-   10|       |fn do_not_add_coverage_2() {
+    9|       |fn do_not_add_coverage_2() {
+   10|       |    #![no_coverage]
    11|       |    println!("called but not covered");
    12|       |}
    13|       |
    28|      0|    println!("not called but covered");
    29|      0|}
    30|       |
-   31|      1|fn main() {
-   32|      1|    do_not_add_coverage_1();
-   33|      1|    do_not_add_coverage_2();
-   34|      1|    add_coverage_1();
-   35|      1|    add_coverage_2();
-   36|      1|}
+   31|       |// FIXME: These test-cases illustrate confusing results of nested functions.
+   32|       |// See https://github.com/rust-lang/rust/issues/93319
+   33|       |mod nested_fns {
+   34|       |    #[no_coverage]
+   35|       |    pub fn outer_not_covered(is_true: bool) {
+   36|      1|        fn inner(is_true: bool) {
+   37|      1|            if is_true {
+   38|      1|                println!("called and covered");
+   39|      1|            } else {
+   40|      0|                println!("absolutely not covered");
+   41|      0|            }
+   42|      1|        }
+   43|       |        println!("called but not covered");
+   44|       |        inner(is_true);
+   45|       |    }
+   46|       |
+   47|      1|    pub fn outer(is_true: bool) {
+   48|      1|        println!("called and covered");
+   49|      1|        inner_not_covered(is_true);
+   50|      1|
+   51|      1|        #[no_coverage]
+   52|      1|        fn inner_not_covered(is_true: bool) {
+   53|      1|            if is_true {
+   54|      1|                println!("called but not covered");
+   55|      1|            } else {
+   56|      1|                println!("absolutely not covered");
+   57|      1|            }
+   58|      1|        }
+   59|      1|    }
+   60|       |
+   61|      1|    pub fn outer_both_covered(is_true: bool) {
+   62|      1|        println!("called and covered");
+   63|      1|        inner(is_true);
+   64|      1|
+   65|      1|        fn inner(is_true: bool) {
+   66|      1|            if is_true {
+   67|      1|                println!("called and covered");
+   68|      1|            } else {
+   69|      0|                println!("absolutely not covered");
+   70|      0|            }
+   71|      1|        }
+   72|      1|    }
+   73|       |}
+   74|       |
+   75|      1|fn main() {
+   76|      1|    let is_true = std::env::args().len() == 1;
+   77|      1|
+   78|      1|    do_not_add_coverage_1();
+   79|      1|    do_not_add_coverage_2();
+   80|      1|    add_coverage_1();
+   81|      1|    add_coverage_2();
+   82|      1|
+   83|      1|    nested_fns::outer_not_covered(is_true);
+   84|      1|    nested_fns::outer(is_true);
+   85|      1|    nested_fns::outer_both_covered(is_true);
+   86|      1|}
 
index 6f8586d9f5ca642ec63c25d8c2f99ad739e1c3c1..0bfbdda2cab037cd1d748d9cb7b063710db15c10 100644 (file)
@@ -6,8 +6,8 @@ fn do_not_add_coverage_1() {
     println!("called but not covered");
 }
 
-#[no_coverage]
 fn do_not_add_coverage_2() {
+    #![no_coverage]
     println!("called but not covered");
 }
 
@@ -28,9 +28,59 @@ fn add_coverage_not_called() {
     println!("not called but covered");
 }
 
+// FIXME: These test-cases illustrate confusing results of nested functions.
+// See https://github.com/rust-lang/rust/issues/93319
+mod nested_fns {
+    #[no_coverage]
+    pub fn outer_not_covered(is_true: bool) {
+        fn inner(is_true: bool) {
+            if is_true {
+                println!("called and covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+        println!("called but not covered");
+        inner(is_true);
+    }
+
+    pub fn outer(is_true: bool) {
+        println!("called and covered");
+        inner_not_covered(is_true);
+
+        #[no_coverage]
+        fn inner_not_covered(is_true: bool) {
+            if is_true {
+                println!("called but not covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+    }
+
+    pub fn outer_both_covered(is_true: bool) {
+        println!("called and covered");
+        inner(is_true);
+
+        fn inner(is_true: bool) {
+            if is_true {
+                println!("called and covered");
+            } else {
+                println!("absolutely not covered");
+            }
+        }
+    }
+}
+
 fn main() {
+    let is_true = std::env::args().len() == 1;
+
     do_not_add_coverage_1();
     do_not_add_coverage_2();
     add_coverage_1();
     add_coverage_2();
+
+    nested_fns::outer_not_covered(is_true);
+    nested_fns::outer(is_true);
+    nested_fns::outer_both_covered(is_true);
 }
index 099b65a23cad6979e2be32d80a5a678c6a6de0d9..e2c778aa8650964a540d747c0ace08018a7bda80 100644 (file)
@@ -7,4 +7,4 @@
 { "type": "test", "name": "c", "event": "ok" }
 { "type": "test", "event": "started", "name": "d" }
 { "type": "test", "name": "d", "event": "ignored" }
-{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
+{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
index fd676799a76649435e0b6aa030ac8c50f629c9e4..68eb00c297ea72a175bbd3c3b952572503d62478 100644 (file)
@@ -7,4 +7,4 @@
 { "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" }
 { "type": "test", "event": "started", "name": "d" }
 { "type": "test", "name": "d", "event": "ignored" }
-{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
+{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
diff --git a/src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile b/src/test/run-make/rustdoc-scrape-examples-whitespace/Makefile
new file mode 100644 (file)
index 0000000..dce8b83
--- /dev/null
@@ -0,0 +1,5 @@
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs
new file mode 100644 (file)
index 0000000..44ff689
--- /dev/null
@@ -0,0 +1,8 @@
+struct Foo;
+impl Foo {
+  fn bar() { foobar::ok(); }
+}
+
+fn main() {
+  Foo::bar();
+}
diff --git a/src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-whitespace/src/lib.rs
new file mode 100644 (file)
index 0000000..28c3471
--- /dev/null
@@ -0,0 +1,3 @@
+// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//code' '  '
+
+pub fn ok() {}
index 7be46a613c4fb159323fb96e5831edfe2f5ee235..2e44dd32d45b4164791938cbad7c0db3f1ecc9a6 100644 (file)
@@ -11,7 +11,7 @@ assert-css: (".main-heading", {
   "flex-direction": "column"
 })
 
-assert-property: (".mobile-topbar h2.location", {"offsetHeight": 45})
+assert-property: (".mobile-topbar h2.location", {"offsetHeight": 48})
 
 // Note: We can't use assert-text here because the 'Since' is set by CSS and
 // is therefore not part of the DOM.
index 60bcffe120beca8385c09f91fdd79427f077b9d2..9581aa74b0f643eafeaa9c3c3f9bcf2bdf2717e2 100644 (file)
@@ -39,4 +39,4 @@ assert-position: ("#method\.must_use", {"y": 45})
 // Check that the bottom-most item on the sidebar menu can be scrolled fully into view.
 click: ".sidebar-menu-toggle"
 scroll-to: ".block.keyword li:nth-child(1)"
-assert-position: (".block.keyword li:nth-child(1)", {"y": 542.96875})
+compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 543})
index ef3a92ad7a6ced12f467c7f3cec63962a91811a8..877cc61b66f24dd65c502d3daf254b60e0321459 100644 (file)
@@ -77,4 +77,11 @@ assert-text: ("#functions + .item-table .item-left > a", "foo")
 
 // Links to trait implementations in the sidebar should not wrap even if they are long.
 goto: file://|DOC_PATH|/lib2/struct.HasALongTraitWithParams.html
-assert-property: (".sidebar-links a", {"offsetHeight": 29})
+assert-property: (".sidebar-links a", {"offsetHeight": 30})
+
+// Test that clicking on of the "In <module>" headings in the sidebar links to the
+// appropriate anchor in index.html.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+click: ".block.mod h3 a"
+// PAGE: index.html
+assert-css: ("#modules", {"background-color": "rgb(253, 255, 211)"})
index 99aa38e87e9251bc12b44aca31ee135492357a1e..d4142511e4373e8a12c252f6cc8bb4d546470851 100644 (file)
@@ -32,6 +32,6 @@ assert-property: (".item-decl pre", {"scrollWidth": "950"})
 size: (600, 600)
 goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html
 // It shouldn't have an overflow in the topbar either.
-assert-property: (".mobile-topbar .location", {"scrollWidth": "986"})
-assert-property: (".mobile-topbar .location", {"clientWidth": "504"})
+assert-property: (".mobile-topbar .location", {"scrollWidth": "493"})
+assert-property: (".mobile-topbar .location", {"clientWidth": "493"})
 assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"})
diff --git a/src/test/rustdoc-ui/block-doc-comment.rs b/src/test/rustdoc-ui/block-doc-comment.rs
new file mode 100644 (file)
index 0000000..c60dfa3
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+// compile-flags:--test
+
+// This test ensures that no code block is detected in the doc comments.
+
+pub mod Wormhole {
+    /** # Returns
+     *
+     */
+    pub fn foofoo() {}
+    /**
+     * # Returns
+     *
+     */
+    pub fn barbar() {}
+}
diff --git a/src/test/rustdoc-ui/block-doc-comment.stdout b/src/test/rustdoc-ui/block-doc-comment.stdout
new file mode 100644 (file)
index 0000000..e5c27be
--- /dev/null
@@ -0,0 +1,5 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+
index 023d620bea2225d13fa04217d591d26c2d424217..e955470148a16cba9c857c43d0877f5d9f99f539 100644 (file)
@@ -23,13 +23,6 @@ pub fn bar() {}
 /// ```
 pub fn foobar() {}
 
-/// barfoo
-///
-/// ```allow-fail,allowfail,allOw_fail
-/// boo
-/// ```
-pub fn barfoo() {}
-
 /// b
 ///
 /// ```test-harness,testharness,tesT_harness
index affd0372a1f5e6d49412d3d2ee70a52a934930f5..b1fa9edf0e4cb3cb6ed3c688e5a8ce3f50cb0c1e 100644 (file)
@@ -111,77 +111,41 @@ error: unknown attribute `nO_run`. Did you mean `no_run`?
    |
    = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
 
-error: unknown attribute `allow-fail`. Did you mean `allow_fail`?
+error: unknown attribute `test-harness`. Did you mean `test_harness`?
   --> $DIR/check-attr-test.rs:26:1
    |
-26 | / /// barfoo
+26 | / /// b
 27 | | ///
-28 | | /// ```allow-fail,allowfail,allOw_fail
+28 | | /// ```test-harness,testharness,tesT_harness
 29 | | /// boo
 30 | | /// ```
    | |_______^
    |
-   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
-error: unknown attribute `allowfail`. Did you mean `allow_fail`?
+error: unknown attribute `testharness`. Did you mean `test_harness`?
   --> $DIR/check-attr-test.rs:26:1
    |
-26 | / /// barfoo
+26 | / /// b
 27 | | ///
-28 | | /// ```allow-fail,allowfail,allOw_fail
+28 | | /// ```test-harness,testharness,tesT_harness
 29 | | /// boo
 30 | | /// ```
    | |_______^
    |
-   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
-error: unknown attribute `allOw_fail`. Did you mean `allow_fail`?
+error: unknown attribute `tesT_harness`. Did you mean `test_harness`?
   --> $DIR/check-attr-test.rs:26:1
    |
-26 | / /// barfoo
+26 | / /// b
 27 | | ///
-28 | | /// ```allow-fail,allowfail,allOw_fail
+28 | | /// ```test-harness,testharness,tesT_harness
 29 | | /// boo
 30 | | /// ```
-   | |_______^
-   |
-   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
-
-error: unknown attribute `test-harness`. Did you mean `test_harness`?
-  --> $DIR/check-attr-test.rs:33:1
-   |
-33 | / /// b
-34 | | ///
-35 | | /// ```test-harness,testharness,tesT_harness
-36 | | /// boo
-37 | | /// ```
-   | |_______^
-   |
-   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
-
-error: unknown attribute `testharness`. Did you mean `test_harness`?
-  --> $DIR/check-attr-test.rs:33:1
-   |
-33 | / /// b
-34 | | ///
-35 | | /// ```test-harness,testharness,tesT_harness
-36 | | /// boo
-37 | | /// ```
-   | |_______^
-   |
-   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
-
-error: unknown attribute `tesT_harness`. Did you mean `test_harness`?
-  --> $DIR/check-attr-test.rs:33:1
-   |
-33 | / /// b
-34 | | ///
-35 | | /// ```test-harness,testharness,tesT_harness
-36 | | /// boo
-37 | | /// ```
    | |_______^
    |
    = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
-error: aborting due to 15 previous errors
+error: aborting due to 12 previous errors
 
index 763bc4c6cddb90028ab956064225984c7f40fcc6..0b3f7bedda5cf9b442a625b2a97e7bb90bd71141 100644 (file)
@@ -30,16 +30,6 @@ pub fn bar() {}
 /// ```
 pub fn foobar() {}
 
-/// barfoo
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-///
-/// ```allow-fail,allowfail,alLow_fail
-/// boo
-/// ```
-pub fn barfoo() {}
-
 /// b
 //~^ ERROR
 //~^^ ERROR
index 9312cfb76f35f4a52e35bffb7242571b30f80819..370b804c56c64a840e3cfd37d909b15342e13be3 100644 (file)
@@ -129,50 +129,8 @@ LL | | /// ```
    |
    = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
 
-error: unknown attribute `allow-fail`. Did you mean `allow_fail`?
-  --> $DIR/check-attr.rs:33:1
-   |
-LL | / /// barfoo
-LL | |
-LL | |
-LL | |
-...  |
-LL | | /// boo
-LL | | /// ```
-   | |_______^
-   |
-   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
-
-error: unknown attribute `allowfail`. Did you mean `allow_fail`?
-  --> $DIR/check-attr.rs:33:1
-   |
-LL | / /// barfoo
-LL | |
-LL | |
-LL | |
-...  |
-LL | | /// boo
-LL | | /// ```
-   | |_______^
-   |
-   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
-
-error: unknown attribute `alLow_fail`. Did you mean `allow_fail`?
-  --> $DIR/check-attr.rs:33:1
-   |
-LL | / /// barfoo
-LL | |
-LL | |
-LL | |
-...  |
-LL | | /// boo
-LL | | /// ```
-   | |_______^
-   |
-   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
-
 error: unknown attribute `test-harness`. Did you mean `test_harness`?
-  --> $DIR/check-attr.rs:43:1
+  --> $DIR/check-attr.rs:33:1
    |
 LL | / /// b
 LL | |
@@ -186,7 +144,7 @@ LL | | /// ```
    = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
 error: unknown attribute `testharness`. Did you mean `test_harness`?
-  --> $DIR/check-attr.rs:43:1
+  --> $DIR/check-attr.rs:33:1
    |
 LL | / /// b
 LL | |
@@ -200,7 +158,7 @@ LL | | /// ```
    = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
 error: unknown attribute `teSt_harness`. Did you mean `test_harness`?
-  --> $DIR/check-attr.rs:43:1
+  --> $DIR/check-attr.rs:33:1
    |
 LL | / /// b
 LL | |
@@ -213,5 +171,5 @@ LL | | /// ```
    |
    = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
-error: aborting due to 15 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules.rs b/src/test/rustdoc-ui/intra-doc/macro-rules.rs
new file mode 100644 (file)
index 0000000..a14e4bd
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+#![allow(rustdoc::private_intra_doc_links)]
+
+macro_rules! foo {
+    () => {};
+}
+
+/// [foo!]
+pub fn baz() {}
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs b/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.rs
new file mode 100644 (file)
index 0000000..744b307
--- /dev/null
@@ -0,0 +1,38 @@
+#![deny(rustdoc::invalid_html_tags)]
+
+/// This Vec<32> thing!
+// Numbers aren't valid HTML tags, so no error.
+pub struct ConstGeneric;
+
+/// This Vec<i32, i32> thing!
+// HTML tags cannot contain commas, so no error.
+pub struct MultipleGenerics;
+
+/// This Vec<i32 class="test"> thing!
+//~^ERROR unclosed HTML tag `i32`
+// HTML attributes shouldn't be treated as Rust syntax, so no suggestions.
+pub struct TagWithAttributes;
+
+/// This Vec<i32></i32> thing!
+// There should be no error, and no suggestion, since the tags are balanced.
+pub struct DoNotWarnOnMatchingTags;
+
+/// This Vec</i32> thing!
+//~^ERROR unopened HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct EndTagsAreNotValidRustSyntax;
+
+/// This 123<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct NumbersAreNotPaths;
+
+/// This Vec:<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct InvalidTurbofish;
+
+/// This [link](https://rust-lang.org)<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+// This should produce an error, but no suggestion.
+pub struct BareTurbofish;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr b/src/test/rustdoc-ui/suggestions/html-as-generics-no-suggestions.stderr
new file mode 100644 (file)
index 0000000..832b8b2
--- /dev/null
@@ -0,0 +1,38 @@
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics-no-suggestions.rs:11:13
+   |
+LL | /// This Vec<i32 class="test"> thing!
+   |             ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/html-as-generics-no-suggestions.rs:1:9
+   |
+LL | #![deny(rustdoc::invalid_html_tags)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unopened HTML tag `i32`
+  --> $DIR/html-as-generics-no-suggestions.rs:20:13
+   |
+LL | /// This Vec</i32> thing!
+   |             ^^^^^^
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics-no-suggestions.rs:25:13
+   |
+LL | /// This 123<i32> thing!
+   |             ^^^^^
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics-no-suggestions.rs:30:14
+   |
+LL | /// This Vec:<i32> thing!
+   |              ^^^^^
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics-no-suggestions.rs:35:39
+   |
+LL | /// This [link](https://rust-lang.org)<i32> thing!
+   |                                       ^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.fixed b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
new file mode 100644 (file)
index 0000000..c0a0de2
--- /dev/null
@@ -0,0 +1,32 @@
+// run-rustfix
+#![deny(rustdoc::invalid_html_tags)]
+
+/// This `Vec<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Generic;
+
+/// This `vec::Vec<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct GenericPath;
+
+/// This `i32<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct PathsCanContainTrailingNumbers;
+
+/// This `Vec::<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Turbofish;
+
+/// This [link](https://rust-lang.org)`::<i32>` thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct BareTurbofish;
+
+/// This <span>`Vec::<i32>`</span> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Nested;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.rs b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
new file mode 100644 (file)
index 0000000..0b6009b
--- /dev/null
@@ -0,0 +1,32 @@
+// run-rustfix
+#![deny(rustdoc::invalid_html_tags)]
+
+/// This Vec<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Generic;
+
+/// This vec::Vec<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct GenericPath;
+
+/// This i32<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct PathsCanContainTrailingNumbers;
+
+/// This Vec::<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Turbofish;
+
+/// This [link](https://rust-lang.org)::<i32> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct BareTurbofish;
+
+/// This <span>Vec::<i32></span> thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct Nested;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.stderr b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
new file mode 100644 (file)
index 0000000..df54b71
--- /dev/null
@@ -0,0 +1,73 @@
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:4:13
+   |
+LL | /// This Vec<i32> thing!
+   |             ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/html-as-generics.rs:2:9
+   |
+LL | #![deny(rustdoc::invalid_html_tags)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try marking as source code
+   |
+LL | /// This `Vec<i32>` thing!
+   |          +        +
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:9:18
+   |
+LL | /// This vec::Vec<i32> thing!
+   |                  ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This `vec::Vec<i32>` thing!
+   |          +             +
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:14:13
+   |
+LL | /// This i32<i32> thing!
+   |             ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This `i32<i32>` thing!
+   |          +        +
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:19:15
+   |
+LL | /// This Vec::<i32> thing!
+   |               ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This `Vec::<i32>` thing!
+   |          +          +
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:24:41
+   |
+LL | /// This [link](https://rust-lang.org)::<i32> thing!
+   |                                         ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This [link](https://rust-lang.org)`::<i32>` thing!
+   |                                       +       +
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:29:21
+   |
+LL | /// This <span>Vec::<i32></span> thing!
+   |                     ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This <span>`Vec::<i32>`</span> thing!
+   |                +          +
+
+error: aborting due to 6 previous errors
+
index ed2297b4fac5daf07f482667879b495fe947ec38..ea28d84f1ffdfe63fd0b41bad05a8c29205c822e 100644 (file)
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
-// The goal of this test is to answer that it won't be generated as a list because
+// The goal of this test is to ensure that it won't be generated as a list because
 // block doc comments can have their lines starting with a star.
 
 // @has foo/fn.foo.html
index e7a9ce94af4d9f52fc0c4c61e19f7097b2709c5d..c0f6118a9f1639354c2cd6e70bf951821b0ae8cd 100644 (file)
@@ -1,40 +1,40 @@
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
-  --> $DIR/not-an-allocator.rs:2:1
+  --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
    | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+   |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
-  --> $DIR/not-an-allocator.rs:2:1
+  --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
    | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+   |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
-  --> $DIR/not-an-allocator.rs:2:1
+  --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
    | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+   |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
-  --> $DIR/not-an-allocator.rs:2:1
+  --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
    | ------------------- in this procedural macro expansion
 LL | static A: usize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+   |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 4c36289f47b857ac0e5c50ae4fa9df26d9dc7863..67b97c21805e684cf757c1f0ef7d6d3af2e5ec37 100644 (file)
@@ -30,7 +30,7 @@ impl Thing for AssocNoCopy {
     type Out = Box<dyn Bar<Assoc: Copy>>;
 
     fn func() -> Self::Out {
-        //~^ ERROR the trait bound `String: Copy` is not satisfied
         Box::new(AssocNoCopy)
+        //~^ ERROR the trait bound `String: Copy` is not satisfied
     }
 }
index a32ab453152a0b4663c06788b189aaba8cd23431..f1dcd34066dbc6bfda6d3db2cf565f5029f53ef2 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18
+  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:33:9
    |
-LL |     fn func() -> Self::Out {
-   |                  ^^^^^^^^^ the trait `Copy` is not implemented for `String`
+LL |         Box::new(AssocNoCopy)
+   |         ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = note: required for the cast to the object type `dyn Bar<Assoc = <AssocNoCopy as Thing>::Out::{opaque#0}>`
 
 error: aborting due to previous error
 
index 5f994f26534bdeefb3a3a329cf547226d066b19d..30e4c1a3c537ba944b33af3544a6f29adb310ec6 100644 (file)
@@ -23,8 +23,8 @@ fn bar() -> impl Bar {
 }
 
 fn baz() -> impl Bar<Item = i32> {
-//~^ ERROR type mismatch resolving `<impl Bar as Foo>::Item == i32`
     bar()
+    //~^ ERROR type mismatch resolving `<impl Bar as Foo>::Item == i32`
 }
 
 fn main() {
index 283ecea735d4156209b9f2b22614e9262fc451db..9523a54d954df0feb04d8715b818b744c4eba4fd 100644 (file)
@@ -1,14 +1,16 @@
 error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
-  --> $DIR/impl-trait-return-missing-constraint.rs:25:13
+  --> $DIR/impl-trait-return-missing-constraint.rs:26:5
    |
 LL | fn bar() -> impl Bar {
-   |             -------- the found opaque type
+   |             -------- the expected opaque type
 ...
-LL | fn baz() -> impl Bar<Item = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
+LL |     bar()
+   |     ^^^^^ expected associated type, found `i32`
    |
-   = note:         expected type `i32`
-           found associated type `<impl Bar as Foo>::Item`
+   = note: expected associated type `<impl Bar as Foo>::Item`
+                         found type `i32`
+   = help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` or calling a method that returns `<impl Bar as Foo>::Item`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
    |
 LL | fn bar() -> impl Bar<Item = i32> {
index 44d60c1d80d881310f01d900ba00a075910bd06b..f21c811512416a34728af743624f6563dfe7def1 100644 (file)
@@ -8,10 +8,10 @@ LL |     Box::new(async { x } )
    |                    may outlive borrowed value `x`
    |
 note: async block is returned here
-  --> $DIR/async-borrowck-escaping-block-error.rs:4:20
+  --> $DIR/async-borrowck-escaping-block-error.rs:6:5
    |
-LL | fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     Box::new(async { x } )
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
    |
 LL |     Box::new(async move { x } )
index 2538f34351e5a51fab1fc4432a1445861b08202c..7cb02e5cf383d14cefb08b06ce701fd9bd49ebb6 100644 (file)
@@ -13,9 +13,9 @@ fn status(&self) -> u16 {
 async fn get() { }
 
 pub fn foo() -> impl Future + Send {
-    //~^ ERROR future cannot be sent between threads safely
     let client = Client(Box::new(true));
     async move {
+        //~^ ERROR future cannot be sent between threads safely
         match client.status() {
             200 => {
                 let _x = get().await;
index d631e6dc7f7e968aa80446b2791fbe7114d8a7fb..3a84907e0c04b31790fdf2742a4733ecc9a07ce2 100644 (file)
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-64130-4-async-move.rs:15:17
+  --> $DIR/issue-64130-4-async-move.rs:17:5
    |
-LL | pub fn foo() -> impl Future + Send {
-   |                 ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+LL |     async move {
+   |     ^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
 note: future is not `Send` as this value is used across an await
index 0609e4fc0817073f0782d9d0ed5b748f51561c54..631389e10f316a8f17e4284c3a9182a6aaae0e5e 100644 (file)
@@ -2,8 +2,8 @@
 
 use std::future::Future;
 fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
-//~^ Error future cannot be sent between threads safely
     async { (ty, ty1) }
+    //~^ Error future cannot be sent between threads safely
 }
 
 fn main() {}
index 20109d4d1166a0e3331d4289ef60d2628ae1b1d9..cb50c70f99847a3984bf09b5ec42072ddc7eeb41 100644 (file)
@@ -1,11 +1,11 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-70818.rs:4:38
+  --> $DIR/issue-70818.rs:5:5
    |
-LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
-   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+LL |     async { (ty, ty1) }
+   |     ^^^^^ future created by async block is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/issue-70818.rs:6:18
+  --> $DIR/issue-70818.rs:5:18
    |
 LL |     async { (ty, ty1) }
    |                  ^^^ has type `U` which is not `Send`
index 2965a7e0654a4edb39d33d962c1c889116ee1d4c..494561229511ec5909fe2cdb882886c8d56e7392 100644 (file)
@@ -8,8 +8,8 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
 }
 
 fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
-    //~^ ERROR: future cannot be sent between threads safely
     async move {
+        //~^ ERROR: future cannot be sent between threads safely
         baz(|| async{
             foo(tx.clone());
         }).await;
index db3099381196b771692e3f1b29677d201c77aea1..ad61f21741bb5875e0af18628abc93281a664ea3 100644 (file)
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-70935-complex-spans.rs:10:45
+  --> $DIR/issue-70935-complex-spans.rs:11:5
    |
-LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
-   |                                             ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+LL |     async move {
+   |     ^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `Sender<i32>`
 note: future is not `Send` as this value is used across an await
index 2722c72c20a339a485453316d57e3382d39f4f7d..cdb141c0e3ea2802c7efd1d6a3a368d832b5e64e 100644 (file)
@@ -14,12 +14,16 @@ LL | | }
    = help: consider adding the following bound: `'a: 'b`
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ret-impl-trait-one.rs:16:65
+  --> $DIR/ret-impl-trait-one.rs:16:80
    |
-LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |                                    --                           ^^^^^^^^^^^^^^
-   |                                    |
-   |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |  ____________________________________--__________________________________________^
+   | |                                    |
+   | |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
index 149692a2c6998e29981b192df521a48fa354c480..2eb3a07059f7bf97d52310280da2d46bf2bbf14b 100644 (file)
@@ -1,19 +1,26 @@
 error[E0623]: lifetime mismatch
-  --> $DIR/ret-impl-trait-one.rs:10:65
+  --> $DIR/ret-impl-trait-one.rs:10:85
    |
-LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
-   |                                                      ------     ^^^^^^^^^^^^^^^^^^^
-   |                                                      |          |
-   |                                                      |          ...but data from `a` is returned here
-   |                                                      this parameter and the return type are declared with different lifetimes...
+LL |   async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
+   |  ______________________________________________________------_____-------------------_^
+   | |                                                      |
+   | |                                                      this parameter and the return type are declared with different lifetimes...
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^ ...but data from `a` is returned here
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ret-impl-trait-one.rs:16:65
+  --> $DIR/ret-impl-trait-one.rs:16:80
    |
-LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |                                    --                           ^^^^^^^^^^^^^^
-   |                                    |
-   |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |  ____________________________________--__________________________________________^
+   | |                                    |
+   | |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
index b3c59734e036f7b0a57b729d99c3cd6f3026cc75..cfb0ef1b33a2b69de5936a9cd44e51ce7b9c84f5 100644 (file)
@@ -3,3 +3,4 @@
 
 pub const async fn x() {}
 //~^ ERROR functions cannot be both `const` and `async`
+//~| ERROR cycle detected
index 90ec646c8c09cbb6a8e9477fdbb830e8ee313f6e..fd76c282f9629c475253bc0197f6cd699999489b 100644 (file)
@@ -7,5 +7,36 @@ LL | pub const async fn x() {}
    |     |     `async` because of this
    |     `const` because of this
 
-error: aborting due to previous error
+error[E0391]: cycle detected when computing type of `x::{opaque#0}`
+  --> $DIR/no-const-async.rs:4:24
+   |
+LL | pub const async fn x() {}
+   |                        ^
+   |
+note: ...which requires borrow-checking `x`...
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `x`...
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `x`...
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0391`.
index aa7733194587da20ba4238a02da39f729f0445a0..edc4cb8ac5df37153345b5a8453538bb330da90a 100644 (file)
@@ -2,7 +2,8 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden when using `async` and `await`.
 
-async fn recursive_async_function() -> () { //~ ERROR
+async fn recursive_async_function() -> () {
+    //~^ ERROR recursion in an `async fn` requires boxing
     recursive_async_function().await;
 }
 
index c7c5b51e7334b87b27e40534c5541d9e7044b960..046f1dfea323878d1d1725abfac6ab76c724fbc4 100644 (file)
@@ -21,7 +21,6 @@ async fn dummy() {}
 async fn suggest_await_in_async_fn_return() {
     dummy()
     //~^ ERROR mismatched types [E0308]
-    //~| HELP consider using a semicolon here
     //~| HELP consider `await`ing on the `Future`
     //~| SUGGESTION .await
 }
index 3cca9616a358a34d7489d0efbd75aca2c185c2ba..a60571dc11df6d4120041ad093068bb25197a461 100644 (file)
@@ -33,13 +33,9 @@ help: consider `await`ing on the `Future`
    |
 LL |     dummy().await
    |            ++++++
-help: consider using a semicolon here
-   |
-LL |     dummy();
-   |            +
 
 error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/suggest-missing-await.rs:35:9
+  --> $DIR/suggest-missing-await.rs:34:9
    |
 LL |       let _x = if true {
    |  ______________-
@@ -53,15 +49,20 @@ LL | |
 LL | |     };
    | |_____- `if` and `else` have incompatible types
    |
-   = note:   expected type `impl Future<Output = ()>`
-           found unit type `()`
+note: while checking the return type of the `async fn`
+  --> $DIR/suggest-missing-await.rs:18:18
+   |
+LL | async fn dummy() {}
+   |                  ^ checked the `Output` of this `async fn`, expected opaque type
+   = note: expected opaque type `impl Future<Output = ()>`
+                found unit type `()`
 help: consider `await`ing on the `Future`
    |
 LL |         dummy().await
    |                ++++++
 
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/suggest-missing-await.rs:45:14
+  --> $DIR/suggest-missing-await.rs:44:14
    |
 LL |       let _x = match 0usize {
    |  ______________-
@@ -89,7 +90,7 @@ LL ~         1 => dummy().await,
    |
 
 error[E0308]: mismatched types
-  --> $DIR/suggest-missing-await.rs:53:9
+  --> $DIR/suggest-missing-await.rs:52:9
    |
 LL |         () => {}
    |         ^^ expected opaque type, found `()`
@@ -107,13 +108,13 @@ LL |     let _x = match dummy().await {
    |                           ++++++
 
 error[E0308]: mismatched types
-  --> $DIR/suggest-missing-await.rs:67:9
+  --> $DIR/suggest-missing-await.rs:66:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^ expected opaque type, found enum `Result`
    |
 note: while checking the return type of the `async fn`
-  --> $DIR/suggest-missing-await.rs:57:28
+  --> $DIR/suggest-missing-await.rs:56:28
    |
 LL | async fn dummy_result() -> Result<(), ()> {
    |                            ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
@@ -125,13 +126,13 @@ LL |     match dummy_result().await {
    |                         ++++++
 
 error[E0308]: mismatched types
-  --> $DIR/suggest-missing-await.rs:69:9
+  --> $DIR/suggest-missing-await.rs:68:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^ expected opaque type, found enum `Result`
    |
 note: while checking the return type of the `async fn`
-  --> $DIR/suggest-missing-await.rs:57:28
+  --> $DIR/suggest-missing-await.rs:56:28
    |
 LL | async fn dummy_result() -> Result<(), ()> {
    |                            ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
index d4a0f9613055ee5abf87eccec3fffe4df7a0dff1..ccf41adce6bd83f769dcb48e8b461691b84be03f 100644 (file)
@@ -18,5 +18,5 @@ fn main() {
     // this is an `*mut fmt::Debug` in practice
     let mut b_raw = Box::into_raw(b);
     // ... and they should not be mixable
-    b_raw = f_raw as *mut _; //~ ERROR is invalid
+    b_raw = f_raw as *mut _; //~ ERROR mismatched types
 }
index f9abfb5225f91c3f5b1fd693f14c6cb245887fed..2d08903c5ef69c39b6007a32eb2ddf33f4cfd53f 100644 (file)
@@ -1,11 +1,19 @@
-error[E0606]: casting `*mut impl Debug + ?Sized` as `*mut impl Debug + ?Sized` is invalid
+error[E0308]: mismatched types
   --> $DIR/casts-differing-anon.rs:21:13
    |
+LL | fn foo() -> Box<impl fmt::Debug+?Sized> {
+   |                 ---------------------- the found opaque type
+...
+LL | fn bar() -> Box<impl fmt::Debug+?Sized> {
+   |                 ---------------------- the expected opaque type
+...
 LL |     b_raw = f_raw as *mut _;
-   |             ^^^^^^^^^^^^^^^
+   |             ^^^^^ expected opaque type, found a different opaque type
    |
-   = note: vtable kinds may not match
+   = note: expected opaque type `impl Debug + ?Sized` (opaque type at <$DIR/casts-differing-anon.rs:7:17>)
+              found opaque type `impl Debug + ?Sized` (opaque type at <$DIR/casts-differing-anon.rs:3:17>)
+   = note: distinct uses of `impl Trait` result in different opaque types
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0606`.
+For more information about this error, try `rustc --explain E0308`.
index bb00465758a4599de8d716969bf2a334989e8e5c..46379a3815a4db9b32188fdefbdc813025176b08 100644 (file)
@@ -8,10 +8,10 @@ LL |        println!("{:?}", p);
    |                         - `p` is borrowed here
    |
 note: closure is returned here
-  --> $DIR/borrowck-4.rs:8:14
+  --> $DIR/borrowck-4.rs:15:5
    |
-LL | fn foo () -> impl FnMut()->() {
-   |              ^^^^^^^^^^^^^^^^
+LL |     c
+   |     ^
 help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword
    |
 LL |     let mut c = move || {
index 357dd25389ecbbed2969ac430dd4b2990f30ef13..e5aef04b6894eaf1b3a9805eb95e812535754894 100644 (file)
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
 LL | extern "路濫狼á́́" fn foo() {}
    |        ^^^^^^^^^ invalid ABI
    |
-   = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+   = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
 
 error: aborting due to previous error
 
index 63a4df242f85f9897247a8b24d4101dd16eaeb35..9dc486980aaca215af8098ac8f9d187ef8e0c4ed 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: `()` is not an iterator
-  --> $DIR/conservative_impl_trait.rs:3:33
+  --> $DIR/conservative_impl_trait.rs:3:60
    |
-LL | fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+LL |   fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
+   |  ____________________________________________________________^
+LL | |
+LL | | }
+   | |_^ `()` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `()`
 
index 308c121a94111ad86386d09611be0325e5fede06..b3bd88ad7d5d8dd3e592978fcbc12a83a56bb394 100644 (file)
@@ -4,8 +4,8 @@ trait Trait {}
 impl<const N: u32> Trait for Uwu<N> {}
 
 fn rawr() -> impl Trait {
-    //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
     Uwu::<10, 12>
+    //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
 }
 
 trait Traitor<const N: u8 = 1, const M: u8 = N> { }
@@ -15,13 +15,13 @@ impl Traitor<1, 2> for u64 {}
 
 
 fn uwu<const N: u8>() -> impl Traitor<N> {
-    //~^ error: the trait bound `u32: Traitor<N, N>` is not satisfied
     1_u32
+    //~^ error: the trait bound `u32: Traitor<N, N>` is not satisfied
 }
 
 fn owo() -> impl Traitor {
-    //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
     1_u64
+    //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
 }
 
 fn main() {
index 8c8bfdc0e4847a82fb8c79c164ff78af1ed60cc8..ec23952114cdfc0a6960cac6762acb13ae0b09a4 100644 (file)
@@ -1,26 +1,26 @@
 error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
-  --> $DIR/rp_impl_trait_fail.rs:6:14
+  --> $DIR/rp_impl_trait_fail.rs:7:5
    |
-LL | fn rawr() -> impl Trait {
-   |              ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>`
+LL |     Uwu::<10, 12>
+   |     ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>`
    |
    = help: the following implementations were found:
              <Uwu<N> as Trait>
 
 error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied
-  --> $DIR/rp_impl_trait_fail.rs:17:26
+  --> $DIR/rp_impl_trait_fail.rs:18:5
    |
-LL | fn uwu<const N: u8>() -> impl Traitor<N> {
-   |                          ^^^^^^^^^^^^^^^ the trait `Traitor<N, N>` is not implemented for `u32`
+LL |     1_u32
+   |     ^^^^^ the trait `Traitor<N, N>` is not implemented for `u32`
    |
    = help: the following implementations were found:
              <u32 as Traitor<N, 2_u8>>
 
 error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
-  --> $DIR/rp_impl_trait_fail.rs:22:13
+  --> $DIR/rp_impl_trait_fail.rs:23:5
    |
-LL | fn owo() -> impl Traitor {
-   |             ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64`
+LL |     1_u64
+   |     ^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64`
    |
    = help: the following implementations were found:
              <u64 as Traitor<1_u8, 2_u8>>
index 6724984d8d7ac1f26f023cecc3e3bed91dc9488f..d301f8c4054c23bb901cac12cc877926b3a90607 100644 (file)
@@ -6,6 +6,10 @@ LL | const TUP: (usize,) = 5usize << 64;
    |
    = note: expected tuple `(usize,)`
                found type `usize`
+help: use a trailing comma to create a tuple with one element
+   |
+LL | const TUP: (usize,) = (5usize << 64,);
+   |                       +            ++
 
 error: aborting due to previous error
 
index d652b5268a8bf3594c8743eab58ca184713245d2..7d9e18cb341f38330e3e99e141386cf3fdeb935e 100644 (file)
@@ -4,7 +4,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
 LL | const fn test1<T: std::ops::Add>() {}
    |                ^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -13,7 +13,7 @@ error[E0658]: trait objects in const fn are unstable
 LL | const fn test2(_x: &dyn Send) {}
    |                ^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -22,7 +22,7 @@ error[E0658]: trait objects in const fn are unstable
 LL | const fn test3() -> &'static dyn Send { loop {} }
    |                     ^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
index fd1ab6f64bf56fe3f05a729de7f7c995b18c1be7..67cb604b6a7be0344258766ec7b3bd21478ab4d8 100644 (file)
@@ -136,7 +136,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
 LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
    |                ^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
@@ -145,7 +145,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
 LL | const fn foo11_2<T: Send>(t: T) -> T { t }
    |                  ^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0013]: constant functions cannot refer to statics
@@ -218,7 +218,7 @@ LL |
 LL |     const fn foo(&self) {}
    |     ------------------- function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
@@ -230,7 +230,7 @@ LL |
 LL |     const fn foo2(&self) {}
    |     -------------------- function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
@@ -242,7 +242,7 @@ LL |
 LL |     const fn foo3(&self) {}
    |     -------------------- function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
@@ -251,7 +251,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
 LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
    |                                  ^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
@@ -268,7 +268,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
 LL | const fn no_apit(_x: impl std::fmt::Debug) {}
    |                      ^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
@@ -285,7 +285,7 @@ error[E0658]: trait objects in const fn are unstable
 LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
    |                       ^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -294,7 +294,7 @@ error[E0658]: trait objects in const fn are unstable
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -305,7 +305,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1
    | |
    | function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -316,7 +316,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1
    | |
    | function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -327,7 +327,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1
    | |
    | function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: function pointers cannot appear in constant functions
index 6eec1df5aeca7ba9fb942827b42f7078ff287237..4c2199101d302318385feb16278201b7722667a8 100644 (file)
@@ -6,7 +6,7 @@ LL | const fn no_inner_dyn_trait2(x: Hide) {
 LL |     x.0.field;
    |     ^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error[E0658]: trait objects in const fn are unstable
@@ -17,7 +17,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    | |
    | function declared as const here
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
index e0bb7dbfae9f1f793113f91a5ea60b519adfa496..eab5a6190ef51a0d62d4039bc6cb15ed1a67bfb2 100644 (file)
@@ -4,11 +4,9 @@
 //~^^^ ERROR `main` function not found in crate
 pub mod foo {
     type MainFn = impl Fn();
-    //~^ ERROR could not find defining uses
 
     fn bar() {}
     pub const BAR: MainFn = bar;
-    //~^ ERROR mismatched types [E0308]
 }
 
 use foo::BAR as main;
index c731c32832222f7d480fadea359dd2a641920362..83a189e01e0132b8dc98ce68cdb4ca2f56ce97c4 100644 (file)
@@ -12,25 +12,6 @@ LL | | use foo::BAR as main;
    |       |
    |       non-function item at `crate::main` is found
 
-error[E0308]: mismatched types
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:29
-   |
-LL |     type MainFn = impl Fn();
-   |                   --------- the expected opaque type
-...
-LL |     pub const BAR: MainFn = bar;
-   |                             ^^^ expected opaque type, found fn item
-   |
-   = note: expected opaque type `impl Fn()`
-                  found fn item `fn() {bar}`
-
-error: could not find defining uses
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:6:19
-   |
-LL |     type MainFn = impl Fn();
-   |                   ^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0601.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.rs b/src/test/ui/feature-gates/feature-gate-allow_fail.rs
deleted file mode 100644 (file)
index 287d4cc..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// check that #[allow_fail] is feature-gated
-
-#[allow_fail] //~ ERROR the `#[allow_fail]` attribute is an experimental feature
-fn ok_to_fail() {
-    assert!(false);
-}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr
deleted file mode 100644 (file)
index 76115fb..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[allow_fail]` attribute is an experimental feature
-  --> $DIR/feature-gate-allow_fail.rs:3:1
-   |
-LL | #[allow_fail]
-   | ^^^^^^^^^^^^^
-   |
-   = note: see issue #46488 <https://github.com/rust-lang/rust/issues/46488> for more information
-   = help: add `#![feature(allow_fail)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index ea82837d4bf55364de91c9d446cbe7fcacfbae4c..6dfd7f6840f1b8807daef10c35f9dc063d8b9c84 100644 (file)
@@ -1,13 +1,13 @@
 // ignore-compare-mode-chalk
+// check-pass
 #![feature(type_alias_impl_trait)]
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR could not find defining uses
 
 struct Bar(Foo);
 fn define() -> Bar {
-    Bar(42) //~ ERROR mismatched types
+    Bar(42)
 }
 
 type Foo2 = impl Debug;
@@ -17,21 +17,18 @@ fn define2() {
 }
 
 type Foo3 = impl Debug;
-//~^ ERROR could not find defining uses
 
 fn define3(x: Foo3) {
-    let y: i32 = x; //~ ERROR mismatched types
+    let y: i32 = x;
 }
 fn define3_1() {
-    define3(42) //~ ERROR mismatched types
+    define3(42)
 }
 
 type Foo4 = impl Debug;
-//~^ ERROR could not find defining uses
 
 fn define4() {
     let y: Foo4 = 42;
-    //~^ ERROR mismatched types [E0308]
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
deleted file mode 100644 (file)
index da3ddb1..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:10:9
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL |     Bar(42)
-   |         ^^ expected opaque type, found integer
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:23:18
-   |
-LL | type Foo3 = impl Debug;
-   |             ---------- the found opaque type
-...
-LL |     let y: i32 = x;
-   |            ---   ^ expected `i32`, found opaque type
-   |            |
-   |            expected due to this
-   |
-   = note:     expected type `i32`
-           found opaque type `impl Debug`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:26:13
-   |
-LL | type Foo3 = impl Debug;
-   |             ---------- the expected opaque type
-...
-LL |     define3(42)
-   |             ^^ expected opaque type, found integer
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:33:19
-   |
-LL | type Foo4 = impl Debug;
-   |             ---------- the expected opaque type
-...
-LL |     let y: Foo4 = 42;
-   |            ----   ^^ expected opaque type, found integer
-   |            |
-   |            expected due to this
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error: could not find defining uses
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:19:13
-   |
-LL | type Foo3 = impl Debug;
-   |             ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13
-   |
-LL | type Foo4 = impl Debug;
-   |             ^^^^^^^^^^
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.rs b/src/test/ui/fmt/format-args-capture-issue-93378.rs
new file mode 100644 (file)
index 0000000..6744444
--- /dev/null
@@ -0,0 +1,11 @@
+fn main() {
+    let a = "a";
+    let b = "b";
+
+    println!("{a} {b} {} {} {c} {}", c = "c");
+    //~^ ERROR: invalid reference to positional arguments 1 and 2 (there is 1 argument)
+
+    let n = 1;
+    println!("{a:.n$} {b:.*}");
+    //~^ ERROR: invalid reference to positional argument 0 (no arguments were given)
+}
diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.stderr b/src/test/ui/fmt/format-args-capture-issue-93378.stderr
new file mode 100644 (file)
index 0000000..5885410
--- /dev/null
@@ -0,0 +1,22 @@
+error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
+  --> $DIR/format-args-capture-issue-93378.rs:5:26
+   |
+LL |     println!("{a} {b} {} {} {c} {}", c = "c");
+   |                          ^^     ^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional argument 0 (no arguments were given)
+  --> $DIR/format-args-capture-issue-93378.rs:9:23
+   |
+LL |     println!("{a:.n$} {b:.*}");
+   |               ------- ^^^--^
+   |               |          |
+   |               |          this precision flag adds an extra required argument at position 0, which is why there are 3 arguments expected
+   |               this parameter corresponds to the precision flag
+   |
+   = note: positional arguments are zero-based
+   = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
+
+error: aborting due to 2 previous errors
+
index e830a5bc9c5c86947d40cbb331377b23beb9b233..d31d2a6c33657fff6b4975c399e33784cea5ccb2 100644 (file)
@@ -5,6 +5,7 @@ fn main() {
     named_argument_takes_precedence_to_captured();
     formatting_parameters_can_be_captured();
     capture_raw_strings_and_idents();
+    repeated_capture();
 
     #[cfg(panic = "unwind")]
     {
@@ -80,3 +81,10 @@ fn formatting_parameters_can_be_captured() {
     let s = format!("{x:-^width$.precision$}");
     assert_eq!(&s, "--7.000--");
 }
+
+fn repeated_capture() {
+    let a = 1;
+    let b = 2;
+    let s = format!("{a} {b} {a}");
+    assert_eq!(&s, "1 2 1");
+}
index ce9159b53e0f0a5b147e1e5f87df731e217e10ef..c4905995a860a59187a6a4779703efd49c78b4b4 100644 (file)
@@ -6,10 +6,10 @@
 use std::ops::Generator;
 
 fn foo(bar: bool) -> impl Generator<(bool,)> {
-//~^ ERROR: type mismatch in generator arguments [E0631]
-//~| NOTE: expected signature of `fn((bool,)) -> _`
     |bar| {
     //~^ NOTE: found signature of `fn(bool) -> _`
+    //~| ERROR: type mismatch in generator arguments [E0631]
+    //~| NOTE: expected signature of `fn((bool,)) -> _`
         if bar {
             yield bar;
         }
index 5bd8ad129fef908d874662b5f04500e772afe288..eaa90a8e60a2351e542a2cc9ff6d98d769850b7a 100644 (file)
@@ -1,11 +1,11 @@
 error[E0631]: type mismatch in generator arguments
-  --> $DIR/issue-88653.rs:8:22
+  --> $DIR/issue-88653.rs:9:5
    |
-LL | fn foo(bar: bool) -> impl Generator<(bool,)> {
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _`
-...
 LL |     |bar| {
-   |     ----- found signature of `fn(bool) -> _`
+   |     ^^^^^
+   |     |
+   |     expected signature of `fn((bool,)) -> _`
+   |     found signature of `fn(bool) -> _`
 
 error: aborting due to previous error
 
index 7774ff48f56b730b7bdc028dccf03771e07cee1e..d1b16b6e10da0fe05f5727e4e61cdb17d01ea137 100644 (file)
@@ -2,8 +2,8 @@
 
 use std::ops::Generator;
 
-fn foo() -> impl Generator<Return = i32> { //~ ERROR type mismatch
-    || {
+fn foo() -> impl Generator<Return = i32> {
+    || { //~ ERROR type mismatch
         if false {
             return Ok(6);
         }
index 3f1f33a3b123f40361e4d54bcbc01667e044a307..3e78e5b53ba1fe818ec46970fc37e16fe33ed7ff 100644 (file)
@@ -13,13 +13,19 @@ LL |             return Ok(6);
    |                    ^^^^^
 
 error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32`
-  --> $DIR/type-mismatch-signature-deduction.rs:5:13
+  --> $DIR/type-mismatch-signature-deduction.rs:6:5
    |
-LL | fn foo() -> impl Generator<Return = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result`
+LL | /     || {
+LL | |         if false {
+LL | |             return Ok(6);
+LL | |         }
+...  |
+LL | |         5
+LL | |     }
+   | |_____^ expected enum `Result`, found `i32`
    |
-   = note: expected type `i32`
-              found enum `Result<{integer}, _>`
+   = note: expected enum `Result<{integer}, _>`
+              found type `i32`
 
 error: aborting due to 2 previous errors
 
index d9d17751fa6e25bdbb696e22945f49d987cc723c..c65f3fb2aa0a114aa6edc8a3c8dfd3869e8070e7 100644 (file)
@@ -16,7 +16,8 @@ pub trait Trait2 {
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = impl Trait1;
-    fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR
+    //~^ ERROR unconstrained opaque type
+    fn foo<'a>() -> Self::FooFuture<'a> {
         Struct(unimplemented!())
     }
 }
index 93513a4563f0701ce01eea50ff8a77c2bb040899..db3a5c819cbf3d7d317f533e3ac33a30fd84f130 100644 (file)
@@ -1,11 +1,10 @@
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/issue-87258_a.rs:19:21
+error: unconstrained opaque type
+  --> $DIR/issue-87258_a.rs:18:26
    |
-LL |     fn foo<'a>() -> Self::FooFuture<'a> {
-   |                     ^^^^^^^^^^^^^^^^^^^
+LL |     type FooFuture<'a> = impl Trait1;
+   |                          ^^^^^^^^^^^
    |
-   = note: hidden type `Struct<'_>` captures lifetime '_#7r
+   = note: `FooFuture` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0700`.
index b29a978f517fffdf9e22dbd01c9daa6beb721f2e..f59e0d7665942f7cc68fe1df2b93c62b9b422e05 100644 (file)
@@ -15,10 +15,11 @@ pub trait Trait2 {
 }
 
 type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
+//~^ ERROR unconstrained opaque type
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = Helper<'c, 'a, S>;
-    fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR
+    fn foo<'a>() -> Self::FooFuture<'a> {
         Struct(unimplemented!())
     }
 }
index e077a423400dfe74c9a035a0ecca4b8103d1d40d..9faccc96124bc9648c915ce51078e78bdb48587b 100644 (file)
@@ -1,11 +1,10 @@
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/issue-87258_b.rs:21:21
+error: unconstrained opaque type
+  --> $DIR/issue-87258_b.rs:17:49
    |
-LL |     fn foo<'a>() -> Self::FooFuture<'a> {
-   |                     ^^^^^^^^^^^^^^^^^^^
+LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
+   |                                                 ^^^^^^^^^^^
    |
-   = note: hidden type `Struct<'_>` captures lifetime '_#7r
+   = note: `Helper` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0700`.
index e397390783f66857560e8be8ad68f9dda875d229..ea1bd2be4529d238096d67386b64e1f0872a6f81 100644 (file)
@@ -18,7 +18,6 @@ trait A<'a> {
 impl<'a> A<'a> for C {
     type B<'b> = impl Clone;
     //~^ ERROR: lifetime bound not satisfied
-    //~| ERROR: could not find defining uses
 
     fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
 }
index cb462871ccd32b7ce26f81ece5e897455eef32b9..e1d55fa228c2efe696621558719839bf9bdef054 100644 (file)
@@ -16,10 +16,10 @@ LL |     type B<'b> = impl Clone;
    |            ^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-88595.rs:23:23
+  --> $DIR/issue-88595.rs:22:35
    |
 LL |     fn a(&'a self) -> Self::B<'a> {}
-   |                       ^^^^^^^^^^^
+   |                                   ^^
    |
 note: lifetime used multiple times
   --> $DIR/issue-88595.rs:18:6
@@ -29,12 +29,6 @@ LL | impl<'a> A<'a> for C {
 LL |     type B<'b> = impl Clone;
    |            ^^
 
-error: could not find defining uses
-  --> $DIR/issue-88595.rs:19:18
-   |
-LL |     type B<'b> = impl Clone;
-   |                  ^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0478`.
index 72ade5774d749898fba7524c13e2a95cbcf6c42f..f8c89829e1646760dbebe5ea832c34b7406f707d 100644 (file)
@@ -1,18 +1,20 @@
 error[E0311]: the parameter type `C` may not live long enough
-  --> $DIR/issue-92096.rs:20:33
+  --> $DIR/issue-92096.rs:24:5
    |
 LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
-   |                 -               ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
-   |                 |
-   |                 help: consider adding an explicit lifetime bound...: `C: 'a`
+   |                 - help: consider adding an explicit lifetime bound...: `C: 'a`
+...
+LL |     async move { c.connect().await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
 
 error[E0311]: the parameter type `C` may not live long enough
-  --> $DIR/issue-92096.rs:20:33
+  --> $DIR/issue-92096.rs:24:5
    |
 LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
-   |                 -               ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
-   |                 |
-   |                 help: consider adding an explicit lifetime bound...: `C: 'a`
+   |                 - help: consider adding an explicit lifetime bound...: `C: 'a`
+...
+LL |     async move { c.connect().await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
index 066132a5d98bb8bea0323094eb2f72dcf672b3e2..2bc1af5506ffd50876bd11eb68b819021799bc33 100644 (file)
@@ -18,12 +18,12 @@ trait Client {
 }
 
 fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
-//[migrate]~^ ERROR the parameter
-//[migrate]~| ERROR the parameter
 where
     C: Client + Send + Sync,
 {
     async move { c.connect().await }
+    //[migrate]~^ ERROR the parameter
+    //[migrate]~| ERROR the parameter
 }
 
 fn main() {}
index c2fbbf94fd66623678df17d392e4507993b2330e..d2452abab02549987b5352dfcd8624a60d307108 100644 (file)
@@ -11,6 +11,7 @@ fn main() {
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
+    //~| ERROR cycle detected
     send(cycle2().clone());
 
     Rc::new(Cell::new(5))
index 634ff14869eb4d371384f31a382a5d4b93a66005..14db864f1c28af51ad3dcbf60085e9860f920818 100644 (file)
@@ -30,47 +30,129 @@ note: ...which requires building MIR for `cycle1`...
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:14:5
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires computing type of `cycle2::{opaque#0}`...
+  --> $DIR/auto-trait-leak.rs:20:16
+   |
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires borrow-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing MIR for `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/auto-trait-leak.rs:1:1
+   |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+...  |
+LL | |     Rc::new(String::from("foo"))
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
+  --> $DIR/auto-trait-leak.rs:12:16
    |
-LL |     send(cycle2().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
+   |
+note: ...which requires borrow-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing MIR for `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:19:16
+  --> $DIR/auto-trait-leak.rs:20:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:5
+  --> $DIR/auto-trait-leak.rs:20:1
    |
-LL |     send(cycle1().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:1:1
@@ -84,6 +166,6 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
index cf2773f4ef59dc921a6e919aab056bb13c89f94a..35994e4a5ba3f5b7556ef82e9cbb6c0def9e12e6 100644 (file)
@@ -19,7 +19,7 @@ impl<T: Send> AnotherTrait for T {}
 // (We treat opaque types as "foreign types" that could grow more impls
 // in the future.)
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
 }
 
 fn main() {}
index 26cd8fb6a9b5c44ecfab90bc567522a4b2a025f3..81009413c9a268f550e356fe32381bf0e3526a88 100644 (file)
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
   --> $DIR/auto-trait.rs:21:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
 
 error: aborting due to previous error
 
index 8ec06e534d14336bd569ab85a615539a542475b3..20ddad0547ef2b8eddf2db970ab1427360ac24ce 100644 (file)
@@ -23,8 +23,8 @@ trait Trait {
 
     /// `T::Assoc` can't be normalized any further here.
     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
-        //~^ ERROR: type mismatch
         Foo(())
+        //~^ ERROR: type mismatch
     }
 }
 
@@ -39,9 +39,9 @@ trait Trait<'a> {
 
     /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
-        //~^ ERROR: type mismatch
-        //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+        //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
         Foo(())
+        //~^ ERROR: type mismatch
     }
 }
 
index afa21c1a858a2efe714f0a471403d0171b6834be..01fb853e1d1f7b568846dbac312974818acd8cfc 100644 (file)
@@ -1,16 +1,16 @@
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:25:32
+  --> $DIR/bound-normalization-fail.rs:26:9
    |
-LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+LL |         Foo(())
+   |         ^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
    |
-note: expected this to be `<T as impl_trait::Trait>::Assoc`
+note: expected this to be `()`
   --> $DIR/bound-normalization-fail.rs:14:19
    |
 LL |     type Output = T;
    |                   ^
-   = note: expected associated type `<T as impl_trait::Trait>::Assoc`
-                    found unit type `()`
+   = note:    expected unit type `()`
+           found associated type `<T as impl_trait::Trait>::Assoc`
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
@@ -23,18 +23,18 @@ LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:41:41
+  --> $DIR/bound-normalization-fail.rs:43:9
    |
-LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
+LL |         Foo(())
+   |         ^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
    |
-note: expected this to be `<T as lifetimes::Trait<'static>>::Assoc`
+note: expected this to be `()`
   --> $DIR/bound-normalization-fail.rs:14:19
    |
 LL |     type Output = T;
    |                   ^
-   = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc`
-                    found unit type `()`
+   = note:    expected unit type `()`
+           found associated type `<T as lifetimes::Trait<'static>>::Assoc`
 help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
    |
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
index f4bd0fde3b6cbfe73efcf94692ea4e95b6002a67..750687e2322284fc055ad262e08b0edd6254ed10 100644 (file)
@@ -7,10 +7,10 @@ LL |         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref
    |                                 may outlive borrowed value `prefix`
    |
 note: closure is returned here
-  --> $DIR/does-not-live-long-enough.rs:5:55
+  --> $DIR/does-not-live-long-enough.rs:6:9
    |
-LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: to force the closure to take ownership of `prefix` (and any other referenced variables), use the `move` keyword
    |
 LL |         self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref())
index 9610618ca11f65f47880ea724d092bed83d6d31b..59770c10da2b2e14ab039a20c45618bc5283208d 100644 (file)
@@ -17,8 +17,8 @@ fn two(x: bool) -> impl Foo {
     //~| expected `i32`, found `u32`
 }
 
-fn sum_to(n: u32) -> impl Foo { //~ ERROR type annotations needed
-    if n == 0 {
+fn sum_to(n: u32) -> impl Foo {
+    if n == 0 { //~ ERROR type annotations needed
         0
     } else {
         n + sum_to(n - 1)
index d9819484a96126123a268201d97d08ef87b8e2b9..4032fbbceba4ce27dc5b930a86fc14d719a81748 100644 (file)
@@ -12,19 +12,13 @@ error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
 LL | fn two(x: bool) -> impl Foo {
-   |                    -------- expected because this return type...
-LL |     if x {
-LL |         return 1_i32;
-   |                ----- ...is found to be `i32` here
-LL |     }
+   |                    -------- the expected opaque type
+...
 LL |     0_u32
    |     ^^^^^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = help: if the trait `Foo` were object safe, you could return a boxed trait object
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
+   = note: expected opaque type `impl Foo`
+                     found type `u32`
 
 error[E0277]: cannot add `impl Foo` to `u32`
   --> $DIR/equality.rs:24:11
@@ -35,10 +29,15 @@ LL |         n + sum_to(n - 1)
    = help: the trait `Add<impl Foo>` is not implemented for `u32`
 
 error[E0283]: type annotations needed
-  --> $DIR/equality.rs:20:22
-   |
-LL | fn sum_to(n: u32) -> impl Foo {
-   |                      ^^^^^^^^ cannot infer type for type `{integer}`
+  --> $DIR/equality.rs:21:5
+   |
+LL | /     if n == 0 {
+LL | |         0
+LL | |     } else {
+LL | |         n + sum_to(n - 1)
+LL | |
+LL | |     }
+   | |_____^ cannot infer type for type `{integer}`
    |
    = note: multiple `impl`s satisfying `{integer}: ToString` found in the `alloc` crate:
            - impl ToString for i8;
index 46053c6e7c1196f4cb10eb13c4814751856b6f33..fd33fa7c674f185e97a24a70987892b6e9af0b95 100644 (file)
@@ -15,9 +15,7 @@ LL | fn hide<T: Foo>(x: T) -> impl Foo {
    |                          -------- the found opaque type
 ...
 LL |     let _: u32 = hide(0_u32);
-   |            ---   ^^^^^^^^^^^ expected `u32`, found opaque type
-   |            |
-   |            expected due to this
+   |                  ^^^^^^^^^^^ expected `u32`, found opaque type
    |
    = note:     expected type `u32`
            found opaque type `impl Foo`
diff --git a/src/test/ui/impl-trait/fallback.rs b/src/test/ui/impl-trait/fallback.rs
new file mode 100644 (file)
index 0000000..1e6eb5b
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+
+fn take_edge_counters(
+    x: &mut Option<Vec<i32>>,
+) -> Option<impl Iterator<Item = i32>> {
+    x.take().map_or(None, |m| Some(m.into_iter()))
+}
+
+fn main() {}
index 2ee004a37a6fc2568a37afbdc387d45f5f368ba5..ae07c89276861140342005edf0fa90f54650ad45 100644 (file)
@@ -26,8 +26,8 @@ fn swap(self, other: Self) {
 // Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and
 // `&'a mut &'l T` are the same type.
 fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
-    //~^ ERROR hidden type
     x
+    //~^ ERROR hidden type
 }
 
 fn dangle_ref() -> &'static [i32; 3] {
@@ -43,8 +43,8 @@ fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
 // This is different to the previous example because the concrete return type
 // only has a single lifetime.
 fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
-    //~^ ERROR hidden type
     x
+    //~^ ERROR hidden type
 }
 
 fn dangle_rc_refcell() -> &'static [i32; 3] {
index c6d11293eec530c3f86c4c59123d8d0d891da1e6..97652f5462ef02487b72a2c6dc7588a4eed0f37d 100644 (file)
@@ -1,10 +1,10 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-lifetimes.rs:28:54
+  --> $DIR/hidden-lifetimes.rs:29:5
    |
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
-   |                 --                                   ^^^^^^^^^^^^^^
-   |                 |
-   |                 hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
+   |                 -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
@@ -12,12 +12,12 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
    |                                                                     ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-lifetimes.rs:45:70
+  --> $DIR/hidden-lifetimes.rs:46:5
    |
 LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
-   |                        --                                            ^^^^^^^^^^^^^^
-   |                        |
-   |                        hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+   |                        -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
index 46188636475db0362549d659208bef75878f060a..a75b9b43b3e8bae8b0544bd387dab33c1348d104 100644 (file)
@@ -10,11 +10,10 @@ impl<S: Default> Bar for S {
     type E = impl Copy;
 
     fn foo<T: Default>() -> Self::E {
-        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-        //~| ERROR impl has stricter requirements than trait
-        //~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
-        //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
+        //~^ ERROR impl has stricter requirements than trait
         (S::default(), T::default())
+        //~^ ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
+        //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
     }
 }
 
index 2d1142fd0c52cff2e0c8db7b6adf44d6a8f0458c..efc57da746132600900295431238ac4498bf995d 100644 (file)
@@ -8,10 +8,10 @@ LL |     fn foo<T: Default>() -> Self::E {
    |               ^^^^^^^ impl has extra requirement `T: Default`
 
 error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:29
+  --> $DIR/issue-55872-1.rs:14:9
    |
-LL |     fn foo<T: Default>() -> Self::E {
-   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
+LL |         (S::default(), T::default())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
    |
    = note: required because it appears within the type `(S, T)`
 help: consider further restricting this bound
@@ -20,10 +20,10 @@ LL | impl<S: Default + std::marker::Copy> Bar for S {
    |                 +++++++++++++++++++
 
 error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:29
+  --> $DIR/issue-55872-1.rs:14:9
    |
-LL |     fn foo<T: Default>() -> Self::E {
-   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
+LL |         (S::default(), T::default())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `(S, T)`
 help: consider further restricting this bound
@@ -31,20 +31,7 @@ help: consider further restricting this bound
 LL |     fn foo<T: Default + std::marker::Copy>() -> Self::E {
    |                       +++++++++++++++++++
 
-error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-1.rs:12:37
-   |
-LL |       fn foo<T: Default>() -> Self::E {
-   |  _____________________________________^
-LL | |
-LL | |
-LL | |
-LL | |
-LL | |         (S::default(), T::default())
-LL | |     }
-   | |_____^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0276, E0277.
 For more information about an error, try `rustc --explain E0276`.
index a519397806e0703ee7e83076dc191016722e607f..f0bc0b5272784dbfcf73c1bafdd92b6424aacf30 100644 (file)
@@ -4,17 +4,16 @@
 #![feature(type_alias_impl_trait)]
 
 pub trait Bar {
-    type E: Copy;
+    type E: Send;
 
     fn foo<T>() -> Self::E;
 }
 
 impl<S> Bar for S {
-    type E = impl std::marker::Copy;
+    type E = impl std::marker::Send;
     fn foo<T>() -> Self::E {
-        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-        //~| ERROR the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied
         async {}
+        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
index 97545ba3d1124c755df086a10ff9195b445ef00f..71090bdbf8061909314c83d226b5f9125424b410 100644 (file)
@@ -1,20 +1,8 @@
-error[E0277]: the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied
-  --> $DIR/issue-55872-2.rs:14:20
-   |
-LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = [async output]>`
-
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-2.rs:14:28
+  --> $DIR/issue-55872-2.rs:15:9
    |
-LL |       fn foo<T>() -> Self::E {
-   |  ____________________________^
-LL | |
-LL | |
-LL | |         async {}
-LL | |     }
-   | |_____^
+LL |         async {}
+   |         ^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issue-55872-3.rs b/src/test/ui/impl-trait/issue-55872-3.rs
new file mode 100644 (file)
index 0000000..f50b31f
--- /dev/null
@@ -0,0 +1,20 @@
+// edition:2018
+// ignore-compare-mode-chalk
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Bar {
+    type E: Copy;
+
+    fn foo<T>() -> Self::E;
+}
+
+impl<S> Bar for S {
+    type E = impl std::marker::Copy;
+    fn foo<T>() -> Self::E {
+        async {}
+        //~^ ERROR the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied [E0277]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55872-3.stderr b/src/test/ui/impl-trait/issue-55872-3.stderr
new file mode 100644 (file)
index 0000000..bafd31f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied
+  --> $DIR/issue-55872-3.rs:15:9
+   |
+LL |         async {}
+   |         ^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = [async output]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index bbd940254178ce45ffe4dfff6ec5c35b8808f50d..65874d22ac6f3c92ae393da33488a801f334dce9 100644 (file)
@@ -11,8 +11,8 @@ impl<S> Bar for S {
     type E = impl Copy;
 
     fn foo<T>() -> Self::E {
-        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         || ()
+        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
index 60654ec34610fc24321c244905b55dc66950a454..7abcf6a05942268c5eb875a073fc3663497ef653 100644 (file)
@@ -1,12 +1,8 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872.rs:13:28
+  --> $DIR/issue-55872.rs:14:9
    |
-LL |       fn foo<T>() -> Self::E {
-   |  ____________________________^
-LL | |
-LL | |         || ()
-LL | |     }
-   | |_____^
+LL |         || ()
+   |         ^^^^^
 
 error: aborting due to previous error
 
index dee5a41f6de375d30f06611cc23677ea8770498f..cf2c8b7e415408faac524e65a15070252072d169 100644 (file)
@@ -5,7 +5,7 @@ pub struct Lint {}
 impl Lint {}
 
 pub fn gather_all() -> impl Iterator<Item = Lint> {
-    //~^ ERROR: cannot resolve opaque type
+    //~^ ERROR `()` is not an iterator
     lint_files().flat_map(|f| gather_from_file(&f))
 }
 
index e57fbf104dc6f5413643c60337b23cb82eb62bdf..4a990286d966d2c0ad009200b3ce9dbcc496dff8 100644 (file)
@@ -10,25 +10,15 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo`
 LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
    |                                         ^^^ use of undeclared crate or module `foo`
 
-error[E0720]: cannot resolve opaque type
+error[E0277]: `()` is not an iterator
   --> $DIR/issue-72911.rs:7:24
    |
 LL | pub fn gather_all() -> impl Iterator<Item = Lint> {
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type
-LL |
-LL |     lint_files().flat_map(|f| gather_from_file(&f))
-   |     -----------------------------------------------
-   |     |
-   |     returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-   |     returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-...
-LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
-   |                                                      -------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-...
-LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
-   |                    -------------------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0433, E0720.
-For more information about an error, try `rustc --explain E0433`.
+Some errors have detailed explanations: E0277, E0433.
+For more information about an error, try `rustc --explain E0277`.
index 853c2a82bede4b000b4045c55c48cbf2cf15c488..8169cfafac71127665f97b6138b61fea1188f89b 100644 (file)
@@ -4,7 +4,7 @@
 type FooRet = impl std::fmt::Debug;
 
 type FooItem = Box<dyn Fn(FooArg) -> FooRet>;
-type Foo = impl Iterator<Item = FooItem>; //~ ERROR: type mismatch
+type Foo = impl Iterator<Item = FooItem>;
 
 #[repr(C)]
 struct Bar(u8);
@@ -28,7 +28,7 @@ fn ham() -> Foo {
 fn oof() -> impl std::fmt::Debug {
     let mut bar = ham();
     let func = bar.next().unwrap();
-    return func(&"oof");
+    return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type
 }
 
 fn main() {
index fe48e92da5eacc7d44c4a758f24b0413679c0cd3..8813bff3c353e3c656efc75d246b37af50949431 100644 (file)
@@ -1,20 +1,19 @@
-error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-  --> $DIR/issue-70877.rs:7:12
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/issue-70877.rs:31:12
    |
-LL | type FooRet = impl std::fmt::Debug;
-   |               -------------------- the found opaque type
-...
-LL | type Foo = impl Iterator<Item = FooItem>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
+LL |     return func(&"oof");
+   |            ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/issue-70877.rs:28:13
    |
-note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-  --> $DIR/issue-70877.rs:13:17
+LL | fn oof() -> impl std::fmt::Debug {
+   |             ^^^^^^^^^^^^^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/issue-70877.rs:4:15
    |
-LL |     type Item = FooItem;
-   |                 ^^^^^^^
-   = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-              found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
+LL | type FooRet = impl std::fmt::Debug;
+   |               ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0271`.
index bdbd20f9d2b884d500e152aee0cb66e2d947ebe8..b13ab6bad7fbed4e25354efeafa036b46e826ac6 100644 (file)
@@ -10,7 +10,8 @@ fn concrete_use() -> F {
             async {}
         }
         let f: F = async { 1 };
-        //~^ ERROR mismatched types [E0308]
+        //~^ ERROR `async` blocks are not allowed in constants
+        //~| ERROR destructors cannot be evaluated at compile-time
         1
     }],
 }
index 130678de2370cd47ed6978b7c50ef91a15a443d9..975c771759f9ba04bf5fbcd808f0b5fd7f8a7b3a 100644 (file)
@@ -1,23 +1,22 @@
-error[E0308]: mismatched types
+error[E0658]: `async` blocks are not allowed in constants
   --> $DIR/issue-78722.rs:12:20
    |
-LL | type F = impl core::future::Future<Output = u8>;
-   |          -------------------------------------- the expected opaque type
-...
 LL |         let f: F = async { 1 };
-   |                -   ^^^^^^^^^^^ expected opaque type, found a different opaque type
-   |                |
-   |                expected due to this
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |                    ^^^^^^^^^^^
    |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
+   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
+   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/issue-78722.rs:12:13
    |
-   = note: expected opaque type `impl Future<Output = u8>`
-              found opaque type `impl Future<Output = [async output]>`
-   = note: distinct uses of `impl Trait` result in different opaque types
+LL |         let f: F = async { 1 };
+   |             ^ constants cannot evaluate destructors
+...
+LL |     }],
+   |     - value is dropped here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0493, E0658.
+For more information about an error, try `rustc --explain E0493`.
index e3386d29def02eabcb4840186426032754fc1bc0..0786e66ca8b06c6969184d2160f97a18bd5c1a3f 100644 (file)
@@ -1,10 +1,10 @@
 #![feature(unboxed_closures)]
 #![feature(type_alias_impl_trait)]
 
+// check-pass
+
 type FunType = impl Fn<()>;
-//~^ ERROR could not find defining uses
 static STATIC_FN: FunType = some_fn;
-//~^ ERROR mismatched types
 
 fn some_fn() {}
 
diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr
deleted file mode 100644 (file)
index b146009..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-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-88236-2.nll.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr
new file mode 100644 (file)
index 0000000..86323ad
--- /dev/null
@@ -0,0 +1,39 @@
+error: higher-ranked subtype error
+  --> $DIR/issue-88236-2.rs:17:5
+   |
+LL |     &()
+   |     ^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-88236-2.rs:17:5
+   |
+LL |     &()
+   |     ^^^
+
+error: lifetime may not live long enough
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                  -- lifetime `'b` defined here
+LL |     x
+   |     ^ returning this value requires that `'b` must outlive `'static`
+   |
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'b`, add `'b` as a bound
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b {
+   |                                                                                  ++++
+
+error: higher-ranked subtype error
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL |     x
+   |     ^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL |     x
+   |     ^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs
new file mode 100644 (file)
index 0000000..f89ab7f
--- /dev/null
@@ -0,0 +1,23 @@
+// this used to cause stack overflows
+
+trait Hrtb<'a> {
+    type Assoc;
+}
+
+impl<'a> Hrtb<'a> for () {
+    type Assoc = ();
+}
+
+impl<'a> Hrtb<'a> for &'a () {
+    type Assoc = ();
+}
+
+fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+    &() //~ ERROR implementation of `Hrtb` is not general enough
+}
+fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+    x //~ ERROR implementation of `Hrtb` is not general enough
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
new file mode 100644 (file)
index 0000000..95c4a52
--- /dev/null
@@ -0,0 +1,20 @@
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:17:5
+   |
+LL |     &()
+   |     ^^^ implementation of `Hrtb` is not general enough
+   |
+   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL |     x
+   |     ^ implementation of `Hrtb` is not general enough
+   |
+   = note: `&()` must implement `Hrtb<'0>`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'_>` is actually implemented for the type `&()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs
new file mode 100644 (file)
index 0000000..2ea3527
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+// this used to cause stack overflows
+
+trait Hrtb<'a> {
+    type Assoc;
+}
+
+impl<'a> Hrtb<'a> for () {
+    type Assoc = ();
+}
+
+impl<'a> Hrtb<'a> for &'a () {
+    type Assoc = ();
+}
+
+fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/lifetimes2.rs b/src/test/ui/impl-trait/lifetimes2.rs
new file mode 100644 (file)
index 0000000..834f2dc
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+pub fn keys<'a>(x: &'a Result<u32, u32>) -> impl std::fmt::Debug + 'a {
+    match x {
+        Ok(map) => Ok(map),
+        Err(map) => Err(map),
+    }
+}
+
+fn main() {}
index 72e9d96da3677fdd96650f93dacd0f477ec5b358..f5aaf1185211b44d67e06cc6b7deffa351b64ea0 100644 (file)
@@ -8,7 +8,6 @@ impl<T: Copy> Copy for CopyIfEq<T, T> {}
 type E<'a, 'b> = impl Sized;
 
 fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
-    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
     let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y);
 
     // This assignment requires that `x` and `y` have the same type due to the
@@ -21,6 +20,7 @@ fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
         let _: &'b i32 = *u.0;
     }
     u.0
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 }
 
 fn main() {}
index 40bec0da2707d589d419fa88b82f9cb64b575084..b837b64110365d47585e9d702a7d52c2f51d33ca 100644 (file)
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/error-handling-2.rs:10:60
+  --> $DIR/error-handling-2.rs:22:5
    |
 LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
-   |        --                                                  ^^^^^^^^^
-   |        |
-   |        hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
+   |        -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
+...
+LL |     u.0
+   |     ^^^
 
 error: aborting due to previous error
 
index 3a97624647efd79be70c7549def20b0c8631c466..47e05bce0f8de747a9f1baa6c588917459f0bf8b 100644 (file)
@@ -14,7 +14,6 @@ impl<T> Trait<'_, '_> for T {}
 // by both `'a` and `'b`.
 
 fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
-//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 where
     'a: 'e,
     'b: 'd,
@@ -27,6 +26,7 @@ fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Tr
     // 'a in ['d, 'e]
     // ```
     if condition() { a } else { b }
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 }
 
 fn condition() -> bool {
index 32829a0a1b2fa60af0e0577a26e32fd92fa4e68b..15476c706a7f2eab942c6a0ef53faea811766d05 100644 (file)
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ordinary-bounds-unrelated.rs:16:74
+  --> $DIR/ordinary-bounds-unrelated.rs:28:33
    |
 LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
-   |                     --                                                   ^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+   |                     -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+...
+LL |     if condition() { a } else { b }
+   |                                 ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
index d4c60a4e89209c883a82972c11c7086f0749ea43..321cb8c92a1774eb825e44c5d681cf48d24a5481 100644 (file)
@@ -16,7 +16,6 @@ impl<T> Trait<'_, '_> for T {}
 // consider the loans for both `'a` and `'b` alive.
 
 fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
-//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 {
     // We return a value:
     //
@@ -30,6 +29,7 @@ fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
     //
     // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
     if condition() { a } else { b }
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 }
 
 fn condition() -> bool {
index 83ad23b253bb3729ebdf6927fbe8ce195ac9e33e..7315aa8e9d4787f617c65d33e42b24eee4614f08 100644 (file)
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ordinary-bounds-unsuited.rs:18:62
+  --> $DIR/ordinary-bounds-unsuited.rs:31:33
    |
 LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
-   |                     --                                       ^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+   |                     -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+...
+LL |     if condition() { a } else { b }
+   |                                 ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
index 2f6bd8ff377a544bdc2f559567cf3e739d62bbc6..eb38f84d4afec35c89c6ba4b691f2fe53d5c553d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:3:23
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----     ^^^^^^^^^
+   |              ----                 ^
    |              |
    |              hidden type `&i32` captures the anonymous lifetime defined here
    |
@@ -12,10 +12,10 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |             --                 ^^^^^^^^^
+   |             --                             ^
    |             |
    |             hidden type `&'a i32` captures the lifetime `'a` as defined here
    |
@@ -67,12 +67,12 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    = help: consider replacing `'a` with `'static`
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:33:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:34:5
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-   |                              --                             ^^^^^^^^^^^^^^^^
-   |                              |
-   |                              hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here
+   |                              -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:34:5: 34:31]` captures the lifetime `'b` as defined here
+LL |     move |_| println!("{}", y)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
@@ -80,10 +80,10 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                                              ++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:38:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:39:5
    |
-LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-   |                                                   ^^^^^^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
index 69d2843ff3f01b0f5184ee1c15209d638ad71a53..02ea0255912ab390240ee006707eaa443e8f8d8a 100644 (file)
@@ -31,13 +31,13 @@ fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERRO
 // Tests that a closure type containing 'b cannot be returned from a type where
 // only 'a was expected.
 fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-    //~^ ERROR: captures lifetime that does not appear in bounds
     move |_| println!("{}", y)
+    //~^ ERROR: captures lifetime that does not appear in bounds
 }
 
 fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-    //~^ ERROR the parameter type `T` may not live long enough
     x
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
index 07ac0a8db35a923946ff2603c0ae527e00714444..77ba0bf908763a90128278f93036c4aa5a8189f7 100644 (file)
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:3:23
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----     ^^^^^^^^^
+   |              ----                 ^
    |              |
    |              hidden type `&i32` captures the anonymous lifetime defined here
    |
@@ -12,10 +12,10 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |             --                 ^^^^^^^^^
+   |             --                             ^
    |             |
    |             hidden type `&'a i32` captures the lifetime `'a` as defined here
    |
@@ -28,15 +28,10 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
   --> $DIR/must_outlive_least_region_or_bound.rs:9:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
-   |               ----                           ^ ...is used here...
+   |               ----                           ^ ...is used and required to live as long as `'static` here
    |               |
    |               this data with an anonymous lifetime `'_`...
    |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:9:24
-   |
-LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
-   |                        ^^^^^^^^^^^^^^^^^^^
 help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
@@ -50,15 +45,10 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:11:55
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-   |                     -------                           ^ ...is used here...
+   |                     -------                           ^ ...is used and required to live as long as `'static` here
    |                     |
    |                     this data with lifetime `'a`...
    |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:11:33
-   |
-LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-   |                                 ^^^^^^^^^^^^^^^^^^^
 help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
@@ -69,10 +59,10 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
    |                     ~~~~~~~~~~~~
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/must_outlive_least_region_or_bound.rs:13:24
+  --> $DIR/must_outlive_least_region_or_bound.rs:13:41
    |
 LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
-   |               ----     ^^^^^^^^^^^^^^ lifetime `'a` required
+   |               ----                      ^ lifetime `'a` required
    |               |
    |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
 
@@ -95,13 +85,8 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:29:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                      ------- this data with lifetime `'a`...        ^ ...is used here...
-   |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:29:34
+   |                      ------- this data with lifetime `'a`...        ^ ...is used and required to live as long as `'static` here
    |
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
@@ -112,12 +97,12 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x
    |                      ~~~~~~~~~~~~
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:33:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:34:5
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-   |                              --                             ^^^^^^^^^^^^^^^^
-   |                              |
-   |                              hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here
+   |                              -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:34:5: 34:31]` captures the lifetime `'b` as defined here
+LL |     move |_| println!("{}", y)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
@@ -125,12 +110,12 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                                              ++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:38:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:39:5
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-   |                                 --                ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-   |                                 |
-   |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
+   |                                 -- help: consider adding an explicit lifetime bound...: `T: 'static +`
+LL |     x
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/must_outlive_least_region_or_bound.rs:16:50
index d173fe83fb7913c35699f933005570245680faac..70e24a3a9d029b946073b198b4d1cbf7583381a1 100644 (file)
@@ -17,7 +17,7 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
 
 // This is in error, because we cannot assume that `OpaqueType: !Debug`
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
 }
 
 fn main() {}
index e39a8e53f7985cbe87b2f75059443eca18c1e88a..6b8cc9e7374239c2c14036bf2ce6bfd6628323ad 100644 (file)
@@ -1,13 +1,13 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
   --> $DIR/negative-reasoning.rs:19:1
    |
 LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
    | ------------------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
    |
-   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `impl OpaqueTrait` in future versions
+   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
 
 error: aborting due to previous error
 
index be2c21a7743ce1e9687c4cf425ab8f141e9cf88f..6eac2dece1f12677ee643ded3eab515470c414a9 100644 (file)
@@ -4,6 +4,7 @@ fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
 
 fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
 //~^ ERROR nested `impl Trait` is not allowed
+//~| ERROR `impl Into<u32>` doesn't implement `Debug`
 
 fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
 //~^ ERROR nested `impl Trait` is not allowed
@@ -16,6 +17,7 @@ fn bad_in_arg_position(_: impl Into<impl Debug>) { }
 impl X {
     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
     //~^ ERROR nested `impl Trait` is not allowed
+    //~| ERROR `impl Into<u32>` doesn't implement `Debug`
 }
 
 fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
index 59c7e4d5f4e92b8aa0a8867f5e04120567f9a026..87ff4ffc4fb17c8b319cf4c794ee6e043dade6d8 100644 (file)
@@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                              outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:8:42
+  --> $DIR/nested_impl_trait.rs:9:42
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ----------^^^^^^^^^^-
@@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:12:37
+  --> $DIR/nested_impl_trait.rs:13:37
    |
 LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
    |                           ----------^^^^^^^^^^-
@@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
    |                           outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:17:44
+  --> $DIR/nested_impl_trait.rs:18:44
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  ----------^^^^^^^^^^-
@@ -35,18 +35,40 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  outer `impl Trait`
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/nested_impl_trait.rs:8:32
+  --> $DIR/nested_impl_trait.rs:9:32
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/nested_impl_trait.rs:25:42
+  --> $DIR/nested_impl_trait.rs:27:42
    |
 LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
    |                                          ^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error[E0277]: `impl Into<u32>` doesn't implement `Debug`
+  --> $DIR/nested_impl_trait.rs:5:70
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                                                      ^ `impl Into<u32>` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider further restricting this bound
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
+   |                                          +++++++++++++++++
+
+error[E0277]: `impl Into<u32>` doesn't implement `Debug`
+  --> $DIR/nested_impl_trait.rs:18:58
+   |
+LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                                          ^ `impl Into<u32>` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider further restricting this bound
+   |
+LL |     fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
+   |                              +++++++++++++++++
+
+error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0562, E0666.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0277, E0562, E0666.
+For more information about an error, try `rustc --explain E0277`.
index 357166d112377aa56b82cfe7a1da18fa4465dbcd..b2f7166f0ae3a19f0311b5bd487dd7354e9b8568 100644 (file)
@@ -2,46 +2,25 @@ error[E0308]: mismatched types
   --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
    |
 LL | fn can() -> impl NotObjectSafe {
-   |             ------------------ expected because this return type...
-LL |     if true {
-LL |         return A;
-   |                - ...is found to be `A` here
-LL |     }
+   |             ------------------ the expected opaque type
+...
 LL |     B
    |     ^ expected struct `A`, found struct `B`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
+   = note: expected opaque type `impl NotObjectSafe`
+                   found struct `B`
 
 error[E0308]: mismatched types
   --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
    |
 LL | fn cat() -> impl ObjectSafe {
-   |             --------------- expected because this return type...
-LL |     if true {
-LL |         return A;
-   |                - ...is found to be `A` here
-LL |     }
+   |             --------------- the expected opaque type
+...
 LL |     B
    |     ^ expected struct `A`, found struct `B`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn cat() -> Box<dyn ObjectSafe> {
-   |             ~~~~~~~           +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         return Box::new(A);
-LL |     }
-LL ~     Box::new(B)
-   |
+   = note: expected opaque type `impl ObjectSafe`
+                   found struct `B`
 
 error: aborting due to 2 previous errors
 
index fa7664a83eee073f7588794011a8f5f73f336117..9f9a6c784e638d64607e03e57c7e70c76db0715e 100644 (file)
@@ -14,10 +14,10 @@ fn bar() -> impl std::fmt::Display {
 }
 
 fn baz() -> impl std::fmt::Display {
-    if false {
+    if false { //~ ERROR mismatched types
         return 0i32;
     } else {
-        1u32 //~ ERROR mismatched types
+        1u32
     }
 }
 
@@ -30,9 +30,9 @@ fn qux() -> impl std::fmt::Display {
 }
 
 fn bat() -> impl std::fmt::Display {
-    match 13 {
+    match 13 { //~ ERROR mismatched types
         0 => return 0i32,
-        _ => 1u32, //~ ERROR mismatched types
+        _ => 1u32,
     }
 }
 
@@ -45,12 +45,12 @@ fn can() -> impl std::fmt::Display {
 }
 
 fn cat() -> impl std::fmt::Display {
-    match 13 {
+    match 13 { //~ ERROR mismatched types
         0 => {
             return 0i32;
         }
         _ => {
-            1u32 //~ ERROR mismatched types
+            1u32
         }
     }
 }
index 970abad5c72e9166c35412786b5fe18803192641..db0d446e559a3415e0876866b7b4e5a1207567b4 100644 (file)
@@ -2,82 +2,40 @@ error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
    |
 LL | fn foo() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     if false {
-LL |         return 0i32;
-   |                ---- ...is found to be `i32` here
-LL |     }
+   |             ---------------------- the expected opaque type
+...
 LL |     1u32
    |     ^^^^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn foo() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         return Box::new(0i32);
-LL |     }
-LL ~     Box::new(1u32)
-   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16
    |
 LL | fn bar() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     if false {
-LL |         return 0i32;
-   |                ---- ...is found to be `i32` here
-LL |     } else {
+   |             ---------------------- the expected opaque type
+...
 LL |         return 1u32;
    |                ^^^^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn bar() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         return Box::new(0i32);
-LL |     } else {
-LL ~         return Box::new(1u32);
-   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9
-   |
-LL | fn baz() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     if false {
-LL |         return 0i32;
-   |                ---- ...is found to be `i32` here
-LL |     } else {
-LL |         1u32
-   |         ^^^^ expected `i32`, found `u32`
-   |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn baz() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:17:5
    |
-LL ~         return Box::new(0i32);
-LL |     } else {
-LL ~         Box::new(1u32)
+LL |   fn baz() -> impl std::fmt::Display {
+   |               ---------------------- the expected opaque type
+LL | /     if false {
+LL | |         return 0i32;
+LL | |     } else {
+LL | |         1u32
+LL | |     }
+   | |_____^ expected `i32`, found `u32`
    |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9
@@ -103,87 +61,50 @@ LL ~         Box::new(1u32)
    |
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14
-   |
-LL | fn bat() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     match 13 {
-LL |         0 => return 0i32,
-   |                     ---- ...is found to be `i32` here
-LL |         _ => 1u32,
-   |              ^^^^ expected `i32`, found `u32`
-   |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn bat() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:33:5
    |
-LL ~         0 => return Box::new(0i32),
-LL ~         _ => Box::new(1u32),
+LL |   fn bat() -> impl std::fmt::Display {
+   |               ---------------------- the expected opaque type
+LL | /     match 13 {
+LL | |         0 => return 0i32,
+LL | |         _ => 1u32,
+LL | |     }
+   | |_____^ expected `i32`, found `u32`
    |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5
    |
 LL |   fn can() -> impl std::fmt::Display {
-   |               ---------------------- expected because this return type...
+   |               ---------------------- the expected opaque type
 LL | /     match 13 {
 LL | |         0 => return 0i32,
-   | |                     ---- ...is found to be `i32` here
 LL | |         1 => 1u32,
 LL | |         _ => 2u32,
 LL | |     }
    | |_____^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn can() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~     Box::new(match 13 {
-LL ~         0 => return Box::new(0i32),
-LL |         1 => 1u32,
-LL |         _ => 2u32,
-LL ~     })
-   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:48:5
    |
-LL | fn cat() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-...
-LL |             return 0i32;
-   |                    ---- ...is found to be `i32` here
-...
-LL |             1u32
-   |             ^^^^ expected `i32`, found `u32`
-   |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn cat() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~             return Box::new(0i32);
-LL |         }
-LL |         _ => {
-LL ~             Box::new(1u32)
+LL |   fn cat() -> impl std::fmt::Display {
+   |               ---------------------- the expected opaque type
+LL | /     match 13 {
+LL | |         0 => {
+LL | |             return 0i32;
+LL | |         }
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ expected `i32`, found `u32`
    |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: `match` arms have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14
@@ -196,16 +117,6 @@ LL | |         1 => 1u32,
 LL | |         _ => 2u32,
 LL | |     }
    | |_____- `match` arms have incompatible types
-   |
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn dog() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         0 => Box::new(0i32),
-LL ~         1 => Box::new(1u32),
-   |
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9
@@ -218,17 +129,6 @@ LL | |         1u32
    | |         ^^^^ expected `i32`, found `u32`
 LL | |     }
    | |_____- `if` and `else` have incompatible types
-   |
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn apt() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         Box::new(0i32)
-LL |     } else {
-LL ~         Box::new(1u32)
-   |
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13
index b4fd6b3e74364d45c81e926c63f4f09213202236..2e7cb21592cb0b714cfacf8a28d7c3b3ce3a859d 100644 (file)
@@ -11,8 +11,8 @@ pub trait Test {}
 impl<T> Test for T where T: Super<Assoc = ()> {}
 
 fn test() -> impl Test {
-    //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()`
     ()
+    //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()`
 }
 
 fn main() {
index 65daabe419d3f3b81862bc8904edf28257ca35ae..5ef1e9abef6319538191a4af186185341c3e9b6e 100644 (file)
@@ -1,10 +1,10 @@
 error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()`
-  --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14
+  --> $DIR/projection-mismatch-in-impl-where-clause.rs:14:5
    |
-LL | fn test() -> impl Test {
-   |              ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()`
+LL |     ()
+   |     ^^ type mismatch resolving `<() as Super>::Assoc == ()`
    |
-note: expected this to be `()`
+note: expected this to be `u8`
   --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18
    |
 LL |     type Assoc = u8;
diff --git a/src/test/ui/impl-trait/question_mark.rs b/src/test/ui/impl-trait/question_mark.rs
new file mode 100644 (file)
index 0000000..211f797
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+fn foo() -> impl MyTrait {
+    panic!();
+    MyStruct
+}
+
+struct MyStruct;
+trait MyTrait {}
+
+impl MyTrait for MyStruct {}
+
+fn main() {}
index 3cc537440977c09f96c24c6765d5f1d979d14f60..540a280f0a319d8303a3071b786b987edd2ea5a4 100644 (file)
@@ -1,9 +1,8 @@
-// Test that an `impl Trait` type that expands to itself is an error.
+// check-pass
 
 #![allow(unconditional_recursion)]
 
 fn test() -> impl Sized {
-    //~^ ERROR E0720
     test()
 }
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
deleted file mode 100644 (file)
index 5a3027e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-direct.rs:5:14
-   |
-LL | fn test() -> impl Sized {
-   |              ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     test()
-   |     ------ returning here with type `impl Sized`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.
index e3c621f0c57424357bc30d7885f70c75b453c683..ffc0cd9d10c34fc9e4bbbf05b38769b5f1b95e5b 100644 (file)
@@ -5,7 +5,7 @@
 #![allow(unconditional_recursion)]
 
 fn option(i: i32) -> impl Sized {
-    //~^ ERROR
+    //~^ ERROR cannot resolve opaque type
     if i < 0 { None } else { Some((option(i - 1), i)) }
 }
 
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
new file mode 100644 (file)
index 0000000..a60e34c
--- /dev/null
@@ -0,0 +1,29 @@
+#![feature(type_alias_impl_trait)]
+
+mod a {
+    type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR unconstrained opaque type
+
+    struct Bar;
+
+    impl PartialEq<(Bar, i32)> for Bar {
+        fn eq(&self, _other: &(Foo, i32)) -> bool {
+            true
+        }
+    }
+}
+
+mod b {
+    type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR unconstrained opaque type
+
+    struct Bar;
+
+    impl PartialEq<(Foo, i32)> for Bar {
+        fn eq(&self, _other: &(Bar, i32)) -> bool {
+            true
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
new file mode 100644 (file)
index 0000000..eae7d38
--- /dev/null
@@ -0,0 +1,18 @@
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:17:16
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
new file mode 100644 (file)
index 0000000..bdabc13
--- /dev/null
@@ -0,0 +1,37 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+mod direct {
+    type Foo = impl PartialEq<(Foo, i32)>;
+
+    struct Bar;
+
+    impl PartialEq<(Foo, i32)> for Bar {
+        fn eq(&self, _other: &(Foo, i32)) -> bool {
+            true
+        }
+    }
+
+    fn foo() -> Foo {
+        Bar
+    }
+}
+
+mod indirect {
+    type Foo = impl PartialEq<(Foo, i32)>;
+
+    struct Bar;
+
+    impl PartialEq<(Bar, i32)> for Bar {
+        fn eq(&self, _other: &(Bar, i32)) -> bool {
+            true
+        }
+    }
+
+    fn foo() -> Foo {
+        Bar
+    }
+}
+
+fn main() {}
index 29243699e44fd11a00e210259009f3654856f41b..18e3a5bcaa449df00b1f6295a4601448b37a3504 100644 (file)
@@ -13,10 +13,10 @@ trait Trait<'a> { }
 impl Trait<'b> for Cell<&'a u32> { }
 
 fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
-    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
 where 'x: 'y
 {
     x
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
 }
 
 fn main() { }
index cf854f67d0456436bcbae328748c2e1283dba6ed..690d049ec8f620bc1de240d1f61197562e646779 100644 (file)
@@ -1,11 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/region-escape-via-bound.rs:15:29
+  --> $DIR/region-escape-via-bound.rs:18:5
    |
-LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
-   |                             ^^^^^^^^^^^^^^
-LL |
 LL | where 'x: 'y
    |       -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
+LL | {
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound
    |
index d792c6eafb32f27ea889552ea03bea1b7fbfa288..f940c1949d0b8345be0c2102b0702330e97bae2d 100644 (file)
@@ -4,14 +4,14 @@ struct A {
 
 impl A {
     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+        self.x.iter().map(|a| a.0)
         //~^ ERROR: captures lifetime that does not appear in bounds
         //~| ERROR: captures lifetime that does not appear in bounds
-        self.x.iter().map(|a| a.0)
     }
     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+        self.x.iter().map(|a| a.0)
         //~^ ERROR: captures lifetime that does not appear in bounds
         //~| ERROR: captures lifetime that does not appear in bounds
-        self.x.iter().map(|a| a.0)
     }
 }
 
index 7424da76182ab3bb703ff03322ce8eaae214d94f..bc8e39f9c504cf7380ce0cdbe7325a1735a694d6 100644 (file)
@@ -1,10 +1,10 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:6:35
+  --> $DIR/static-return-lifetime-infered.rs:7:9
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         -----     ^^^^^^^^^^^^^^^^^^^^^^^
-   |                         |
-   |                         hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here
+   |                         ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
    |
@@ -12,12 +12,12 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:6:35
+  --> $DIR/static-return-lifetime-infered.rs:7:9
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         -----     ^^^^^^^^^^^^^^^^^^^^^^^
-   |                         |
-   |                         hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here
+   |                         ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
    |
@@ -25,12 +25,12 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:11:37
+  --> $DIR/static-return-lifetime-infered.rs:12:9
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    --               ^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here
+   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
    |
@@ -38,12 +38,12 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:11:37
+  --> $DIR/static-return-lifetime-infered.rs:12:9
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    --               ^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here
+   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
    |
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.rs b/src/test/ui/impl-trait/two_tait_defining_each_other.rs
new file mode 100644 (file)
index 0000000..6eb2a11
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+type A = impl Foo;
+type B = impl Foo;
+
+trait Foo {}
+
+fn muh(x: A) -> B {
+    if false {
+        return Bar; // B's hidden type is Bar
+    }
+    x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other
+    //~^ ERROR opaque type's hidden type cannot be another opaque type
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other.stderr
new file mode 100644 (file)
index 0000000..1a42ac5
--- /dev/null
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/two_tait_defining_each_other.rs:12:5
+   |
+LL |     x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other
+   |     ^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/two_tait_defining_each_other.rs:4:10
+   |
+LL | type B = impl Foo;
+   |          ^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/two_tait_defining_each_other.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs
new file mode 100644 (file)
index 0000000..3b16d0f
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+type A = impl Foo;
+type B = impl Foo;
+
+trait Foo {}
+
+fn muh(x: A) -> B {
+    x // B's hidden type is A (opaquely)
+    //~^ ERROR opaque type's hidden type cannot be another opaque type
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr
new file mode 100644 (file)
index 0000000..ef2089a
--- /dev/null
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/two_tait_defining_each_other2.rs:9:5
+   |
+LL |     x // B's hidden type is A (opaquely)
+   |     ^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/two_tait_defining_each_other2.rs:4:10
+   |
+LL | type B = impl Foo;
+   |          ^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/two_tait_defining_each_other2.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.rs b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs
new file mode 100644 (file)
index 0000000..37f8ae1
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+type A = impl Foo;
+type B = impl Foo;
+
+trait Foo {}
+
+fn muh(x: A) -> B {
+    if false {
+        return x;  // B's hidden type is A (opaquely)
+        //~^ ERROR opaque type's hidden type cannot be another opaque type
+    }
+    Bar // A's hidden type is `Bar`, because all the return types are compared with each other
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr
new file mode 100644 (file)
index 0000000..b06dc16
--- /dev/null
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/two_tait_defining_each_other3.rs:10:16
+   |
+LL |         return x;  // B's hidden type is A (opaquely)
+   |                ^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/two_tait_defining_each_other3.rs:4:10
+   |
+LL | type B = impl Foo;
+   |          ^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/two_tait_defining_each_other3.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
index 039cb62f86656a69f511b6364d7935181de85bde..e0b77544d439d0b0279f5276c20db6ae5b81845b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/type_parameters_captured.rs:7:20
+  --> $DIR/type_parameters_captured.rs:8:5
    |
-LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |                    ^^^^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
index 6c9c9d4a42af5a2a592fe62a3691aeb4f633a996..81ee7d3f8a561dc5436d1d4b32990348b3fc58fa 100644 (file)
@@ -5,8 +5,8 @@ impl<T> Any for T {}
 
 // Check that type parameters are captured and not considered 'static
 fn foo<T>(x: T) -> impl Any + 'static {
-    //~^ ERROR the parameter type `T` may not live long enough
     x
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
index 40e50b9922f8d2e9f6269cc113ab756df0ec3cc1..c0de4f4b4a0c5edcaff88849391435fc031ae264 100644 (file)
@@ -1,10 +1,10 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/type_parameters_captured.rs:7:20
+  --> $DIR/type_parameters_captured.rs:8:5
    |
 LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |        -           ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-   |        |
-   |        help: consider adding an explicit lifetime bound...: `T: 'static`
+   |        - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     x
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
index 462508f306ef34f4b1f3de692f996a79a3d894e8..d5a87b5d468340b3673d52c926b971597a9cc834 100644 (file)
@@ -1,8 +1,7 @@
-//! Ideally, these tests would go in `where-allowed.rs`, but we bail out
-//! too early to display them.
 use std::fmt::Debug;
 
-// Disallowed
-fn in_adt_in_return() -> Vec<impl Debug> { panic!() } //~ ERROR cannot resolve opaque type
+// check-pass
+
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
deleted file mode 100644 (file)
index b8e0672..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0720]: cannot resolve opaque type
-  --> $DIR/where-allowed-2.rs:6:30
-   |
-LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-   |                              ^^^^^^^^^^    -------- this returned value is of `!` type
-   |                              |
-   |                              cannot resolve opaque type
-   |
-   = help: this error will resolve once the item's body returns a concrete type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.
index 21bbc6f20b294341ca41140e956ff44a9f154caf..c29a15025a9c29d27c802af015d131b03c2187c7 100644 (file)
@@ -1,6 +1,7 @@
-// When a MULTI-character string literal is used where a char should be,
+// When a MULTI/NO-character string literal is used where a char should be,
 // DO NOT suggest changing to single quotes.
 
 fn main() {
     let _: char = "foo"; //~ ERROR mismatched types
+    let _: char = ""; //~ ERROR mismatched types
 }
index c3ba17a5579ad55978a625e643626d21bc0fa646..297ca2b548f7141d2b90868739dd7f67a06f2c55 100644 (file)
@@ -6,6 +6,14 @@ LL |     let _: char = "foo";
    |            |
    |            expected due to this
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-multi.rs:6:19
+   |
+LL |     let _: char = "";
+   |            ----   ^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index fecba721ac9fdeb101053fd43ce0b7e2789ee00e..89e07037afd424bf797e17bec9917a39d0c332f1 100644 (file)
@@ -1,5 +1,6 @@
 fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
-    *x //~^ ERROR `u32` is not a future
+    *x
+    //~^ ERROR `u32` is not a future
 }
 
 fn main() {
index bc4dc9ebf9e00b4c6569c43cecde89d654d5ce6a..1efa886436e0d3ed8eea9a73c62ee4ae0b458b2a 100644 (file)
@@ -1,14 +1,14 @@
 error[E0425]: cannot find value `u` in this scope
-  --> $DIR/issues-71798.rs:6:24
+  --> $DIR/issues-71798.rs:7:24
    |
 LL |     let _ = test_ref & u;
    |                        ^ not found in this scope
 
 error[E0277]: `u32` is not a future
-  --> $DIR/issues-71798.rs:1:25
+  --> $DIR/issues-71798.rs:2:5
    |
-LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
+LL |     *x
+   |     ^^ `u32` is not a future
    |
    = help: the trait `Future` is not implemented for `u32`
    = note: u32 must be a future or must implement `IntoFuture` to be awaited
index fa13bf0b12719050bb268f8014248e718bc62c1d..e5f26822f26708c43b30e1af545b6a218f7a521c 100644 (file)
@@ -1,8 +1,8 @@
 error: requires `generator` lang_item
-  --> $DIR/lang-item-missing-generator.rs:15:17
+  --> $DIR/lang-item-missing-generator.rs:15:22
    |
 LL | pub fn abc() -> impl FnOnce(f32) {
-   |                 ^^^^^^^^^^^^^^^^
+   |                      ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
new file mode 100644 (file)
index 0000000..84bfa2d
--- /dev/null
@@ -0,0 +1,46 @@
+// check-pass
+
+#![feature(gen_future, generator_trait, negative_impls, const_fn_trait_bound, const_impl_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::task::{Poll, Context};
+use std::future::{Future};
+use std::ptr::NonNull;
+use std::pin::Pin;
+
+fn main() {}
+
+#[derive(Debug, Copy, Clone)]
+pub struct ResumeTy(NonNull<Context<'static>>);
+
+unsafe impl Send for ResumeTy {}
+
+unsafe impl Sync for ResumeTy {}
+
+pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+where
+    T: Generator<ResumeTy, Yield = ()>,
+{
+    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
+
+    // We rely on the fact that async/await futures are immovable in order to create
+    // self-referential borrows in the underlying generator.
+    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
+
+    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
+        type Output = T::Return;
+        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+            // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
+            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
+
+            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
+            // `.await` lowering will safely cast that back to a `&mut Context`.
+            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
+                GeneratorState::Yielded(()) => Poll::Pending,
+                GeneratorState::Complete(x) => Poll::Ready(x),
+            }
+        }
+    }
+
+    GenFuture(gen)
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs b/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs
new file mode 100644 (file)
index 0000000..d07d732
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+
+fn main() {}
+
+trait Reader {}
+
+struct Unit<R>(R);
+struct ResDwarf<R>(R);
+
+struct Context<R: Reader> {
+    dwarf: ResDwarf<R>,
+}
+
+struct Range;
+
+struct ResUnit<R>(R);
+
+impl<R: Reader + 'static> Context<R> {
+    fn find_dwarf_unit(&self, probe: u64) -> Option<&Unit<R>> {
+        let x = self.find_units(probe);
+        None
+    }
+
+    fn find_units(&self, probe: u64) -> impl Iterator<Item = &ResUnit<R>> {
+        std::iter::empty()
+    }
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs b/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs
new file mode 100644 (file)
index 0000000..f75a88a
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+
+fn main() {}
+
+fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
+    move || iter.nth(step)
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/nested.rs b/src/test/ui/lazy-type-alias-impl-trait/nested.rs
new file mode 100644 (file)
index 0000000..f829111
--- /dev/null
@@ -0,0 +1,23 @@
+// check-pass
+
+fn main() {}
+
+struct RawTableInner<A> {
+    alloc: A,
+}
+
+impl<A> RawTableInner<A> {
+    fn prepare_resize(
+        self,
+    ) -> ScopeGuard<Self, impl FnMut(&mut Self)> {
+        ScopeGuard { dropfn: move |self_| {}, value: self,  }
+    }
+}
+
+pub struct ScopeGuard<T, F>
+where
+    F: FnMut(&mut T),
+{
+    dropfn: F,
+    value: T,
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs b/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs
new file mode 100644 (file)
index 0000000..8d03b51
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+fn main() {}
+
+fn filter_fold<T, Acc, PRED: FnMut(&T) -> bool, FOLD: FnMut(Acc, T) -> Acc>(
+    mut predicate: PRED,
+    mut fold: FOLD,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs b/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs
new file mode 100644 (file)
index 0000000..0071014
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+fn main() {}
+
+pub struct PairSlices<'a, 'b, T> {
+    pub(crate) a0: &'a mut [T],
+    pub(crate) a1: &'a mut [T],
+    pub(crate) b0: &'b [T],
+    pub(crate) b1: &'b [T],
+}
+
+impl<'a, 'b, T> PairSlices<'a, 'b, T> {
+    pub fn remainder(self) -> impl Iterator<Item = &'b [T]> {
+        IntoIterator::into_iter([self.b0, self.b1])
+    }
+}
index ea0d0ccbc553270c9fc290f10065a3080571377d..fd49b4842a74f6036e52865310a179f9c9db7264 100644 (file)
@@ -6,8 +6,8 @@ trait Future {
 use std::error::Error;
 
 fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
-//~^ ERROR not satisfied
     Ok(())
+    //~^ ERROR not satisfied
 }
 
 fn main() {}
index ef1127c59ac4cfee3380c9a506f1b5916723a07b..7f8384d7eca8d90e511deba1a542ffd2eb14bb11 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied
-  --> $DIR/lifetime-elision-return-type-trait.rs:8:13
+  --> $DIR/lifetime-elision-return-type-trait.rs:9:5
    |
-LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>`
+LL |     Ok(())
+   |     ^^^^^^ the trait `Future` is not implemented for `Result<(), _>`
 
 error: aborting due to previous error
 
index 6321b3c76e4d18a8bbedcf9e087aa0e17f24807e..13dab7ed954f85b5ec7a13da761a91ab95f42c84 100644 (file)
@@ -23,7 +23,7 @@ impl Trait for () {
     type T = Self;
 
     #[inline] //~ ERROR attribute should be applied to function or closure
-    type U = impl Trait; //~ ERROR could not find defining uses
+    type U = impl Trait; //~ ERROR unconstrained opaque type
 }
 
 extern "C" {
index 6ac884c12ceb9a7df3455f0d8d7dcae478ad3e87..fc7e89e4f4cce6dae3bf812d0c727aa7ef1c5746 100644 (file)
@@ -61,11 +61,13 @@ LL |     #[inline]
 LL |     type T;
    |     ------- not a function or closure
 
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/inline-trait-and-foreign-items.rs:26:14
    |
 LL |     type U = impl Trait;
    |              ^^^^^^^^^^
+   |
+   = note: `U` must be used in combination with a concrete type within the same module
 
 error: aborting due to 6 previous errors; 2 warnings emitted
 
index fe578f51b63a0e4280b580764c0458b5eb7f5139..691047c8a405b56551985c1b26f21aa99f6efbb1 100644 (file)
@@ -23,7 +23,7 @@ pub struct A<T: Foo> {
 }
 
 extern "C" {
-    pub fn lint_me() -> A<()>; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
index 36dbe3217d75ada5d0e445ea6b3f217c669109cf..7c85e9fa85c632cfc27d83171e2617dc5e6eaf41 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73249-2.rs:26:25
    |
 LL |     pub fn lint_me() -> A<()>;
index ec12de00739e4b7a24ad66fc80e0e7523ae4a4a4..ef8ab7e03d2f07277c0105a158398ebc231d7a04 100644 (file)
@@ -17,7 +17,7 @@ pub struct A {
 }
 
 extern "C" {
-    pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> A; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
index e987ec90228c1d4bc19027c8a4da6f8e4fe4b8e0..83e2a233c43355aab8670baf6591a89c49ac7b44 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73249-3.rs:20:25
    |
 LL |     pub fn lint_me() -> A;
index 58c2d7a501ad5060a4b2991b41f40c25bdf44d99..083fb6c5fb16dcc447c250aa1ebebecc39ac1b8f 100644 (file)
@@ -17,7 +17,7 @@ pub struct A {
 }
 
 extern "C" {
-    pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> A; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
index 749714c7df8d7535a446ac02a182f62890736157..37781d78cf28c03513b830662d90e6b2ff5efbaa 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73249-5.rs:20:25
    |
 LL |     pub fn lint_me() -> A;
index dc4c7efd7ef233e5b5be66822eff261c43594b9d..145ba784f7c66955e5a3a8ee068c9e188388bd8a 100644 (file)
@@ -20,7 +20,7 @@ fn assign() -> Qux {
 }
 
 extern "C" {
-    pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
index 505ccd5a930ce4de02f6e80852f954da8c681e6b..76b19d37e21a6d9eaeb5fddf3ec26b2d72f161ae 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73251-1.rs:23:25
    |
 LL |     pub fn lint_me() -> <u32 as Foo>::Assoc;
index 717ca4986f700e6e0fca62692bfb1790f8eb656f..df71a94579624bd51dc28637579094a281210639 100644 (file)
@@ -33,7 +33,7 @@ fn use_of_b() -> AliasB {
 }
 
 extern "C" {
-    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA<Assoc = u32>`
+    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `AliasA`
 }
 
 fn main() {}
index d7e10db441ec23eb11ca485e468a1bb96785682b..64f0fb2d892a45d31448a07da8a1bf46be8ded0c 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl TraitA<Assoc = u32>`, which is not FFI-safe
+error: `extern` block uses type `AliasA`, which is not FFI-safe
   --> $DIR/lint-ctypes-73251-2.rs:36:25
    |
 LL |     pub fn lint_me() -> <AliasB as TraitB>::Assoc;
index 3a62b6a21a56a6dc859d77adc2bece27ea285ebc..b7cc38e99fc37bdddacf11c89dfb60a9c5bdee91 100644 (file)
@@ -9,7 +9,7 @@ pub fn ret_closure() -> A {
 
 extern "C" {
     pub fn a(_: A);
-    //~^ ERROR `extern` block uses type `impl Fn()`, which is not FFI-safe [improper_ctypes]
+    //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes]
 }
 
 fn main() {}
index 5afbef778b3e35d29b38472d517b0f48729794fd..62d00fd6835eee19568dc430c5a4b0de43d9d3f1 100644 (file)
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Fn()`, which is not FFI-safe
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/opaque-ty-ffi-unsafe.rs:11:17
    |
 LL |     pub fn a(_: A);
index 3b896ec9d70c2b1200b37bf22bd922d8e618cfb6..7d020841180012580290b044c221ea6b79b2df02 100644 (file)
@@ -6,7 +6,8 @@ fn main() {}
 
 trait T {}
 
-fn should_ret_unit() -> impl T {
-    //~^ ERROR the trait bound `(): T` is not satisfied
-    panic!()
+fn should_ret_unit() {
+    foo(panic!()) //~ ERROR
 }
+
+fn foo(_: impl T) {}
index 670f76867ce45122b29e6ebba4a3c628318c9507..54abed383000dc8134137db45fa06923d8cfe74e 100644 (file)
@@ -1,8 +1,14 @@
 error[E0277]: the trait bound `(): T` is not satisfied
-  --> $DIR/feature-gate-never_type_fallback.rs:9:25
+  --> $DIR/feature-gate-never_type_fallback.rs:10:5
    |
-LL | fn should_ret_unit() -> impl T {
-   |                         ^^^^^^ the trait `T` is not implemented for `()`
+LL |     foo(panic!())
+   |     ^^^ the trait `T` is not implemented for `()`
+   |
+note: required by a bound in `foo`
+  --> $DIR/feature-gate-never_type_fallback.rs:13:16
+   |
+LL | fn foo(_: impl T) {}
+   |                ^ required by this bound in `foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/never_type/impl_trait_fallback.rs b/src/test/ui/never_type/impl_trait_fallback.rs
new file mode 100644 (file)
index 0000000..cc9520c
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+fn main() {}
+
+trait T {}
+impl T for () {}
+
+fn should_ret_unit() -> impl T {
+    panic!()
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback2.rs b/src/test/ui/never_type/impl_trait_fallback2.rs
new file mode 100644 (file)
index 0000000..f73d953
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait T {}
+impl T for i32 {}
+
+fn should_ret_unit() -> impl T {
+    //~^ ERROR `(): T` is not satisfied
+    panic!()
+}
+
+type Foo = impl T;
+
+fn a() -> Foo {
+    panic!()
+}
+
+fn b() -> Foo {
+    42
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback2.stderr b/src/test/ui/never_type/impl_trait_fallback2.stderr
new file mode 100644 (file)
index 0000000..2f50b9d
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): T` is not satisfied
+  --> $DIR/impl_trait_fallback2.rs:8:25
+   |
+LL | fn should_ret_unit() -> impl T {
+   |                         ^^^^^^ the trait `T` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/never_type/impl_trait_fallback3.rs b/src/test/ui/never_type/impl_trait_fallback3.rs
new file mode 100644 (file)
index 0000000..26ce9b9
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait T {
+    type Assoc;
+}
+
+type Foo = impl T;
+//~^ ERROR unconstrained opaque type
+
+fn a() -> Foo {
+    // This is not a defining use, it doesn't actually constrain the opaque type.
+    panic!()
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback3.stderr b/src/test/ui/never_type/impl_trait_fallback3.stderr
new file mode 100644 (file)
index 0000000..121019d
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/impl_trait_fallback3.rs:9:12
+   |
+LL | type Foo = impl T;
+   |            ^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/never_type/impl_trait_fallback4.rs b/src/test/ui/never_type/impl_trait_fallback4.rs
new file mode 100644 (file)
index 0000000..fe62773
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(type_alias_impl_trait)]
+
+trait T {
+    type Assoc: Cake;
+}
+
+trait Cake: std::fmt::Display {
+    fn cake() -> Self;
+}
+
+type Foo = impl T;
+
+fn foo() -> impl T {
+    //~^ ERROR `(): T` is not satisfied
+    panic!()
+}
+
+fn a() -> Foo {
+    foo()
+}
+
+fn main() {
+    println!("{}", <Foo as T>::Assoc::cake());
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback4.stderr b/src/test/ui/never_type/impl_trait_fallback4.stderr
new file mode 100644 (file)
index 0000000..f2e216e
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): T` is not satisfied
+  --> $DIR/impl_trait_fallback4.rs:13:13
+   |
+LL | fn foo() -> impl T {
+   |             ^^^^^^ the trait `T` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 0d7ee0376924dc618028d5db3d1b02375ce180cd..2f4cbf8322bbd13f648cc30c708c8f1eae2f7683 100644 (file)
@@ -29,9 +29,9 @@ fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazi
 fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
     let x = move || {
         let value: &'a u32 = value;
-        data.push(value);
+        data.push(value); //~ ERROR lifetime may not live long enough
     };
-    x //~ ERROR lifetime may not live long enough
+    x
 }
 
 fn main() {}
index f70ae2edd7facd8555ad362fca93853a7a72edfe..42ff1866893e6d923e707653ad8db4c3b6e204e7 100644 (file)
@@ -1,13 +1,13 @@
 error: lifetime may not live long enough
-  --> $DIR/issue-52113.rs:34:5
+  --> $DIR/issue-52113.rs:32:9
    |
 LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
    |                --  -- lifetime `'b` defined here
    |                |
    |                lifetime `'a` defined here
 ...
-LL |     x
-   |     ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+LL |         data.push(value);
+   |         ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
 
index 9af5180343bf28c71a5a97589be702205da2fcd2..c834f8bd9c4f5b545c7e335b38f73c6670c21062 100644 (file)
@@ -4,7 +4,7 @@ error[E0658]: trait objects in const fn are unstable
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
 error: aborting due to previous error
index e29ba09b3694dbabcc901566b2d72813a67f55c0..97dc016068bed85abe50f1e81c3ff81c9ccaf4c2 100644 (file)
@@ -7,8 +7,8 @@
 
 impl<'a> Foo<'a> {
     fn make_it(&self) -> impl Iterator<Item = u8> {
-        //~^ ERROR: captures lifetime that does not appear in bounds
         self.0.iter().copied()
+        //~^ ERROR: captures lifetime that does not appear in bounds
     }
 }
 
index 6c7cd0c8254938c8b1f49c5abe5dd03cca59eb1c..a3e9c0b44c21078c76a54e23a4bbeb177dac259a 100644 (file)
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/issue-73159-rpit-static.rs:9:26
+  --> $DIR/issue-73159-rpit-static.rs:10:9
    |
 LL | impl<'a> Foo<'a> {
    |      -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
 LL |     fn make_it(&self) -> impl Iterator<Item = u8> {
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         self.0.iter().copied()
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 8af23aad7261b80a3bdba5c104be56bcb8abb76f..c04185d08142481a928ae978c214943acaff011b 100644 (file)
@@ -8,8 +8,8 @@ trait Foo<'a> {
 impl<'a, T> Foo<'a> for T { }
 
 fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-//~^ ERROR captures lifetime that does not appear in bounds
     x
+    //~^ ERROR captures lifetime that does not appear in bounds
 }
 
 fn main() {}
index 3e6fe789a8b55a71856e2f1606b5230c0e010161..42d9f057aaa08dcf8773d4765bf4546f6509383d 100644 (file)
@@ -1,10 +1,10 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/impl-trait-captures.rs:10:25
+  --> $DIR/impl-trait-captures.rs:11:5
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-   |                  --     ^^^^^^^^^^^^
-   |                  |
-   |                  hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
+   |                  -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))` lifetime bound
    |
index 0c7d8acb05223e2b3c8f918c6aaf7e0d8c5458b3..3548ad03a7d3d9fc6a7578dc21bf59f646d6f251 100644 (file)
@@ -5,11 +5,11 @@
 use std::fmt::Debug;
 
 fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 where
     T: Debug,
 {
     x
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 }
 
 fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
@@ -20,11 +20,11 @@ fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
 }
 
 fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 where
     T: 'b + Debug,
 {
     x
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 }
 
 fn outlives_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
index 053aef951f2644e2452fc13e464a9e0626dd1371..31ee540cce9f70ccf63bcd4f9baed4e8f5276ae7 100644 (file)
@@ -1,16 +1,16 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:7:35
+  --> $DIR/impl-trait-outlives.rs:11:5
    |
-LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-   |                                   ^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:22:42
+  --> $DIR/impl-trait-outlives.rs:26:5
    |
-LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-   |                                          ^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
index 91a63bafd99a9688d6847e380c863a8ee8768dca..cf5d3dab4aadad1f5b3e73b5f4b98db565906d25 100644 (file)
@@ -9,8 +9,9 @@ async fn ff1() {} // OK.
     unsafe fn ff2() {} // OK.
     const fn ff3() {} // OK.
     extern "C" fn ff4() {} // OK.
-    const async unsafe extern "C" fn ff5() {} // OK.
+    const async unsafe extern "C" fn ff5() {}
     //~^ ERROR functions cannot be both `const` and `async`
+    //~| ERROR cycle detected
 
     trait X {
         async fn ft1(); //~ ERROR functions in traits cannot be declared `async`
@@ -26,15 +27,14 @@ trait X {
     struct Y;
     impl X for Y {
         async fn ft1() {} //~ ERROR functions in traits cannot be declared `async`
-        //~^ ERROR method `ft1` has an incompatible type for trait
         unsafe fn ft2() {} // OK.
         const fn ft3() {} //~ ERROR functions in traits cannot be declared const
         extern "C" fn ft4() {}
         const async unsafe extern "C" fn ft5() {}
         //~^ ERROR functions in traits cannot be declared `async`
         //~| ERROR functions in traits cannot be declared const
-        //~| ERROR method `ft5` has an incompatible type for trait
         //~| ERROR functions cannot be both `const` and `async`
+        //~| ERROR cycle detected
     }
 
     impl Y {
@@ -44,6 +44,7 @@ const fn fi3() {} // OK.
         extern "C" fn fi4() {} // OK.
         const async unsafe extern "C" fn fi5() {}
         //~^ ERROR functions cannot be both `const` and `async`
+        //~| ERROR cycle detected
     }
 
     extern "C" {
index 8eaba559a6240b68ee31a730574a5a763f5ec850..1d7460b8d36057c584527abe95a40628c3fc01f9 100644 (file)
@@ -1,14 +1,14 @@
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:12:5
    |
-LL |     const async unsafe extern "C" fn ff5() {} // OK.
+LL |     const async unsafe extern "C" fn ff5() {}
    |     ^^^^^-^^^^^------------------------------
    |     |     |
    |     |     `async` because of this
    |     `const` because of this
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:16:9
+  --> $DIR/fn-header-semantic-fail.rs:17:9
    |
 LL |         async fn ft1();
    |         -----^^^^^^^^^^
@@ -19,19 +19,19 @@ LL |         async fn ft1();
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:18:9
+  --> $DIR/fn-header-semantic-fail.rs:19:9
    |
 LL |         const fn ft3();
    |         ^^^^^ functions in traits cannot be const
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:20:9
+  --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^ functions in traits cannot be const
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:20:9
+  --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL |         const async unsafe extern "C" fn ft5();
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:20:9
+  --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^-^^^^^----------------------------
@@ -51,7 +51,7 @@ LL |         const async unsafe extern "C" fn ft5();
    |         `const` because of this
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:28:9
+  --> $DIR/fn-header-semantic-fail.rs:29:9
    |
 LL |         async fn ft1() {}
    |         -----^^^^^^^^^^^^
@@ -103,7 +103,7 @@ LL |         const async unsafe extern "C" fn fi5() {}
    |         `const` because of this
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:50:18
+  --> $DIR/fn-header-semantic-fail.rs:51:18
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -116,7 +116,7 @@ LL |         fn fe1();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:51:19
+  --> $DIR/fn-header-semantic-fail.rs:52:19
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -130,7 +130,7 @@ LL |         fn fe2();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:52:18
+  --> $DIR/fn-header-semantic-fail.rs:53:18
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -144,7 +144,7 @@ LL |         fn fe3();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:53:23
+  --> $DIR/fn-header-semantic-fail.rs:54:23
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -158,7 +158,7 @@ LL |         fn fe4();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:54:42
+  --> $DIR/fn-header-semantic-fail.rs:55:42
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -172,7 +172,7 @@ LL |         fn fe5();
    |         ~~
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:54:9
+  --> $DIR/fn-header-semantic-fail.rs:55:9
    |
 LL |         const async unsafe extern "C" fn fe5();
    |         ^^^^^-^^^^^----------------------------
@@ -180,43 +180,115 @@ LL |         const async unsafe extern "C" fn fe5();
    |         |     `async` because of this
    |         `const` because of this
 
-error[E0053]: method `ft1` has an incompatible type for trait
-  --> $DIR/fn-header-semantic-fail.rs:28:24
+error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}`
+  --> $DIR/fn-header-semantic-fail.rs:12:44
    |
-LL |         async fn ft1() {}
-   |                        ^
-   |                        |
-   |                        checked the `Output` of this `async fn`, found opaque type
-   |                        expected `()`, found opaque type
+LL |     const async unsafe extern "C" fn ff5() {}
+   |                                            ^
    |
-   = note: while checking the return type of the `async fn`
-note: type in trait
-  --> $DIR/fn-header-semantic-fail.rs:16:23
+note: ...which requires borrow-checking `main::ff5`...
+  --> $DIR/fn-header-semantic-fail.rs:12:5
    |
-LL |         async fn ft1();
-   |                       ^
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn() -> impl Future<Output = ()>`
+LL |     const async unsafe extern "C" fn ff5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `main::ff5`...
+  --> $DIR/fn-header-semantic-fail.rs:12:5
+   |
+LL |     const async unsafe extern "C" fn ff5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `main::ff5`...
+  --> $DIR/fn-header-semantic-fail.rs:12:5
+   |
+LL |     const async unsafe extern "C" fn ff5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/fn-header-semantic-fail.rs:5:1
+   |
+LL | / #![feature(const_extern_fn)]
+LL | |
+LL | | fn main() {
+LL | |     async fn ff1() {} // OK.
+...  |
+LL | |     }
+LL | | }
+   | |_^
 
-error[E0053]: method `ft5` has an incompatible type for trait
+error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 38:6>::ft5::{opaque#0}`
   --> $DIR/fn-header-semantic-fail.rs:33:48
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |                                                ^
-   |                                                |
-   |                                                checked the `Output` of this `async fn`, found opaque type
-   |                                                expected `()`, found opaque type
    |
-   = note: while checking the return type of the `async fn`
-note: type in trait
-  --> $DIR/fn-header-semantic-fail.rs:20:47
+note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 38:6>::ft5`...
+  --> $DIR/fn-header-semantic-fail.rs:33:9
    |
-LL |         const async unsafe extern "C" fn ft5();
-   |                                               ^
-   = note: expected fn pointer `unsafe extern "C" fn()`
-              found fn pointer `unsafe extern "C" fn() -> impl Future<Output = ()>`
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 38:6>::ft5`...
+  --> $DIR/fn-header-semantic-fail.rs:33:9
+   |
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 38:6>::ft5`...
+  --> $DIR/fn-header-semantic-fail.rs:33:9
+   |
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 38:6>::ft5::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/fn-header-semantic-fail.rs:5:1
+   |
+LL | / #![feature(const_extern_fn)]
+LL | |
+LL | | fn main() {
+LL | |     async fn ff1() {} // OK.
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 48:6>::fi5::{opaque#0}`
+  --> $DIR/fn-header-semantic-fail.rs:45:48
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |                                                ^
+   |
+note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 48:6>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:45:9
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 48:6>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:45:9
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 48:6>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:45:9
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 48:6>::fi5::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/fn-header-semantic-fail.rs:5:1
+   |
+LL | / #![feature(const_extern_fn)]
+LL | |
+LL | | fn main() {
+LL | |     async fn ff1() {} // OK.
+...  |
+LL | |     }
+LL | | }
+   | |_^
 
-error: aborting due to 20 previous errors
+error: aborting due to 21 previous errors
 
-Some errors have detailed explanations: E0053, E0379, E0706.
-For more information about an error, try `rustc --explain E0053`.
+Some errors have detailed explanations: E0379, E0391, E0706.
+For more information about an error, try `rustc --explain E0379`.
index 5a29ce2221fc2c218b77664d36450fbf03e4201b..5f8d4315de829c48c21c2766f9a8c05ea23c4c1a 100644 (file)
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
 LL |   "invalid-ab_isize"
    |   ^^^^^^^^^^^^^^^^^^ invalid ABI
    |
-   = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+   = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
 
 error: aborting due to previous error
 
index f295cf15d08c6005d850282b4ce3c36b790942f2..68ea4a026d7bf3622e0f9e3d6117e977c05a07ad 100644 (file)
@@ -32,7 +32,6 @@ fn finish<T, Y, R>(mut t: T) -> Vec<YieldOrReturn<Y, R>>
 
 #[rustc_polymorphize_error]
 pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-    //~^ ERROR item has unused generic parameters
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
@@ -58,7 +57,6 @@ pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Retu
 
 #[rustc_polymorphize_error]
 pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-    //~^ ERROR item has unused generic parameters
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
index c4e566a42d0cf53db6b4b69cdbaae952ab6da273..1152bcb0734a63490ef7a65683f52b7de7afc8a0 100644 (file)
@@ -8,11 +8,10 @@ LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
 error: item has unused generic parameters
-  --> $DIR/generators.rs:36:5
+  --> $DIR/generators.rs:35:5
    |
 LL |   pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
    |                      - generic parameter `T` is unused
-LL |
 LL | /     || {
 LL | |
 LL | |         yield 1;
@@ -21,17 +20,10 @@ LL | |     }
    | |_____^
 
 error: item has unused generic parameters
-  --> $DIR/generators.rs:34:8
-   |
-LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-   |        ^^^^^^^^^^^ - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/generators.rs:62:5
+  --> $DIR/generators.rs:60:5
    |
 LL |   pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
    |                             - generic parameter `T` is unused
-LL |
 LL | /     || {
 LL | |
 LL | |         yield 1;
@@ -39,11 +31,5 @@ LL | |         2
 LL | |     }
    | |_____^
 
-error: item has unused generic parameters
-  --> $DIR/generators.rs:60:8
-   |
-LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-   |        ^^^^^^^^^^^^       - generic parameter `T` is unused
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
index cc36f054bc3a0c3ca9b2a4f170d708537d9c8e0d..49462f52fb4c2355375bd633eb76b28dcd730501 100644 (file)
@@ -14,7 +14,6 @@ trait B {
 impl B for A {
     async fn associated(); //~ ERROR without body
     //~^ ERROR cannot be declared `async`
-    //~| ERROR incompatible type for trait
 }
 
 fn main() {}
index d3214458eac13cc8f89bedfcf498812c5aad6116..a473f42fc2cf805ffdd235531abac1672d17c56a 100644 (file)
@@ -44,25 +44,6 @@ LL |     async fn associated();
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
-error[E0053]: method `associated` has an incompatible type for trait
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
-   |
-LL |     async fn associated();
-   |                          ^
-   |                          |
-   |                          checked the `Output` of this `async fn`, found opaque type
-   |                          expected `()`, found opaque type
-   |
-   = note: while checking the return type of the `async fn`
-note: type in trait
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26
-   |
-LL |     async fn associated();
-   |                          ^
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn() -> impl Future<Output = ()>`
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0053, E0706.
-For more information about an error, try `rustc --explain E0053`.
+For more information about this error, try `rustc --explain E0706`.
index 96af085c5b6b8d8692ed0c7d8e2f196447589cf1..30479580f11a3c0122291b0020d1738bf15406f4 100644 (file)
@@ -11,7 +11,7 @@ trait Service {
 struct Struct;
 
 impl Service for Struct {
-    type Future = impl Trait; //~ ERROR: could not find defining uses
+    type Future = impl Trait; //~ ERROR: unconstrained opaque type
 }
 
 fn main() {}
index 3af6d0a3e076e74dcfb886c0e0d77e79037a64a2..4a4bf9a6996bc489aade43388ffe581b7185de76 100644 (file)
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/issue-68621.rs:14:19
    |
 LL |     type Future = impl Trait;
    |                   ^^^^^^^^^^
+   |
+   = note: `Future` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
index 61ac7731777b473f1fe0ebbf445a980139e60ce7..570a08cb58768ff9c1fc6ded908cade51d391b22 100644 (file)
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -          ^^^^^^^^^^
+   |                          -                     ^^^^^^^^
    |                          |
    |                          hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here
    |
index 6f8200739b9deb222f6cd6ff7a7bd4d96380251a..abdc650c68e78d46b85949e92ba38e38c448123a 100644 (file)
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                    -----      ^^^^^^^^^^
+   |                    -----                   ^^^^
    |                    |
    |                    hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
index 2c3ee5fcb803908fd7d50eba98ea1fc55ae16a95..5403b8d6d2871ae65a8f548ff6e39e2e2b9a1659 100644 (file)
@@ -10,6 +10,12 @@ fn main() {
 
     let _: Option<(i8,)> = Some();
     //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
+
+    let _: Option<(i32,)> = Some(5_usize);
+    //~^ ERROR mismatched types
+
+    let _: Option<(i32,)> = Some((5_usize));
+    //~^ ERROR mismatched types
 }
 
 fn int_bool(_: (i32, bool)) {
index a2ad602dbd47a0e65fa8eb1b6f69a7e9060f506e..ddcdfb1c3b34413be0a3bc9e6504cbb75db0897a 100644 (file)
@@ -15,7 +15,7 @@ LL |     int_bool(1, 2);
    |     expected 1 argument
    |
 note: function defined here
-  --> $DIR/args-instead-of-tuple-errors.rs:15:4
+  --> $DIR/args-instead-of-tuple-errors.rs:21:4
    |
 LL | fn int_bool(_: (i32, bool)) {
    |    ^^^^^^^^ --------------
@@ -28,6 +28,25 @@ LL |     let _: Option<(i8,)> = Some();
    |                            |
    |                            expected 1 argument
 
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+  --> $DIR/args-instead-of-tuple-errors.rs:14:34
+   |
+LL |     let _: Option<(i32,)> = Some(5_usize);
+   |                                  ^^^^^^^ expected tuple, found `usize`
+   |
+   = note: expected tuple `(i32,)`
+               found type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/args-instead-of-tuple-errors.rs:17:34
+   |
+LL |     let _: Option<(i32,)> = Some((5_usize));
+   |                                  ^^^^^^^^^ expected tuple, found `usize`
+   |
+   = note: expected tuple `(i32,)`
+               found type `usize`
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0061`.
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
index c9b8a41d469b99ba384d62cd7622978eb8f41f28..66e53f9ce2c80bef49c642f16571fc521fb0f458 100644 (file)
@@ -11,6 +11,12 @@ fn main() {
     let _: Option<()> = Some(());
     //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
 
+    let _: Option<(i32,)> = Some((3,));
+    //~^ ERROR mismatched types
+
+    let _: Option<(i32,)> = Some((3,));
+    //~^ ERROR mismatched types
+
     two_ints((1, 2)); //~ ERROR this function takes 1 argument
 
     with_generic((3, 4)); //~ ERROR this function takes 1 argument
index d4cc3024dd0d228d20f879fb60f7ebbfeb46822d..a15bff07ebfe6766e2a99ea097f7d23ea7397215 100644 (file)
@@ -11,6 +11,12 @@ fn main() {
     let _: Option<()> = Some();
     //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
 
+    let _: Option<(i32,)> = Some(3);
+    //~^ ERROR mismatched types
+
+    let _: Option<(i32,)> = Some((3));
+    //~^ ERROR mismatched types
+
     two_ints(1, 2); //~ ERROR this function takes 1 argument
 
     with_generic(3, 4); //~ ERROR this function takes 1 argument
index 172db7ee3df38973b3ae976458a0c24d0005124e..6a7602c9d0f45cc3742ad56b50a52b0b5719e1c1 100644 (file)
@@ -31,14 +31,40 @@ help: expected the unit value `()`; create it with empty parentheses
 LL |     let _: Option<()> = Some(());
    |                              ++
 
+error[E0308]: mismatched types
+  --> $DIR/args-instead-of-tuple.rs:14:34
+   |
+LL |     let _: Option<(i32,)> = Some(3);
+   |                                  ^ expected tuple, found integer
+   |
+   = note: expected tuple `(i32,)`
+               found type `{integer}`
+help: use a trailing comma to create a tuple with one element
+   |
+LL |     let _: Option<(i32,)> = Some((3,));
+   |                                  + ++
+
+error[E0308]: mismatched types
+  --> $DIR/args-instead-of-tuple.rs:17:34
+   |
+LL |     let _: Option<(i32,)> = Some((3));
+   |                                  ^^^ expected tuple, found integer
+   |
+   = note: expected tuple `(i32,)`
+               found type `{integer}`
+help: use a trailing comma to create a tuple with one element
+   |
+LL |     let _: Option<(i32,)> = Some((3,));
+   |                                    +
+
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/args-instead-of-tuple.rs:14:5
+  --> $DIR/args-instead-of-tuple.rs:20:5
    |
 LL |     two_ints(1, 2);
    |     ^^^^^^^^ -  - supplied 2 arguments
    |
 note: function defined here
-  --> $DIR/args-instead-of-tuple.rs:19:4
+  --> $DIR/args-instead-of-tuple.rs:25:4
    |
 LL | fn two_ints(_: (i32, i32)) {
    |    ^^^^^^^^ -------------
@@ -48,13 +74,13 @@ LL |     two_ints((1, 2));
    |              +    +
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/args-instead-of-tuple.rs:16:5
+  --> $DIR/args-instead-of-tuple.rs:22:5
    |
 LL |     with_generic(3, 4);
    |     ^^^^^^^^^^^^ -  - supplied 2 arguments
    |
 note: function defined here
-  --> $DIR/args-instead-of-tuple.rs:22:4
+  --> $DIR/args-instead-of-tuple.rs:28:4
    |
 LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
    |    ^^^^^^^^^^^^                 ----------------
@@ -64,13 +90,13 @@ LL |     with_generic((3, 4));
    |                  +    +
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/args-instead-of-tuple.rs:25:9
+  --> $DIR/args-instead-of-tuple.rs:31:9
    |
 LL |         with_generic(a, b);
    |         ^^^^^^^^^^^^ -  - supplied 2 arguments
    |
 note: function defined here
-  --> $DIR/args-instead-of-tuple.rs:22:4
+  --> $DIR/args-instead-of-tuple.rs:28:4
    |
 LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
    |    ^^^^^^^^^^^^                 ----------------
@@ -79,6 +105,7 @@ help: use parentheses to construct a tuple
 LL |         with_generic((a, b));
    |                      +    +
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0061`.
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
index d826222a06ae5d95fbd5838bc2b3fac95821e218..07c1d8bccbaba1e39ed3a8358cc194b60e0950e4 100644 (file)
@@ -1,10 +1,11 @@
 error[E0277]: the trait bound `(): Bar` is not satisfied
-  --> $DIR/impl-trait-return-trailing-semicolon.rs:3:13
+  --> $DIR/impl-trait-return-trailing-semicolon.rs:3:22
    |
-LL | fn foo() -> impl Bar {
-   |             ^^^^^^^^ the trait `Bar` is not implemented for `()`
-LL |     5;
-   |      - consider removing this semicolon
+LL |   fn foo() -> impl Bar {
+   |  ______________________^
+LL | |     5;
+LL | | }
+   | |_^ the trait `Bar` is not implemented for `()`
 
 error: aborting due to previous error
 
index 2a72159e5774bbc3e1fbb2fd6e000b036682567f..f13e653cb06bda42de0288a36c7535ace1cf5322 100644 (file)
@@ -1,19 +1,23 @@
 error[E0277]: `()` doesn't implement `std::fmt::Display`
-  --> $DIR/issue-81098.rs:3:13
+  --> $DIR/issue-81098.rs:3:37
    |
-LL | fn wat() -> impl core::fmt::Display {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
+LL |   fn wat() -> impl core::fmt::Display {
+   |  _____________________________________^
+LL | |     fn why() {}
+LL | | }
+   | |_^ `()` cannot be formatted with the default formatter
    |
    = help: the trait `std::fmt::Display` is not implemented for `()`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 
 error[E0277]: `()` doesn't implement `std::fmt::Display`
-  --> $DIR/issue-81098.rs:9:12
+  --> $DIR/issue-81098.rs:9:36
    |
-LL | fn ok() -> impl core::fmt::Display {
-   |            ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
-LL |     1;
-   |      - consider removing this semicolon
+LL |   fn ok() -> impl core::fmt::Display {
+   |  ____________________________________^
+LL | |     1;
+LL | | }
+   | |_^ `()` cannot be formatted with the default formatter
    |
    = help: the trait `std::fmt::Display` is not implemented for `()`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
index 9c8356a528470b53cfb023c7ea79bae9611e2b05..0016f19284250eae33697601612bed322883c80c 100644 (file)
@@ -11,7 +11,7 @@ LL |     let _x: (i32,) = (5);
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _x: (i32,) = (5,);
-   |                      ~~~~
+   |                        +
 
 error[E0308]: mismatched types
   --> $DIR/issue-86100-tuple-paren-comma.rs:13:9
@@ -24,7 +24,7 @@ LL |     foo((Some(3)));
 help: use a trailing comma to create a tuple with one element
    |
 LL |     foo((Some(3),));
-   |         ~~~~~~~~~~
+   |                 +
 
 error[E0308]: mismatched types
   --> $DIR/issue-86100-tuple-paren-comma.rs:17:22
@@ -37,7 +37,7 @@ LL |     let _s = S { _s: ("abc".to_string()) };
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _s = S { _s: ("abc".to_string(),) };
-   |                      ~~~~~~~~~~~~~~~~~~~~
+   |                                        +
 
 error[E0308]: mismatched types
   --> $DIR/issue-86100-tuple-paren-comma.rs:23:22
index a5b50634c71ea28103dbce76f4adef2b038b4a7f..c7f1215c8cc44f30b8aec22e940928972783711f 100644 (file)
@@ -7,13 +7,18 @@ LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is used here...
+   |                        ...is used and required to live as long as `'static` here
    |
-note: ...and is required to live as long as `'static` here
+note: `'static` lifetime requirement introduced by the return type
   --> $DIR/trait-object-nested-in-impl-trait.rs:27:23
    |
-LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
+LL | /         Iter {
+LL | |             current: None,
+LL | |             remaining: self.0.iter(),
+LL | |         }
+   | |_________- because of this returned expression
 help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
@@ -32,13 +37,18 @@ LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is used here...
+   |                        ...is used and required to live as long as `'static` here
    |
-note: ...and is required to live as long as `'static` here
+note: `'static` lifetime requirement introduced by the return type
   --> $DIR/trait-object-nested-in-impl-trait.rs:38:23
    |
-LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
+LL | /         Iter {
+LL | |             current: None,
+LL | |             remaining: self.0.iter(),
+LL | |         }
+   | |_________- because of this returned expression
 help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> + '_ {
@@ -53,13 +63,18 @@ LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is used here...
+   |                        ...is used and required to live as long as `'static` here
    |
-note: ...and is required to live as long as `'static` here
+note: `'static` lifetime requirement introduced by the return type
   --> $DIR/trait-object-nested-in-impl-trait.rs:49:30
    |
-LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
+LL | /         Iter {
+LL | |             current: None,
+LL | |             remaining: self.0.iter(),
+LL | |         }
+   | |_________- because of this returned expression
 help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> + 'a {
@@ -74,13 +89,18 @@ LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is used here...
+   |                        ...is used and required to live as long as `'static` here
    |
-note: ...and is required to live as long as `'static` here
+note: `'static` lifetime requirement introduced by the return type
   --> $DIR/trait-object-nested-in-impl-trait.rs:60:30
    |
-LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
+LL | /         Iter {
+LL | |             current: None,
+LL | |             remaining: self.0.iter(),
+LL | |         }
+   | |_________- because of this returned expression
 help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
index 6aa93a24d2f04badad96d70142113ee6b07a00f6..a02664ad7ca69e8f1cb405cfd6d93bfe9cb501e9 100644 (file)
@@ -16,6 +16,9 @@ fn extra_semicolon() {
 async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
 //~| NOTE while checking the return type of the `async fn`
 //~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE checked the `Output` of this `async fn`, expected opaque type
 async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
 //~| NOTE checked the `Output` of this `async fn`, found opaque type
 //~| NOTE while checking the return type of the `async fn`
@@ -31,7 +34,7 @@ async fn async_extra_semicolon_same() {
         }
         false => async_dummy(), //~ ERROR `match` arms have incompatible types
         //~^ NOTE expected `()`, found opaque type
-        //~| NOTE expected type `()`
+        //~| NOTE expected unit type `()`
         //~| HELP consider `await`ing on the `Future`
     };
 }
@@ -44,7 +47,7 @@ async fn async_extra_semicolon_different() {
         }
         false => async_dummy2(), //~ ERROR `match` arms have incompatible types
         //~^ NOTE expected `()`, found opaque type
-        //~| NOTE expected type `()`
+        //~| NOTE expected unit type `()`
         //~| HELP consider `await`ing on the `Future`
     };
 }
@@ -55,7 +58,7 @@ async fn async_different_futures() {
         //~| HELP consider `await`ing on both `Future`s
         false => async_dummy2(), //~ ERROR `match` arms have incompatible types
         //~^ NOTE expected opaque type, found a different opaque type
-        //~| NOTE expected type `impl Future<Output = ()>`
+        //~| NOTE expected opaque type `impl Future<Output = ()>`
         //~| NOTE distinct uses of `impl Trait` result in different opaque types
     };
 }
index b55c51b92809a35f5d9e020a6d0db9ee332d5afa..4c4b782bd6fb17047767617efbe86e64c2906b3d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/match-prev-arm-needing-semi.rs:32:18
+  --> $DIR/match-prev-arm-needing-semi.rs:35:18
    |
 LL |       let _ = match true {
    |  _____________-
@@ -20,8 +20,8 @@ note: while checking the return type of the `async fn`
    |
 LL | async fn async_dummy() {}
    |                        ^ checked the `Output` of this `async fn`, found opaque type
-   = note:     expected type `()`
-           found opaque type `impl Future<Output = ()>`
+   = note: expected unit type `()`
+            found opaque type `impl Future<Output = ()>`
 help: consider `await`ing on the `Future`
    |
 LL |         false => async_dummy().await,
@@ -33,7 +33,7 @@ LL +             async_dummy()
    | 
 
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/match-prev-arm-needing-semi.rs:45:18
+  --> $DIR/match-prev-arm-needing-semi.rs:48:18
    |
 LL |       let _ = match true {
    |  _____________-
@@ -50,12 +50,12 @@ LL | |     };
    | |_____- `match` arms have incompatible types
    |
 note: while checking the return type of the `async fn`
-  --> $DIR/match-prev-arm-needing-semi.rs:19:25
+  --> $DIR/match-prev-arm-needing-semi.rs:22:25
    |
 LL | async fn async_dummy2() {}
    |                         ^ checked the `Output` of this `async fn`, found opaque type
-   = note:     expected type `()`
-           found opaque type `impl Future<Output = ()>`
+   = note: expected unit type `()`
+            found opaque type `impl Future<Output = ()>`
 help: consider `await`ing on the `Future`
    |
 LL |         false => async_dummy2().await,
@@ -69,7 +69,7 @@ LL ~         false => Box::new(async_dummy2()),
    |
 
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/match-prev-arm-needing-semi.rs:56:18
+  --> $DIR/match-prev-arm-needing-semi.rs:59:18
    |
 LL |       let _ = match true {
    |  _____________-
@@ -84,12 +84,17 @@ LL | |     };
    | |_____- `match` arms have incompatible types
    |
 note: while checking the return type of the `async fn`
-  --> $DIR/match-prev-arm-needing-semi.rs:19:25
+  --> $DIR/match-prev-arm-needing-semi.rs:16:24
+   |
+LL | async fn async_dummy() {}
+   |                        ^ checked the `Output` of this `async fn`, expected opaque type
+note: while checking the return type of the `async fn`
+  --> $DIR/match-prev-arm-needing-semi.rs:22:25
    |
 LL | async fn async_dummy2() {}
    |                         ^ checked the `Output` of this `async fn`, found opaque type
-   = note:     expected type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
-           found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>)
+   = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
+              found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>)
    = note: distinct uses of `impl Trait` result in different opaque types
 help: consider `await`ing on both `Future`s
    |
index e065e0aaa8e0622480eef0c1d5d679d706a8ce28..133ffb058739250011df2fe7c15174346a1213d9 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/opaque-type-error.rs:20:9
    |
+LL |   fn thing_one() -> impl Future<Output = Result<(), ()>> {
+   |                     ------------------------------------ the expected opaque type
+...
 LL |   fn thing_two() -> impl Future<Output = Result<(), ()>> {
    |                     ------------------------------------ the found opaque type
 ...
@@ -13,8 +16,8 @@ LL | |         thing_two()
 LL | |     }.await
    | |_____- `if` and `else` have incompatible types
    |
-   = note:     expected type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
-           found opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
+   = note: expected opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
+              found opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
    = note: distinct uses of `impl Trait` result in different opaque types
 help: consider `await`ing on both `Future`s
    |
diff --git a/src/test/ui/test-attrs/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs
deleted file mode 100644 (file)
index 29ce9f7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-// compile-flags: --test
-#![feature(allow_fail)]
-#![feature(cfg_panic)]
-
-#[test]
-#[allow_fail]
-fn test1() {
-    #[cfg(not(panic = "abort"))]
-    panic!();
-}
-
-#[test]
-#[allow_fail]
-fn test2() {
-    assert!(true);
-}
index 0013d5d66f172389733c6123a51f0394ef2f1da4..04320e72076830aab187c2e7b7dbf43e08d73051 100644 (file)
@@ -8,6 +8,6 @@ fn mk_opaque() -> OpaqueType {
 trait AnotherTrait {}
 impl<T: Send> AnotherTrait for T {}
 impl AnotherTrait for OpaqueType {}
-//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
+//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
 //~| ERROR cannot implement trait on type alias impl trait
 fn main() {}
index 6a3498a389375e3806243cde691d6ae85f3064c0..4f19e6607c8d9f3256b34b61a969316754d8e956 100644 (file)
@@ -10,13 +10,13 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
   --> $DIR/issue-83613.rs:10:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
 
 error: aborting due to 2 previous errors
 
index 8427b5b1fe854eec5fc8690e47951c65049559d6..185207b9800bbc0c41b4f53d5d7e1fb106965e2c 100644 (file)
@@ -1,14 +1,12 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
-
+// check-pass
 use std::fmt::Debug;
 
 type Foo = impl Debug;
 
-// FIXME: This should compile, but it currently doesn't
 fn foo1(mut x: Foo) {
     x = 22_u32;
-    //~^ ERROR: mismatched types [E0308]
 }
 
 fn foo2(mut x: Foo) {
diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr
deleted file mode 100644 (file)
index a87e44a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/argument-types.rs:10:9
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL | fn foo1(mut x: Foo) {
-   |                --- expected due to this parameter type
-LL |     x = 22_u32;
-   |         ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
index 4a49d6e4ab8fd7aaac23229cdcfea5e659138662..0664275b2ad0a359520c9df3d97743000f2b5f54 100644 (file)
@@ -2,15 +2,15 @@ error[E0277]: `Rc<u32>` cannot be sent between threads safely
   --> $DIR/auto-trait-leakage2.rs:17:13
    |
 LL |     type Foo = impl std::fmt::Debug;
-   |                -------------------- within this `impl Debug`
+   |                -------------------- within this `Foo`
 ...
 LL |     is_send(m::foo());
    |     ------- ^^^^^^^^ `Rc<u32>` cannot be sent between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `impl Debug`, the trait `Send` is not implemented for `Rc<u32>`
-   = note: required because it appears within the type `impl Debug`
+   = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`
+   = note: required because it appears within the type `Foo`
 note: required by a bound in `is_send`
   --> $DIR/auto-trait-leakage2.rs:14:15
    |
index 5fb7a9473d3dfbc57cef2537e10e59729a553908..b456b1445e7845ebbe29bf76a8514dd2bd57d4a6 100644 (file)
@@ -6,6 +6,7 @@
 mod m {
     type Foo = impl std::fmt::Debug;
     //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
+    //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
 
     pub fn foo() -> Foo {
         22_u32
index c0147e56c9364a6bb2d3f99d8c1f014a20768539..4c44875b4a548eb85a4d3a51fbe115d571b87d78 100644 (file)
@@ -5,11 +5,10 @@ LL |     type Foo = impl std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires type-checking `m::bar`...
-  --> $DIR/auto-trait-leakage3.rs:15:9
+  --> $DIR/auto-trait-leakage3.rs:15:5
    |
-LL |         is_send(foo());
-   |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/auto-trait-leakage3.rs:6:1
@@ -17,6 +16,24 @@ note: cycle used when checking item types in module `m`
 LL | mod m {
    | ^^^^^
 
-error: aborting due to previous error
+error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
+  --> $DIR/auto-trait-leakage3.rs:7:16
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `m::bar`...
+  --> $DIR/auto-trait-leakage3.rs:15:5
+   |
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
+   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in module `m`
+  --> $DIR/auto-trait-leakage3.rs:6:1
+   |
+LL | mod m {
+   | ^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
index cee8186dd8f8c432c3a2ccf10f49ae3822e120f5..4d2890b5de583c48bc63a8e6d727e4d3516f03f1 100644 (file)
@@ -7,13 +7,12 @@ trait TraitWithAssoc {
 }
 
 type Foo<V> = impl Trait<V>;
-//~^ ERROR could not find defining uses
 
 trait Trait<U> {}
 
 impl<W> Trait<W> for () {}
 
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-    //~^ ERROR non-defining opaque type use in defining scope
     ()
+    //~^ ERROR non-defining opaque type use
 }
index 03e696fe8980376392a3df6e8219d9ae3dbd03fc..c405b1f6af2057428a78bf0dc88993d954d99ad7 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/bound_reduction2.rs:16:46
+  --> $DIR/bound_reduction2.rs:16:5
    |
-LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-   |                                              ^^^^^^^^^^^^^
+LL |     ()
+   |     ^^
    |
 note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
   --> $DIR/bound_reduction2.rs:9:10
@@ -10,11 +10,5 @@ note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
 LL | type Foo<V> = impl Trait<V>;
    |          ^
 
-error: could not find defining uses
-  --> $DIR/bound_reduction2.rs:9:15
-   |
-LL | type Foo<V> = impl Trait<V>;
-   |               ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index eecef2338c146095d6e4ae31c4cc73c5612fc10a..83d22161e4e75617fb3845576e8b6843d0eb966a 100644 (file)
@@ -4,11 +4,11 @@
 #![feature(type_alias_impl_trait)]
 
 type X<'a> = impl Into<&'static str> + From<&'a str>;
-//~^ ERROR mismatched types
 
 fn f<'a: 'static>(t: &'a str) -> X<'a> {
     //~^ WARNING unnecessary lifetime parameter
     t
+    //~^ ERROR non-defining opaque type use
 }
 
 fn extend_lt<'a>(o: &'a str) -> &'static str {
index da9f81d6bd370cbebfb09a3d4b95c9fa89cd9d4e..d87ef2ec79c1a26bd14f122938098e1605769ab1 100644 (file)
@@ -1,26 +1,19 @@
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/bounds-are-checked.rs:9:6
+  --> $DIR/bounds-are-checked.rs:8:6
    |
 LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
    |      ^^^^^^^^^^^
    |
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
-error[E0308]: mismatched types
-  --> $DIR/bounds-are-checked.rs:6:14
+error: non-defining opaque type use in defining scope
+  --> $DIR/bounds-are-checked.rs:10:5
    |
 LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
-   |
-   = note: expected trait `From<&'a str>`
-              found trait `From<&'static str>`
-note: the lifetime `'a` as defined here...
-  --> $DIR/bounds-are-checked.rs:6:8
-   |
-LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
-   |        ^^
-   = note: ...does not necessarily outlive the static lifetime
+   |        -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+...
+LL |     t
+   |     ^
 
 error: aborting due to previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0308`.
index c4bf56a919721140d2f3168ebd76ef65c9673ecc..6febd07157aa60fdbdcda2d5f8698e4ba7f78b00 100644 (file)
@@ -3,4 +3,4 @@
 fn main() {}
 
 // declared but never defined
-type Bar = impl std::fmt::Debug; //~ ERROR could not find defining uses
+type Bar = impl std::fmt::Debug; //~ ERROR unconstrained opaque type
index 21c2e8a9db618ceffe81427738ab2ddc426244b6..60bc24320a301c25bf90ce300ee2a1813351d4b4 100644 (file)
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/declared_but_never_defined.rs:6:12
    |
 LL | type Bar = impl std::fmt::Debug;
    |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Bar` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
index 7ea517eb734a459701bfd6d1887416af6f228559..5bda5f0fceaaa6dba9dd7e78fa2e554ee3d2ebb2 100644 (file)
@@ -4,7 +4,7 @@ fn main() {}
 
 mod boo {
     // declared in module but not defined inside of it
-    pub type Boo = impl ::std::fmt::Debug; //~ ERROR could not find defining uses
+    pub type Boo = impl ::std::fmt::Debug; //~ ERROR unconstrained opaque type
 }
 
 fn bomp() -> boo::Boo {
index 0b4c262bbb43b97f0a52e7bb8d9a60cc75a83d2c..26308c6ff6b1511936c671cb83239f649595cb4a 100644 (file)
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/declared_but_not_defined_in_scope.rs:7:20
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Boo` must be used in combination with a concrete type within the same module
 
 error[E0308]: mismatched types
   --> $DIR/declared_but_not_defined_in_scope.rs:11:5
@@ -10,13 +12,11 @@ error[E0308]: mismatched types
 LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ---------------------- the expected opaque type
 ...
-LL | fn bomp() -> boo::Boo {
-   |              -------- expected `impl Debug` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
-   = note: expected opaque type `impl Debug`
-                found reference `&'static str`
+   = note: expected opaque type `Boo`
+                found reference `&str`
 
 error: aborting due to 2 previous errors
 
index 95cbcfec2dc1557762ecb7b9976446b0c62d0234..7740f774ebca4ad58af5c3869026abc758ce473d 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(type_alias_impl_trait)]
-
+// check-pass
 fn main() {}
 
 // two definitions with different types
@@ -10,11 +10,9 @@ fn foo() -> Foo {
 }
 
 fn bar() -> Foo {
-    //~^ ERROR concrete type differs from previous
     panic!()
 }
 
 fn boo() -> Foo {
-    //~^ ERROR concrete type differs from previous
     loop {}
 }
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
deleted file mode 100644 (file)
index 6274029..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type.rs:12:1
-   |
-LL | fn bar() -> Foo {
-   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()`
-   |
-note: previous use here
-  --> $DIR/different_defining_uses_never_type.rs:8:1
-   |
-LL | fn foo() -> Foo {
-   | ^^^^^^^^^^^^^^^
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type.rs:17:1
-   |
-LL | fn boo() -> Foo {
-   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()`
-   |
-note: previous use here
-  --> $DIR/different_defining_uses_never_type.rs:8:1
-   |
-LL | fn foo() -> Foo {
-   | ^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
index fe1ca2230dacade16cd3108df900f4f594ce49cb..d7e93335f47faaa2b4f4f08f7e676e44cda0ba8d 100644 (file)
@@ -1,5 +1,5 @@
-// Tests that we correctly handle the instantiated
-// inference variable being completely unconstrained.
+// Tests that we correctly handle opaque types being used opaquely,
+// even within their defining scope.
 //
 // check-pass
 #![feature(type_alias_impl_trait)]
index 91494a82d0fb201eaf492bd2932ca974aea52843..d99ed58127bd44e127e390f73958b1f9f1aaddd3 100644 (file)
@@ -1,12 +1,11 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME This should compile, but it currently doesn't
+// check-pass
 
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR: could not find defining uses
 
 struct Bar {
     foo: Foo,
@@ -14,7 +13,6 @@ struct Bar {
 
 fn bar() -> Bar {
     Bar { foo: "foo" }
-    //~^ ERROR: mismatched types [E0308]
 }
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/field-types.stderr b/src/test/ui/type-alias-impl-trait/field-types.stderr
deleted file mode 100644 (file)
index 18c2abb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/field-types.rs:16:16
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL |     Bar { foo: "foo" }
-   |                ^^^^^ expected opaque type, found `&str`
-   |
-   = note: expected opaque type `impl Debug`
-                found reference `&'static str`
-
-error: could not find defining uses
-  --> $DIR/field-types.rs:8:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index 885aae619d6a2bf5249b79df995508a4a63b336b..c9b9e128f88e2af5930ded809662381f75202870 100644 (file)
@@ -3,9 +3,9 @@
 fn main() {}
 
 type Two<'a, 'b> = impl std::fmt::Debug;
-//~^ ERROR could not find defining uses
+
 
 fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
-    //~^ ERROR non-defining opaque type use
     t
+    //~^ ERROR non-defining opaque type use
 }
index b99c6a51f4b1d24faa3cf2984eb3d9ff09da53ec..222aaea78d9829a60638027746bcfeab425718f3 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_lifetime_param.rs:8:26
+  --> $DIR/generic_duplicate_lifetime_param.rs:9:5
    |
-LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
-   |                          ^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: lifetime used multiple times
   --> $DIR/generic_duplicate_lifetime_param.rs:5:10
@@ -10,11 +10,5 @@ note: lifetime used multiple times
 LL | type Two<'a, 'b> = impl std::fmt::Debug;
    |          ^^  ^^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_lifetime_param.rs:5:20
-   |
-LL | type Two<'a, 'b> = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 33cd2f6ba07539da18608740f78f3efa94f4de54..093c1c231861f1893fb4c0e68d35a21546575ddc 100644 (file)
@@ -6,23 +6,23 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type TwoTys<T, U> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type TwoLifetimes<'a, 'b> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type TwoConsts<const X: usize, const Y: usize> = impl Debug;
-//~^ ERROR could not find defining uses
+
 
 fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
+    //~^ ERROR non-defining opaque type use in defining scope
 }
index 52c60d1777e49131ecfc4b132c9096dd71b700bb..922e41e0f688344b8a0ad57c80fa7926f758f699 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:15:30
+  --> $DIR/generic_duplicate_param_use.rs:16:5
    |
-LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-   |                              ^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: type used multiple times
   --> $DIR/generic_duplicate_param_use.rs:8:13
@@ -10,17 +10,11 @@ note: type used multiple times
 LL | type TwoTys<T, U> = impl Debug;
    |             ^  ^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:8:21
-   |
-LL | type TwoTys<T, U> = impl Debug;
-   |                     ^^^^^^^^^^
-
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:20:36
+  --> $DIR/generic_duplicate_param_use.rs:21:5
    |
-LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
-   |                                    ^^^^^^^^^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: lifetime used multiple times
   --> $DIR/generic_duplicate_param_use.rs:10:19
@@ -28,17 +22,11 @@ note: lifetime used multiple times
 LL | type TwoLifetimes<'a, 'b> = impl Debug;
    |                   ^^  ^^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:10:29
-   |
-LL | type TwoLifetimes<'a, 'b> = impl Debug;
-   |                             ^^^^^^^^^^
-
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:25:50
+  --> $DIR/generic_duplicate_param_use.rs:26:5
    |
-LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-   |                                                  ^^^^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: constant used multiple times
   --> $DIR/generic_duplicate_param_use.rs:12:22
@@ -46,11 +34,5 @@ note: constant used multiple times
 LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                      ^               ^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:12:50
-   |
-LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
-   |                                                  ^^^^^^^^^^
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
index 04fb57b39c052c3467fb45d3a7a3ab6cde829cc1..81bf9770d02a8b3cf7367f6f3407a3febcb9d470 100644 (file)
@@ -8,11 +8,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `T` doesn't implement `Debug`
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    t
-}
-
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
 }
index fca9b70d1844173127303eb69e8b2ca171e5a9c3..84aa260b099b65c9f63bea169118d3c4dfe0ef6d 100644 (file)
@@ -1,15 +1,3 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use2.rs:11:27
-   |
-LL | fn one<T: Debug>(t: T) -> Two<T, T> {
-   |                           ^^^^^^^^^
-   |
-note: type used multiple times
-  --> $DIR/generic_duplicate_param_use2.rs:8:10
-   |
-LL | type Two<T, U> = impl Debug;
-   |          ^  ^
-
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use2.rs:8:18
    |
@@ -21,6 +9,6 @@ help: consider restricting type parameter `T`
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index 1a755d3902612f125a17b5f5477634743baf941a..c95692182c2780a0dc3faba27906c5cd79e52b37 100644 (file)
@@ -8,11 +8,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `T` doesn't implement `Debug`
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    t
-}
-
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
 }
index 90b04c043a00ccb1d0fa28571d9e7ffaaa54fdee..e5a70fa8ce56e38e4b06000d7839e876af427308 100644 (file)
@@ -1,23 +1,11 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use3.rs:11:27
-   |
-LL | fn one<T: Debug>(t: T) -> Two<T, T> {
-   |                           ^^^^^^^^^
-   |
-note: type used multiple times
-  --> $DIR/generic_duplicate_param_use3.rs:8:10
-   |
-LL | type Two<T, U> = impl Debug;
-   |          ^  ^
-
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use3.rs:20:1
+  --> $DIR/generic_duplicate_param_use3.rs:15:1
    |
 LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use3.rs:16:1
+  --> $DIR/generic_duplicate_param_use3.rs:11:1
    |
 LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,6 +21,6 @@ help: consider restricting type parameter `T`
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 50d95c83d58e644600976228707615908d42cec6..aee2550e9078a8ed23e7c27bc20046b1e817bd70 100644 (file)
@@ -8,11 +8,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `U` doesn't implement `Debug`
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    t
-}
-
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
     u
 }
index c4be2fa83f130fd068f7be5f14eddb4ac529ef93..0491d61030e3442f75741deeb9f0c8588c8959ce 100644 (file)
@@ -1,15 +1,3 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use4.rs:11:27
-   |
-LL | fn one<T: Debug>(t: T) -> Two<T, T> {
-   |                           ^^^^^^^^^
-   |
-note: type used multiple times
-  --> $DIR/generic_duplicate_param_use4.rs:8:10
-   |
-LL | type Two<T, U> = impl Debug;
-   |          ^  ^
-
 error[E0277]: `U` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use4.rs:8:18
    |
@@ -21,6 +9,6 @@ help: consider restricting type parameter `U`
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
    |              +++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index cf43085877f4c7864eefd534a8cb071c130989a6..f39741a6a625cc2d693309227e45982ad3515156 100644 (file)
@@ -5,25 +5,25 @@
 fn main() {}
 
 type OneTy<T> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type OneLifetime<'a> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type OneConst<const X: usize> = impl Debug;
-//~^ ERROR could not find defining uses
+
 
 // Not defining uses, because they doesn't define *all* possible generics.
 
 fn concrete_ty() -> OneTy<u32> {
-    //~^ ERROR non-defining opaque type use in defining scope
     5u32
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn concrete_lifetime() -> OneLifetime<'static> {
-    //~^ ERROR non-defining opaque type use in defining scope
     6u32
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn concrete_const() -> OneConst<{ 123 }> {
-    //~^ ERROR non-defining opaque type use in defining scope
     7u32
+    //~^ ERROR non-defining opaque type use in defining scope
 }
index 3aa42a25484d1dcc169f6ed6423f5b4ded454225..36694900c17b4af5615f2b501cd68e15af2c4ce2 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:16:21
+  --> $DIR/generic_nondefining_use.rs:17:5
    |
-LL | fn concrete_ty() -> OneTy<u32> {
-   |                     ^^^^^^^^^^
+LL |     5u32
+   |     ^^^^
    |
 note: used non-generic type `u32` for generic parameter
   --> $DIR/generic_nondefining_use.rs:7:12
@@ -10,32 +10,20 @@ note: used non-generic type `u32` for generic parameter
 LL | type OneTy<T> = impl Debug;
    |            ^
 
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:7:17
-   |
-LL | type OneTy<T> = impl Debug;
-   |                 ^^^^^^^^^^
-
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:21:27
+  --> $DIR/generic_nondefining_use.rs:22:5
    |
 LL | type OneLifetime<'a> = impl Debug;
    |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
 ...
-LL | fn concrete_lifetime() -> OneLifetime<'static> {
-   |                           ^^^^^^^^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:9:24
-   |
-LL | type OneLifetime<'a> = impl Debug;
-   |                        ^^^^^^^^^^
+LL |     6u32
+   |     ^^^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:26:24
+  --> $DIR/generic_nondefining_use.rs:27:5
    |
-LL | fn concrete_const() -> OneConst<{ 123 }> {
-   |                        ^^^^^^^^^^^^^^^^^
+LL |     7u32
+   |     ^^^^
    |
 note: used non-generic constant `123_usize` for generic parameter
   --> $DIR/generic_nondefining_use.rs:11:21
@@ -43,11 +31,5 @@ note: used non-generic constant `123_usize` for generic parameter
 LL | type OneConst<const X: usize> = impl Debug;
    |                     ^
 
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:11:33
-   |
-LL | type OneConst<const X: usize> = impl Debug;
-   |                                 ^^^^^^^^^^
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
index dd6300a64f42e0c95193436578f432aeaedc50db..c70f473cff57890ebdb6ba49478610756d9e6902 100644 (file)
@@ -6,6 +6,6 @@ fn main() {}
 //~^ ERROR: at least one trait must be specified
 
 fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
-    //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
     v
+    //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
 }
index 8015ff7eded9061fc4f84aec174c66bfe1db052d..fd720239a5239adb002b24137a9bb4f58d4594b8 100644 (file)
@@ -5,14 +5,10 @@ LL | type WrongGeneric<T: 'static> = impl 'static;
    |                                 ^^^^^^^^^^^^
 
 error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/generic_not_used.rs:8:73
+  --> $DIR/generic_not_used.rs:9:5
    |
-LL |   fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
-   |  _________________________________________________________________________^
-LL | |
-LL | |     v
-LL | | }
-   | |_^
+LL |     v
+   |     ^
 
 error: aborting due to 2 previous errors
 
index f4e1de8e50f688399b52757f244d6c5200f17405..dc85db66d32ba4d9adad945b9a9c4ef848712567 100644 (file)
@@ -1,41 +1,29 @@
 error: at least one trait must be specified
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:24
    |
 LL | type WrongGeneric<T> = impl 'static;
    |                        ^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: non-defining opaque type use in defining scope
   --> $DIR/generic_type_does_not_live_long_enough.rs:6:18
    |
 LL |     let z: i32 = x;
-   |            ---   ^ expected `i32`, found opaque type
-   |            |
-   |            expected due to this
-...
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ------------ the found opaque type
-   |
-   = note:     expected type `i32`
-           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:12:30
+   |                  ^
    |
-LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-   |                              ^^^^^^^^^^^^^^^
+note: used non-generic type `&'static i32` for generic parameter
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:19
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+LL | type WrongGeneric<T> = impl 'static;
+   |                   ^
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:14:5
    |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
    = 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`.
+For more information about this error, try `rustc --explain E0310`.
index 78d25e30e0382eba41de11a042664471784ca8a2..cb90776472b5dc543fd395548d0cbe41082ca61f 100644 (file)
@@ -3,13 +3,14 @@
 fn main() {
     let y = 42;
     let x = wrong_generic(&y);
-    let z: i32 = x; //~ ERROR mismatched types
+    let z: i32 = x;
+    //~^ ERROR non-defining opaque type use
 }
 
 type WrongGeneric<T> = impl 'static;
 //~^ ERROR: at least one trait must be specified
 
 fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-    //~^ ERROR the parameter type `T` may not live long enough
     t
+    //~^ ERROR the parameter type `T` may not live long enough
 }
index 568784372e5191db73218523175ccec67dafc72c..15ec2eed3da4b0d521b2ea5e834841dc50969134 100644 (file)
@@ -1,32 +1,29 @@
 error: at least one trait must be specified
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:24
    |
 LL | type WrongGeneric<T> = impl 'static;
    |                        ^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: non-defining opaque type use in defining scope
   --> $DIR/generic_type_does_not_live_long_enough.rs:6:18
    |
 LL |     let z: i32 = x;
-   |            ---   ^ expected `i32`, found opaque type
-   |            |
-   |            expected due to this
-...
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ------------ the found opaque type
+   |                  ^
+   |
+note: used non-generic type `&'static i32` for generic parameter
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:19
    |
-   = note:     expected type `i32`
-           found opaque type `impl Sized`
+LL | type WrongGeneric<T> = impl 'static;
+   |                   ^
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:14:5
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-   |                  -           ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-   |                  |
-   |                  help: consider adding an explicit lifetime bound...: `T: 'static`
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     t
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0308, E0310.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0310`.
index c781e200bf8eeb5532ff513ad89e261ceef424d8..608572978a3511028bd6aee0d4b00ae4eeb0471a 100644 (file)
@@ -3,7 +3,8 @@
 
 mod m {
     type Foo = impl std::fmt::Debug;
-    //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
+    //~^ ERROR cycle detected
+    //~| ERROR cycle detected
 
     // Cycle: error today, but it'd be nice if it eventually worked
 
@@ -17,7 +18,6 @@ pub fn bar() {
 
     fn baz() {
         let f: Foo = 22_u32;
-        //~^ ERROR: mismatched types [E0308]
     }
 
     fn is_send<T: Send>(_: T) {}
index e12124664778ed249087f4e88bb0011577b7e323..3ed86fae8a18de54ec6d4c4ba3ba522a49360ae5 100644 (file)
@@ -5,11 +5,10 @@ LL |     type Foo = impl std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires type-checking `m::bar`...
-  --> $DIR/inference-cycle.rs:15:9
+  --> $DIR/inference-cycle.rs:15:5
    |
-LL |         is_send(foo()); // Today: error
-   |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/inference-cycle.rs:4:1
@@ -17,21 +16,24 @@ note: cycle used when checking item types in module `m`
 LL | mod m {
    | ^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/inference-cycle.rs:19:22
+error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
+  --> $DIR/inference-cycle.rs:5:16
    |
 LL |     type Foo = impl std::fmt::Debug;
-   |                -------------------- the expected opaque type
-...
-LL |         let f: Foo = 22_u32;
-   |                ---   ^^^^^^ expected opaque type, found `u32`
-   |                |
-   |                expected due to this
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `m::bar`...
+  --> $DIR/inference-cycle.rs:15:5
+   |
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
+   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in module `m`
+  --> $DIR/inference-cycle.rs:4:1
+   |
+LL | mod m {
+   | ^^^^^
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0391.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0391`.
index 37b330ba4b8fc39620c1b612155a76968db5b36b..34be42027440904a206ea52cc130dbb0268634a6 100644 (file)
@@ -18,8 +18,8 @@ impl Foo for S2 {
     type Item = impl Debug;
 
     fn foo<T: Debug>(_: T) -> Self::Item {
-        //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         S::<T>(Default::default())
+        //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
index 4c8144a2359309a5f19a7724d317b9f0e2c91ec1..34f0aa0d98d9ab781fb346b9592bca16dcc87f95 100644 (file)
@@ -1,12 +1,8 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-53598.rs:20:42
+  --> $DIR/issue-53598.rs:21:9
    |
-LL |       fn foo<T: Debug>(_: T) -> Self::Item {
-   |  __________________________________________^
-LL | |
-LL | |         S::<T>(Default::default())
-LL | |     }
-   | |_____^
+LL |         S::<T>(Default::default())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index a4ccae4eb7ed99e7b5b49de3479f78aa5db2f44b..1538274d45cb22a5c3b9db37c3f9b5c06ac23a82 100644 (file)
@@ -1,38 +1,14 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:21:9
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:21:9
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
 LL |         |x| x
    |         ^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:17: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<(&'static X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:21:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:17:16
-   |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`...
-   = note: ...but it actually implements `FnOnce<(&'static X,)>`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
index 625e46b6bc0122b4ed5e1d74367e150e5e2595dc..7c6e764248479544c20025f46403e2bb04741252 100644 (file)
@@ -17,8 +17,8 @@ impl Foo for X {
     type Bar = impl Baz<Self, Self>;
 
     fn bar(&self) -> Self::Bar {
-        //~^ ERROR implementation of `FnOnce` is not general enough
         |x| x
+        //~^ ERROR implementation of `FnOnce` is not general enough
     }
 }
 
index 54d237159d80b56fd0edb903825ec19682ab342e..45329ea292dcf6791c327d5c0c742135f9dccb8a 100644 (file)
@@ -1,8 +1,8 @@
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:19:22
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
-LL |     fn bar(&self) -> Self::Bar {
-   |                      ^^^^^^^^^ implementation of `FnOnce` is not general enough
+LL |         |x| x
+   |         ^^^^^ implementation of `FnOnce` is not general enough
    |
    = 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`
index f1db4d3291b40709ade965658f99167fefc8e654..ba8bda76cecf6cf5473af6e0e9beafec3bb2a037 100644 (file)
@@ -14,8 +14,8 @@ impl<C> Foo for C {
     type Bar = impl Foo;
 
     fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
-        //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         self
+        //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
index c701e3e74ef591cecee73607b7c2ca1df6cf8e52..56ad997f843142e7de6f4213810ea76a4003aad2 100644 (file)
@@ -1,12 +1,8 @@
 error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-57700.rs:16:58
+  --> $DIR/issue-57700.rs:17:9
    |
-LL |       fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
-   |  __________________________________________________________^
-LL | |
-LL | |         self
-LL | |     }
-   | |_____^
+LL |         self
+   |         ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-58951-2.rs b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs
new file mode 100644 (file)
index 0000000..e4ba7f8
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+mod defining_use_scope {
+    pub type A = impl Iterator;
+
+    pub fn def_a() -> A {
+        0..1
+    }
+}
+use defining_use_scope::*;
+
+pub fn use_a() {
+    def_a().map(|x| x);
+}
+
+fn main() {}
index 9d2ba849c8667539ae6a40efbfb3505387ac0cbd..37a2f28ce074fed466fbb7dcb3f4b95ef7a0a7cd 100644 (file)
@@ -11,7 +11,6 @@ impl Bug for &() {
 
     const FUN: fn() -> Self::Item = || ();
     //~^ ERROR the trait bound `(): Bug` is not satisfied
-    //~| ERROR non-defining opaque type use in defining scope
 }
 
 fn main() {}
index 62ab7eb456010c8d166c7640c89ec19b532b55c3..3666b6e97ecfddbfe748d9c1c3d198186327ba78 100644 (file)
@@ -11,21 +11,12 @@ error[E0277]: the trait bound `(): Bug` is not satisfied
   --> $DIR/issue-60371.rs:12:40
    |
 LL |     const FUN: fn() -> Self::Item = || ();
-   |                                        ^ the trait `Bug` is not implemented for `()`
+   |                                        ^^ the trait `Bug` is not implemented for `()`
    |
    = help: the following implementations were found:
              <&() as Bug>
 
-error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60371.rs:12:37
-   |
-LL | impl Bug for &() {
-   |              - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-...
-LL |     const FUN: fn() -> Self::Item = || ();
-   |                                     ^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0658.
 For more information about an error, try `rustc --explain E0277`.
index 44dcec2c3da98f3ca47adaed7e089a8c88593ac1..4fc7679311a2e55b031dd0cf0c460c979476212b 100644 (file)
@@ -6,7 +6,6 @@ trait IterBits {
 }
 
 type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-//~^ ERROR could not find defining uses
 
 impl<T: Copy, E> IterBits for T
 where
@@ -18,8 +17,8 @@ impl<T: Copy, E> IterBits for T
 {
     type BitsIter = IterBitsIter<T, E, u8>;
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-        //~^ ERROR non-defining opaque type use in defining scope
         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+        //~^ ERROR non-defining opaque type use in defining scope
     }
 }
 
index 6b73fbef011ec8483e3b748637f32f905223ddfa..bbc93657be32f27501c851460adbfb0554ee0826 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:20:34
+  --> $DIR/issue-60564.rs:20:9
    |
-LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
-   |                                  ^^^^^^^^^^^^^^
+LL |         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: used non-generic type `u8` for generic parameter
   --> $DIR/issue-60564.rs:8:25
@@ -10,11 +10,5 @@ note: used non-generic type `u8` for generic parameter
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         ^
 
-error: could not find defining uses
-  --> $DIR/issue-60564.rs:8:30
-   |
-LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 875cce4df2390b0d9ad38d7c9d2bab320a5a6986..057a908bbee7477ebc76e1a4fee02e37ca103e98 100644 (file)
@@ -5,7 +5,10 @@
 type Closure = impl FnOnce();
 
 fn c() -> Closure {
-    || -> Closure { || () } //~ ERROR: mismatched types
+    || -> Closure { || () }
+    //~^ ERROR: mismatched types
+    //~| ERROR: mismatched types
+    //~| ERROR: expected a `FnOnce<()>` closure, found `()`
 }
 
 fn main() {}
index 5fde8c2ef1e1138e896cfa4d3b37d998a9cf3d24..4b7dbbd6a56cc2f9d7a89c4d80ea326407f9f32b 100644 (file)
@@ -1,17 +1,34 @@
+error[E0277]: expected a `FnOnce<()>` closure, found `()`
+  --> $DIR/issue-63279.rs:8:11
+   |
+LL |     || -> Closure { || () }
+   |           ^^^^^^^ expected an `FnOnce<()>` closure, found `()`
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `()`
+   = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-63279.rs:8:21
+   |
+LL |     || -> Closure { || () }
+   |                     ^^^^^ expected `()`, found closure
+   |
+   = note: expected unit type `()`
+                found closure `[closure@$DIR/issue-63279.rs:8:21: 8:26]`
+
 error[E0308]: mismatched types
   --> $DIR/issue-63279.rs:8:5
    |
 LL | type Closure = impl FnOnce();
-   |                ------------- the found opaque type
+   |                ------------- the expected opaque type
 ...
 LL |     || -> Closure { || () }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure
    |
-   = note: expected type `[closure@$DIR/issue-63279.rs:8:21: 8:26]`
-           found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]`
-   = note: no two closures, even if identical, have the same type
-   = help: consider boxing your closure and/or using it as a trait object
+   = note: expected opaque type `Closure`
+                  found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]`
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
index ff4fd5dcec73c87b4a5763888470ee0513caa328..7066a0535e1848e975b2cf124b605fbdddbdb241 100644 (file)
@@ -1,6 +1,5 @@
 #![feature(type_alias_impl_trait)]
-#![feature(type_alias_impl_trait)]
-#![allow(incomplete_features)]
+// check-pass
 
 pub trait Foo {}
 
@@ -28,11 +27,8 @@ fn foo() -> Self::Foo {
     }
 }
 
-// FIXME(#86731): The below is illegal use of `type_alias_impl_trait`
-// but the compiler doesn't report it, we should fix it.
 pub type FooImpl = impl Foo;
 pub type BarImpl = impl Bar<Foo = FooImpl>;
-//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()`
 
 impl Baz for () {
     type Foo = FooImpl;
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr
deleted file mode 100644 (file)
index 6fc6b4b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()`
-  --> $DIR/issue-63355.rs:34:20
-   |
-LL | pub type FooImpl = impl Foo;
-   |                    -------- the found opaque type
-LL | pub type BarImpl = impl Bar<Foo = FooImpl>;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()`
-   |
-note: expected this to be `()`
-  --> $DIR/issue-63355.rs:24:16
-   |
-LL |     type Foo = FooImpl;
-   |                ^^^^^^^
-   = note: expected unit type `()`
-            found opaque type `impl Foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
index 2e6354088ac5a6dfe2dc88bff55b4b7edd565682..5223fb1c702d6753c92e6f6ac2e9938732faf792 100644 (file)
@@ -5,7 +5,7 @@
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
-//~^ ERROR could not find defining uses
+
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR non-defining opaque type use in defining scope
 
index 721f99a3f0d182f8dab52331ce8c85cb0871124a..7fb9a0c410e83c8c976a78979f913279f462b84e 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use-2.rs:9:15
+  --> $DIR/issue-68368-non-defining-use-2.rs:9:29
    |
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   |               ^^^^^^^^^^^^^
+   |                             ^^
    |
 note: used non-generic type `()` for generic parameter
   --> $DIR/issue-68368-non-defining-use-2.rs:7:16
@@ -10,11 +10,5 @@ note: used non-generic type `()` for generic parameter
 LL | type Alias<'a, U> = impl Trait<U>;
    |                ^
 
-error: could not find defining uses
-  --> $DIR/issue-68368-non-defining-use-2.rs:7:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 3addd8dcc4fb3486e5aa91f515a011eb9ab166b8..b50462bf237bb9509f9d090097ef9675af48b8b8 100644 (file)
@@ -5,7 +5,7 @@
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
-//~^ ERROR could not find defining uses
+
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR non-defining opaque type use in defining scope
 
index f5b8fccf65d167779a5cc91b7185a6dd153bfec6..8059621b61a096bc84ed17714d7130d44e864d72 100644 (file)
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use.rs:9:15
+  --> $DIR/issue-68368-non-defining-use.rs:9:29
    |
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   |               ^^^^^^^^^^^^^
+   |                             ^^
    |
 note: used non-generic type `()` for generic parameter
   --> $DIR/issue-68368-non-defining-use.rs:7:16
@@ -10,11 +10,5 @@ note: used non-generic type `()` for generic parameter
 LL | type Alias<'a, U> = impl Trait<U>;
    |                ^
 
-error: could not find defining uses
-  --> $DIR/issue-68368-non-defining-use.rs:7:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index f6b369dd8d51827d0ec572e925405673d318779a..38591e37f53585d36d9b9feb1f837f06c360accc 100644 (file)
@@ -1,8 +1,14 @@
 error[E0308]: mismatched types
   --> $DIR/issue-74280.rs:9:5
    |
+LL | type Test = impl Copy;
+   |             --------- the expected opaque type
+...
 LL |     7
    |     ^ expected `()`, found integer
+   |
+   = note: expected opaque type `Test`
+                     found type `{integer}`
 
 error: aborting due to previous error
 
index 15205ba9b419e244513bcd6e55a84e68a60cbc49..053546e4b9285e29d0175fc6dde04fd1a43f1427 100644 (file)
@@ -5,7 +5,7 @@ LL | fn test() -> Pointer<_> {
    |              --------^-
    |              |       |
    |              |       not allowed in type signatures
-   |              help: replace with the correct return type: `Box<i32>`
+   |              help: replace with the correct return type: `Pointer<i32>`
 
 error: aborting due to previous error
 
index 19ed9a7476c1b872bded84d1f988665a2067bfca..3a75dc6fe7ba05403f8b471b457780cc009c2776 100644 (file)
@@ -2,18 +2,18 @@ error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as
   --> $DIR/issue-89686.rs:7:17
    |
 LL | type G<'a, T> = impl Future<Output = ()>;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
 ...
 LL |         async move { self.f().await }
-   |                    ------------------ the found `async` block
+   |                    ------------------ the expected `async` block
    |
   ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
+   |                                           ------------------------------- the expected opaque type
    |
-   = note:    expected unit type `()`
-           found associated type `<impl Future<Output = [async output]> as Future>::Output`
+   = note: expected associated type `<impl Future<Output = [async output]> as Future>::Output`
+                    found unit type `()`
    = help: consider constraining the associated type `<impl Future<Output = [async output]> as Future>::Output` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-93411.rs b/src/test/ui/type-alias-impl-trait/issue-93411.rs
new file mode 100644 (file)
index 0000000..1f8c789
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+// this test used to stack overflow due to infinite recursion.
+// check-pass
+// compile-flags: --edition=2018
+
+use std::future::Future;
+
+fn main() {
+    let _ = move || async move {
+        let value = 0u8;
+        blah(&value).await;
+    };
+}
+
+type BlahFut<'a> = impl Future<Output = ()> + Send + 'a;
+fn blah<'a>(_value: &'a u8) -> BlahFut<'a> {
+    async {}
+}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
new file mode 100644 (file)
index 0000000..08cb48c
--- /dev/null
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/73481
+// This test used to cause unsoundness, since one of the two possible
+// resolutions was chosen at random instead of erroring due to conflicts.
+
+#![feature(type_alias_impl_trait)]
+
+type Y<A, B> = impl std::fmt::Debug;
+
+fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
+    (42_i64, 60) //~^ ERROR concrete type differs from previous defining opaque type use
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
new file mode 100644 (file)
index 0000000..3f57612
--- /dev/null
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1
+   |
+LL | fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, got `i32`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1
+   |
+LL | fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
new file mode 100644 (file)
index 0000000..f39bf4a
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo<'a, 'b> = impl std::fmt::Debug;
+
+fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
+    (i, i) //~^ ERROR concrete type differs from previous
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
new file mode 100644 (file)
index 0000000..49d08dd
--- /dev/null
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:5:1
+   |
+LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a i32`, got `&'b i32`
+   |
+note: previous use here
+  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:5:1
+   |
+LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index f412b2d0e7db7959e0685b46b989e0126d57d902..83fd9a1da450bb543ecabea12259512822250859 100644 (file)
@@ -7,6 +7,15 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>)
     (a.clone(), a)
 }
 
+type Foo<'a, 'b> = impl std::fmt::Debug;
+
+fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
+    (i, j)
+}
+
 fn main() {
     println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1));
+    let meh = 42;
+    let muh = 69;
+    println!("{:?}", foo(&meh, &muh));
 }
index da845e86147b7ffb620f880936aae59069a2095f..46bac5a34f5c08408bf76071e77e40a1ed9cce7e 100644 (file)
@@ -7,8 +7,8 @@
 type X<A, B> = impl Into<&'static A>;
 
 fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
-    //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
     (a, a)
+    //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
 }
 
 fn main() {
index 4df2f52a9e427e795b4439727e7cbfd17a105717..f4d8b4509d43d1942614519e10049e129f5dcf2a 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
-  --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
+  --> $DIR/multiple-def-uses-in-one-fn.rs:10:9
    |
-LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
-   |                                             ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
+LL |     (a, a)
+   |         ^ the trait `From<&A>` is not implemented for `&'static B`
    |
    = note: required because of the requirements on the impl of `Into<&'static B>` for `&A`
 help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
index bbe709dccab4eb6e9404d4b5cba860ad4a7a2592..db4b60461ef38435344f008e7448d25d50d76982 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
    |
+LL | type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
+   |                                                    ------------- the expected opaque type
+...
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
    |      |
@@ -8,8 +11,8 @@ LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A
 LL |     (a, b)
    |         ^ expected type parameter `A`, found type parameter `B`
    |
-   = note: expected type parameter `A`
-              found type parameter `B`
+   = note: expected opaque type `X<A, B>`
+           found type parameter `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
 
index efb88dabf34cd3a251504fc90c9a74107d99917f..784a6c75886d427cd0951410e87c58f891c664f1 100644 (file)
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
@@ -12,7 +10,9 @@ trait Foo<A> { }
 impl Foo<()> for () { }
 
 fn foo() -> impl Foo<FooX> {
+    // FIXME(type-alias-impl-trait): We could probably make this work.
     ()
+    //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
 }
 
 fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr
new file mode 100644 (file)
index 0000000..9472cac
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
+  --> $DIR/nested-tait-inference.rs:14:5
+   |
+LL |     ()
+   |     ^^ the trait `Foo<FooX>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Foo<()>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 9b26a6529785236543e4c4b3c5c9d230a76d337b..00bd44c493c83475abaeabcd376dbd6e403973fd 100644 (file)
@@ -4,7 +4,6 @@
 use std::fmt::Debug;
 
 type FooX = impl Debug;
-//~^ ERROR: could not find defining uses
 
 trait Foo<A> {}
 
@@ -12,8 +11,8 @@ impl Foo<()> for () {}
 impl Foo<u32> for () {}
 
 fn foo() -> impl Foo<FooX> {
-    //~^ ERROR: the trait bound `(): Foo<impl Debug>` is not satisfied [E0277]
     ()
+    //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
 }
 
 fn main() {}
index 7e24ee644b1ceb7f5ff33aa1aa19b4b6bde5b835..ec1b4642d08226adc3eaaacc53f8e9c350f2c6d4 100644 (file)
@@ -1,19 +1,13 @@
-error[E0277]: the trait bound `(): Foo<impl Debug>` is not satisfied
-  --> $DIR/nested-tait-inference2.rs:14:13
+error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
+  --> $DIR/nested-tait-inference2.rs:14:5
    |
-LL | fn foo() -> impl Foo<FooX> {
-   |             ^^^^^^^^^^^^^^ the trait `Foo<impl Debug>` is not implemented for `()`
+LL |     ()
+   |     ^^ the trait `Foo<FooX>` is not implemented for `()`
    |
    = help: the following implementations were found:
              <() as Foo<()>>
              <() as Foo<u32>>
 
-error: could not find defining uses
-  --> $DIR/nested-tait-inference2.rs:6:13
-   |
-LL | type FooX = impl Debug;
-   |             ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
new file mode 100644 (file)
index 0000000..fbab547
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+type FooX = impl Debug;
+//~^ unconstrained opaque type
+
+trait Foo<A> { }
+
+impl Foo<FooX> for () { }
+
+fn foo() -> impl Foo<FooX> {
+    ()
+}
+
+fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
new file mode 100644 (file)
index 0000000..b1d947a
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/nested-tait-inference3.rs:6:13
+   |
+LL | type FooX = impl Debug;
+   |             ^^^^^^^^^^
+   |
+   = note: `FooX` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs
new file mode 100644 (file)
index 0000000..6b866be
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+type Bar = impl Trait<Foo>;
+
+trait Trait<T> {}
+
+impl<T, U> Trait<T> for U {}
+
+fn bar() -> Bar {
+    42
+}
+
+fn main() {
+    println!("{:?}", bar());
+    //~^ ERROR `Bar` doesn't implement `Debug`
+}
diff --git a/src/test/ui/type-alias-impl-trait/nested.stderr b/src/test/ui/type-alias-impl-trait/nested.stderr
new file mode 100644 (file)
index 0000000..cf4d236
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: `Bar` doesn't implement `Debug`
+  --> $DIR/nested.rs:15:22
+   |
+LL |     println!("{:?}", bar());
+   |                      ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `Bar`
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 6282264d8fee59cdccf392c9afbfb686c992c032..60b6e1aac6281672b544be3f2dc979251b3f507e 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(type_alias_impl_trait)]
-// build-pass (FIXME(62277): could be check-pass?)
+
 mod my_mod {
     use std::fmt::Debug;
 
@@ -11,7 +11,7 @@ pub fn get_foo() -> Foo {
     }
 
     pub fn get_foot() -> Foot {
-        get_foo()
+        get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr
new file mode 100644 (file)
index 0000000..fa6ecf6
--- /dev/null
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/nested_type_alias_impl_trait.rs:14:9
+   |
+LL |         get_foo()
+   |         ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/nested_type_alias_impl_trait.rs:7:21
+   |
+LL |     pub type Foot = impl Debug;
+   |                     ^^^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/nested_type_alias_impl_trait.rs:6:20
+   |
+LL |     pub type Foo = impl Debug;
+   |                    ^^^^^^^^^^
+
+error: aborting due to previous error
+
index 8787c023eb0c78708e7a8554b3c4ef7eb4860889..fed5ac07c901e5266345ff8ad8e30764126b2e45 100644 (file)
@@ -1,8 +1,7 @@
 #![feature(type_alias_impl_trait)]
-
+// check-pass
 fn main() {}
 
-// don't reveal the concrete type
 type NoReveal = impl std::fmt::Debug;
 
 fn define_no_reveal() -> NoReveal {
@@ -10,6 +9,6 @@ fn define_no_reveal() -> NoReveal {
 }
 
 fn no_reveal(x: NoReveal) {
-    let _: &'static str = x; //~ mismatched types
-    let _ = x as &'static str; //~ non-primitive cast
+    let _: &'static str = x;
+    let _ = x as &'static str;
 }
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
deleted file mode 100644 (file)
index b438f84..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/never_reveal_concrete_type.rs:13:27
-   |
-LL | type NoReveal = impl std::fmt::Debug;
-   |                 -------------------- the found opaque type
-...
-LL |     let _: &'static str = x;
-   |            ------------   ^ expected `&str`, found opaque type
-   |            |
-   |            expected due to this
-   |
-   = note: expected reference `&'static str`
-            found opaque type `impl Debug`
-
-error[E0605]: non-primitive cast: `impl Debug` as `&'static str`
-  --> $DIR/never_reveal_concrete_type.rs:14:13
-   |
-LL |     let _ = x as &'static str;
-   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0605.
-For more information about an error, try `rustc --explain E0308`.
index 1197c7bc58ece3859519faa1ef1f8fcf80bdf8bf..fa578eced5f2b21bb31d9f06e1a2c4ae2f076bf8 100644 (file)
@@ -1,9 +1,9 @@
 // Issue 52985: user code provides no use case that allows a type alias `impl Trait`
-// We now emit a 'could not find defining uses' error
+// We now emit a 'unconstrained opaque type' error
 
 #![feature(type_alias_impl_trait)]
 
-type Foo = impl Copy; //~ could not find defining uses
+type Foo = impl Copy; //~ unconstrained opaque type
 
 // make compiler happy about using 'Foo'
 fn bar(x: Foo) -> Foo {
index 61025e846921e3dfc7c39d65c1178c702a95df40..009935347e66c6d1975e0fd4df822f82a41fcaea 100644 (file)
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/no_inferrable_concrete_type.rs:6:12
    |
 LL | type Foo = impl Copy;
    |            ^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
index 67752acb8c9afd6d389ea21ba76e00135b818ccb..e691d8781c0f1cff7d2bcac93a715f97bd37e4c8 100644 (file)
@@ -5,12 +5,10 @@ LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ---------------------- the found opaque type
 ...
 LL |     let _: &str = bomp();
-   |            ----   ^^^^^^ expected `&str`, found opaque type
-   |            |
-   |            expected due to this
+   |                   ^^^^^^ expected `&str`, found opaque type
    |
    = note: expected reference `&str`
-            found opaque type `impl Debug`
+            found opaque type `Boo`
 
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
@@ -18,13 +16,11 @@ error[E0308]: mismatched types
 LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ---------------------- the expected opaque type
 ...
-LL | fn bomp() -> boo::Boo {
-   |              -------- expected `impl Debug` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
-   = note: expected opaque type `impl Debug`
-                found reference `&'static str`
+   = note: expected opaque type `Boo`
+                found reference `&str`
 
 error: aborting due to 2 previous errors
 
index 107cd394579355d2d05b010c4615a592f13b1f35..5b332b8cb6bd8ce63a3142350d1d5b99d58a226b 100644 (file)
@@ -7,11 +7,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `T` doesn't implement `Debug`
 
-fn two<T: Debug>(t: T) -> Two<T, u32> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    (t, 4i8)
-}
-
 fn three<T: Debug, U>(t: T) -> Two<T, U> {
     (t, 5i8)
 }
index 08e49845521c6ab18e3d7dd92a2fe77f8519df4e..f946dc48a4bf98e3b5a2a7ec6b98655e62c9d5ee 100644 (file)
@@ -1,23 +1,11 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/not_a_defining_use.rs:10:27
-   |
-LL | fn two<T: Debug>(t: T) -> Two<T, u32> {
-   |                           ^^^^^^^^^^^
-   |
-note: used non-generic type `u32` for generic parameter
-  --> $DIR/not_a_defining_use.rs:7:13
-   |
-LL | type Two<T, U> = impl Debug;
-   |             ^
-
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/not_a_defining_use.rs:29:1
+  --> $DIR/not_a_defining_use.rs:24:1
    |
 LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
 note: previous use here
-  --> $DIR/not_a_defining_use.rs:15:1
+  --> $DIR/not_a_defining_use.rs:10:1
    |
 LL | fn three<T: Debug, U>(t: T) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,6 +22,6 @@ help: consider restricting type parameter `T`
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.rs b/src/test/ui/type-alias-impl-trait/self-referential-2.rs
new file mode 100644 (file)
index 0000000..dc7054d
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+type Bar = impl PartialEq<Foo>;
+
+fn bar() -> Bar {
+    42_i32 //~ ERROR can't compare `i32` with `Foo`
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
new file mode 100644 (file)
index 0000000..6997676
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0277]: can't compare `i32` with `Foo`
+  --> $DIR/self-referential-2.rs:7:5
+   |
+LL |     42_i32
+   |     ^^^^^^ no implementation for `i32 == Foo`
+   |
+   = help: the trait `PartialEq<Foo>` is not implemented for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-3.rs b/src/test/ui/type-alias-impl-trait/self-referential-3.rs
new file mode 100644 (file)
index 0000000..d407157
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(type_alias_impl_trait)]
+
+type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
+
+fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    i
+}
+
+fn main() {
+    let meh = 42;
+    let muh = 42;
+    assert_eq!(bar(&meh), bar(&muh));
+}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.rs b/src/test/ui/type-alias-impl-trait/self-referential-4.rs
new file mode 100644 (file)
index 0000000..697ec56
--- /dev/null
@@ -0,0 +1,25 @@
+#![feature(type_alias_impl_trait)]
+
+type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'static>> + std::fmt::Debug;
+
+fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Bar<'b, 'static>`
+}
+
+type Foo<'a, 'b> = impl PartialEq<Foo<'static, 'b>> + std::fmt::Debug;
+
+fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Foo<'static, 'b>`
+}
+
+type Moo<'a, 'b> = impl PartialEq<Moo<'static, 'a>> + std::fmt::Debug;
+
+fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Moo<'static, 'a>`
+}
+
+fn main() {
+    let meh = 42;
+    let muh = 69;
+    assert_eq!(bar(&meh), bar(&meh));
+}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
new file mode 100644 (file)
index 0000000..4a6ee2f
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0277]: can't compare `&i32` with `Bar<'b, 'static>`
+  --> $DIR/self-referential-4.rs:6:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Bar<'b, 'static>`
+   |
+   = help: the trait `PartialEq<Bar<'b, 'static>>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `Foo<'static, 'b>`
+  --> $DIR/self-referential-4.rs:12:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Foo<'static, 'b>`
+   |
+   = help: the trait `PartialEq<Foo<'static, 'b>>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `Moo<'static, 'a>`
+  --> $DIR/self-referential-4.rs:18:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Moo<'static, 'a>`
+   |
+   = help: the trait `PartialEq<Moo<'static, 'a>>` is not implemented for `&i32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.rs b/src/test/ui/type-alias-impl-trait/self-referential.rs
new file mode 100644 (file)
index 0000000..4974ac7
--- /dev/null
@@ -0,0 +1,25 @@
+#![feature(type_alias_impl_trait)]
+
+type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'a>> + std::fmt::Debug;
+
+fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Bar<'b, 'a>`
+}
+
+type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug);
+
+fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
+    (42, i) //~ ERROR can't compare `&i32` with `(i32, &i32)`
+}
+
+type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug);
+
+fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
+    (42, i) //~ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
+}
+
+fn main() {
+    let meh = 42;
+    let muh = 69;
+    assert_eq!(bar(&meh), bar(&meh));
+}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr
new file mode 100644 (file)
index 0000000..0626e6b
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0277]: can't compare `&i32` with `Bar<'b, 'a>`
+  --> $DIR/self-referential.rs:6:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Bar<'b, 'a>`
+   |
+   = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `(i32, &i32)`
+  --> $DIR/self-referential.rs:12:10
+   |
+LL |     (42, i)
+   |          ^ no implementation for `&i32 == (i32, &i32)`
+   |
+   = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
+  --> $DIR/self-referential.rs:18:10
+   |
+LL |     (42, i)
+   |          ^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})`
+   |
+   = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 86b685022b20ec7dd71e5b9b757c57c01253285c..748a279e43989521e548e817598db416d1643876 100644 (file)
@@ -1,13 +1,13 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME: This should compile, but it currently doesn't
+// check-pass
 
 use std::fmt::Debug;
 
-type Foo = impl Debug; //~ ERROR could not find defining uses
+type Foo = impl Debug;
 
-static FOO1: Foo = 22_u32; //~ ERROR mismatched types
-const FOO2: Foo = 22_u32; //~ ERROR mismatched types
+static FOO1: Foo = 22_u32;
+const FOO2: Foo = 22_u32;
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.stderr b/src/test/ui/type-alias-impl-trait/static-const-types.stderr
deleted file mode 100644 (file)
index 6f4c294..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:10:20
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-LL | 
-LL | static FOO1: Foo = 22_u32;
-   |                    ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:11:19
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL | const FOO2: Foo = 22_u32;
-   |                   ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error: could not find defining uses
-  --> $DIR/static-const-types.rs:8:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index 51a7b6454c35ef3189deb551f1a578b3e16d2dda..cab742d23f57d05e1a9b9233491d967c2cab13ba 100644 (file)
@@ -11,9 +11,9 @@ const fn leak_free() -> Bar {
 const LEAK_FREE: Bar = leak_free();
 
 fn leak_free_test() {
-    match todo!() {
+    match LEAK_FREE {
         LEAK_FREE => (),
-        //~^ `impl Send` cannot be used in patterns
+        //~^ `Bar` cannot be used in patterns
         _ => (),
     }
 }
index 7e41b374452a3c2a9f99a40c9096e3e9cd51f1a5..aacc0cc7aa69b768afd9cc8ccda621d9bdb5d654 100644 (file)
@@ -1,4 +1,4 @@
-error: `impl Send` cannot be used in patterns
+error: `Bar` cannot be used in patterns
   --> $DIR/structural-match-no-leak.rs:15:9
    |
 LL |         LEAK_FREE => (),
index 73558d39ad56163a69a0fa30840a9f31885d8414..c8825c68e33cc3b0ed351cdfcd1fd80407860dd6 100644 (file)
@@ -12,9 +12,9 @@ const fn value() -> Foo {
 const VALUE: Foo = value();
 
 fn test() {
-    match todo!() {
+    match VALUE {
         VALUE => (),
-        //~^ `impl Send` cannot be used in patterns
+        //~^ `Foo` cannot be used in patterns
         _ => (),
     }
 }
index b43f2148dea5ec84c4abe5e24a08a38325286aa8..28ae9c212d979f104b491a1527e5ea4069b1dab6 100644 (file)
@@ -1,4 +1,4 @@
-error: `impl Send` cannot be used in patterns
+error: `Foo` cannot be used in patterns
   --> $DIR/structural-match.rs:16:9
    |
 LL |         VALUE => (),
index 1a8113848f9239349e8e4bf1132ca1024707d28e..5630e036be34b317cb9eea81a716b718fc81d9b4 100644 (file)
@@ -1,13 +1,11 @@
 #![feature(type_alias_impl_trait)]
-
+// check-pass
 // Ensures that `const` items can constrain an opaque `impl Trait`.
 
 use std::fmt::Debug;
 
 pub type Foo = impl Debug;
-//~^ ERROR could not find defining uses
 
 const _FOO: Foo = 5;
-//~^ ERROR mismatched types [E0308]
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
deleted file mode 100644 (file)
index e2567e8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/type-alias-impl-trait-const.rs:10:19
-   |
-LL | pub type Foo = impl Debug;
-   |                ---------- the expected opaque type
-...
-LL | const _FOO: Foo = 5;
-   |                   ^ expected opaque type, found integer
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error: could not find defining uses
-  --> $DIR/type-alias-impl-trait-const.rs:7:16
-   |
-LL | pub type Foo = impl Debug;
-   |                ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index c009952eab75051197e6698707e3e6d57120f40c..e5e7fb677ede91e66d1deb4f5eda564d42425d74 100644 (file)
@@ -1,7 +1,7 @@
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Fn() -> Foo;
-//~^ ERROR: could not find defining uses
+//~^ ERROR: unconstrained opaque type
 
 fn crash(x: Foo) -> Foo {
     x
index 726f4ea6e00f71c5006f71ec819b6db13d0544f8..a770eeac39b7d5beaae0149e9c72d12a6126bd4b 100644 (file)
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12
    |
 LL | type Foo = impl Fn() -> Foo;
    |            ^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
index f3898bca64b9b3b94f3ebb813c45313d92ab55d0..7c7a1b405bcdcd5caedbfe50e676eb72f02115b9 100644 (file)
@@ -5,7 +5,7 @@ pub trait Bar<T> {
 }
 
 type Foo = impl Bar<Foo, Item = Foo>;
-//~^ ERROR: could not find defining uses
+//~^ ERROR: unconstrained opaque type
 
 fn crash(x: Foo) -> Foo {
     x
index 3947cc4d27055f5972f5b183beba416da1604957..3f3699ce5324aa984087c42f8fa103870ff25113 100644 (file)
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12
    |
 LL | type Foo = impl Bar<Foo, Item = Foo>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
index d2c8c1f63df1c89062bb97f42006bfd7fec3f0b3..70c2ee4278ca218be1d44876c135cad0b505cc95 100644 (file)
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![allow(dead_code)]
 #![allow(unused_assignments)]
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs
new file mode 100644 (file)
index 0000000..67f56bc
--- /dev/null
@@ -0,0 +1,84 @@
+// check-pass
+
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![feature(type_alias_impl_trait)]
+
+fn main() {
+    assert_eq!(foo().to_string(), "foo");
+    assert_eq!(bar1().to_string(), "bar1");
+    assert_eq!(bar2().to_string(), "bar2");
+    let mut x = bar1();
+    x = bar2();
+    assert_eq!(my_iter(42u8).collect::<Vec<u8>>(), vec![42u8]);
+}
+
+use defining_use_scope::*;
+
+mod defining_use_scope {
+    // single definition
+    pub type Foo = impl std::fmt::Display;
+
+    pub fn foo() -> Foo {
+        "foo"
+    }
+
+    // two definitions
+    pub type Bar = impl std::fmt::Display;
+
+    pub fn bar1() -> Bar {
+        "bar1"
+    }
+
+    pub fn bar2() -> Bar {
+        "bar2"
+    }
+
+    pub type MyIter<T> = impl Iterator<Item = T>;
+
+    pub fn my_iter<T>(t: T) -> MyIter<T> {
+        std::iter::once(t)
+    }
+
+    fn my_iter2<T>(t: T) -> MyIter<T> {
+        std::iter::once(t)
+    }
+
+    // param names should not have an effect!
+    fn my_iter3<U>(u: U) -> MyIter<U> {
+        std::iter::once(u)
+    }
+
+    // param position should not have an effect!
+    fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
+        std::iter::once(v)
+    }
+
+    // param names should not have an effect!
+    type MyOtherIter<T> = impl Iterator<Item = T>;
+
+    fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
+        std::iter::once(u)
+    }
+
+    trait Trait {}
+    type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
+
+    fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
+        t
+    }
+
+    mod pass_through {
+        pub type Passthrough<T: 'static> = impl Sized + 'static;
+
+        fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
+            t
+        }
+    }
+
+    fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> {
+        x
+    }
+
+}
index 7f8e6127cca3b2faf3b078c5bb6f34823fe1e857..4e9d1788b94d833e6fca30adec602bbdaf3a141c 100644 (file)
@@ -1,27 +1,20 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME This should compile, but it currently doesn't
-
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR: could not find defining uses
 
 fn foo1() -> u32 {
     let x: Foo = 22_u32;
-    //~^ ERROR: mismatched types [E0308]
     x
-    //~^ ERROR: mismatched types [E0308]
 }
 
 fn foo2() -> u32 {
     let x: Foo = 22_u32;
-    //~^ ERROR: mismatched types [E0308]
     let y: Foo = x;
-    same_type((x, y));
-    y
-    //~^ ERROR: mismatched types [E0308]
+    same_type((x, y)); //~ ERROR use of moved value
+    y //~ ERROR use of moved value
 }
 
 fn same_type<T>(x: (T, T)) {}
index cac8d6841afda098ec95f81178252b7c16d75123..1dabe4586c5b93123e9c9a3e00a2b129b7753b02 100644 (file)
@@ -1,67 +1,23 @@
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:12:18
+error[E0382]: use of moved value: `x`
+  --> $DIR/type_of_a_let.rs:16:16
    |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
 LL |     let x: Foo = 22_u32;
-   |            ---   ^^^^^^ expected opaque type, found `u32`
-   |            |
-   |            expected due to this
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:14:5
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the found opaque type
-...
-LL | fn foo1() -> u32 {
-   |              --- expected `u32` because of return type
-...
-LL |     x
-   |     ^ expected `u32`, found opaque type
-   |
-   = note:     expected type `u32`
-           found opaque type `impl Debug`
+   |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
+LL |     let y: Foo = x;
+   |                  - value moved here
+LL |     same_type((x, y));
+   |                ^ value used here after move
 
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:19:18
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL |     let x: Foo = 22_u32;
-   |            ---   ^^^^^^ expected opaque type, found `u32`
-   |            |
-   |            expected due to this
+error[E0382]: use of moved value: `y`
+  --> $DIR/type_of_a_let.rs:17:5
    |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:23:5
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the found opaque type
-...
-LL | fn foo2() -> u32 {
-   |              --- expected `u32` because of return type
-...
+LL |     let y: Foo = x;
+   |         - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait
+LL |     same_type((x, y));
+   |                   - value moved here
 LL |     y
-   |     ^ expected `u32`, found opaque type
-   |
-   = note:     expected type `u32`
-           found opaque type `impl Debug`
-
-error: could not find defining uses
-  --> $DIR/type_of_a_let.rs:8:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
+   |     ^ value used here after move
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0382`.
index 7512039a480bb95e191d17eed4b34d3708643d42..5407b5e8ed93e8c014503b099723485fc67660c3 100644 (file)
@@ -32,6 +32,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
                 | ty::PredicateKind::Projection(_)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::OpaqueType(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
                 ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
                 ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
index 27d59bc01f22a23f8a876862709df4ae464d8f69..da7a19139c65b3f28d019b33fbeef5ad883a7e0e 100644 (file)
@@ -922,10 +922,11 @@ pub fn make_test_description<R: Read>(
         name,
         ignore,
         should_panic,
-        allow_fail: false,
         compile_fail: false,
         no_run: false,
         test_type: test::TestType::Unknown,
+        #[cfg(bootstrap)]
+        allow_fail: false,
     }
 }