From 264cd05b16198c2838ec6cd585bd122491e3f7a9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 14 Feb 2022 16:10:22 +0000 Subject: [PATCH 01/26] Revert "Auto merge of #93893 - oli-obk:sad_revert, r=oli-obk" This reverts commit 6499c5e7fc173a3f55b7a3bd1e6a50e9edef782d, reversing changes made to 78450d2d602b06d9b94349aaf8cece1a4acaf3a8. --- .../src/diagnostics/bound_region_errors.rs | 112 ++++- compiler/rustc_borrowck/src/lib.rs | 6 +- .../rustc_borrowck/src/region_infer/mod.rs | 4 +- .../src/region_infer/opaque_types.rs | 58 ++- .../src/type_check/canonical.rs | 9 +- .../src/type_check/free_region_relations.rs | 2 +- .../src/type_check/input_output.rs | 8 +- compiler/rustc_borrowck/src/type_check/mod.rs | 271 +++------- .../src/type_check/relate_tys.rs | 37 +- .../rustc_borrowck/src/universal_regions.rs | 14 +- .../src/transform/check_consts/check.rs | 19 +- .../src/transform/validate.rs | 5 +- compiler/rustc_data_structures/src/vec_map.rs | 16 +- compiler/rustc_infer/src/infer/at.rs | 21 +- .../src/infer/canonical/query_response.rs | 67 ++- compiler/rustc_infer/src/infer/combine.rs | 26 +- compiler/rustc_infer/src/infer/equate.rs | 22 +- compiler/rustc_infer/src/infer/glb.rs | 10 +- compiler/rustc_infer/src/infer/lattice.rs | 27 +- compiler/rustc_infer/src/infer/lub.rs | 10 +- compiler/rustc_infer/src/infer/mod.rs | 63 ++- .../rustc_infer/src/infer/nll_relate/mod.rs | 38 +- .../rustc_infer/src/infer/opaque_types.rs | 461 +++++++++--------- .../src/infer/opaque_types/table.rs | 88 ++++ .../rustc_infer/src/infer/outlives/mod.rs | 1 + .../src/infer/outlives/obligations.rs | 3 +- compiler/rustc_infer/src/infer/sub.rs | 39 +- compiler/rustc_infer/src/infer/undo_log.rs | 6 +- compiler/rustc_infer/src/traits/util.rs | 3 + compiler/rustc_lint/src/builtin.rs | 1 + compiler/rustc_middle/src/infer/canonical.rs | 6 + compiler/rustc_middle/src/ty/_match.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 11 +- compiler/rustc_middle/src/ty/flags.rs | 4 + compiler/rustc_middle/src/ty/fold.rs | 14 +- compiler/rustc_middle/src/ty/mod.rs | 20 +- compiler/rustc_middle/src/ty/print/pretty.rs | 28 +- .../rustc_middle/src/ty/structural_impls.rs | 6 + compiler/rustc_middle/src/ty/sty.rs | 7 + compiler/rustc_mir_build/src/build/block.rs | 6 +- .../src/dep_graph/serialized.rs | 2 - .../rustc_trait_selection/src/opaque_types.rs | 18 +- .../src/traits/auto_trait.rs | 1 + .../src/traits/codegen.rs | 5 + .../src/traits/error_reporting/mod.rs | 4 + .../src/traits/error_reporting/suggestions.rs | 2 + .../src/traits/fulfill.rs | 17 + .../src/traits/object_safety.rs | 2 + .../src/traits/query/type_op/custom.rs | 32 +- .../src/traits/query/type_op/mod.rs | 11 +- .../src/traits/select/candidate_assembly.rs | 1 + .../src/traits/select/mod.rs | 49 +- .../rustc_trait_selection/src/traits/wf.rs | 4 + compiler/rustc_traits/src/chalk/lowering.rs | 4 + compiler/rustc_traits/src/chalk/mod.rs | 2 + .../src/implied_outlives_bounds.rs | 1 + .../src/normalize_erasing_regions.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 8 + compiler/rustc_typeck/src/check/_match.rs | 20 +- compiler/rustc_typeck/src/check/callee.rs | 2 +- compiler/rustc_typeck/src/check/check.rs | 54 +- compiler/rustc_typeck/src/check/closure.rs | 108 +++- compiler/rustc_typeck/src/check/coercion.rs | 2 +- .../rustc_typeck/src/check/expectation.rs | 28 +- compiler/rustc_typeck/src/check/expr.rs | 3 +- compiler/rustc_typeck/src/check/fallback.rs | 65 +-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 43 +- .../rustc_typeck/src/check/fn_ctxt/mod.rs | 3 - compiler/rustc_typeck/src/check/inherited.rs | 9 +- .../rustc_typeck/src/check/method/probe.rs | 4 + compiler/rustc_typeck/src/check/mod.rs | 1 + compiler/rustc_typeck/src/check/upvar.rs | 5 - compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- compiler/rustc_typeck/src/check/writeback.rs | 71 +-- compiler/rustc_typeck/src/collect/type_of.rs | 63 ++- .../src/impl_wf_check/min_specialization.rs | 1 + .../rustc_typeck/src/outlives/explicit.rs | 1 + src/bootstrap/bin/rustc.rs | 6 + src/librustdoc/clean/mod.rs | 1 + .../incremental/hashes/function_interfaces.rs | 2 +- .../assoc-type-eq-with-dyn-atb-fail.rs | 2 +- .../assoc-type-eq-with-dyn-atb-fail.stderr | 8 +- .../impl-trait-return-missing-constraint.rs | 2 +- ...mpl-trait-return-missing-constraint.stderr | 14 +- ...async-borrowck-escaping-block-error.stderr | 6 +- .../async-await/issue-64130-4-async-move.rs | 2 +- .../issue-64130-4-async-move.stderr | 6 +- src/test/ui/async-await/issue-70818.rs | 2 +- src/test/ui/async-await/issue-70818.stderr | 8 +- .../async-await/issue-70935-complex-spans.rs | 2 +- .../issue-70935-complex-spans.stderr | 6 +- .../ret-impl-trait-one.nll.stderr | 14 +- .../ret-impl-trait-one.stderr | 29 +- src/test/ui/async-await/no-const-async.rs | 1 + src/test/ui/async-await/no-const-async.stderr | 33 +- .../recursive-async-impl-trait-type.rs | 3 +- .../ui/async-await/suggest-missing-await.rs | 1 - .../async-await/suggest-missing-await.stderr | 27 +- src/test/ui/cast/casts-differing-anon.rs | 2 +- src/test/ui/cast/casts-differing-anon.stderr | 16 +- src/test/ui/chalkify/bugs/async.stderr | 8 +- .../diagnostics/borrowck/borrowck-4.stderr | 6 +- src/test/ui/conservative_impl_trait.stderr | 9 +- .../defaults/rp_impl_trait_fail.rs | 6 +- .../defaults/rp_impl_trait_fail.stderr | 18 +- ...orted_main_const_fn_item_type_forbidden.rs | 2 - ...d_main_const_fn_item_type_forbidden.stderr | 25 +- .../feature-gate-type_alias_impl_trait.rs | 11 +- .../feature-gate-type_alias_impl_trait.stderr | 73 --- src/test/ui/generator/issue-88653.rs | 4 +- src/test/ui/generator/issue-88653.stderr | 10 +- .../type-mismatch-signature-deduction.rs | 4 +- .../type-mismatch-signature-deduction.stderr | 16 +- .../bugs/issue-86218.stderr | 12 +- .../bugs/issue-89008.stderr | 26 +- .../generic-associated-types/issue-87258_a.rs | 3 +- .../issue-87258_a.stderr | 11 +- .../generic-associated-types/issue-87258_b.rs | 3 +- .../issue-87258_b.stderr | 11 +- .../generic-associated-types/issue-88595.rs | 1 - .../issue-88595.stderr | 12 +- .../issue-92096.migrate.stderr | 18 +- .../generic-associated-types/issue-92096.rs | 4 +- src/test/ui/impl-trait/auto-trait-leak.rs | 1 + src/test/ui/impl-trait/auto-trait-leak.stderr | 112 ++++- src/test/ui/impl-trait/auto-trait.rs | 2 +- src/test/ui/impl-trait/auto-trait.stderr | 4 +- .../ui/impl-trait/bound-normalization-fail.rs | 6 +- .../bound-normalization-fail.stderr | 24 +- .../does-not-live-long-enough.stderr | 6 +- src/test/ui/impl-trait/equality.stderr | 14 +- src/test/ui/impl-trait/equality2.stderr | 4 +- src/test/ui/impl-trait/fallback.rs | 9 + src/test/ui/impl-trait/hidden-lifetimes.rs | 4 +- .../ui/impl-trait/hidden-lifetimes.stderr | 16 +- .../ui/impl-trait/hidden-type-is-opaque-2.rs | 34 ++ .../impl-trait/hidden-type-is-opaque-2.stderr | 11 + .../ui/impl-trait/hidden-type-is-opaque.rs | 32 ++ src/test/ui/impl-trait/issue-55872-1.rs | 7 +- src/test/ui/impl-trait/issue-55872-1.stderr | 27 +- src/test/ui/impl-trait/issue-55872-2.rs | 7 +- src/test/ui/impl-trait/issue-55872-2.stderr | 20 +- src/test/ui/impl-trait/issue-55872-3.rs | 20 + src/test/ui/impl-trait/issue-55872-3.stderr | 9 + src/test/ui/impl-trait/issue-55872.rs | 2 +- src/test/ui/impl-trait/issue-55872.stderr | 10 +- src/test/ui/impl-trait/issue-72911.rs | 2 +- src/test/ui/impl-trait/issue-72911.stderr | 22 +- src/test/ui/impl-trait/issues/issue-70877.rs | 6 +- .../ui/impl-trait/issues/issue-70877.stderr | 40 +- src/test/ui/impl-trait/issues/issue-78722.rs | 5 +- .../ui/impl-trait/issues/issue-78722.stderr | 35 +- src/test/ui/impl-trait/issues/issue-86201.rs | 4 +- .../ui/impl-trait/issues/issue-86201.stderr | 21 - .../issues/issue-88236-2.nll.stderr | 51 ++ .../ui/impl-trait/issues/issue-88236-2.rs | 23 + .../ui/impl-trait/issues/issue-88236-2.stderr | 20 + src/test/ui/impl-trait/issues/issue-88236.rs | 19 + src/test/ui/impl-trait/lifetimes2.rs | 10 + .../multiple-lifetimes/error-handling-2.rs | 2 +- .../error-handling-2.stderr | 9 +- .../ordinary-bounds-unrelated.rs | 2 +- .../ordinary-bounds-unrelated.stderr | 9 +- .../ordinary-bounds-unsuited.rs | 2 +- .../ordinary-bounds-unsuited.stderr | 9 +- ...t_outlive_least_region_or_bound.nll.stderr | 22 +- .../must_outlive_least_region_or_bound.rs | 4 +- .../must_outlive_least_region_or_bound.stderr | 49 +- src/test/ui/impl-trait/negative-reasoning.rs | 2 +- .../ui/impl-trait/negative-reasoning.stderr | 6 +- src/test/ui/impl-trait/nested_impl_trait.rs | 2 + .../ui/impl-trait/nested_impl_trait.stderr | 38 +- ...trait-in-return-position-impl-trait.stderr | 37 +- ...-to-type-err-cause-on-impl-trait-return.rs | 12 +- ...type-err-cause-on-impl-trait-return.stderr | 190 ++------ ...rojection-mismatch-in-impl-where-clause.rs | 2 +- ...ction-mismatch-in-impl-where-clause.stderr | 8 +- src/test/ui/impl-trait/question_mark.rs | 13 + .../recursive-impl-trait-type-direct.rs | 3 +- .../recursive-impl-trait-type-direct.stderr | 12 - .../recursive-impl-trait-type-indirect.rs | 2 +- ...alias-impl-trait-declaration-too-subtle.rs | 29 ++ ...s-impl-trait-declaration-too-subtle.stderr | 18 + ...rsive-type-alias-impl-trait-declaration.rs | 37 ++ .../ui/impl-trait/region-escape-via-bound.rs | 2 +- .../impl-trait/region-escape-via-bound.stderr | 9 +- .../static-return-lifetime-infered.rs | 4 +- .../static-return-lifetime-infered.stderr | 32 +- .../two_tait_defining_each_other.rs | 19 + .../two_tait_defining_each_other.stderr | 19 + .../two_tait_defining_each_other2.rs | 16 + .../two_tait_defining_each_other2.stderr | 19 + .../two_tait_defining_each_other3.rs | 19 + .../two_tait_defining_each_other3.stderr | 19 + .../type_parameters_captured.nll.stderr | 6 +- .../ui/impl-trait/type_parameters_captured.rs | 2 +- .../type_parameters_captured.stderr | 8 +- src/test/ui/impl-trait/where-allowed-2.rs | 7 +- src/test/ui/impl-trait/where-allowed-2.stderr | 13 - src/test/ui/issues-71798.rs | 3 +- src/test/ui/issues-71798.stderr | 8 +- .../lang-item-missing-generator.stderr | 4 +- .../freeze_cycle.rs | 46 ++ .../infer_cross_function.rs | 27 + .../lifetime_inference.rs | 7 + .../ui/lazy-type-alias-impl-trait/nested.rs | 23 + .../opaque_vs_opaque.rs | 10 + .../unsized_sized_opaque.rs | 16 + .../lifetime-elision-return-type-trait.rs | 2 +- .../lifetime-elision-return-type-trait.stderr | 6 +- .../ui/lint/inline-trait-and-foreign-items.rs | 2 +- .../inline-trait-and-foreign-items.stderr | 4 +- src/test/ui/lint/lint-ctypes-73249-2.rs | 2 +- src/test/ui/lint/lint-ctypes-73249-2.stderr | 2 +- src/test/ui/lint/lint-ctypes-73249-3.rs | 2 +- src/test/ui/lint/lint-ctypes-73249-3.stderr | 2 +- src/test/ui/lint/lint-ctypes-73249-5.rs | 2 +- src/test/ui/lint/lint-ctypes-73249-5.stderr | 2 +- src/test/ui/lint/lint-ctypes-73251-1.rs | 2 +- src/test/ui/lint/lint-ctypes-73251-1.stderr | 2 +- src/test/ui/lint/lint-ctypes-73251-2.rs | 2 +- src/test/ui/lint/lint-ctypes-73251-2.stderr | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.rs | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.stderr | 2 +- .../feature-gate-never_type_fallback.rs | 7 +- .../feature-gate-never_type_fallback.stderr | 12 +- src/test/ui/never_type/impl_trait_fallback.rs | 10 + .../ui/never_type/impl_trait_fallback2.rs | 21 + .../ui/never_type/impl_trait_fallback2.stderr | 9 + .../ui/never_type/impl_trait_fallback3.rs | 15 + .../ui/never_type/impl_trait_fallback3.stderr | 10 + .../ui/never_type/impl_trait_fallback4.rs | 24 + .../ui/never_type/impl_trait_fallback4.stderr | 9 + src/test/ui/nll/issue-52113.rs | 4 +- src/test/ui/nll/issue-52113.stderr | 6 +- src/test/ui/nll/issue-73159-rpit-static.rs | 2 +- .../ui/nll/issue-73159-rpit-static.stderr | 5 +- src/test/ui/nll/relate_tys/opaque-hrtb.rs | 16 + src/test/ui/nll/relate_tys/opaque-hrtb.stderr | 11 + .../ui/nll/ty-outlives/impl-trait-captures.rs | 2 +- .../ty-outlives/impl-trait-captures.stderr | 8 +- .../ui/nll/ty-outlives/impl-trait-outlives.rs | 4 +- .../ty-outlives/impl-trait-outlives.stderr | 12 +- src/test/ui/parser/fn-header-semantic-fail.rs | 7 +- .../ui/parser/fn-header-semantic-fail.stderr | 154 ++++-- src/test/ui/polymorphization/generators.rs | 2 - .../ui/polymorphization/generators.stderr | 20 +- ...ue-70736-async-fn-no-body-def-collector.rs | 1 - ...0736-async-fn-no-body-def-collector.stderr | 23 +- src/test/ui/save-analysis/issue-68621.rs | 2 +- src/test/ui/save-analysis/issue-68621.stderr | 4 +- ...types_pin_lifetime_impl_trait-async.stderr | 4 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- ...mpl-trait-return-trailing-semicolon.stderr | 11 +- src/test/ui/suggestions/issue-81098.stderr | 20 +- .../trait-object-nested-in-impl-trait.stderr | 52 +- .../match-prev-arm-needing-semi.rs | 9 +- .../match-prev-arm-needing-semi.stderr | 27 +- .../ui/suggestions/opaque-type-error.stderr | 7 +- src/test/ui/traits/alias/issue-83613.rs | 2 +- src/test/ui/traits/alias/issue-83613.stderr | 4 +- .../traits/pointee-tail-is-generic-errors.rs | 2 +- .../pointee-tail-is-generic-errors.stderr | 6 +- .../type-alias-impl-trait/argument-types.rs | 4 +- .../argument-types.stderr | 17 - .../auto-trait-leakage2.stderr | 6 +- .../auto-trait-leakage3.rs | 1 + .../auto-trait-leakage3.stderr | 27 +- .../type-alias-impl-trait/bound_reduction2.rs | 3 +- .../bound_reduction2.stderr | 14 +- .../bounds-are-checked.rs | 2 +- .../bounds-are-checked.stderr | 21 +- .../declared_but_never_defined.rs | 2 +- .../declared_but_never_defined.stderr | 4 +- .../declared_but_not_defined_in_scope.rs | 2 +- .../declared_but_not_defined_in_scope.stderr | 10 +- .../different_defining_uses_never_type.rs | 4 +- .../different_defining_uses_never_type.stderr | 26 - src/test/ui/type-alias-impl-trait/fallback.rs | 4 +- .../ui/type-alias-impl-trait/field-types.rs | 4 +- .../type-alias-impl-trait/field-types.stderr | 21 - .../generic_duplicate_lifetime_param.rs | 4 +- .../generic_duplicate_lifetime_param.stderr | 14 +- .../generic_duplicate_param_use.rs | 12 +- .../generic_duplicate_param_use.stderr | 38 +- .../generic_duplicate_param_use2.rs | 5 - .../generic_duplicate_param_use2.stderr | 14 +- .../generic_duplicate_param_use3.rs | 5 - .../generic_duplicate_param_use3.stderr | 18 +- .../generic_duplicate_param_use4.rs | 5 - .../generic_duplicate_param_use4.stderr | 14 +- .../generic_nondefining_use.rs | 12 +- .../generic_nondefining_use.stderr | 38 +- .../type-alias-impl-trait/generic_not_used.rs | 2 +- .../generic_not_used.stderr | 10 +- ..._type_does_not_live_long_enough.nll.stderr | 36 +- .../generic_type_does_not_live_long_enough.rs | 5 +- ...eric_type_does_not_live_long_enough.stderr | 29 +- .../type-alias-impl-trait/inference-cycle.rs | 4 +- .../inference-cycle.stderr | 36 +- .../ui/type-alias-impl-trait/issue-53598.rs | 2 +- .../type-alias-impl-trait/issue-53598.stderr | 10 +- .../issue-57611-trait-alias.nll.stderr | 34 +- .../issue-57611-trait-alias.rs | 2 +- .../issue-57611-trait-alias.stderr | 6 +- .../ui/type-alias-impl-trait/issue-57700.rs | 2 +- .../type-alias-impl-trait/issue-57700.stderr | 10 +- .../ui/type-alias-impl-trait/issue-58951-2.rs | 18 + .../ui/type-alias-impl-trait/issue-60371.rs | 1 - .../type-alias-impl-trait/issue-60371.stderr | 13 +- .../ui/type-alias-impl-trait/issue-60564.rs | 3 +- .../type-alias-impl-trait/issue-60564.stderr | 14 +- .../ui/type-alias-impl-trait/issue-63279.rs | 5 +- .../type-alias-impl-trait/issue-63279.stderr | 33 +- .../ui/type-alias-impl-trait/issue-63355.rs | 5 +- .../type-alias-impl-trait/issue-63355.stderr | 19 - .../issue-68368-non-defining-use-2.rs | 2 +- .../issue-68368-non-defining-use-2.stderr | 12 +- .../issue-68368-non-defining-use.rs | 2 +- .../issue-68368-non-defining-use.stderr | 12 +- .../type-alias-impl-trait/issue-74280.stderr | 6 + .../type-alias-impl-trait/issue-77179.stderr | 2 +- .../ui/type-alias-impl-trait/issue-93411.rs | 19 + .../multiple-def-uses-in-one-fn-infer.rs | 13 + .../multiple-def-uses-in-one-fn-infer.stderr | 14 + .../multiple-def-uses-in-one-fn-lifetimes.rs | 9 + ...ltiple-def-uses-in-one-fn-lifetimes.stderr | 14 + .../multiple-def-uses-in-one-fn-pass.rs | 9 + .../multiple-def-uses-in-one-fn.rs | 2 +- .../multiple-def-uses-in-one-fn.stderr | 6 +- .../multiple-def-uses-in-one-fn3.stderr | 7 +- .../nested-tait-inference.rs | 4 +- .../nested-tait-inference.stderr | 12 + .../nested-tait-inference2.rs | 3 +- .../nested-tait-inference2.stderr | 16 +- .../nested-tait-inference3.rs | 17 + .../nested-tait-inference3.stderr | 10 + src/test/ui/type-alias-impl-trait/nested.rs | 17 + .../ui/type-alias-impl-trait/nested.stderr | 12 + .../nested_type_alias_impl_trait.rs | 4 +- .../nested_type_alias_impl_trait.stderr | 19 + .../never_reveal_concrete_type.rs | 7 +- .../never_reveal_concrete_type.stderr | 24 - .../no_inferrable_concrete_type.rs | 4 +- .../no_inferrable_concrete_type.stderr | 4 +- ...o_revealing_outside_defining_module.stderr | 12 +- .../not_a_defining_use.rs | 5 - .../not_a_defining_use.stderr | 18 +- .../self-referential-2.rs | 10 + .../self-referential-2.stderr | 11 + .../self-referential-3.rs | 14 + .../self-referential-4.rs | 25 + .../self-referential-4.stderr | 27 + .../type-alias-impl-trait/self-referential.rs | 25 + .../self-referential.stderr | 27 + .../static-const-types.rs | 8 +- .../static-const-types.stderr | 33 -- .../structural-match-no-leak.rs | 4 +- .../structural-match-no-leak.stderr | 2 +- .../type-alias-impl-trait/structural-match.rs | 4 +- .../structural-match.stderr | 2 +- .../type-alias-impl-trait-const.rs | 4 +- .../type-alias-impl-trait-const.stderr | 21 - .../type-alias-impl-trait-with-cycle-error.rs | 2 +- ...e-alias-impl-trait-with-cycle-error.stderr | 4 +- ...type-alias-impl-trait-with-cycle-error2.rs | 2 +- ...-alias-impl-trait-with-cycle-error2.stderr | 4 +- .../type-alias-impl-trait.rs | 2 +- .../type-alias-impl-trait2.rs | 84 ++++ .../ui/type-alias-impl-trait/type_of_a_let.rs | 11 +- .../type_of_a_let.stderr | 76 +-- .../clippy_utils/src/qualify_min_const_fn.rs | 1 + 372 files changed, 3642 insertions(+), 2498 deletions(-) create mode 100644 compiler/rustc_infer/src/infer/opaque_types/table.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr create mode 100644 src/test/ui/impl-trait/fallback.rs create mode 100644 src/test/ui/impl-trait/hidden-type-is-opaque-2.rs create mode 100644 src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr create mode 100644 src/test/ui/impl-trait/hidden-type-is-opaque.rs create mode 100644 src/test/ui/impl-trait/issue-55872-3.rs create mode 100644 src/test/ui/impl-trait/issue-55872-3.stderr delete mode 100644 src/test/ui/impl-trait/issues/issue-86201.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.rs create mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-88236.rs create mode 100644 src/test/ui/impl-trait/lifetimes2.rs create mode 100644 src/test/ui/impl-trait/question_mark.rs delete mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other.rs create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other.stderr create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other2.rs create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other2.stderr create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other3.rs create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other3.stderr delete mode 100644 src/test/ui/impl-trait/where-allowed-2.stderr create mode 100644 src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/nested.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback2.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback2.stderr create mode 100644 src/test/ui/never_type/impl_trait_fallback3.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback3.stderr create mode 100644 src/test/ui/never_type/impl_trait_fallback4.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback4.stderr create mode 100644 src/test/ui/nll/relate_tys/opaque-hrtb.rs create mode 100644 src/test/ui/nll/relate_tys/opaque-hrtb.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/argument-types.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/field-types.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-58951-2.rs delete mode 100644 src/test/ui/type-alias-impl-trait/issue-63355.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-93411.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr create mode 100644 src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr create mode 100644 src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs create mode 100644 src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr create mode 100644 src/test/ui/type-alias-impl-trait/nested.rs create mode 100644 src/test/ui/type-alias-impl-trait/nested.stderr create mode 100644 src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-2.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-2.stderr create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-3.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-4.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-4.stderr create mode 100644 src/test/ui/type-alias-impl-trait/self-referential.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/static-const-types.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr create mode 100644 src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 7507ea76ed07d..8601fbe27f3fa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -2,9 +2,13 @@ use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::region_constraints::Constraint; +use rustc_infer::infer::region_constraints::RegionConstraintData; +use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _}; use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::RegionVid; +use rustc_middle::ty::UniverseIndex; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op; @@ -76,6 +80,15 @@ crate trait ToUniverseInfo<'tcx> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>; } +impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { + fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType { + base_universe: Some(base_universe), + ..self + }))) + } +} + impl<'tcx> ToUniverseInfo<'tcx> for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>> { @@ -116,6 +129,12 @@ impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::Custo } } +impl<'tcx> ToUniverseInfo<'tcx> for ! { + fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + self + } +} + #[allow(unused_lifetimes)] trait TypeOpInfo<'tcx> { /// Returns an error to be reported if rerunning the type op fails to @@ -130,7 +149,7 @@ trait TypeOpInfo<'tcx> { fn nice_error( &self, - tcx: TyCtxt<'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -175,7 +194,7 @@ trait TypeOpInfo<'tcx> { debug!(?placeholder_region); let span = cause.span; - let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region); + let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region); if let Some(nice_error) = nice_error { mbcx.buffer_error(nice_error); @@ -208,16 +227,16 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn nice_error( &self, - tcx: TyCtxt<'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical( + mbcx.infcx.tcx.infer_ctxt().enter_with_canonical( cause.span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); + let mut fulfill_cx = >::new(infcx.tcx); type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause); try_extract_error_from_fulfill_cx( fulfill_cx, @@ -255,16 +274,16 @@ where fn nice_error( &self, - tcx: TyCtxt<'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical( + mbcx.infcx.tcx.infer_ctxt().enter_with_canonical( cause.span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); + let mut fulfill_cx = >::new(infcx.tcx); let mut selcx = SelectionContext::new(infcx); @@ -316,16 +335,16 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn nice_error( &self, - tcx: TyCtxt<'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical( + mbcx.infcx.tcx.infer_ctxt().enter_with_canonical( cause.span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); + let mut fulfill_cx = >::new(infcx.tcx); type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)) .ok()?; try_extract_error_from_fulfill_cx( @@ -339,6 +358,43 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { } } +impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { + fn fallback_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, + // and is only the fallback when the nice error fails. Consider improving this some more. + tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!") + } + + fn base_universe(&self) -> ty::UniverseIndex { + self.base_universe.unwrap() + } + + fn nice_error( + &self, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, + _cause: ObligationCause<'tcx>, + placeholder_region: ty::Region<'tcx>, + error_region: Option>, + ) -> Option> { + try_extract_error_from_region_constraints( + mbcx.infcx, + placeholder_region, + error_region, + self.region_constraints.as_ref().unwrap(), + // We're using the original `InferCtxt` that we + // started MIR borrowchecking with, so the region + // constraints have already been taken. Use the data from + // our `mbcx` instead. + |vid| mbcx.regioncx.var_infos[vid].origin, + |vid| mbcx.regioncx.var_infos[vid].universe, + ) + } +} + #[instrument(skip(fulfill_cx, infcx), level = "debug")] fn try_extract_error_from_fulfill_cx<'tcx>( mut fulfill_cx: Box + 'tcx>, @@ -346,15 +402,30 @@ fn try_extract_error_from_fulfill_cx<'tcx>( placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - let tcx = infcx.tcx; - // We generally shouldn't have errors here because the query was // already run, but there's no point using `delay_span_bug` // when we're going to emit an error here anyway. let _errors = fulfill_cx.select_all_or_error(infcx); + let region_constraints = infcx.with_region_constraints(|r| r.clone()); + try_extract_error_from_region_constraints( + infcx, + placeholder_region, + error_region, + ®ion_constraints, + |vid| infcx.region_var_origin(vid), + |vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))), + ) +} - let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| { - debug!("{:#?}", region_constraints); +fn try_extract_error_from_region_constraints<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + placeholder_region: ty::Region<'tcx>, + error_region: Option>, + region_constraints: &RegionConstraintData<'tcx>, + mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin, + mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex, +) -> Option> { + let (sub_region, cause) = region_constraints.constraints.iter().find_map(|(constraint, cause)| { match *constraint { Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => { @@ -362,12 +433,11 @@ fn try_extract_error_from_fulfill_cx<'tcx>( } // FIXME: Should this check the universe of the var? Constraint::VarSubReg(vid, sup) if sup == placeholder_region => { - Some((tcx.mk_region(ty::ReVar(vid)), cause.clone())) + Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone())) } _ => None, } - }) - })?; + })?; debug!(?sub_region, "cause = {:#?}", cause); let nice_error = match (error_region, *sub_region) { @@ -375,7 +445,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( infcx, RegionResolutionError::SubSupConflict( vid, - infcx.region_var_origin(vid), + region_var_origin(vid), cause.clone(), error_region, cause.clone(), @@ -392,8 +462,8 @@ fn try_extract_error_from_fulfill_cx<'tcx>( infcx, RegionResolutionError::UpperBoundUniverseConflict( vid, - infcx.region_var_origin(vid), - infcx.universe_of_region(sub_region), + region_var_origin(vid), + universe_of_region(vid), cause.clone(), placeholder_region, ), diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 6f78c8160932a..58b246ec873ca 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -7,6 +7,7 @@ #![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] +#![feature(never_type)] #![feature(stmt_expr_attributes)] #![feature(trusted_step)] #![feature(try_blocks)] @@ -125,8 +126,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 @@ -141,7 +143,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>, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 20f54d0477760..1f81f7dda1334 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -45,6 +45,7 @@ mod reverse_sccs; pub mod values; pub struct RegionInferenceContext<'tcx> { + pub var_infos: VarInfos, /// Contains the definition for every region variable. Region /// variables are identified by their index (`RegionVid`). The /// definition contains information about where the region came @@ -267,7 +268,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> Self { // Create a RegionDefinition for each inference variable. let definitions: IndexVec<_, _> = var_infos - .into_iter() + .iter() .map(|info| RegionDefinition::new(info.universe, info.origin)) .collect(); @@ -292,6 +293,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r))); let mut result = Self { + var_infos, definitions, liveness_constraints, constraints, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 60c48d8a7648e..a23788028023a 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -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, OpaqueTypeDecl<'tcx>>, + opaque_ty_decls: VecMap, (Ty<'tcx>, Span, OpaqueTyOrigin)>, span: Span, ) -> VecMap, 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.kind() { + // 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 @@ impl<'tcx> RegionInferenceContext<'tcx> { 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 @@ impl<'tcx> RegionInferenceContext<'tcx> { 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() { diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 0fa72ed8241bc..3856b7f4a4b82 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -33,12 +33,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) -> Fallible where Op: type_op::TypeOp<'tcx, Output = R>, - Canonical<'tcx, Op>: ToUniverseInfo<'tcx>, + Op::ErrorInfo: ToUniverseInfo<'tcx>, { let old_universe = self.infcx.universe(); - let TypeOpOutput { output, constraints, canonicalized_query } = - op.fully_perform(self.infcx)?; + let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?; if let Some(data) = &constraints { self.push_region_constraints(locations, category, data); @@ -47,8 +46,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let universe = self.infcx.universe(); if old_universe != universe { - let universe_info = match canonicalized_query { - Some(canonicalized_query) => canonicalized_query.to_universe_info(old_universe), + let universe_info = match error_info { + Some(error_info) => error_info.to_universe_info(old_universe), None => UniverseInfo::other(), }; for u in old_universe..universe { diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 2e7798beb6484..0b9d0a0e9220b 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -267,7 +267,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { TypeOpOutput { output: self.infcx.tcx.ty_error(), constraints: None, - canonicalized_query: None, + error_info: None, } }); // Note: we need this in examples like diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index bc740de515065..83c8ecba1f17a 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -147,9 +147,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // 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 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 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, ) { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a7cf25d43d230..2d4bb272df55a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -5,6 +5,7 @@ use std::{fmt, iter, mem}; 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,8 +16,8 @@ use rustc_hir::def_id::LocalDefId; 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::region_constraints::RegionConstraintData; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ InferCtxt, InferOk, LateBoundRegionConversionTime, NllRegionVariableOrigin, @@ -39,9 +40,11 @@ use rustc_target::abi::VariantIdx; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::query::type_op; +use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; +use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use rustc_trait_selection::traits::query::Fallible; -use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}; +use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation}; use rustc_const_eval::transform::{ check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression, @@ -75,7 +78,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)*), ), @@ -199,59 +202,44 @@ pub(crate) fn type_check<'mir, 'tcx>( ); 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() }, @@ -283,7 +271,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 }; @@ -340,7 +328,6 @@ enum FieldAccessError { /// is a problem. struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, - body: &'b Body<'tcx>, promoted: &'b IndexVec>, last_span: Span, errors_reported: bool, @@ -476,7 +463,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { 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); } @@ -535,10 +522,13 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn new( cx: &'a mut TypeChecker<'b, 'tcx>, - body: &'b Body<'tcx>, promoted: &'b IndexVec>, ) -> 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> { @@ -563,7 +553,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ) -> 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() { @@ -608,7 +598,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // 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. @@ -644,7 +634,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { 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); @@ -706,7 +696,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { })) } 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 { @@ -915,7 +905,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, crate universal_region_relations: Frozen>, - crate opaque_type_values: VecMap, OpaqueTypeDecl<'tcx>>, + crate opaque_type_values: VecMap, (Ty<'tcx>, Span, OpaqueTyOrigin)>, } /// A collection of region constraints that must be satisfied for the @@ -1065,17 +1055,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 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)); @@ -1216,131 +1208,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 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 = impl Debug; - /// - /// fn foo(t: T) -> Box> { - /// Box::new((t, 22_u32)) - /// } - /// ``` - /// - /// Here, the function signature would be something like - /// `fn(T) -> Box`. 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>` where `Foo` 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>` (where `Foo` is an opaque type) - // to `Box`, returning an `opaque_type_map` mapping `{Foo -> ?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 } @@ -2772,19 +2639,31 @@ impl NormalizeLocation for Location { } } -#[derive(Debug, Default)] -struct ObligationAccumulator<'tcx> { - obligations: PredicateObligations<'tcx>, +/// Runs `infcx.instantiate_opaque_types`. Unlike other `TypeOp`s, +/// this is not canonicalized - it directly affects the main `InferCtxt` +/// that we use during MIR borrowchecking. +#[derive(Debug)] +pub(super) struct InstantiateOpaqueType<'tcx> { + pub base_universe: Option, + pub region_constraints: Option>, + pub obligation: PredicateObligation<'tcx>, } -impl<'tcx> ObligationAccumulator<'tcx> { - fn add(&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 +impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { + type Output = (); + /// We use this type itself to store the information used + /// when reporting errors. Since this is not a query, we don't + /// re-run anything during error reporting - we just use the information + /// we saved to help extract an error from the already-existing region + /// constraints in our `InferCtxt` + type ErrorInfo = InstantiateOpaqueType<'tcx>; + + fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible> { + let (mut output, region_constraints) = scrape_region_constraints(infcx, || { + Ok(InferOk { value: (), obligations: vec![self.obligation.clone()] }) + })?; + self.region_constraints = Some(region_constraints); + output.error_info = Some(self); + Ok(output) } } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 590a7a9164155..a032095bf981e 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,13 +1,15 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::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::{InstantiateOpaqueType, 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 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { } 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 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> // 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: Const<'tcx>, _b: Const<'tcx>) {} fn normalization() -> NormalizationStrategy { @@ -126,4 +135,30 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> 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, + InstantiateOpaqueType { + obligation: self.type_checker.infcx.opaque_ty_obligation( + a, + b, + a_is_expected, + param_env, + cause, + ), + // These fields are filled in during exectuion of the operation + base_universe: None, + region_constraints: None, + }, + ) + .unwrap(); + } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 478dbe31fba7e..e9c64049817f5 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -725,6 +725,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { 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( &self, origin: NllRegionVariableOrigin, @@ -735,22 +736,15 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { 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 @@ -765,6 +759,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// 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, @@ -776,6 +771,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { 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()); } }); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 223b3ad0cf9ce..8790baa010c12 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::*; 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::error_reporting::InferCtxtExt; @@ -47,7 +47,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { 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; } @@ -101,7 +104,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { 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 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { // 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) diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index deeca78b75d99..e68e1a055d916 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -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 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 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); diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index cc7ec9432faed..2f4b3844430e3 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -30,6 +30,11 @@ where } } + /// Removes the entry from the map and returns the removed value + pub fn remove(&mut self, k: &K) -> Option { + 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(&self, k: &Q) -> Option<&V> where @@ -39,6 +44,15 @@ where 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(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow, + 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 @@ where // 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) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index ff8082840e1e0..71ee4f1e76d6d 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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 } } /// Forks the inference context, creating a new inference context with the same inference @@ -59,6 +65,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Self { tcx: self.tcx.clone(), defining_use_anchor: self.defining_use_anchor.clone(), + reveal_defining_opaque_types: self.reveal_defining_opaque_types.clone(), in_progress_typeck_results: self.in_progress_typeck_results.clone(), inner: self.inner.clone(), skip_leak_check: self.skip_leak_check.clone(), @@ -86,6 +93,10 @@ pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { } 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, @@ -216,7 +227,7 @@ impl<'a, 'tcx> Trace<'a, '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) @@ -233,7 +244,7 @@ impl<'a, 'tcx> Trace<'a, '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) @@ -248,7 +259,7 @@ impl<'a, 'tcx> Trace<'a, '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 .lub(a_is_expected) .relate(a, b) @@ -263,7 +274,7 @@ impl<'a, 'tcx> Trace<'a, '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 .glb(a_is_expected) .relate(a, b) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 48d5c21f9eb88..20f65962db4f7 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -26,6 +26,7 @@ use rustc_middle::ty::fold::TypeFoldable; 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 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { var_values: inference_vars, region_constraints: QueryRegionConstraints::default(), certainty: Certainty::Proven, // Ambiguities are OK! + opaque_types: vec![], value: answer, }) } @@ -133,14 +135,27 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { 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 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { 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. @@ -343,20 +357,25 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { 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 @@ -371,9 +390,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { fn query_response_substitution_guess( &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>, { @@ -473,7 +493,16 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { .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 @@ -629,6 +658,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 } @@ -684,4 +717,14 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { 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(), + )); + } } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index e1b5d04ccfb8f..41995ca509ef6 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -51,6 +51,12 @@ pub struct CombineFields<'infcx, 'tcx> { pub cause: Option, 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 @@ impl<'infcx, 'tcx> CombineFields<'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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // 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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // 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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { /// 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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { 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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { 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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { 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 }) } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 5ac9ad6850c40..c1c075e9a4cad 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -66,18 +66,19 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, '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 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, '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)?; } diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index e98f33ea86eef..0d38b94965afe 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -6,7 +6,7 @@ use super::InferCtxt; 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}; @@ -113,12 +113,20 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, &self.fields.trace.cause } + fn add_obligations(&mut self, obligations: Vec>) { + 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> { diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index 32affd6a14e1c..f4c749492d3bc 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -20,7 +20,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}; @@ -35,6 +35,10 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { fn cause(&self) -> &ObligationCause<'tcx>; + fn add_obligations(&mut self, obligations: Vec>); + + 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. // @@ -45,6 +49,7 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { } /// Relates two types using a given lattice. +#[instrument(skip(this), level = "debug")] pub fn super_lattice_tys<'a, 'tcx: 'a, L>( this: &mut L, a: Ty<'tcx>, @@ -53,15 +58,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 @@ -98,6 +105,22 @@ where 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), } } diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index bc85a4ac609a7..498c1e907c4e1 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -6,7 +6,7 @@ use super::InferCtxt; 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}; @@ -119,10 +119,18 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, &self.fields.trace.cause } + fn add_obligations(&mut self, obligations: Vec>) { + 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 + } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 83ba9c96978d0..63ffb5bde3846 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -5,7 +5,7 @@ pub use self::RegionVariableOrigin::*; 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}; @@ -191,18 +191,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>>, + /// Caches for opaque type inference. + pub opaque_type_storage: OpaqueTypeStorage<'tcx>, } impl<'tcx> InferCtxtInner<'tcx> { @@ -216,8 +206,7 @@ impl<'tcx> 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(), } } @@ -236,6 +225,11 @@ impl<'tcx> InferCtxtInner<'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, @@ -296,6 +290,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, + /// 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, @@ -571,6 +569,7 @@ pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option>>, defining_use_anchor: Option, + reveal_defining_opaque_types: bool, } pub trait TyCtxtInferExt<'tcx> { @@ -579,7 +578,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, + } } } @@ -603,6 +607,13 @@ impl<'tcx> InferCtxtBuilder<'tcx> { 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 @@ -627,11 +638,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn enter(&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), @@ -766,6 +783,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, + define_opaque_types: bool, ) -> CombineFields<'a, 'tcx> { CombineFields { infcx: self, @@ -773,6 +791,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: None, param_env, obligations: PredicateObligations::new(), + define_opaque_types, } } @@ -1088,12 +1107,20 @@ impl<'a, 'tcx> InferCtxt<'a, '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) } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 69db6509b798d..2c7f3adafdc96 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -24,11 +24,13 @@ 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 @@ where 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 @@ -88,6 +91,7 @@ pub trait TypeRelatingDelegate<'tcx> { ); fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); /// Creates a new universe index. Used when instantiating placeholders. fn create_next_universe(&mut self) -> ty::UniverseIndex; @@ -277,7 +281,6 @@ where 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 +289,8 @@ where 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 +536,8 @@ where #[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 +566,35 @@ where (&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 => { diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e7dca94806cb7..46420fbe0c305 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -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}; @@ -14,14 +15,28 @@ use std::ops::ControlFlow; pub type OpaqueTypeMap<'tcx> = VecMap, 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 - /// - /// this method would create two type variables, `?0` and `?1`. It would - /// return the type `?0` but also the obligations: - /// - /// ?0: Iterator - /// ?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>( + 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 { 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 @@ impl<'a, 'tcx> InferCtxt<'a, '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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { op: |r| { self.member_constraint( opaque_type_key.def_id, - opaque_defn.definition_span, + span, concrete_ty, r, &choice_regions, @@ -328,15 +393,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }); } - fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - 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 { + 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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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 @@ where } } -struct Instantiator<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - value_span: Span, - obligations: Vec>, +pub enum UseKind { + DefiningUse, + OpaqueUse, } -impl<'a, 'tcx> Instantiator<'a, 'tcx> { - fn instantiate_opaque_types_in_map>(&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 index 0000000000000..202afea559c61 --- /dev/null +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -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, Clone)] +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>) { + 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> { + 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 + } +} diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 03d6c45a65345..b60ffc1878be4 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -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)) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5d8cc94e05c29..45aa2bcba86f2 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -153,6 +153,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// 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>, @@ -164,8 +165,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { "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 { diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 9ec1b3390d0ad..85bae8b823b06 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -2,6 +2,7 @@ use super::combine::{CombineFields, RelationDir}; 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 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, '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 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, '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 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, '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) diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index ecd886b547834..49bef4face3ef 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -4,13 +4,15 @@ use rustc_data_structures::snapshot_vec as sv; 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 ()>, @@ -19,6 +21,7 @@ pub struct Snapshot<'tcx> { /// Records the "undo" data for a single operation that affects some form of inference variable. #[derive(Clone)] pub(crate) enum UndoLog<'tcx> { + OpaqueTypes(OpaqueTypeKey<'tcx>, Option>), TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), @@ -65,6 +68,7 @@ impl_from! { impl<'tcx> Rollback> 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), diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 674c75fdee561..6600d5e4d0279 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -167,6 +167,9 @@ impl<'tcx> Elaborator<'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. diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 50a3df21a3bc9..cec32823ee2e3 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1675,6 +1675,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Coerce(..) | ConstEvaluatable(..) | ConstEquate(..) | + OpaqueType(..) | TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 419ed429246ac..f3ea83a32b586 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -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, } diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index 738c48dbb5c59..3243ef28ff005 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -53,17 +53,17 @@ impl<'tcx> TypeRelation<'tcx> for Match<'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); } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f51e6c2bc1f4d..ac9f04ee05575 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -33,6 +33,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; 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::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -485,9 +486,13 @@ pub struct TypeckResults<'tcx> { /// this field will be set to `Some(ErrorGuaranteed)`. pub tainted_by_errors: Option, - /// All the opaque types that are restricted to concrete types - /// by this function. - pub concrete_opaque_types: FxHashSet, + /// 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>>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 7a3d615862cba..06ac21e5d5794 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -265,6 +265,10 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } + ty::PredicateKind::OpaqueType(opaque, ty) => { + self.add_ty(opaque); + self.add_ty(ty); + } } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 780d380da365e..388109e6512dd 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1243,15 +1243,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; #[inline] - #[instrument(level = "trace")] - fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow { - 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 { + let flags = t.flags(); + trace!(t.flags=?t.flags()); + if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { ControlFlow::CONTINUE diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 31db66dc242f1..4208ef1a7f49f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -632,6 +632,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 @@ -999,6 +1004,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1017,6 +1023,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1057,7 +1064,18 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -#[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>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5cfd9a5edfb19..d5f5a1572b89e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -647,20 +647,23 @@ pub trait PrettyPrinter<'tcx>: 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) => { @@ -2651,6 +2654,9 @@ define_print_and_forward_display! { 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) ,"`") + } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 5c7910db362d2..576f4121c42e3 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -198,6 +198,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } + ty::PredicateKind::OpaqueType(a, b) => { + write!(f, "OpaqueType({:?}, {:?})", a.kind(), b.kind()) + } } } } @@ -471,6 +474,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { 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)?)) + } } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index dc16460ca436e..335ddeb66db05 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1925,6 +1925,13 @@ impl<'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) => { diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index f98025f7953f9..679043bdc30f9 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -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_span::Span; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -190,7 +190,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // 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); diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 9778f77384cf9..7fd20b45e77cd 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -181,7 +181,6 @@ impl EncoderState { } } - #[instrument(level = "debug", skip(self, record_graph))] fn encode_node( &mut self, node: &NodeInfo, @@ -208,7 +207,6 @@ impl EncoderState { 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); diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index c93ff0aa6e277..c5531222fef0d 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -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 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // 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 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { 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>>, 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>>, hidden_ty: Ty<'tcx>, @@ -108,7 +106,6 @@ impl<'tcx> ReverseMapper<'tcx> { ) -> Self { Self { tcx, - tainted_by_errors, opaque_type_def_id, map, map_missing_regions_to_empty: false, @@ -167,9 +164,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'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 @@ crate fn required_region_bounds<'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 diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index ee9983ee8b8d8..ee8b3a6245316 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -865,6 +865,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} }; } diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index a607fb6c1b87c..22182faa0c62c 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -92,6 +92,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(&*tcx.arena.alloc(impl_source)) }) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 468c7a3c55b36..218abdd573df2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -797,6 +797,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, "TypeWellFormedFromEnv predicate should only exist in the environment" ), + + ty::PredicateKind::OpaqueType(..) => { + todo!("{:#?}", obligation); + } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d65b390af3460..39da99ac25293 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1294,6 +1294,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { 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, @@ -1673,6 +1674,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )); 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 diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 1b8628344671d..d55d06ebbf409 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -413,6 +413,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } + ty::PredicateKind::OpaqueType(..) => { + todo!("{:#?}", obligation); + } }, Some(pred) => match pred { ty::PredicateKind::Trait(data) => { @@ -662,6 +665,20 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { 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, + )), + } + } }, } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 6cceec8621304..eab207600ab58 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -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, } } @@ -344,6 +345,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, } }) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 0a85676f4315e..605c9ace5ed06 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -3,7 +3,8 @@ use crate::infer::{InferCtxt, InferOk}; 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::infer::region_constraints::RegionConstraintData; use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; @@ -31,6 +32,9 @@ where G: Fn() -> String, { type Output = R; + /// We can't do any custom error reporting for `CustomTypeOp`, so + /// we can use `!` to enforce that the implementation never provides it. + type ErrorInfo = !; /// Processes the operation and all resulting obligations, /// returning the final result along with any region constraints @@ -40,7 +44,7 @@ where info!("fully_perform({:?})", self); } - scrape_region_constraints(infcx, || (self.closure)(infcx)) + Ok(scrape_region_constraints(infcx, || (self.closure)(infcx))?.0) } } @@ -55,12 +59,11 @@ where /// Executes `op` and then scrapes out all the "old style" region /// constraints that result, creating query-region-constraints. -fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( +pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( infcx: &InferCtxt<'_, 'tcx>, op: impl FnOnce() -> Fallible>, -) -> Fallible> { +) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> { let mut fulfill_cx = >::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 +78,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() { @@ -99,12 +101,18 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( ); if region_constraints.is_empty() { - Ok(TypeOpOutput { output: value, constraints: None, canonicalized_query: None }) + Ok(( + TypeOpOutput { output: value, constraints: None, error_info: None }, + region_constraint_data, + )) } else { - Ok(TypeOpOutput { - output: value, - constraints: Some(Rc::new(region_constraints)), - canonicalized_query: None, - }) + Ok(( + TypeOpOutput { + output: value, + constraints: Some(Rc::new(region_constraints)), + error_info: None, + }, + region_constraint_data, + )) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index d662f61e2cf4d..1e72dd693396a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -28,6 +28,7 @@ pub use rustc_middle::traits::query::type_op::*; /// cannot be completed). pub trait TypeOp<'tcx>: Sized + fmt::Debug { type Output; + type ErrorInfo; /// Processes the operation and all resulting obligations, /// returning the final result along with any region constraints @@ -41,9 +42,8 @@ pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> { pub output: Op::Output, /// Any region constraints from performing the type op. pub constraints: Option>>, - /// The canonicalized form of the query. - /// This for error reporting to be able to rerun the query. - pub canonicalized_query: Option>, + /// Used for error reporting to be able to rerun the query + pub error_info: Option, } /// "Query type ops" are type ops that are implemented using a @@ -119,10 +119,11 @@ where Q: QueryTypeOp<'tcx>, { type Output = Q::QueryResponse; + type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>; fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible> { let mut region_constraints = QueryRegionConstraints::default(); - let (output, canonicalized_query, mut obligations, _) = + let (output, error_info, mut obligations, _) = Q::fully_perform_into(self, infcx, &mut region_constraints)?; // Typically, instantiating NLL query results does not @@ -160,6 +161,6 @@ where let region_constraints = if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) }; - Ok(TypeOpOutput { output, constraints: region_constraints, canonicalized_query }) + Ok(TypeOpOutput { output, constraints: region_constraints, error_info }) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3e7a2252318be..cf472813e9e32 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -256,6 +256,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; 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`). // // This is somewhat problematic, as the current scheme can't really diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 72d156067a1dd..9b8a49e512b95 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -33,6 +33,7 @@ use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fast_reject::{self, TreatParams}; +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}; @@ -672,6 +673,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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), + } + } } }); @@ -1313,6 +1327,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + #[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>, @@ -1353,6 +1368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// 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>, @@ -1360,10 +1376,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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() { @@ -1414,7 +1427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .collect(); - debug!(?matching_bounds, "match_projection_obligation_against_definition_bounds"); + debug!(?matching_bounds); matching_bounds } @@ -1444,6 +1457,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); 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 @@ -1506,6 +1520,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let is_match = 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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![] } } } } @@ -2220,6 +2246,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, ()> { 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(|_| ()) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index b4ed5b95b1047..2ac68cea5448f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -148,6 +148,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") } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e3c865ce9e632..1d5b5c6c3cd63 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -110,6 +110,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; @@ -202,6 +203,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) } @@ -621,6 +623,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } @@ -750,6 +753,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index 3c2a266dab9bc..4e19479da87fb 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -134,6 +134,7 @@ crate fn evaluate_goal<'tcx>( var_values: CanonicalVarValues { var_values }, region_constraints: QueryRegionConstraints::default(), certainty: Certainty::Proven, + opaque_types: vec![], value: (), }, }; @@ -162,6 +163,7 @@ crate fn evaluate_goal<'tcx>( .make_identity(tcx), region_constraints: QueryRegionConstraints::default(), certainty: Certainty::Ambiguous, + opaque_types: vec![], value: (), }, }; diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 90c698db8fb54..1535a46a01b47 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -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); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index a4aa965ec9533..1d26f6a12a36d 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -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, } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index e26f0033156bc..b015e40b6836f 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -61,6 +61,14 @@ bitflags! { | 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, diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 9529e1528a8b9..79be8bde55ab1 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diagnostic}; 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}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_span::{MultiSpan, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -98,8 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // provide a structured suggestion in that case. pub(crate) fn opt_suggest_box_span( &self, - span: Span, outer_ty: Ty<'tcx>, orig_expected: Expectation<'tcx>, ) -> Option { - 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 { diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index d5187c109e33d..2a5cf03e9d0ba 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -538,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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. diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e57d55fdc2377..1a5f118ea505c 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; @@ -83,8 +83,6 @@ pub(super) fn check_fn<'a, 'tcx>( can_be_generator: Option, return_type_pre_known: bool, ) -> (FnCtxt<'a, 'tcx>, Option>) { - 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); @@ -97,21 +95,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; @@ -253,7 +238,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() { @@ -656,6 +641,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, @@ -670,25 +657,13 @@ 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,), + ); } } @@ -701,7 +676,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 @@ -710,6 +685,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(); }); } diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 59c8febdc30da..83ef76a48cd2c 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, ) -> (Option>, Option) { 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Option>, Option) { 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) = @@ -235,6 +259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// The `cause_span` should be the span that caused us to /// have this expected signature, or `None` if we can't readily /// know that. + #[instrument(level = "debug", skip(self, cause_span))] fn deduce_sig_from_projection( &self, cause_span: Option, @@ -242,15 +267,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { let tcx = self.tcx; - debug!("deduce_sig_from_projection({:?})", projection); - let trait_def_id = projection.trait_def_id(tcx); let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some(); let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span); let is_gen = gen_trait == trait_def_id; if !is_fn && !is_gen { - debug!("deduce_sig_from_projection: not fn or generator"); + debug!("not fn or generator"); return None; } @@ -259,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // associated item and not yield. let return_assoc_item = self.tcx.associated_item_def_ids(gen_trait)[1]; if return_assoc_item != projection.projection_def_id() { - debug!("deduce_sig_from_projection: not return assoc item of generator"); + debug!("not return assoc item of generator"); return None; } } @@ -267,7 +290,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let input_tys = if is_fn { let arg_param_ty = projection.skip_binder().projection_ty.substs.type_at(1); let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); - debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); + debug!(?arg_param_ty); match arg_param_ty.kind() { &ty::Tuple(tys) => tys, @@ -282,7 +305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Since this is a return parameter type it is safe to unwrap. let ret_param_ty = projection.skip_binder().term.ty().unwrap(); let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty); - debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty); + debug!(?ret_param_ty); let sig = projection.rebind(self.tcx.mk_fn_sig( input_tys.iter(), @@ -291,7 +314,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Unsafety::Normal, Abi::Rust, )); - debug!("deduce_sig_from_projection: sig={:?}", sig); + debug!(?sig); Some(ExpectedSig { cause_span, sig }) } @@ -401,9 +424,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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 +618,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => 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 +640,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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`, 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> { - 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 +698,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), }; + let item_bounds = self.tcx.explicit_item_bounds(def_id); + // Search for a pending obligation like // // `::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 { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index c0eda02a99967..2f973a54f88a7 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1272,7 +1272,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// 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) diff --git a/compiler/rustc_typeck/src/check/expectation.rs b/compiler/rustc_typeck/src/check/expectation.rs index e9e810344776b..9e1a70b7dfb92 100644 --- a/compiler/rustc_typeck/src/check/expectation.rs +++ b/compiler/rustc_typeck/src/check/expectation.rs @@ -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 @@ impl<'a, 'tcx> Expectation<'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> { - 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> { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index e5784259ce875..81cebaef3aa92 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -965,8 +965,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; 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); diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index 7214cdf3312a7..8513231782407 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -24,7 +24,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { 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 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // 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 @@ impl<'tcx> FnCtxt<'_, 'tcx> { 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 { - /// None - /// } - /// ``` - /// - /// In the above snippet, the inference variable created by - /// instantiating `Option` 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. diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index e3439a6f1d963..83587951f2532 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -372,23 +372,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (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>( - &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 @@ -749,6 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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)) @@ -775,6 +759,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Vec> { let formal_ret = self.resolve_vars_with_obligations(formal_ret); let Some(ret_ty) = expected_ret.only_has_type(self) else { return Vec::new() }; + + // HACK(oli-obk): This is a backwards compatibility hack. Without it, the inference + // variable will get instantiated with the opaque type. The inference variable often + // has various helpful obligations registered for it that help closures figure out their + // signature. If we infer the inference var to the opaque type, the closure won't be able + // to find those obligations anymore, and it can't necessarily find them from the opaque + // type itself. We could be more powerful with inference if we *combined* the obligations + // so that we got both the obligations from the opaque type and the ones from the inference + // variable. That will accept more code than we do right now, so we need to carefully consider + // the implications. + // Note: this check is pessimistic, as the inference type could be matched with something other + // than the opaque type, but then we need a new `TypeRelation` just for this specific case and + // can't re-use `sup` below. + if formal_ret.has_infer_types() { + for ty in ret_ty.walk() { + if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() { + if let ty::Opaque(def_id, _) = *ty.kind() { + if self.infcx.opaque_type_origin(def_id, DUMMY_SP).is_some() { + return Vec::new(); + } + } + } + } + } + let expect_args = self .fudge_inference_if_ok(|| { // Attempt to apply a subtyping relationship between the formal diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 222c14d0d47b9..6c55f8212940e 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -57,8 +57,6 @@ pub struct FnCtxt<'a, 'tcx> { /// any). pub(super) ret_coercion: Option>>, - pub(super) ret_coercion_impl_trait: Option>, - pub(super) ret_type_span: Option, /// Used exclusively to reduce cost of advanced evaluation used for @@ -130,7 +128,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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), diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index beb6b371b2bb8..b775f24f8efd8 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -95,6 +95,13 @@ impl<'tcx> InheritedBuilder<'tcx> { 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 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { } } + #[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); } diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 704866c2cc2ac..26119e5a06407 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -858,6 +858,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); @@ -1476,6 +1477,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { 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))) => { @@ -1505,6 +1507,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // 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, @@ -1655,6 +1658,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); if self .at(&ObligationCause::dummy(), self.param_env) + .define_opaque_types(false) .sup(return_ty, xform_ret_ty) .is_err() { diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 31cc3fa2ac648..b6111793678aa 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -343,6 +343,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, diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 7106f8f9d7a82..70bc46c5123b6 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -335,11 +335,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Returns a list of `Ty`s for each upvar. fn final_upvar_tys(&self, closure_id: DefId) -> Vec> { - // 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) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index d6eeef3323cad..250576bff048f 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -968,7 +968,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), diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index c1cb9a1a8d139..35f1ddb65aa27 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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(); @@ -497,64 +496,18 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { 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() -> Foo` - // * `fn foo() -> Foo` - // from being defining. - - // Also replace all generic params with the ones from the opaque type - // definition so that - // ```rust - // type Foo = impl Baz + 'static; - // fn foo() -> Foo { .. } - // ``` - // 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); } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index d422f355ad3a4..885713cd2f36a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -8,7 +8,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -359,28 +359,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(_) = - tcx.typeck(owner).tainted_by_errors - { + let table = tcx.typeck(owner); + if let Some(_) = 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); @@ -575,7 +569,21 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } // 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; } @@ -629,7 +637,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { 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); @@ -637,7 +645,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } } 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); @@ -645,7 +653,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } } 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); } @@ -655,12 +663,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { 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 @@ -687,7 +695,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { 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() } } diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 6cef3e9d9409e..737e6002005a7 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -425,6 +425,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs index bbf31de527eb3..7839ce5e4ff48 100644 --- a/compiler/rustc_typeck/src/outlives/explicit.rs +++ b/compiler/rustc_typeck/src/outlives/explicit.rs @@ -59,6 +59,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), } } diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 7105a2457e282..d9467e8fd6bc1 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -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 = diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e3260ce9ae2b..5256fe762484e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -306,6 +306,7 @@ impl<'a> Clean> for ty::Predicate<'a> { | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } } diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 4124eada188e8..31564a0cbd5c6 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -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")] diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs index 4c36289f47b85..67b97c21805e6 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -30,7 +30,7 @@ impl Thing for AssocNoCopy { type Out = Box>; 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 } } diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index a32ab453152a0..f1dcd34066dbc 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -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::Out::{opaque#0}>` error: aborting due to previous error diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs index 5f994f26534bd..30e4c1a3c537b 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs @@ -23,8 +23,8 @@ fn bar() -> impl Bar { } fn baz() -> impl Bar { -//~^ ERROR type mismatch resolving `::Item == i32` bar() + //~^ ERROR type mismatch resolving `::Item == i32` } fn main() { diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 283ecea735d41..9523a54d954df 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -1,14 +1,16 @@ error[E0271]: type mismatch resolving `::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 { - | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type +LL | bar() + | ^^^^^ expected associated type, found `i32` | - = note: expected type `i32` - found associated type `::Item` + = note: expected associated type `::Item` + found type `i32` + = help: consider constraining the associated type `::Item` to `i32` or calling a method that returns `::Item` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html help: consider constraining the associated type `::Item` to `i32` | LL | fn bar() -> impl Bar { diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index 44d60c1d80d88..f21c811512416 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -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> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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 } ) diff --git a/src/test/ui/async-await/issue-64130-4-async-move.rs b/src/test/ui/async-await/issue-64130-4-async-move.rs index 2538f34351e5a..7cb02e5cf383d 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.rs +++ b/src/test/ui/async-await/issue-64130-4-async-move.rs @@ -13,9 +13,9 @@ impl Client { 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; diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index d631e6dc7f7e9..3a84907e0c04b 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -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 diff --git a/src/test/ui/async-await/issue-70818.rs b/src/test/ui/async-await/issue-70818.rs index 0609e4fc08170..631389e10f316 100644 --- a/src/test/ui/async-await/issue-70818.rs +++ b/src/test/ui/async-await/issue-70818.rs @@ -2,8 +2,8 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { -//~^ Error future cannot be sent between threads safely async { (ty, ty1) } + //~^ Error future cannot be sent between threads safely } fn main() {} diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 20109d4d1166a..cb50c70f99847 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -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(ty: T, ty1: U) -> impl Future + 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` diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs index 2965a7e0654a4..494561229511e 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.rs +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -8,8 +8,8 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { } fn foo(tx: std::sync::mpsc::Sender) -> 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; diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index db3099381196b..ad61f21741bb5 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -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) -> 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` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr index 2722c72c20a33..cdb141c0e3ea2 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr @@ -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 | diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 149692a2c6998..2eb3a07059f7b 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -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 | diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs index b3c59734e036f..cfb0ef1b33a2b 100644 --- a/src/test/ui/async-await/no-const-async.rs +++ b/src/test/ui/async-await/no-const-async.rs @@ -3,3 +3,4 @@ pub const async fn x() {} //~^ ERROR functions cannot be both `const` and `async` +//~| ERROR cycle detected diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index 90ec646c8c09c..fd76c282f9629 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -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` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: 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`. diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs index aa7733194587d..edc4cb8ac5df3 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.rs +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.rs @@ -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; } diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index c7c5b51e7334b..046f1dfea3238 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -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 } diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 76073c4c87996..07d6f8986fa60 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -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` - 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` + 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 | let _x = match dummy() { | ------- this expression has type `impl Future` @@ -109,7 +110,7 @@ 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 | match dummy_result() { | -------------- this expression has type `impl Future>` @@ -118,7 +119,7 @@ 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 @@ -130,7 +131,7 @@ LL | match dummy_result().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:69:9 + --> $DIR/suggest-missing-await.rs:68:9 | LL | match dummy_result() { | -------------- this expression has type `impl Future>` @@ -139,7 +140,7 @@ 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 diff --git a/src/test/ui/cast/casts-differing-anon.rs b/src/test/ui/cast/casts-differing-anon.rs index d4a0f9613055e..ccf41adce6bd8 100644 --- a/src/test/ui/cast/casts-differing-anon.rs +++ b/src/test/ui/cast/casts-differing-anon.rs @@ -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 } diff --git a/src/test/ui/cast/casts-differing-anon.stderr b/src/test/ui/cast/casts-differing-anon.stderr index f9abfb5225f91..2d08903c5ef69 100644 --- a/src/test/ui/cast/casts-differing-anon.stderr +++ b/src/test/ui/cast/casts-differing-anon.stderr @@ -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 { + | ---------------------- the found opaque type +... +LL | fn bar() -> Box { + | ---------------------- 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`. diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr index 3d62f059f37cd..b5519fc9cd6a6 100644 --- a/src/test/ui/chalkify/bugs/async.stderr +++ b/src/test/ui/chalkify/bugs/async.stderr @@ -28,12 +28,6 @@ note: required by a bound in `from_generator` LL | T: Generator, | ^^^^^^^^^^ required by this bound in `from_generator` -error[E0280]: the requirement `::Output == u32` is not satisfied - --> $DIR/async.rs:7:25 - | -LL | async fn foo(x: u32) -> u32 { - | ^^^ - -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/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr index bb00465758a45..46379a3815a4d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -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 || { diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr index 63a4df242f85f..9dc486980aaca 100644 --- a/src/test/ui/conservative_impl_trait.stderr +++ b/src/test/ui/conservative_impl_trait.stderr @@ -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 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator +LL | fn will_ice(something: &u32) -> impl Iterator { + | ____________________________________________________________^ +LL | | +LL | | } + | |_^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs index 308c121a94111..b3bd88ad7d5d8 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -4,8 +4,8 @@ trait Trait {} impl Trait for Uwu {} 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 { } @@ -15,13 +15,13 @@ impl Traitor<1, 2> for u64 {} fn uwu() -> impl Traitor { - //~^ error: the trait bound `u32: Traitor` is not satisfied 1_u32 + //~^ error: the trait bound `u32: Traitor` 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() { diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 19813a491c96e..1cfaf83c5a69e 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -1,27 +1,27 @@ 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: as Trait> error[E0277]: the trait bound `u32: Traitor` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:17:26 + --> $DIR/rp_impl_trait_fail.rs:18:5 | -LL | fn uwu() -> impl Traitor { - | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` +LL | 1_u32 + | ^^^^^ the trait `Traitor` is not implemented for `u32` | = help: the following implementations were found: > > 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: > diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs index dab9c687e2498..405d6e2a9f560 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs @@ -3,11 +3,9 @@ #![allow(incomplete_features)] 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; //~ ERROR `main` function not found in crate diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index b9bc0262a56b2..fabb6ffb02f77 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -1,30 +1,11 @@ error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden` - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:13:22 + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:11:22 | LL | use foo::BAR as main; | ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs` | | | non-function item at `crate::main` is found -error[E0308]: mismatched types - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:9: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:5: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-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index ea82837d4bf55..6dfd7f6840f1b 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -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 index da3ddb1c50979..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ /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/generator/issue-88653.rs b/src/test/ui/generator/issue-88653.rs index ce9159b53e0f0..c4905995a860a 100644 --- a/src/test/ui/generator/issue-88653.rs +++ b/src/test/ui/generator/issue-88653.rs @@ -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; } diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr index 5bd8ad129fef9..eaa90a8e60a23 100644 --- a/src/test/ui/generator/issue-88653.stderr +++ b/src/test/ui/generator/issue-88653.stderr @@ -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 diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs index 7774ff48f56b7..d1b16b6e10da0 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.rs +++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs @@ -2,8 +2,8 @@ use std::ops::Generator; -fn foo() -> impl Generator { //~ ERROR type mismatch - || { +fn foo() -> impl Generator { + || { //~ ERROR type mismatch if false { return Ok(6); } diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 3f1f33a3b123f..3e78e5b53ba1f 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -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 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr index 98a5f4254bb1b..fbf1c8f95feca 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr @@ -1,4 +1,4 @@ -error[E0477]: the type `impl Stream` does not fulfill the required lifetime +error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime --> $DIR/issue-86218.rs:23:28 | LL | type InnerStream<'s> = impl Stream + 's; @@ -10,6 +10,14 @@ note: type must outlive the lifetime `'s` as defined here as required by this bi LL | type InnerStream<'s> = impl Stream + 's; | ^^ -error: aborting due to previous error +error: unconstrained opaque type + --> $DIR/issue-86218.rs:23:28 + | +LL | type InnerStream<'s> = impl Stream + 's; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `InnerStream` must be used in combination with a concrete type within the same module + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr index 3e607d4004e85..5cbadfacc1b60 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr @@ -1,21 +1,19 @@ -error[E0271]: type mismatch resolving `::Output == impl Stream` - --> $DIR/issue-89008.rs:39:43 +error[E0271]: type mismatch resolving ` as Stream>::Item == Repr` + --> $DIR/issue-89008.rs:40:9 | -LL | type LineStream<'a, Repr> = impl Stream; - | ------------------------ the expected opaque type -... LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found struct `Empty` + | ---- this type parameter +LL | async {empty()} + | ^^^^^^^^^^^^^^^ type mismatch resolving ` as Stream>::Item == Repr` | - = note: expected opaque type `impl Stream` - found struct `Empty<_>` - -error: could not find defining uses - --> $DIR/issue-89008.rs:35:33 +note: expected this to be `()` + --> $DIR/issue-89008.rs:18:17 | -LL | type LineStream<'a, Repr> = impl Stream; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Item = (); + | ^^ + = note: expected unit type `()` + found type parameter `Repr` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs index d9d17751fa6e2..c65f3fb2aa0a1 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.rs +++ b/src/test/ui/generic-associated-types/issue-87258_a.rs @@ -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!()) } } diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr index 93513a4563f07..db3a5c819cbf3 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -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`. diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs index b29a978f517ff..f59e0d7665942 100644 --- a/src/test/ui/generic-associated-types/issue-87258_b.rs +++ b/src/test/ui/generic-associated-types/issue-87258_b.rs @@ -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!()) } } diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr index e077a423400df..9faccc96124bc 100644 --- a/src/test/ui/generic-associated-types/issue-87258_b.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr @@ -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`. diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs index c97d17811ba7c..e0796dfecbbcc 100644 --- a/src/test/ui/generic-associated-types/issue-88595.rs +++ b/src/test/ui/generic-associated-types/issue-88595.rs @@ -17,7 +17,6 @@ struct C; impl<'a> A<'a> for C { type B<'b> = impl Clone; - //~^ ERROR: could not find defining uses fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope } diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr index 4e4f86bbac87c..79d3479af8c8f 100644 --- a/src/test/ui/generic-associated-types/issue-88595.stderr +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-88595.rs:22:23 + --> $DIR/issue-88595.rs:21:35 | LL | fn a(&'a self) -> Self::B<'a> {} - | ^^^^^^^^^^^ + | ^^ | note: lifetime used multiple times --> $DIR/issue-88595.rs:18:6 @@ -12,11 +12,5 @@ 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 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr index 72ade5774d749..f8c89829e1646 100644 --- a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr +++ b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr @@ -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) -> 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) -> 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 diff --git a/src/test/ui/generic-associated-types/issue-92096.rs b/src/test/ui/generic-associated-types/issue-92096.rs index 066132a5d98bb..2bc1af5506ffd 100644 --- a/src/test/ui/generic-associated-types/issue-92096.rs +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -18,12 +18,12 @@ trait Client { } fn call_connect(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() {} diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs index c2fbbf94fd666..d2452abab0254 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.rs +++ b/src/test/ui/impl-trait/auto-trait-leak.rs @@ -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)) diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 634ff14869eb4..14db864f1c28a 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -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) {} +... | +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`. diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs index cf2773f4ef59d..35994e4a5ba3f 100644 --- a/src/test/ui/impl-trait/auto-trait.rs +++ b/src/test/ui/impl-trait/auto-trait.rs @@ -19,7 +19,7 @@ impl AnotherTrait for T {} // (We treat opaque types as "foreign types" that could grow more impls // in the future.) impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` } fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr index 26cd8fb6a9b5c..81009413c9a26 100644 --- a/src/test/ui/impl-trait/auto-trait.stderr +++ b/src/test/ui/impl-trait/auto-trait.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` --> $DIR/auto-trait.rs:21:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index 8ec06e534d143..20ddad0547ef2 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -23,8 +23,8 @@ mod impl_trait { /// `T::Assoc` can't be normalized any further here. fn foo_fail() -> impl FooLike { - //~^ ERROR: type mismatch Foo(()) + //~^ ERROR: type mismatch } } @@ -39,9 +39,9 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ 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 } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index afa21c1a858a2..01fb853e1d1f7 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -1,16 +1,16 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` - --> $DIR/bound-normalization-fail.rs:25:32 + --> $DIR/bound-normalization-fail.rs:26:9 | -LL | fn foo_fail() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` +LL | Foo(()) + | ^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` | -note: expected this to be `::Assoc` +note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected associated type `::Assoc` - found unit type `()` + = note: expected unit type `()` + found associated type `::Assoc` help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -23,18 +23,18 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as FooLike>::Output == >::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 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` +LL | Foo(()) + | ^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` | -note: expected this to be `>::Assoc` +note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected associated type `>::Assoc` - found unit type `()` + = note: expected unit type `()` + found associated type `>::Assoc` help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/impl-trait/does-not-live-long-enough.stderr b/src/test/ui/impl-trait/does-not-live-long-enough.stderr index f4bd0fde3b6cb..750687e232228 100644 --- a/src/test/ui/impl-trait/does-not-live-long-enough.stderr +++ b/src/test/ui/impl-trait/does-not-live-long-enough.stderr @@ -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 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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()) diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 536a4726c6de2..185a3f53f6557 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -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 - = help: if the trait `Foo` were object safe, you could return a boxed trait object - = note: for information on trait objects, see - = 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 diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index 46053c6e7c119..fd33fa7c674f1 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -15,9 +15,7 @@ LL | fn hide(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 index 0000000000000..1e6eb5bb35588 --- /dev/null +++ b/src/test/ui/impl-trait/fallback.rs @@ -0,0 +1,9 @@ +// check-pass + +fn take_edge_counters( + x: &mut Option>, +) -> Option> { + x.take().map_or(None, |m| Some(m.into_iter())) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/hidden-lifetimes.rs b/src/test/ui/impl-trait/hidden-lifetimes.rs index 2ee004a37a6fc..ae07c89276861 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.rs +++ b/src/test/ui/impl-trait/hidden-lifetimes.rs @@ -26,8 +26,8 @@ impl Swap for Rc> { // 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 dangle_ref() -> &'static [i32; 3] { // 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>) -> impl Swap + 'a { - //~^ ERROR hidden type x + //~^ ERROR hidden type } fn dangle_rc_refcell() -> &'static [i32; 3] { diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index c6d11293eec53..97652f5462ef0 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -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>) -> impl Swap + 'a { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `Rc>` captures the lifetime `'b` as defined here + | -- hidden type `Rc>` 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 | diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs new file mode 100644 index 0000000000000..1b65685a6c06f --- /dev/null +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs @@ -0,0 +1,34 @@ +// This doesn't work, because we don't flow information from opaque types +// into function arguments via the function's generic parameters +// FIXME(oli-obk): make `expected_inputs_for_expected_output` support this + +fn reify_as() -> Thunk Continuation> { + Thunk::new(|mut cont| { //~ ERROR type annotations needed + cont.reify_as(); + cont + }) +} + +#[must_use] +struct Thunk(F); + +impl Thunk { + fn new(f: F) -> Self + where + F: ContFn, + { + Thunk(f) + } +} + +trait ContFn {} + +impl Continuation> ContFn for F {} + +struct Continuation; + +impl Continuation { + fn reify_as(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr new file mode 100644 index 0000000000000..e538aaeb4c5ed --- /dev/null +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/hidden-type-is-opaque-2.rs:6:17 + | +LL | Thunk::new(|mut cont| { + | ^^^^^^^^ consider giving this closure parameter a type + | + = note: type must be known at this point + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque.rs b/src/test/ui/impl-trait/hidden-type-is-opaque.rs new file mode 100644 index 0000000000000..b302ae36ef42c --- /dev/null +++ b/src/test/ui/impl-trait/hidden-type-is-opaque.rs @@ -0,0 +1,32 @@ +// check-pass + +fn reify_as() -> Thunk { + Thunk::new(|mut cont| { + cont.reify_as(); + cont + }) +} + +#[must_use] +struct Thunk(F); + +impl Thunk { + fn new(f: F) -> Self + where + F: FnOnce(Continuation) -> Continuation, + { + Thunk(f) + } +} + +trait ContFn {} + +impl Continuation> ContFn for F {} + +struct Continuation; + +impl Continuation { + fn reify_as(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs index 46188636475db..a75b9b43b3e8b 100644 --- a/src/test/ui/impl-trait/issue-55872-1.rs +++ b/src/test/ui/impl-trait/issue-55872-1.rs @@ -10,11 +10,10 @@ impl Bar for S { type E = impl Copy; fn foo() -> 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] } } diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index 2d1142fd0c52c..efc57da746132 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -8,10 +8,10 @@ LL | fn foo() -> 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() -> 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 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() -> 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() -> 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() -> 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`. diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index 1841d7b3d372d..4443d3c4d0df1 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -3,17 +3,16 @@ #![feature(type_alias_impl_trait)] pub trait Bar { - type E: Copy; + type E: Send; fn foo() -> Self::E; } impl Bar for S { - type E = impl std::marker::Copy; + type E = impl std::marker::Send; fn foo() -> Self::E { - //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //~| ERROR the trait bound `impl Future: Copy` is not satisfied async {} + //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 76122e60c4cb6..11b8485c8bbfe 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -1,20 +1,8 @@ -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/issue-55872-2.rs:13:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `impl Future` - 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:13:28 + --> $DIR/issue-55872-2.rs:14:9 | -LL | fn foo() -> 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 index 0000000000000..bc2d0b1d757e2 --- /dev/null +++ b/src/test/ui/impl-trait/issue-55872-3.rs @@ -0,0 +1,20 @@ +// edition:2018 +// ignore-compare-mode-chalk + +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type E: Copy; + + fn foo() -> Self::E; +} + +impl Bar for S { + type E = impl std::marker::Copy; + fn foo() -> Self::E { + async {} + //~^ ERROR the trait bound `impl Future: 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 index 0000000000000..69a5c8d613577 --- /dev/null +++ b/src/test/ui/impl-trait/issue-55872-3.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:15:9 + | +LL | async {} + | ^^^^^^^^ the trait `Copy` is not implemented for `impl Future` + +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.rs b/src/test/ui/impl-trait/issue-55872.rs index 183728b0f7f0a..c4e6f64360854 100644 --- a/src/test/ui/impl-trait/issue-55872.rs +++ b/src/test/ui/impl-trait/issue-55872.rs @@ -10,8 +10,8 @@ impl Bar for S { type E = impl Copy; fn foo() -> 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 } } diff --git a/src/test/ui/impl-trait/issue-55872.stderr b/src/test/ui/impl-trait/issue-55872.stderr index 39d870dc003bb..cb370fbe1c41d 100644 --- a/src/test/ui/impl-trait/issue-55872.stderr +++ b/src/test/ui/impl-trait/issue-55872.stderr @@ -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:12:28 + --> $DIR/issue-55872.rs:13:9 | -LL | fn foo() -> Self::E { - | ____________________________^ -LL | | -LL | | || () -LL | | } - | |_____^ +LL | || () + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index dee5a41f6de37..cf2c8b7e41540 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -5,7 +5,7 @@ pub struct Lint {} impl Lint {} pub fn gather_all() -> impl Iterator { - //~^ ERROR: cannot resolve opaque type + //~^ ERROR `()` is not an iterator lint_files().flat_map(|f| gather_from_file(&f)) } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index e57fbf104dc6f..4a990286d966d 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -10,25 +10,15 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | fn lint_files() -> impl Iterator { | ^^^ 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 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type -LL | -LL | lint_files().flat_map(|f| gather_from_file(&f)) - | ----------------------------------------------- - | | - | returning here with type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` - | returning here with type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` -... -LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator { - | -------------------------- returning this opaque type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` -... -LL | fn lint_files() -> impl Iterator { - | -------------------------------------- returning this opaque type `FlatMap, [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`. diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs index 853c2a82bede4..1a86fa00ed1a0 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -4,7 +4,7 @@ type FooArg<'a> = &'a dyn ToString; type FooRet = impl std::fmt::Debug; type FooItem = Box FooRet>; -type Foo = impl Iterator; //~ ERROR: type mismatch +type Foo = impl Iterator; #[repr(C)] struct Bar(u8); @@ -13,7 +13,7 @@ impl Iterator for Bar { type Item = FooItem; fn next(&mut self) -> Option { - Some(Box::new(quux)) + Some(Box::new(quux)) //~ ERROR mismatched types } } @@ -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() { diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr index fe48e92da5eac..7cbd58bdabf2f 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -1,20 +1,34 @@ -error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:7:12 +error[E0308]: mismatched types + --> $DIR/issue-70877.rs:16:9 | LL | type FooRet = impl std::fmt::Debug; - | -------------------- the found opaque type + | -------------------- the expected opaque type ... -LL | type Foo = impl Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` +LL | fn next(&mut self) -> Option { + | ------------------ expected `Option Fn(&'r (dyn ToString + 'r)) -> FooRet + 'static)>>` because of return type +LL | Some(Box::new(quux)) + | ^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found fn item | -note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:13:17 + = note: expected enum `Option Fn(&'r (dyn ToString + 'r)) -> FooRet + 'static)>>` + found enum `Option fn(&'r (dyn ToString + 'r)) -> FooRet {quux}>>` + +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/issue-70877.rs:31:12 + | +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 | -LL | type Item = FooItem; - | ^^^^^^^ - = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` +LL | fn oof() -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/issue-70877.rs:4:15 + | +LL | type FooRet = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs index bdbd20f9d2b88..5498793bc28da 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.rs +++ b/src/test/ui/impl-trait/issues/issue-78722.rs @@ -7,10 +7,11 @@ type F = impl core::future::Future; struct Bug { V1: [(); { fn concrete_use() -> F { - async {} + async {} //~ ERROR type mismatch } 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 }], } diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 86bde9a0cddab..624d85570c7de 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -1,23 +1,28 @@ -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; - | -------------------------------------- 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 + = note: see issue #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 | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type +LL | let f: F = async { 1 }; + | ^ constants cannot evaluate destructors +... +LL | }], + | - value is dropped here + +error[E0271]: type mismatch resolving `::Output == u8` + --> $DIR/issue-78722.rs:10:13 | - = note: expected opaque type `impl Future` - found opaque type `impl Future` - = note: distinct uses of `impl Trait` result in different opaque types +LL | async {} + | ^^^^^^^^ expected `()`, found `u8` -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: E0271, E0493, E0658. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs index e3386d29def02..0786e66ca8b06 100644 --- a/src/test/ui/impl-trait/issues/issue-86201.rs +++ b/src/test/ui/impl-trait/issues/issue-86201.rs @@ -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 index b1460096ded66..0000000000000 --- a/src/test/ui/impl-trait/issues/issue-86201.stderr +++ /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 index 0000000000000..9cf8ff76c87f8 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr @@ -0,0 +1,51 @@ +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: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: 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: implementation of `Hrtb` is not general enough + --> $DIR/issue-88236-2.rs:20:5 + | +LL | x + | ^ 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: `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: 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 index 0000000000000..f89ab7fbd364b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs @@ -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 index 0000000000000..95c4a52803698 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr @@ -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 index 0000000000000..2ea35270a7e3b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236.rs @@ -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 index 0000000000000..834f2dc6cb5b6 --- /dev/null +++ b/src/test/ui/impl-trait/lifetimes2.rs @@ -0,0 +1,10 @@ +// check-pass + +pub fn keys<'a>(x: &'a Result) -> impl std::fmt::Debug + 'a { + match x { + Ok(map) => Ok(map), + Err(map) => Err(map), + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs index 72e9d96da3677..f5aaf1185211b 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs @@ -8,7 +8,6 @@ impl Copy for CopyIfEq {} 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() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr index 40bec0da2707d..b837b64110365 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -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 diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs index 3a97624647efd..47e05bce0f8de 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs @@ -14,7 +14,6 @@ struct Ordinary<'a>(&'a u8); // 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 @@ where // '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 { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 32829a0a1b2fa..15476c706a7f2 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -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 | diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs index d4c60a4e89209..321cb8c92a177 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs @@ -16,7 +16,6 @@ struct Ordinary<'a>(&'a u8); // 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 { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 83ad23b253bb3..7315aa8e9d478 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -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 | diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 2f6bd8ff377a5..eb38f84d4afec 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -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(x: T) -> impl Debug + 'static { - | ^^^^^^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'static`... diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 69d2843ff3f01..02ea0255912ab 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -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(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() {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 07ac0a8db35a9..77ba0bf908763 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -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(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 diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs index d173fe83fb791..70e24a3a9d029 100644 --- a/src/test/ui/impl-trait/negative-reasoning.rs +++ b/src/test/ui/impl-trait/negative-reasoning.rs @@ -17,7 +17,7 @@ impl AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` } fn main() {} diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr index e39a8e53f7985..6b8cc9e737423 100644 --- a/src/test/ui/impl-trait/negative-reasoning.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -1,13 +1,13 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` --> $DIR/negative-reasoning.rs:19:1 | LL | impl AnotherTrait for T {} | ------------------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` | - = 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 diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index 06a2191a01761..ec2d49d936744 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -4,6 +4,7 @@ fn fine(x: impl Into) -> impl Into { x } fn bad_in_ret_position(x: impl Into) -> impl Into { x } //~^ ERROR nested `impl Trait` is not allowed +//~| ERROR `impl Into` doesn't implement `Debug` fn bad_in_fn_syntax(x: fn() -> impl Into) {} //~^ ERROR nested `impl Trait` is not allowed @@ -16,6 +17,7 @@ struct X; impl X { fn bad(x: impl Into) -> impl Into { x } //~^ ERROR nested `impl Trait` is not allowed + //~| ERROR `impl Into` doesn't implement `Debug` } fn allowed_in_assoc_type() -> impl Iterator { diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 4444e6a454f89..248d1254ef7c2 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { 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) {} | ----------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | 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) { } | ----------^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into) { } | 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) -> impl Into { x } | ----------^^^^^^^^^^- @@ -35,18 +35,40 @@ LL | fn bad(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/nested_impl_trait.rs:8:32 + --> $DIR/nested_impl_trait.rs:9:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/nested_impl_trait.rs:25:42 + --> $DIR/nested_impl_trait.rs:27:42 | LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { | ^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0277]: `impl Into` doesn't implement `Debug` + --> $DIR/nested_impl_trait.rs:5:70 + | +LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } + | ^ `impl Into` 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 + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ + +error[E0277]: `impl Into` doesn't implement `Debug` + --> $DIR/nested_impl_trait.rs:18:58 + | +LL | fn bad(x: impl Into) -> impl Into { x } + | ^ `impl Into` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider further restricting this bound + | +LL | fn bad(x: impl Into + std::fmt::Debug) -> impl Into { 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`. diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr index 357166d112377..b2f7166f0ae3a 100644 --- a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr +++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr @@ -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 - = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object - = note: for information on trait objects, see - = 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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs index fa7664a83eee0..9f9a6c784e638 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs @@ -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 } } } diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index 970abad5c72e9..db0d446e559a3 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 - = note: for information on trait objects, see - = 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 { - | ~~~~~~~ + -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 { - | ~~~~~~~ + -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 { - | ~~~~~~~ + -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 diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs index b4fd6b3e74364..2e7cb21592cb0 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs @@ -11,8 +11,8 @@ pub trait Test {} impl Test for T where T: Super {} fn test() -> impl Test { - //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` () + //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` } fn main() { diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index 65daabe419d3f..5ef1e9abef631 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -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 index 0000000000000..211f7972dbca8 --- /dev/null +++ b/src/test/ui/impl-trait/question_mark.rs @@ -0,0 +1,13 @@ +// check-pass + +fn foo() -> impl MyTrait { + panic!(); + MyStruct +} + +struct MyStruct; +trait MyTrait {} + +impl MyTrait for MyStruct {} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs index 3cc537440977c..540a280f0a319 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -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 index 5a3027ec751a9..0000000000000 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr +++ /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`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs index e3c621f0c5742..ffc0cd9d10c34 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs @@ -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 index 0000000000000..a60e34c17b671 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs @@ -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 index 0000000000000..eae7d38d1162b --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -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 index 0000000000000..bdabc13c36a96 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -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() {} diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs index e834f96dbbeeb..a04cb1702b638 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.rs +++ b/src/test/ui/impl-trait/region-escape-via-bound.rs @@ -12,10 +12,10 @@ trait Trait<'a> { } impl<'a, 'b> Trait<'b> for Cell<&'a u32> { } fn foo<'x, 'y>(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() { } diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index ecec34e0115c6..bc02f7694d7f6 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -1,10 +1,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/region-escape-via-bound.rs:14:37 + --> $DIR/region-escape-via-bound.rs:17:5 | LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here + | -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here +... +LL | x + | ^ | help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound | diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs index d792c6eafb32f..f940c1949d0b8 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs @@ -4,14 +4,14 @@ struct A { impl A { fn iter_values_anon(&self) -> impl Iterator { + 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 { + 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) } } diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 7424da76182ab..bc8e39f9c504c 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -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 { - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here + | ----- hidden type `Map, [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 + '_ { | ++++ 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 { - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here + | ----- hidden type `Map, [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 + '_ { | ++++ 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 { - | -- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here + | -- hidden type `Map, [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 + '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 { - | -- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here + | -- hidden type `Map, [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 index 0000000000000..6eb2a11b22c5f --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other.rs @@ -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 index 0000000000000..1a42ac525a6a8 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other.stderr @@ -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 index 0000000000000..3b16d0f5e047f --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs @@ -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 index 0000000000000..ef2089a6c5b17 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr @@ -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 index 0000000000000..37f8ae1b84b55 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs @@ -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 index 0000000000000..b06dc16d5e700 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr @@ -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 + diff --git a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr index 039cb62f86656..e0b77544d439d 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr @@ -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(x: T) -> impl Any + 'static { - | ^^^^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'static`... diff --git a/src/test/ui/impl-trait/type_parameters_captured.rs b/src/test/ui/impl-trait/type_parameters_captured.rs index 6c9c9d4a42af5..81ee7d3f8a561 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.rs +++ b/src/test/ui/impl-trait/type_parameters_captured.rs @@ -5,8 +5,8 @@ impl Any for T {} // Check that type parameters are captured and not considered 'static fn foo(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() {} diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr index 40e50b9922f8d..c0de4f4b4a0c5 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.stderr @@ -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(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 diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs index 462508f306ef3..d5a87b5d46834 100644 --- a/src/test/ui/impl-trait/where-allowed-2.rs +++ b/src/test/ui/impl-trait/where-allowed-2.rs @@ -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 { panic!() } //~ ERROR cannot resolve opaque type +// check-pass + +fn in_adt_in_return() -> Vec { 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 index b8e06725cbcdd..0000000000000 --- a/src/test/ui/impl-trait/where-allowed-2.stderr +++ /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 { 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`. diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs index fecba721ac9fd..89e07037afd42 100644 --- a/src/test/ui/issues-71798.rs +++ b/src/test/ui/issues-71798.rs @@ -1,5 +1,6 @@ fn test_ref(x: &u32) -> impl std::future::Future + '_ { - *x //~^ ERROR `u32` is not a future + *x + //~^ ERROR `u32` is not a future } fn main() { diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index bc4dc9ebf9e00..1efa886436e0d 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -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 + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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 diff --git a/src/test/ui/lang-items/lang-item-missing-generator.stderr b/src/test/ui/lang-items/lang-item-missing-generator.stderr index fa13bf0b12719..e5f26822f2670 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-items/lang-item-missing-generator.stderr @@ -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 index 0000000000000..10f6bd74031ac --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs @@ -0,0 +1,46 @@ +// check-pass + +#![feature(gen_future, generator_trait, negative_impls)] + +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>); + +unsafe impl Send for ResumeTy {} + +unsafe impl Sync for ResumeTy {} + +pub const fn from_generator(gen: T) -> impl Future +where + T: Generator, +{ + struct GenFuture>(T); + + // We rely on the fact that async/await futures are immovable in order to create + // self-referential borrows in the underlying generator. + impl> !Unpin for GenFuture {} + + impl> Future for GenFuture { + type Output = T::Return; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // 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::>())) { + 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 index 0000000000000..d07d732c78570 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs @@ -0,0 +1,27 @@ +// check-pass + +fn main() {} + +trait Reader {} + +struct Unit(R); +struct ResDwarf(R); + +struct Context { + dwarf: ResDwarf, +} + +struct Range; + +struct ResUnit(R); + +impl Context { + fn find_dwarf_unit(&self, probe: u64) -> Option<&Unit> { + let x = self.find_units(probe); + None + } + + fn find_units(&self, probe: u64) -> impl Iterator> { + 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 index 0000000000000..f75a88aa8f064 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() {} + +fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { + 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 index 0000000000000..f8291112739c1 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/nested.rs @@ -0,0 +1,23 @@ +// check-pass + +fn main() {} + +struct RawTableInner { + alloc: A, +} + +impl RawTableInner { + fn prepare_resize( + self, + ) -> ScopeGuard { + ScopeGuard { dropfn: move |self_| {}, value: self, } + } +} + +pub struct ScopeGuard +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 index 0000000000000..8d03b5158d662 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() {} + +fn filter_fold 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 index 0000000000000..007101498238d --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs @@ -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 { + IntoIterator::into_iter([self.b0, self.b1]) + } +} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index ea0d0ccbc5532..fd49b4842a74f 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -6,8 +6,8 @@ trait Future { use std::error::Error; fn foo() -> impl Future> { -//~^ ERROR not satisfied Ok(()) + //~^ ERROR not satisfied } fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index ef1127c59ac4c..7f8384d7eca8d 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -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> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>` +LL | Ok(()) + | ^^^^^^ the trait `Future` is not implemented for `Result<(), _>` error: aborting due to previous error diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.rs b/src/test/ui/lint/inline-trait-and-foreign-items.rs index 6321b3c76e4d1..13dab7ed954f8 100644 --- a/src/test/ui/lint/inline-trait-and-foreign-items.rs +++ b/src/test/ui/lint/inline-trait-and-foreign-items.rs @@ -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" { diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr index 6ac884c12ceb9..fc7e89e4f4cce 100644 --- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr +++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr @@ -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 diff --git a/src/test/ui/lint/lint-ctypes-73249-2.rs b/src/test/ui/lint/lint-ctypes-73249-2.rs index fe578f51b63a0..691047c8a405b 100644 --- a/src/test/ui/lint/lint-ctypes-73249-2.rs +++ b/src/test/ui/lint/lint-ctypes-73249-2.rs @@ -23,7 +23,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() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-2.stderr b/src/test/ui/lint/lint-ctypes-73249-2.stderr index 36dbe3217d75a..7c85e9fa85c63 100644 --- a/src/test/ui/lint/lint-ctypes-73249-2.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-2.stderr @@ -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<()>; diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs index ec12de00739e4..ef8ab7e03d2f0 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.rs +++ b/src/test/ui/lint/lint-ctypes-73249-3.rs @@ -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() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-3.stderr b/src/test/ui/lint/lint-ctypes-73249-3.stderr index e987ec90228c1..83e2a233c4335 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.stderr @@ -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; diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs index 58c2d7a501ad5..083fb6c5fb16d 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.rs +++ b/src/test/ui/lint/lint-ctypes-73249-5.rs @@ -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() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-5.stderr b/src/test/ui/lint/lint-ctypes-73249-5.stderr index 749714c7df8d7..37781d78cf28c 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.stderr @@ -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; diff --git a/src/test/ui/lint/lint-ctypes-73251-1.rs b/src/test/ui/lint/lint-ctypes-73251-1.rs index dc4c7efd7ef23..145ba784f7c66 100644 --- a/src/test/ui/lint/lint-ctypes-73251-1.rs +++ b/src/test/ui/lint/lint-ctypes-73251-1.rs @@ -20,7 +20,7 @@ fn assign() -> Qux { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr index 505ccd5a930ce..76b19d37e21a6 100644 --- a/src/test/ui/lint/lint-ctypes-73251-1.stderr +++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr @@ -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() -> ::Assoc; diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs index 717ca4986f700..df71a94579624 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.rs +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -33,7 +33,7 @@ fn use_of_b() -> AliasB { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl TraitA` + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr index d7e10db441ec2..64f0fb2d892a4 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.stderr +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl TraitA`, 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() -> ::Assoc; diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs index 3a62b6a21a56a..b7cc38e99fc37 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs @@ -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() {} diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr index 5afbef778b3e3..62d00fd6835ee 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -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); diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.rs b/src/test/ui/never_type/feature-gate-never_type_fallback.rs index 3b896ec9d70c2..7d02084118001 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.rs +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.rs @@ -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) {} diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr index 670f76867ce45..54abed383000d 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr @@ -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 index 0000000000000..cc9520c1b24c8 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback.rs @@ -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 index 0000000000000..f73d953bdbd0b --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback2.rs @@ -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 index 0000000000000..2f50b9d245900 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback2.stderr @@ -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 index 0000000000000..26ce9b93105e6 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback3.rs @@ -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 index 0000000000000..121019d5f69ae --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback3.stderr @@ -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 index 0000000000000..fe62773fa02db --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback4.rs @@ -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!("{}", ::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 index 0000000000000..f2e216e9044c0 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback4.stderr @@ -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`. diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs index 0d7ee0376924d..2f4cbf8322bbd 100644 --- a/src/test/ui/nll/issue-52113.rs +++ b/src/test/ui/nll/issue-52113.rs @@ -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() {} diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr index f70ae2edd7fac..42ff1866893e6 100644 --- a/src/test/ui/nll/issue-52113.stderr +++ b/src/test/ui/nll/issue-52113.stderr @@ -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` diff --git a/src/test/ui/nll/issue-73159-rpit-static.rs b/src/test/ui/nll/issue-73159-rpit-static.rs index e29ba09b3694d..97dc016068bed 100644 --- a/src/test/ui/nll/issue-73159-rpit-static.rs +++ b/src/test/ui/nll/issue-73159-rpit-static.rs @@ -7,8 +7,8 @@ struct Foo<'a>(&'a [u8]); impl<'a> Foo<'a> { fn make_it(&self) -> impl Iterator { - //~^ ERROR: captures lifetime that does not appear in bounds self.0.iter().copied() + //~^ ERROR: captures lifetime that does not appear in bounds } } diff --git a/src/test/ui/nll/issue-73159-rpit-static.stderr b/src/test/ui/nll/issue-73159-rpit-static.stderr index 6c7cd0c825493..a3e9c0b44c210 100644 --- a/src/test/ui/nll/issue-73159-rpit-static.stderr +++ b/src/test/ui/nll/issue-73159-rpit-static.stderr @@ -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>` captures the lifetime `'a` as defined here LL | fn make_it(&self) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | self.0.iter().copied() + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/nll/relate_tys/opaque-hrtb.rs b/src/test/ui/nll/relate_tys/opaque-hrtb.rs new file mode 100644 index 0000000000000..0fbe6a63c0b68 --- /dev/null +++ b/src/test/ui/nll/relate_tys/opaque-hrtb.rs @@ -0,0 +1,16 @@ +#![feature(nll)] + +trait MyTrait {} + +struct Foo; +impl MyTrait for Foo {} + +fn bar() -> impl MyTrait { + Foo +} + +fn foo() -> impl for<'a> MyTrait<&'a str> { + bar() //~ ERROR implementation of `MyTrait` is not general enough +} + +fn main() {} diff --git a/src/test/ui/nll/relate_tys/opaque-hrtb.stderr b/src/test/ui/nll/relate_tys/opaque-hrtb.stderr new file mode 100644 index 0000000000000..4c8b66f21abe0 --- /dev/null +++ b/src/test/ui/nll/relate_tys/opaque-hrtb.stderr @@ -0,0 +1,11 @@ +error: implementation of `MyTrait` is not general enough + --> $DIR/opaque-hrtb.rs:13:5 + | +LL | bar() + | ^^^^^ implementation of `MyTrait` is not general enough + | + = note: `impl MyTrait<&'2 str>` must implement `MyTrait<&'1 str>`, for any lifetime `'1`... + = note: ...but it actually implements `MyTrait<&'2 str>`, for some specific lifetime `'2` + +error: aborting due to previous error + diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs index 8af23aad7261b..c04185d081424 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -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() {} diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 3e6fe789a8b55..42d9f057aaa08 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -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 | diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs index 0c7d8acb05223..3548ad03a7d3d 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -5,11 +5,11 @@ use std::fmt::Debug; fn no_region<'a, T>(x: Box) -> 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) -> impl Debug + 'a @@ -20,11 +20,11 @@ where } fn wrong_region<'a, 'b, T>(x: Box) -> 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) -> impl Debug + 'a diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 053aef951f264..31ee540cce9f7 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -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) -> 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) -> impl Debug + 'a - | ^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'a`... diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index 91a63bafd99a9..cf5d3dab4aada 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -9,8 +9,9 @@ fn main() { 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 @@ fn main() { 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 @@ fn main() { 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" { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 8eaba559a6240..1d7460b8d3605 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -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` +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` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: 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::::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::::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` +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::::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` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::::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::::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::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::::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` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::::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`. diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs index f295cf15d08c6..68ea4a026d7bf 100644 --- a/src/test/ui/polymorphization/generators.rs +++ b/src/test/ui/polymorphization/generators.rs @@ -32,7 +32,6 @@ where #[rustc_polymorphize_error] pub fn unused_type() -> 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() -> impl Generator<(), Yield = u32, Retu #[rustc_polymorphize_error] pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - //~^ ERROR item has unused generic parameters || { //~^ ERROR item has unused generic parameters yield 1; diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr index c4e566a42d0cf..1152bcb0734a6 100644 --- a/src/test/ui/polymorphization/generators.stderr +++ b/src/test/ui/polymorphization/generators.stderr @@ -8,11 +8,10 @@ LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)] = note: see issue #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() -> 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() -> 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() -> 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() -> 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 diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs index cc36f054bc3a0..49462f52fb4c2 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -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() {} diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index d3214458eac13..a473f42fc2cf8 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -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` - -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`. diff --git a/src/test/ui/save-analysis/issue-68621.rs b/src/test/ui/save-analysis/issue-68621.rs index 96af085c5b6b8..30479580f11a3 100644 --- a/src/test/ui/save-analysis/issue-68621.rs +++ b/src/test/ui/save-analysis/issue-68621.rs @@ -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() {} diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr index 3af6d0a3e076e..4a4bf9a6996bc 100644 --- a/src/test/ui/save-analysis/issue-68621.stderr +++ b/src/test/ui/save-analysis/issue-68621.stderr @@ -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 diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 61ac7731777b4..570a08cb58768 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -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 | diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 6f8200739b9de..abdc650c68e78 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -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 | diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index d826222a06ae5..07c1d8bccbaba 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -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 diff --git a/src/test/ui/suggestions/issue-81098.stderr b/src/test/ui/suggestions/issue-81098.stderr index 2a72159e5774b..f13e653cb06bd 100644 --- a/src/test/ui/suggestions/issue-81098.stderr +++ b/src/test/ui/suggestions/issue-81098.stderr @@ -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 diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index a5b50634c71ea..c7f1215c8cc44 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -7,13 +7,18 @@ LL | fn iter(&self) -> impl Iterator> { 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> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter(&self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + '_ { @@ -32,13 +37,18 @@ LL | fn iter(&self) -> impl Iterator> + '_ { 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> + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + '_ { @@ -53,13 +63,18 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> + '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> + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter<'a>(&'a self) -> impl Iterator> + '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> + 'a { @@ -74,13 +89,18 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> { 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> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + 'a { diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index 6aa93a24d2f04..a02664ad7ca69 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -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` + //~| NOTE expected opaque type `impl Future` //~| NOTE distinct uses of `impl Trait` result in different opaque types }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index b55c51b92809a..4c4b782bd6fb1 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -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` + = note: expected unit type `()` + found opaque type `impl Future` 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` + = note: expected unit type `()` + found opaque type `impl Future` 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` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) - found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) + = note: expected opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future` (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 | diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index e065e0aaa8e06..133ffb0587392 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -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> { + | ------------------------------------ the expected opaque type +... LL | fn thing_two() -> impl Future> { | ------------------------------------ the found opaque type ... @@ -13,8 +16,8 @@ LL | | thing_two() LL | | }.await | |_____- `if` and `else` have incompatible types | - = note: expected type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) - found opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: expected opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future>` (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/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs index 0013d5d66f172..04320e7207683 100644 --- a/src/test/ui/traits/alias/issue-83613.rs +++ b/src/test/ui/traits/alias/issue-83613.rs @@ -8,6 +8,6 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl 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() {} diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr index 6a3498a389375..4f19e6607c8d9 100644 --- a/src/test/ui/traits/alias/issue-83613.stderr +++ b/src/test/ui/traits/alias/issue-83613.stderr @@ -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 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 diff --git a/src/test/ui/traits/pointee-tail-is-generic-errors.rs b/src/test/ui/traits/pointee-tail-is-generic-errors.rs index d081721aca275..28bc1da964dbc 100644 --- a/src/test/ui/traits/pointee-tail-is-generic-errors.rs +++ b/src/test/ui/traits/pointee-tail-is-generic-errors.rs @@ -14,7 +14,7 @@ fn a() { //~^ ERROR type mismatch resolving `::Metadata == ()` is_thin::(); - //~^ ERROR type mismatch resolving `::Metadata == ()` + //~^ ERROR type mismatch resolving `::Metadata == ()` } fn is_thin + ?Sized>() {} diff --git a/src/test/ui/traits/pointee-tail-is-generic-errors.stderr b/src/test/ui/traits/pointee-tail-is-generic-errors.stderr index fa5fe67e53cb6..8456f84562ff2 100644 --- a/src/test/ui/traits/pointee-tail-is-generic-errors.stderr +++ b/src/test/ui/traits/pointee-tail-is-generic-errors.stderr @@ -14,7 +14,7 @@ note: required by a bound in `is_thin` LL | fn is_thin + ?Sized>() {} | ^^^^^^^^^^^^^ required by this bound in `is_thin` -error[E0271]: type mismatch resolving `::Metadata == ()` +error[E0271]: type mismatch resolving `::Metadata == ()` --> $DIR/pointee-tail-is-generic-errors.rs:16:5 | LL | type Opaque = impl std::fmt::Debug + ?Sized; @@ -24,13 +24,13 @@ LL | is_thin::(); | ^^^^^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `::Metadata` + found associated type `::Metadata` note: required by a bound in `is_thin` --> $DIR/pointee-tail-is-generic-errors.rs:20:33 | LL | fn is_thin + ?Sized>() {} | ^^^^^^^^^^^^^ required by this bound in `is_thin` -help: consider constraining the associated type `::Metadata` to `()` +help: consider constraining the associated type `::Metadata` to `()` | LL | type Opaque = impl std::fmt::Debug + ?Sized; | +++++++++++++++ diff --git a/src/test/ui/type-alias-impl-trait/argument-types.rs b/src/test/ui/type-alias-impl-trait/argument-types.rs index 8427b5b1fe854..185207b9800bb 100644 --- a/src/test/ui/type-alias-impl-trait/argument-types.rs +++ b/src/test/ui/type-alias-impl-trait/argument-types.rs @@ -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 index a87e44a048b25..0000000000000 --- a/src/test/ui/type-alias-impl-trait/argument-types.stderr +++ /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`. diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index 4a49d6e4ab8fd..0664275b2ad0a 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -2,15 +2,15 @@ error[E0277]: `Rc` 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` 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` - = note: required because it appears within the type `impl Debug` + = help: within `Foo`, the trait `Send` is not implemented for `Rc` + = note: required because it appears within the type `Foo` note: required by a bound in `is_send` --> $DIR/auto-trait-leakage2.rs:14:15 | diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 5fb7a9473d3df..b456b1445e784 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index c0147e56c9364..4c44875b4a548 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index cee8186dd8f8c..4d2890b5de583 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -7,13 +7,12 @@ trait TraitWithAssoc { } type Foo = impl Trait; -//~^ ERROR could not find defining uses trait Trait {} impl Trait for () {} fn foo_desugared(_: T) -> Foo { - //~^ ERROR non-defining opaque type use in defining scope () + //~^ ERROR non-defining opaque type use } diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index 03e696fe89803..c405b1f6af205 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -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) -> Foo { - | ^^^^^^^^^^^^^ +LL | () + | ^^ | note: used non-generic type `::Assoc` for generic parameter --> $DIR/bound_reduction2.rs:9:10 @@ -10,11 +10,5 @@ note: used non-generic type `::Assoc` for generic parameter LL | type Foo = impl Trait; | ^ -error: could not find defining uses - --> $DIR/bound_reduction2.rs:9:15 - | -LL | type Foo = impl Trait; - | ^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs index eecef2338c146..83d22161e4e75 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -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 { diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index da9f81d6bd370..d87ef2ec79c1a 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs index c4bf56a919721..6febd07157aa6 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs +++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr index 21c2e8a9db618..60bc24320a301 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs index 7ea517eb734a4..5bda5f0fceaaa 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs @@ -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 { diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr index 0b4c262bbb43b..26308c6ff6b15 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs index 95cbcfec2dc15..7740f774ebca4 100644 --- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs +++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs @@ -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 index 6274029e4f524..0000000000000 --- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr +++ /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 - diff --git a/src/test/ui/type-alias-impl-trait/fallback.rs b/src/test/ui/type-alias-impl-trait/fallback.rs index fe1ca2230daca..d7e93335f47fa 100644 --- a/src/test/ui/type-alias-impl-trait/fallback.rs +++ b/src/test/ui/type-alias-impl-trait/fallback.rs @@ -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)] diff --git a/src/test/ui/type-alias-impl-trait/field-types.rs b/src/test/ui/type-alias-impl-trait/field-types.rs index 91494a82d0fb2..d99ed58127bd4 100644 --- a/src/test/ui/type-alias-impl-trait/field-types.rs +++ b/src/test/ui/type-alias-impl-trait/field-types.rs @@ -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 index 18c2abbdf3721..0000000000000 --- a/src/test/ui/type-alias-impl-trait/field-types.stderr +++ /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`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs index 885aae619d6a2..c9b9e128f88e2 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -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 } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr index b99c6a51f4b1d..222aaea78d982 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index 33cd2f6ba0753..093c1c231861f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -6,23 +6,23 @@ fn main() {} // test that unused generic parameters are ok type TwoTys = impl Debug; -//~^ ERROR could not find defining uses + type TwoLifetimes<'a, 'b> = impl Debug; -//~^ ERROR could not find defining uses + type TwoConsts = impl Debug; -//~^ ERROR could not find defining uses + fn one_ty(t: T) -> TwoTys { - //~^ 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(t: *mut [u8; N]) -> TwoConsts { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 52c60d1777e49..922e41e0f6883 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -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: T) -> TwoTys { - | ^^^^^^^^^^^^ +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 = impl Debug; | ^ ^ -error: could not find defining uses - --> $DIR/generic_duplicate_param_use.rs:8:21 - | -LL | type TwoTys = 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(t: *mut [u8; N]) -> TwoConsts { - | ^^^^^^^^^^^^^^^ +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 = impl Debug; | ^ ^ -error: could not find defining uses - --> $DIR/generic_duplicate_param_use.rs:12:50 - | -LL | type TwoConsts = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs index 04fb57b39c052..81bf9770d02a8 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs @@ -8,11 +8,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` -fn one(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope - t -} - fn two(t: T, _: U) -> Two { t } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index fca9b70d18441..84aa260b099b6 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -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: T) -> Two { - | ^^^^^^^^^ - | -note: type used multiple times - --> $DIR/generic_duplicate_param_use2.rs:8:10 - | -LL | type Two = 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 = 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/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index 1a755d3902612..c95692182c278 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -8,11 +8,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` -fn one(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope - t -} - fn two(t: T, _: U) -> Two { t } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index 90b04c043a00c..e5a70fa8ce56e 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -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: T) -> Two { - | ^^^^^^^^^ - | -note: type used multiple times - --> $DIR/generic_duplicate_param_use3.rs:8:10 - | -LL | type Two = 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: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: T, _: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,6 +21,6 @@ help: consider restricting type parameter `T` LL | type Two = 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/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs index 50d95c83d58e6..aee2550e9078a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs @@ -8,11 +8,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `U` doesn't implement `Debug` -fn one(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope - t -} - fn three(_: T, u: U) -> Two { u } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index c4be2fa83f130..0491d61030e34 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -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: T) -> Two { - | ^^^^^^^^^ - | -note: type used multiple times - --> $DIR/generic_duplicate_param_use4.rs:8:10 - | -LL | type Two = 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 = 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/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs index cf43085877f4c..f39741a6a625c 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -5,25 +5,25 @@ use std::fmt::Debug; fn main() {} type OneTy = impl Debug; -//~^ ERROR could not find defining uses + type OneLifetime<'a> = impl Debug; -//~^ ERROR could not find defining uses + type OneConst = impl Debug; -//~^ ERROR could not find defining uses + // Not defining uses, because they doesn't define *all* possible generics. fn concrete_ty() -> OneTy { - //~^ 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 } diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 3aa42a25484d1..36694900c17b4 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -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 { - | ^^^^^^^^^^ +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 = impl Debug; | ^ -error: could not find defining uses - --> $DIR/generic_nondefining_use.rs:7:17 - | -LL | type OneTy = 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 = impl Debug; | ^ -error: could not find defining uses - --> $DIR/generic_nondefining_use.rs:11:33 - | -LL | type OneConst = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.rs b/src/test/ui/type-alias-impl-trait/generic_not_used.rs index dd6300a64f42e..c70f473cff578 100644 --- a/src/test/ui/type-alias-impl-trait/generic_not_used.rs +++ b/src/test/ui/type-alias-impl-trait/generic_not_used.rs @@ -6,6 +6,6 @@ type WrongGeneric = impl 'static; //~^ ERROR: at least one trait must be specified fn wrong_generic(_: U, v: V) -> WrongGeneric { - //~^ 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 } diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.stderr b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr index 8015ff7eded90..fd720239a5239 100644 --- a/src/test/ui/type-alias-impl-trait/generic_not_used.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr @@ -5,14 +5,10 @@ LL | type WrongGeneric = 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, v: V) -> WrongGeneric { - | _________________________________________________________________________^ -LL | | -LL | | v -LL | | } - | |_^ +LL | v + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr index f4e1de8e50f68..dc85db66d32ba 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr @@ -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 = 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 = 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) -> WrongGeneric { - | ^^^^^^^^^^^^^^^ +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 = 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 = 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`. diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index 78d25e30e0382..cb90776472b5d 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -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 = impl 'static; //~^ ERROR: at least one trait must be specified fn wrong_generic(t: T) -> WrongGeneric { - //~^ ERROR the parameter type `T` may not live long enough t + //~^ ERROR the parameter type `T` may not live long enough } diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 568784372e519..15ec2eed3da4b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -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 = 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 = 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 = 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) -> WrongGeneric { - | - ^^^^^^^^^^^^^^^ ...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`. diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs index c781e200bf8ee..608572978a351 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs @@ -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 @@ mod m { fn baz() { let f: Foo = 22_u32; - //~^ ERROR: mismatched types [E0308] } fn is_send(_: T) {} diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr index e12124664778e..3ed86fae8a18d 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.rs b/src/test/ui/type-alias-impl-trait/issue-53598.rs index f936dc42f133d..9c1cbf926f54d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53598.rs @@ -17,8 +17,8 @@ impl Foo for S2 { type Item = impl Debug; fn foo(_: 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::(Default::default()) + //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.stderr index 9971c7e0e20ee..f8b8201e2ebed 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53598.stderr @@ -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:19:42 + --> $DIR/issue-53598.rs:20:9 | -LL | fn foo(_: T) -> Self::Item { - | __________________________________________^ -LL | | -LL | | S::(Default::default()) -LL | | } - | |_____^ +LL | S::(Default::default()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index a4ccae4eb7ed9..91daa65d6563a 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -1,38 +1,26 @@ -error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 - | -LL | |x| x - | ^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 - | -LL | |x| x - | ^^^^^ - error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:17:16 + --> $DIR/issue-57611-trait-alias.rs:20:9 | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +LL | |x| x + | ^^^^^ one type is more general than the other | = note: expected type `for<'r> Fn<(&'r X,)>` - found type `Fn<(&'static X,)>` + found type `Fn<(&X,)>` note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:20:9 | LL | |x| x | ^^^^^ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:17:16 + --> $DIR/issue-57611-trait-alias.rs:20:9 | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough +LL | |x| x + | ^^^^^ 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,)>` + = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 625e46b6bc012..7c6e764248479 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -17,8 +17,8 @@ impl Foo for X { type Bar = impl Baz; fn bar(&self) -> Self::Bar { - //~^ ERROR implementation of `FnOnce` is not general enough |x| x + //~^ ERROR implementation of `FnOnce` is not general enough } } diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index 54d237159d80b..45329ea292dcf 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -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` diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.rs b/src/test/ui/type-alias-impl-trait/issue-57700.rs index 13a6b7c2f7ceb..4845893870243 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57700.rs @@ -13,8 +13,8 @@ impl Foo for C { type Bar = impl Foo; fn foo(self: impl Deref) -> Self::Bar { - //~^ Error type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias self + //~^ Error type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.stderr index b2e3f46f1f582..31b6df5d4c318 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57700.stderr @@ -1,12 +1,8 @@ error: type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-57700.rs:15:58 + --> $DIR/issue-57700.rs:16:9 | -LL | fn foo(self: impl Deref) -> 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 index 0000000000000..e4ba7f8e2a623 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs @@ -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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs index badf35484f360..9a40f3d9b64ea 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -9,7 +9,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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index dc8a381aece94..5fec078956bfc 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -11,21 +11,12 @@ error[E0277]: the trait bound `(): Bug` is not satisfied --> $DIR/issue-60371.rs:10: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:10: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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 44dcec2c3da98..4fc7679311a2e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -6,7 +6,6 @@ trait IterBits { } type IterBitsIter = impl std::iter::Iterator; -//~^ ERROR could not find defining uses impl IterBits for T where @@ -18,8 +17,8 @@ where { type BitsIter = IterBitsIter; 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 } } diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index 6b73fbef011ec..bbc93657be32f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -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 = impl std::iter::Iterator; | ^ -error: could not find defining uses - --> $DIR/issue-60564.rs:8:30 - | -LL | type IterBitsIter = impl std::iter::Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.rs b/src/test/ui/type-alias-impl-trait/issue-63279.rs index 875cce4df2390..057a908bbee74 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 5fde8c2ef1e11..4b7dbbd6a56cc 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs index 9f617153e3fd5..7066a0535e184 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63355.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63355.rs @@ -1,5 +1,5 @@ #![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] +// check-pass pub trait Foo {} @@ -27,11 +27,8 @@ impl Bar for () { } } -// 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; -//~^ 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 index 2dbd5a55a625f..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-63355.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()` - --> $DIR/issue-63355.rs:33:20 - | -LL | pub type FooImpl = impl Foo; - | -------- the found opaque type -LL | pub type BarImpl = impl Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()` - | -note: expected this to be `()` - --> $DIR/issue-63355.rs:23: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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs index 2e6354088ac5a..5223fb1c702d6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -5,7 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; -//~^ ERROR could not find defining uses + fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 721f99a3f0d18..7fb9a0c410e83 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -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; | ^ -error: could not find defining uses - --> $DIR/issue-68368-non-defining-use-2.rs:7:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index 3addd8dcc4fb3..b50462bf237bb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -5,7 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; -//~^ ERROR could not find defining uses + fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index f5b8fccf65d16..8059621b61a09 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -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; | ^ -error: could not find defining uses - --> $DIR/issue-68368-non-defining-use.rs:7:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-74280.stderr b/src/test/ui/type-alias-impl-trait/issue-74280.stderr index f6b369dd8d518..38591e37f5358 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/issue-77179.stderr b/src/test/ui/type-alias-impl-trait/issue-77179.stderr index 15205ba9b419e..053546e4b9285 100644 --- a/src/test/ui/type-alias-impl-trait/issue-77179.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-77179.stderr @@ -5,7 +5,7 @@ LL | fn test() -> Pointer<_> { | --------^- | | | | | not allowed in type signatures - | help: replace with the correct return type: `Box` + | help: replace with the correct return type: `Pointer` error: aborting due to previous error 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 index 0000000000000..1f8c789267d1b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-93411.rs @@ -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 + 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 index 0000000000000..08cb48ccf308c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs @@ -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 = impl std::fmt::Debug; + +fn g() -> (Y, Y) { + (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 index 0000000000000..3f57612684e41 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr @@ -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() -> (Y, Y) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, got `i32` + | +note: previous use here + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1 + | +LL | fn g() -> (Y, Y) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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 index 0000000000000..f39bf4aeb29ae --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -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 index 0000000000000..49d08dda9f994 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -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 + diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs index f412b2d0e7db7..83fd9a1da450b 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs @@ -7,6 +7,15 @@ fn f(a: A, b: B) -> (X, X) (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!("{}", as ToString>::to_string(&f(42_i32, String::new()).1)); + let meh = 42; + let muh = 69; + println!("{:?}", foo(&meh, &muh)); } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs index da845e86147b7..46bac5a34f5c0 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs @@ -7,8 +7,8 @@ type X = impl Into<&'static A>; fn f(a: &'static A, b: B) -> (X, X) { - //~^ 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() { diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr index 4df2f52a9e427..f4d8b4509d43d 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -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: &'static A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^ 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 diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index bbe709dccab4e..db4b60461ef38 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 | +LL | type X = impl ToString; + | ------------- the expected opaque type +... LL | fn g(a: A, b: B) -> (X, X) { | - - found type parameter | | @@ -8,8 +11,8 @@ LL | fn g(a: A, b: B) -> (X, X` + 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 diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs index efb88dabf34cd..784a6c75886d4 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] #![allow(dead_code)] @@ -12,7 +10,9 @@ trait Foo { } impl Foo<()> for () { } fn foo() -> impl Foo { + // FIXME(type-alias-impl-trait): We could probably make this work. () + //~^ ERROR: the trait bound `(): Foo` 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 index 0000000000000..9472cac63554e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference.rs:14:5 + | +LL | () + | ^^ the trait `Foo` 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`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs index 9b26a65297852..00bd44c493c83 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -4,7 +4,6 @@ use std::fmt::Debug; type FooX = impl Debug; -//~^ ERROR: could not find defining uses trait Foo {} @@ -12,8 +11,8 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] () + //~^ ERROR: the trait bound `(): Foo` is not satisfied } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 7e24ee644b1ce..ec1b4642d0822 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -1,19 +1,13 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:14:13 +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference2.rs:14:5 | -LL | fn foo() -> impl Foo { - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +LL | () + | ^^ the trait `Foo` is not implemented for `()` | = help: the following implementations were found: <() as Foo<()>> <() as Foo> -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 index 0000000000000..fbab5470b4f6d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -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 { } + +impl Foo for () { } + +fn foo() -> impl Foo { + () +} + +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 index 0000000000000..b1d947a9ccf4e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -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 index 0000000000000..6b866be7d173f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl Trait; + +trait Trait {} + +impl Trait 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 index 0000000000000..cf4d23656e0e1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs index 6282264d8fee5..60b6e1aac6281 100644 --- a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs +++ b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -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 @@ mod my_mod { } 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 index 0000000000000..fa6ecf68d28f3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr @@ -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 + diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs index 8787c023eb0c7..fed5ac07c901e 100644 --- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs +++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs @@ -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 index b438f84451649..0000000000000 --- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr +++ /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`. diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs index 1197c7bc58ece..fa578eced5f2b 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -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 { diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr index 61025e846921e..009935347e66c 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr index 67752acb8c9af..e691d8781c0f1 100644 --- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr +++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index 107cd39457935..5b332b8cb6bd8 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -7,11 +7,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` -fn two(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope - (t, 4i8) -} - fn three(t: T) -> Two { (t, 5i8) } diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr index 08e49845521c6..f946dc48a4bf9 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -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: T) -> Two { - | ^^^^^^^^^^^ - | -note: used non-generic type `u32` for generic parameter - --> $DIR/not_a_defining_use.rs:7:13 - | -LL | type Two = 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: T) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::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: T) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,6 +22,6 @@ help: consider restricting type parameter `T` LL | type Two = 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 index 0000000000000..dc7054da5ec19 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl PartialEq; + +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 index 0000000000000..6997676260dd6 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -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` 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 index 0000000000000..d40715717d49d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-3.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + 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 index 0000000000000..697ec56825a9c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + 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> + 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> + 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 index 0000000000000..4a6ee2f9279d1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr @@ -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>` 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>` 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>` 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 index 0000000000000..4974ac72dad18 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + 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> + 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> + 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 index 0000000000000..0626e6be0d5a5 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -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>` 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`. diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs index 86b685022b20e..748a279e43989 100644 --- a/src/test/ui/type-alias-impl-trait/static-const-types.rs +++ b/src/test/ui/type-alias-impl-trait/static-const-types.rs @@ -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 index 6f4c2944f7285..0000000000000 --- a/src/test/ui/type-alias-impl-trait/static-const-types.stderr +++ /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`. diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs index 219837aa04bab..c2ab6a9d10aa6 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -10,9 +10,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 _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr index 889c4fd4b0405..dbc183f54f46b 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -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:14:9 | LL | LEAK_FREE => (), diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs index c9e669cad603a..7cc9ccaabdca4 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match.rs @@ -11,9 +11,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 _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match.stderr b/src/test/ui/type-alias-impl-trait/structural-match.stderr index 262fd0726137e..61287f268066e 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match.stderr @@ -1,4 +1,4 @@ -error: `impl Send` cannot be used in patterns +error: `Foo` cannot be used in patterns --> $DIR/structural-match.rs:15:9 | LL | VALUE => (), diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs index 1a8113848f923..5630e036be34b 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -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 index e2567e87ac676..0000000000000 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr +++ /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`. diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs index c009952eab750..e5e7fb677ede9 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr index 726f4ea6e00f7..a770eeac39b7d 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -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 diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs index f3898bca64b9b..7c7a1b405bcdc 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs @@ -5,7 +5,7 @@ pub trait Bar { } type Foo = impl Bar; -//~^ ERROR: could not find defining uses +//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { x diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr index 3947cc4d27055..3f3699ce5324a 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -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; | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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/type-alias-impl-trait/type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs index d2c8c1f63df1c..70c2ee4278ca2 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs @@ -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 index 0000000000000..67f56bcde939a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs @@ -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![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 = impl Iterator; + + pub fn my_iter(t: T) -> MyIter { + std::iter::once(t) + } + + fn my_iter2(t: T) -> MyIter { + std::iter::once(t) + } + + // param names should not have an effect! + fn my_iter3(u: U) -> MyIter { + std::iter::once(u) + } + + // param position should not have an effect! + fn my_iter4(_: U, v: V) -> MyIter { + std::iter::once(v) + } + + // param names should not have an effect! + type MyOtherIter = impl Iterator; + + fn my_other_iter(u: U) -> MyOtherIter { + 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 = impl Sized + 'static; + + fn define_passthrough(t: T) -> Passthrough { + t + } + } + + fn use_passthrough(x: pass_through::Passthrough) -> pass_through::Passthrough { + x + } + +} diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs index 7f8e6127cca3b..4e9d1788b94d8 100644 --- a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs @@ -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(x: (T, T)) {} diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr index cac8d6841afda..1dabe4586c5b9 100644 --- a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -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`. diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 891531951c1a0..f099d2c07d18f 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -33,6 +33,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Trait(..) + | 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), From f42a6793ce3d32a8d414519b8ec82141f7996479 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Feb 2022 14:15:20 +0000 Subject: [PATCH 02/26] Fail more aggressively --- compiler/rustc_trait_selection/src/traits/codegen.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 22182faa0c62c..4b6784aee9782 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -92,10 +92,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()); + // There should be no opaque types during codegen, they all get revealed. + let opaque_types = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + if !opaque_types.is_empty() { + bug!("{:#?}", opaque_types); + } debug!("Cache miss: {:?} => {:?}", trait_ref, impl_source); Ok(&*tcx.arena.alloc(impl_source)) From 1c5bfb17703975ff9952243c24c46cf54fe0d49c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Feb 2022 14:53:50 +0000 Subject: [PATCH 03/26] Don't bind hidden types when searching for matching impls --- .../src/traits/select/mod.rs | 1 + src/test/ui/impl-trait/nested_impl_trait.rs | 4 +-- .../ui/impl-trait/nested_impl_trait.stderr | 18 ++++------- ...ias-impl-trait-declaration-too-subtle-2.rs | 17 ++++++++++ ...impl-trait-declaration-too-subtle-2.stderr | 11 +++++++ ...rsive-type-alias-impl-trait-declaration.rs | 32 ++++--------------- src/test/ui/impl-trait/trait_resolution.rs | 30 +++++++++++++++++ 7 files changed, 74 insertions(+), 39 deletions(-) create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr create mode 100644 src/test/ui/impl-trait/trait_resolution.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9b8a49e512b95..76526df646159 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2163,6 +2163,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&cause, obligation.param_env) + .define_opaque_types(false) .eq(placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index ec2d49d936744..85c6f8c462cbb 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -4,7 +4,7 @@ fn fine(x: impl Into) -> impl Into { x } fn bad_in_ret_position(x: impl Into) -> impl Into { x } //~^ ERROR nested `impl Trait` is not allowed -//~| ERROR `impl Into` doesn't implement `Debug` +//~| ERROR the trait bound `impl Debug: From>` is not satisfied fn bad_in_fn_syntax(x: fn() -> impl Into) {} //~^ ERROR nested `impl Trait` is not allowed @@ -17,7 +17,7 @@ struct X; impl X { fn bad(x: impl Into) -> impl Into { x } //~^ ERROR nested `impl Trait` is not allowed - //~| ERROR `impl Into` doesn't implement `Debug` + //~| ERROR the trait bound `impl Debug: From>` is not satisfied } fn allowed_in_assoc_type() -> impl Iterator { diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 248d1254ef7c2..a10e4ec318230 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -46,27 +46,21 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { | ^^^^^^^^^^^^^^ -error[E0277]: `impl Into` doesn't implement `Debug` +error[E0277]: the trait bound `impl Debug: From>` is not satisfied --> $DIR/nested_impl_trait.rs:5:70 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^ `impl Into` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^ the trait `From>` is not implemented for `impl Debug` | -help: consider further restricting this bound - | -LL | fn bad_in_ret_position(x: impl Into + std::fmt::Debug) -> impl Into { x } - | +++++++++++++++++ + = note: required because of the requirements on the impl of `Into` for `impl Into` -error[E0277]: `impl Into` doesn't implement `Debug` +error[E0277]: the trait bound `impl Debug: From>` is not satisfied --> $DIR/nested_impl_trait.rs:18:58 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^ `impl Into` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -help: consider further restricting this bound + | ^ the trait `From>` is not implemented for `impl Debug` | -LL | fn bad(x: impl Into + std::fmt::Debug) -> impl Into { x } - | +++++++++++++++++ + = note: required because of the requirements on the impl of `Into` for `impl Into` error: aborting due to 8 previous errors diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs new file mode 100644 index 0000000000000..6b200d7e3a89e --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +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 //~ ERROR can't compare `Bar` with `(Bar, i32)` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr new file mode 100644 index 0000000000000..5476bf9d27745 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr @@ -0,0 +1,11 @@ +error[E0277]: can't compare `Bar` with `(Bar, i32)` + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:14:5 + | +LL | Bar + | ^^^ no implementation for `Bar == (Bar, i32)` + | + = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. 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 index bdabc13c36a96..ad0a003e87948 100644 --- 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 @@ -2,36 +2,18 @@ #![feature(type_alias_impl_trait)] -mod direct { - type Foo = impl PartialEq<(Foo, i32)>; +type Foo = impl PartialEq<(Foo, i32)>; - struct Bar; +struct Bar; - impl PartialEq<(Foo, i32)> for Bar { - fn eq(&self, _other: &(Foo, i32)) -> bool { - true - } - } - - fn foo() -> Foo { - Bar +impl PartialEq<(Bar, i32)> for Bar { + fn eq(&self, _other: &(Bar, i32)) -> bool { + true } } -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 foo() -> Foo { + Bar } fn main() {} diff --git a/src/test/ui/impl-trait/trait_resolution.rs b/src/test/ui/impl-trait/trait_resolution.rs new file mode 100644 index 0000000000000..8dcbbfd6e6492 --- /dev/null +++ b/src/test/ui/impl-trait/trait_resolution.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::fmt::Debug; + +pub struct EventStream { + stream: S, +} + +impl EventStream { + fn into_stream(self) -> impl Debug { + unimplemented!() + } + + pub fn into_reader(self) -> impl Debug { + ReaderStream::from(self.into_stream()) + } +} + +#[derive(Debug)] +pub struct ReaderStream { + stream: S, +} + +impl From for ReaderStream { + fn from(stream: S) -> Self { + ReaderStream { stream } + } +} + +fn main() {} From 4cfaf9a93121f3b4a57f59ebfc1991c6f4b892a8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Feb 2022 17:53:35 +0000 Subject: [PATCH 04/26] Normalize all projections in mir validation again --- .../src/transform/validate.rs | 7 ++++- src/test/ui/impl-trait/projection.rs | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/projection.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index e68e1a055d916..263959f3cb376 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -169,8 +169,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Equal types, all is good. return true; } + // Normalization reveals opaque types, but we may be validating MIR while computing + // said opaque types, causing cycles. + if (src, dest).has_opaque_types() { + return true; + } // Normalize projections and things like that. - let param_env = self.param_env; + let param_env = self.param_env.with_reveal_all_normalized(self.tcx); let src = self.tcx.normalize_erasing_regions(param_env, src); let dest = self.tcx.normalize_erasing_regions(param_env, dest); diff --git a/src/test/ui/impl-trait/projection.rs b/src/test/ui/impl-trait/projection.rs new file mode 100644 index 0000000000000..21fc6591e97bf --- /dev/null +++ b/src/test/ui/impl-trait/projection.rs @@ -0,0 +1,29 @@ +// build-pass +// needs to be build-pass, because it is a regression test for a mir validation failure +// that only happens during codegen. + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { None } +} + +fn run(f: F) + where for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} \ No newline at end of file From 4b249b062bea6c3ed81e605ccac852ca8ad60986 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Feb 2022 14:14:39 +0000 Subject: [PATCH 05/26] Remove some dead code --- compiler/rustc_infer/src/infer/opaque_types.rs | 6 +----- compiler/rustc_infer/src/infer/opaque_types/table.rs | 10 +--------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 46420fbe0c305..38b092cfd7034 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Ok(_) => span_bug!( cause.span, "opaque types are never equal to anything but themselves: {:#?}", - (a, b) + (a.kind(), b.kind()) ), Err(e) => Err(e), } @@ -450,10 +450,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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 diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 202afea559c61..55da42e98f476 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -29,14 +29,6 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { } } - 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) @@ -69,7 +61,7 @@ pub struct OpaqueTypeTable<'a, 'tcx> { impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { #[instrument(skip(self), level = "debug")] - pub fn register( + pub(crate) fn register( &mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>, From d5b6510bfb8484a964428fe44e2a66eebb15e66e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Feb 2022 16:44:17 +0000 Subject: [PATCH 06/26] Have the spans of TAIT type conflict errors point to the actual site instead of the owning function --- compiler/rustc_borrowck/src/nll.rs | 8 ++--- .../src/region_infer/opaque_types.rs | 32 ++++++++--------- compiler/rustc_borrowck/src/type_check/mod.rs | 16 ++++----- .../rustc_infer/src/infer/opaque_types.rs | 36 ++----------------- .../src/infer/opaque_types/table.rs | 4 +-- compiler/rustc_infer/src/infer/undo_log.rs | 4 +-- compiler/rustc_middle/src/mir/query.rs | 4 +-- compiler/rustc_middle/src/ty/mod.rs | 32 +++++++++++++++++ .../rustc_trait_selection/src/opaque_types.rs | 14 ++++---- compiler/rustc_typeck/src/collect/type_of.rs | 27 +++++++------- src/test/ui/impl-trait/issue-86465.rs | 2 +- src/test/ui/impl-trait/issue-86465.stderr | 12 +++---- .../different_defining_uses.rs | 2 +- .../different_defining_uses.stderr | 12 +++---- .../different_lifetimes_defining_uses.rs | 2 +- .../different_lifetimes_defining_uses.stderr | 12 +++---- .../generic_different_defining_uses.rs | 2 +- .../generic_different_defining_uses.stderr | 12 +++---- .../generic_duplicate_param_use3.rs | 2 +- .../generic_duplicate_param_use3.stderr | 12 +++---- .../generic_duplicate_param_use5.rs | 2 +- .../generic_duplicate_param_use5.stderr | 12 +++---- .../generic_duplicate_param_use6.rs | 2 +- .../generic_duplicate_param_use6.stderr | 12 +++---- .../generic_duplicate_param_use8.rs | 2 +- .../generic_duplicate_param_use8.stderr | 12 +++---- .../generic_duplicate_param_use9.rs | 2 +- .../generic_duplicate_param_use9.stderr | 12 +++---- .../issue-52843-closure-constrain.stderr | 8 ++--- .../multiple-def-uses-in-one-fn-infer.rs | 2 +- .../multiple-def-uses-in-one-fn-infer.stderr | 12 +++---- .../multiple-def-uses-in-one-fn-lifetimes.rs | 2 +- ...ltiple-def-uses-in-one-fn-lifetimes.stderr | 12 +++---- .../multiple-def-uses-in-one-fn2.rs | 2 +- .../multiple-def-uses-in-one-fn2.stderr | 12 +++---- .../not_a_defining_use.rs | 2 +- .../not_a_defining_use.stderr | 12 +++---- 37 files changed, 180 insertions(+), 187 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 03b4a6ea98354..9242c6aeb8b28 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, OpaqueTypeKey, Region, RegionVid, Ty}; +use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid}; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; @@ -43,7 +43,7 @@ pub type PoloniusOutput = Output; /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub opaque_type_values: VecMap, Ty<'tcx>>, + pub opaque_type_values: VecMap, OpaqueHiddenType<'tcx>>, pub polonius_input: Option>, pub polonius_output: Option>, pub opt_closure_req: Option>, @@ -305,7 +305,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( infcx.set_tainted_by_errors(); } - let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span); + let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values); NllOutput { regioncx, @@ -372,7 +372,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, - opaque_type_values: &VecMap, Ty<'tcx>>, + opaque_type_values: &VecMap, OpaqueHiddenType<'tcx>>, errors: &mut crate::error::BorrowckErrors<'tcx>, ) { let tcx = infcx.tcx; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index a23788028023a..f454141dc5229 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -3,7 +3,7 @@ use rustc_data_structures::vec_map::VecMap; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -53,15 +53,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, - opaque_ty_decls: VecMap, (Ty<'tcx>, Span, OpaqueTyOrigin)>, - span: Span, - ) -> VecMap, Ty<'tcx>> { + opaque_ty_decls: VecMap, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, + ) -> VecMap, OpaqueHiddenType<'tcx>> { opaque_ty_decls .into_iter() - .map(|(opaque_type_key, (concrete_type, decl_span, origin))| { + .map(|(opaque_type_key, (concrete_type, origin))| { let substs = opaque_type_key.substs; - // 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]; @@ -85,7 +82,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { None => { subst_regions.push(vid); infcx.tcx.sess.delay_span_bug( - span, + concrete_type.span, "opaque type with non-universal region substs", ); infcx.tcx.lifetimes.re_static @@ -113,17 +110,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { let remapped_type = infcx.infer_opaque_definition_from_instantiation( opaque_type_key, universal_concrete_type, - span, ); - - ( + let ty = if check_opaque_type_parameter_valid( + infcx.tcx, opaque_type_key, - if check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) { - remapped_type - } else { - infcx.tcx.ty_error() - }, - ) + origin, + concrete_type.span, + ) { + remapped_type + } else { + infcx.tcx.ty_error() + }; + (opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span }) }) .collect() } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 2d4bb272df55a..3ee0aafebfd84 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -31,8 +31,8 @@ use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::{ - self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, - ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, + self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType, + OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; @@ -225,21 +225,21 @@ pub(crate) fn type_check<'mir, 'tcx>( ), ) .unwrap(); - let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type.ty); + let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); trace!( "finalized opaque type {:?} to {:#?}", opaque_type_key, - hidden_type.kind() + hidden_type.ty.kind() ); if hidden_type.has_infer_types_or_consts() { infcx.tcx.sess.delay_span_bug( decl.hidden_type.span, - &format!("could not resolve {:#?}", hidden_type.kind()), + &format!("could not resolve {:#?}", hidden_type.ty.kind()), ); - hidden_type = infcx.tcx.ty_error(); + hidden_type.ty = infcx.tcx.ty_error(); } - (opaque_type_key, (hidden_type, decl.hidden_type.span, decl.origin)) + (opaque_type_key, (hidden_type, decl.origin)) }) .collect() }, @@ -905,7 +905,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, crate universal_region_relations: Frozen>, - crate opaque_type_values: VecMap, (Ty<'tcx>, Span, OpaqueTyOrigin)>, + crate opaque_type_values: VecMap, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, } /// A collection of region constraints that must be satisfied for the diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 38b092cfd7034..ba74aa804e336 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -8,7 +8,9 @@ use rustc_hir as hir; 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}; +use rustc_middle::ty::{ + self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor, +}; use rustc_span::Span; use std::ops::ControlFlow; @@ -35,38 +37,6 @@ pub struct OpaqueTypeDecl<'tcx> { 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: - /// - /// ```ignore (incomplete snippet) - /// type Foo = impl Baz; - /// fn bar() -> Foo { - /// // ^^^ This is the span we are looking for! - /// } - /// ``` - /// - /// 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 span: Span, - - /// The type variable that represents the value of the opaque type - /// that we require. In other words, after we compile this function, - /// we will be created a constraint like: - /// - /// Foo<'a, T> = ?C - /// - /// where `?C` is the value of this type variable. =) It may - /// naturally refer to the type and lifetime parameters in scope - /// in this function, though ultimately it should only reference - /// 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 ty: Ty<'tcx>, -} - impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn handle_opaque_type( &self, diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 55da42e98f476..fb12da0cc13f0 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,11 +1,11 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_hir::OpaqueTyOrigin; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty}; +use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty}; use rustc_span::DUMMY_SP; use crate::infer::{InferCtxtUndoLogs, UndoLog}; -use super::{OpaqueHiddenType, OpaqueTypeDecl, OpaqueTypeMap}; +use super::{OpaqueTypeDecl, OpaqueTypeMap}; #[derive(Default, Debug, Clone)] pub struct OpaqueTypeStorage<'tcx> { diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 49bef4face3ef..1b696f21cbcf4 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -4,15 +4,13 @@ use rustc_data_structures::snapshot_vec as sv; 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::{self, OpaqueTypeKey}; +use rustc_middle::ty::{self, OpaqueHiddenType, 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 ()>, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 00d1370625f9c..811b9da3740d7 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,7 +1,7 @@ //! Values computed by queries that use MIR. use crate::mir::{Body, Promoted}; -use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorGuaranteed; @@ -242,7 +242,7 @@ pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. Unlike the value in `TypeckResults`, this has /// unerased regions. - pub concrete_opaque_types: VecMap, Ty<'tcx>>, + pub concrete_opaque_types: VecMap, OpaqueHiddenType<'tcx>>, pub closure_requirements: Option>, pub used_mut_upvars: SmallVec<[Field; 8]>, pub tainted_by_errors: Option, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4208ef1a7f49f..069cf32e51589 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1081,6 +1081,38 @@ pub struct OpaqueTypeKey<'tcx> { pub substs: SubstsRef<'tcx>, } +#[derive(Copy, Clone, Debug, TypeFoldable, HashStable, TyEncodable, TyDecodable)] +pub struct OpaqueHiddenType<'tcx> { + /// The span of this particular definition of the opaque type. So + /// for example: + /// + /// ```ignore (incomplete snippet) + /// type Foo = impl Baz; + /// fn bar() -> Foo { + /// // ^^^ This is the span we are looking for! + /// } + /// ``` + /// + /// 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 span: Span, + + /// The type variable that represents the value of the opaque type + /// that we require. In other words, after we compile this function, + /// we will be created a constraint like: + /// + /// Foo<'a, T> = ?C + /// + /// where `?C` is the value of this type variable. =) It may + /// naturally refer to the type and lifetime parameters in scope + /// in this function, though ultimately it should only reference + /// 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 ty: Ty<'tcx>, +} + rustc_index::newtype_index! { /// "Universes" are used during type- and trait-checking in the /// presence of `for<..>` binders to control what sets of names are diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index c5531222fef0d..eb70de48368dc 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -5,15 +5,14 @@ use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::Span; pub trait InferCtxtExt<'tcx> { fn infer_opaque_definition_from_instantiation( &self, opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: Ty<'tcx>, - span: Span, + instantiated_ty: OpaqueHiddenType<'tcx>, ) -> Ty<'tcx>; } @@ -45,8 +44,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { fn infer_opaque_definition_from_instantiation( &self, opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: Ty<'tcx>, - span: Span, + instantiated_ty: OpaqueHiddenType<'tcx>, ) -> Ty<'tcx> { if self.is_tainted_by_errors() { return self.tcx.ty_error(); @@ -69,12 +67,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Convert the type from the function into a type valid outside // the function, by replacing invalid regions with 'static, // after producing an error for each of them. - let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new( + let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new( self.tcx, def_id, map, - instantiated_ty, - span, + instantiated_ty.ty, + instantiated_ty.span, )); debug!(?definition_ty); diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 885713cd2f36a..4e1edd17194bc 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -358,6 +358,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() + .map(|concrete| concrete.ty) .unwrap_or_else(|| { let table = tcx.typeck(owner); if let Some(_) = table.tainted_by_errors { @@ -556,7 +557,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { /// with the first type that we find, and then later types are /// checked against it (we also carry the span of that first /// type). - found: Option<(Span, Ty<'tcx>)>, + found: Option>, } impl ConstraintLocator<'_> { @@ -580,7 +581,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // ``` let tables = self.tcx.typeck(def_id); if let Some(_) = tables.tainted_by_errors { - self.found = Some((DUMMY_SP, self.tcx.ty_error())); + self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error() }); return; } if tables.concrete_opaque_types.get(&self.def_id).is_none() { @@ -590,7 +591,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for (opaque_type_key, concrete_type) in concrete_opaque_types { + for &(opaque_type_key, concrete_type) in concrete_opaque_types { if opaque_type_key.def_id != self.def_id { // Ignore constraints for other opaque types. continue; @@ -598,26 +599,22 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { debug!(?concrete_type, ?opaque_type_key.substs, "found constraint"); - // FIXME(oli-obk): trace the actual span from inference to improve errors. - let span = self.tcx.def_span(def_id); - - if let Some((prev_span, prev_ty)) = self.found { - if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() { - debug!(?span); + if let Some(prev) = self.found { + if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() { // Found different concrete types for the opaque type. let mut err = self.tcx.sess.struct_span_err( - span, + concrete_type.span, "concrete type differs from previous defining opaque type use", ); err.span_label( - span, - format!("expected `{}`, got `{}`", prev_ty, concrete_type), + concrete_type.span, + format!("expected `{}`, got `{}`", prev.ty, concrete_type.ty), ); - err.span_note(prev_span, "previous use here"); + err.span_note(prev.span, "previous use here"); err.emit(); } } else { - self.found = Some((span, *concrete_type)); + self.found = Some(concrete_type); } } } @@ -692,7 +689,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } match locator.found { - Some((_, ty)) => ty, + Some(hidden) => hidden.ty, None => { let span = tcx.def_span(def_id); let name = tcx.item_name(tcx.parent(def_id.to_def_id()).unwrap()); diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs index a6976daff0186..a79bb6474d8ba 100644 --- a/src/test/ui/impl-trait/issue-86465.rs +++ b/src/test/ui/impl-trait/issue-86465.rs @@ -3,8 +3,8 @@ type X<'a, 'b> = impl std::fmt::Debug; fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { - //~^ ERROR concrete type differs from previous defining opaque type use (a, a) + //~^ ERROR concrete type differs from previous defining opaque type use } fn main() {} diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr index 595b16aa68554..fc7bad601835b 100644 --- a/src/test/ui/impl-trait/issue-86465.stderr +++ b/src/test/ui/impl-trait/issue-86465.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/issue-86465.rs:5:1 + --> $DIR/issue-86465.rs:6:5 | -LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32` +LL | (a, a) + | ^^^^^^ expected `&'a u32`, got `&'b u32` | note: previous use here - --> $DIR/issue-86465.rs:5:1 + --> $DIR/issue-86465.rs:6:5 | -LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (a, a) + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses.rs index 272af7a5204fc..4505c4d95248c 100644 --- a/src/test/ui/type-alias-impl-trait/different_defining_uses.rs +++ b/src/test/ui/type-alias-impl-trait/different_defining_uses.rs @@ -10,6 +10,6 @@ fn foo() -> Foo { } fn bar() -> Foo { - //~^ ERROR concrete type differs from previous 42i32 + //~^ ERROR concrete type differs from previous } diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr index eaa716bc71c3e..a8b4cd7afe8a9 100644 --- a/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr +++ b/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/different_defining_uses.rs:12:1 + --> $DIR/different_defining_uses.rs:13:5 | -LL | fn bar() -> Foo { - | ^^^^^^^^^^^^^^^ expected `&'static str`, got `i32` +LL | 42i32 + | ^^^^^ expected `&'static str`, got `i32` | note: previous use here - --> $DIR/different_defining_uses.rs:8:1 + --> $DIR/different_defining_uses.rs:9:5 | -LL | fn foo() -> Foo { - | ^^^^^^^^^^^^^^^ +LL | "" + | ^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs index d0001976d657e..4f424b8c665ad 100644 --- a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs +++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs @@ -8,8 +8,8 @@ fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { } fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { - //~^ ERROR: concrete type differs from previous defining opaque type use b + //~^ ERROR: concrete type differs from previous defining opaque type use } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr index 9493a59cf1ead..0c50a84e89436 100644 --- a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr +++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/different_lifetimes_defining_uses.rs:10:1 + --> $DIR/different_lifetimes_defining_uses.rs:11:5 | -LL | fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32` +LL | b + | ^ expected `&'a u32`, got `&'b u32` | note: previous use here - --> $DIR/different_lifetimes_defining_uses.rs:6:1 + --> $DIR/different_lifetimes_defining_uses.rs:7:5 | -LL | fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | a + | ^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs index 075351307589b..8b683ad282883 100644 --- a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs +++ b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs @@ -9,6 +9,6 @@ fn my_iter(t: T) -> MyIter { } fn my_iter2(t: T) -> MyIter { - //~^ ERROR concrete type differs from previous Some(t).into_iter() + //~^ ERROR concrete type differs from previous } diff --git a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr index f8a058170e37f..47ac3346259e9 100644 --- a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_different_defining_uses.rs:11:1 + --> $DIR/generic_different_defining_uses.rs:12:5 | -LL | fn my_iter2(t: T) -> MyIter { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once`, got `std::option::IntoIter` +LL | Some(t).into_iter() + | ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once`, got `std::option::IntoIter` | note: previous use here - --> $DIR/generic_different_defining_uses.rs:7:1 + --> $DIR/generic_different_defining_uses.rs:8:5 | -LL | fn my_iter(t: T) -> MyIter { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | std::iter::once(t) + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index c95692182c278..7747626d96df6 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -13,6 +13,6 @@ fn two(t: T, _: U) -> Two { } fn three(_: T, u: U) -> Two { - //~^ ERROR concrete type differs from previous defining opaque type use u + //~^ ERROR concrete type differs from previous defining opaque type use } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index e5a70fa8ce56e..88c450704bfec 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use3.rs:15:1 + --> $DIR/generic_duplicate_param_use3.rs:16:5 | -LL | fn three(_: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U` +LL | u + | ^ expected `T`, got `U` | note: previous use here - --> $DIR/generic_duplicate_param_use3.rs:11:1 + --> $DIR/generic_duplicate_param_use3.rs:12:5 | -LL | fn two(t: T, _: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | t + | ^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use3.rs:8:18 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs index dd2f202cf5dc0..03bd00a039dfd 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -14,6 +14,6 @@ fn two(t: T, u: U) -> Two { } fn three(t: T, u: U) -> Two { - //~^ concrete type differs from previous (u, t) + //~^ concrete type differs from previous } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr index 6cc6b35668c94..d46a3ebe175c8 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use5.rs:16:1 + --> $DIR/generic_duplicate_param_use5.rs:17:5 | -LL | fn three(t: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)` +LL | (u, t) + | ^^^^^^ expected `(T, U)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use5.rs:12:1 + --> $DIR/generic_duplicate_param_use5.rs:13:5 | -LL | fn two(t: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (t, u) + | ^^^^^^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use5.rs:8:18 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index d54d3cd62e020..a8c801dc887c6 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -13,6 +13,6 @@ fn two(t: T, u: U) -> Two { } fn three(t: T, u: U) -> Two { - //~^ ERROR concrete type differs from previous (u, t) + //~^ ERROR concrete type differs from previous } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index e7520988e34bd..7e89b574b5c50 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use6.rs:15:1 + --> $DIR/generic_duplicate_param_use6.rs:16:5 | -LL | fn three(t: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)` +LL | (u, t) + | ^^^^^^ expected `(T, T)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use6.rs:11:1 + --> $DIR/generic_duplicate_param_use6.rs:12:5 | -LL | fn two(t: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (t, t) + | ^^^^^^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use6.rs:8:18 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index 4a723b64cdc4f..57527e758db1f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -12,6 +12,6 @@ fn two(t: T, _: U) -> Two { } fn three(_: T, u: U) -> Two { - //~^ concrete type differs from previous (u, 4u32) + //~^ concrete type differs from previous } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr index 44bdbdc95cc26..1a6ec3aec142b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use8.rs:14:1 + --> $DIR/generic_duplicate_param_use8.rs:15:5 | -LL | fn three(_: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` +LL | (u, 4u32) + | ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` | note: previous use here - --> $DIR/generic_duplicate_param_use8.rs:10:1 + --> $DIR/generic_duplicate_param_use8.rs:11:5 | -LL | fn two(t: T, _: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (t, 4u32) + | ^^^^^^^^^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use8.rs:7:18 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 4baf198b12fae..5878ad9269879 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -19,5 +19,5 @@ fn two(t: T, u: U) -> Two { } fn three(t: T, u: U) -> Two { - (t, u, 42) //~^ ERROR concrete type differs from previous + (t, u, 42) //~ ERROR concrete type differs from previous } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 43471f980b2af..ef7573246af4c 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use9.rs:21:1 + --> $DIR/generic_duplicate_param_use9.rs:22:5 | -LL | fn three(t: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` +LL | (t, u, 42) + | ^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` | note: previous use here - --> $DIR/generic_duplicate_param_use9.rs:17:1 + --> $DIR/generic_duplicate_param_use9.rs:18:5 | -LL | fn two(t: T, u: U) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ error[E0277]: the trait bound `A: Foo` is not satisfied --> $DIR/generic_duplicate_param_use9.rs:7:18 diff --git a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr index d82050e263ee6..4c5fd22556aae 100644 --- a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/issue-52843-closure-constrain.rs:10:16 + --> $DIR/issue-52843-closure-constrain.rs:10:31 | LL | let null = || -> Opaque { 0 }; - | ^^^^^^^^^^^^^^^^^^ expected `String`, got `i32` + | ^ expected `String`, got `i32` | note: previous use here - --> $DIR/issue-52843-closure-constrain.rs:9:5 + --> $DIR/issue-52843-closure-constrain.rs:9:30 | LL | fn _unused() -> Opaque { String::new() } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to previous error 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 index 08cb48ccf308c..b887fcf30831d 100644 --- 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 @@ -7,7 +7,7 @@ type Y = impl std::fmt::Debug; fn g() -> (Y, Y) { - (42_i64, 60) //~^ ERROR concrete type differs from previous defining opaque type use + (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 index 3f57612684e41..e3709d822ff0e 100644 --- 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 @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1 + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5 | -LL | fn g() -> (Y, Y) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, got `i32` +LL | (42_i64, 60) + | ^^^^^^^^^^^^ expected `i64`, got `i32` | note: previous use here - --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1 + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5 | -LL | fn g() -> (Y, Y) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (42_i64, 60) + | ^^^^^^^^^^^^ 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 index f39bf4aeb29ae..3f122f1060956 100644 --- 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 @@ -3,7 +3,7 @@ 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 + (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 index 49d08dda9f994..ed2e48e4aff54 100644 --- 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 @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:5:1 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 | -LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a i32`, got `&'b i32` +LL | (i, i) + | ^^^^^^ expected `&'a i32`, got `&'b i32` | note: previous use here - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:5:1 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 | -LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (i, i) + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs index 06e1990fd7f45..14510a5294e69 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs @@ -7,8 +7,8 @@ type X = impl ToString; fn f(a: A, b: B) -> (X, X) { - //~^ ERROR concrete type differs from previous defining opaque type (a.clone(), a) + //~^ ERROR concrete type differs from previous defining opaque type } fn main() { diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr index 52b0462de988c..de3f87007081a 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1 + --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5 | -LL | fn f(a: A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `B` +LL | (a.clone(), a) + | ^^^^^^^^^^^^^^ expected `A`, got `B` | note: previous use here - --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1 + --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5 | -LL | fn f(a: A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (a.clone(), a) + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index 5b332b8cb6bd8..289784ce747fd 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -22,8 +22,8 @@ impl Bar for u32 { } fn four(t: T) -> Two { - //~^ ERROR concrete type differs from previous (t, ::FOO) + //~^ ERROR concrete type differs from previous } fn is_sync() {} diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr index f946dc48a4bf9..6068cfeb51ebe 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,14 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/not_a_defining_use.rs:24:1 + --> $DIR/not_a_defining_use.rs:25:5 | -LL | fn four(t: T) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` +LL | (t, ::FOO) + | ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` | note: previous use here - --> $DIR/not_a_defining_use.rs:10:1 + --> $DIR/not_a_defining_use.rs:11:5 | -LL | fn three(t: T) -> Two { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (t, 5i8) + | ^^^^^^^^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/not_a_defining_use.rs:7:18 From 3136bfef9319a40c95efc38409ad3e57d40882dd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Feb 2022 17:39:28 +0000 Subject: [PATCH 07/26] Special case the situation where the previous span is the same as the new one --- compiler/rustc_typeck/src/collect/type_of.rs | 6 +++++- src/test/ui/impl-trait/issue-86465.stderr | 9 +++------ .../multiple-def-uses-in-one-fn-infer.stderr | 9 +++------ .../multiple-def-uses-in-one-fn-lifetimes.stderr | 9 +++------ .../multiple-def-uses-in-one-fn2.stderr | 9 +++------ 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 4e1edd17194bc..95d1b6a15f51a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -610,7 +610,11 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { concrete_type.span, format!("expected `{}`, got `{}`", prev.ty, concrete_type.ty), ); - err.span_note(prev.span, "previous use here"); + if prev.span == concrete_type.span { + err.span_label(prev.span, "this expression supplies two conflicting concrete types for the same opaque type"); + } else { + err.span_note(prev.span, "previous use here"); + } err.emit(); } } else { diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr index fc7bad601835b..90d6904ed6164 100644 --- a/src/test/ui/impl-trait/issue-86465.stderr +++ b/src/test/ui/impl-trait/issue-86465.stderr @@ -1,14 +1,11 @@ error: concrete type differs from previous defining opaque type use --> $DIR/issue-86465.rs:6:5 | -LL | (a, a) - | ^^^^^^ expected `&'a u32`, got `&'b u32` - | -note: previous use here - --> $DIR/issue-86465.rs:6:5 - | LL | (a, a) | ^^^^^^ + | | + | expected `&'a u32`, got `&'b u32` + | this expression supplies two conflicting concrete types for the same opaque type error: aborting due to previous error 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 index e3709d822ff0e..2781170091245 100644 --- 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 @@ -1,14 +1,11 @@ error: concrete type differs from previous defining opaque type use --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5 | -LL | (42_i64, 60) - | ^^^^^^^^^^^^ expected `i64`, got `i32` - | -note: previous use here - --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5 - | LL | (42_i64, 60) | ^^^^^^^^^^^^ + | | + | expected `i64`, got `i32` + | this expression supplies two conflicting concrete types for the same opaque type error: aborting due to previous error 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 index ed2e48e4aff54..81e603e2355df 100644 --- 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 @@ -1,14 +1,11 @@ error: concrete type differs from previous defining opaque type use --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 | -LL | (i, i) - | ^^^^^^ expected `&'a i32`, got `&'b i32` - | -note: previous use here - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | LL | (i, i) | ^^^^^^ + | | + | expected `&'a i32`, got `&'b i32` + | this expression supplies two conflicting concrete types for the same opaque type error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr index de3f87007081a..0f752212ac9c6 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -1,14 +1,11 @@ error: concrete type differs from previous defining opaque type use --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5 | -LL | (a.clone(), a) - | ^^^^^^^^^^^^^^ expected `A`, got `B` - | -note: previous use here - --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5 - | LL | (a.clone(), a) | ^^^^^^^^^^^^^^ + | | + | expected `A`, got `B` + | this expression supplies two conflicting concrete types for the same opaque type error: aborting due to previous error From 86e1860495403ee0154608e51fe4b4d81203e15f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 16 Feb 2022 15:48:46 +0000 Subject: [PATCH 08/26] Revert to inference variable based hidden type computation for RPIT --- .../rustc_infer/src/infer/opaque_types.rs | 2 +- compiler/rustc_typeck/src/check/check.rs | 45 ++++++++++- compiler/rustc_typeck/src/check/writeback.rs | 24 +++++- .../impl-trait-return-missing-constraint.rs | 3 +- ...mpl-trait-return-missing-constraint.stderr | 31 ++++++- .../async-await/issue-64130-4-async-move.rs | 2 +- .../issue-64130-4-async-move.stderr | 6 +- src/test/ui/async-await/issue-70818.rs | 2 +- src/test/ui/async-await/issue-70818.stderr | 8 +- .../async-await/issue-70935-complex-spans.rs | 2 +- .../issue-70935-complex-spans.stderr | 6 +- src/test/ui/conservative_impl_trait.stderr | 9 +-- .../defaults/rp_impl_trait_fail.rs | 9 ++- .../defaults/rp_impl_trait_fail.stderr | 64 ++++++++++++--- src/test/ui/generator/issue-88653.rs | 8 +- src/test/ui/generator/issue-88653.stderr | 28 +++++-- .../type-mismatch-signature-deduction.rs | 4 +- .../type-mismatch-signature-deduction.stderr | 32 +++++--- .../issue-92096.migrate.stderr | 18 ++--- .../generic-associated-types/issue-92096.rs | 4 +- .../ui/impl-trait/bound-normalization-fail.rs | 6 +- .../bound-normalization-fail.stderr | 63 +++++++++++++-- .../impl-trait/cross-return-site-inference.rs | 45 +++++++++++ .../cross-return-site-inference.stderr | 26 ++++++ src/test/ui/impl-trait/divergence.rs | 13 +++ src/test/ui/impl-trait/equality.stderr | 5 +- src/test/ui/impl-trait/issues/issue-70877.rs | 2 +- .../ui/impl-trait/issues/issue-70877.stderr | 11 ++- .../ui/impl-trait/issues/issue-88236-2.rs | 4 +- .../ui/impl-trait/issues/issue-88236-2.stderr | 15 ++-- ...t_outlive_least_region_or_bound.nll.stderr | 2 +- .../must_outlive_least_region_or_bound.rs | 3 +- .../must_outlive_least_region_or_bound.stderr | 48 ++++++++--- .../ui/impl-trait/nested_impl_trait.stderr | 8 +- ...trait-in-return-position-impl-trait.stderr | 10 +-- ...-to-type-err-cause-on-impl-trait-return.rs | 12 +-- ...type-err-cause-on-impl-trait-return.stderr | 81 +++++-------------- ...rojection-mismatch-in-impl-where-clause.rs | 2 +- ...ction-mismatch-in-impl-where-clause.stderr | 6 +- src/test/ui/impl-trait/question_mark.rs | 31 +++++-- .../type_parameters_captured.nll.stderr | 2 +- .../ui/impl-trait/type_parameters_captured.rs | 3 +- .../type_parameters_captured.stderr | 23 ++++-- src/test/ui/issues-71798.rs | 2 +- src/test/ui/issues-71798.stderr | 6 +- .../lang-item-missing-generator.stderr | 4 +- .../lifetime-elision-return-type-trait.rs | 3 +- .../lifetime-elision-return-type-trait.stderr | 19 ++++- .../impl-trait-return-trailing-semicolon.rs | 1 + ...mpl-trait-return-trailing-semicolon.stderr | 11 ++- src/test/ui/suggestions/issue-81098.rs | 2 + src/test/ui/suggestions/issue-81098.stderr | 27 ++++++- .../trait-object-nested-in-impl-trait.stderr | 52 ++++-------- .../nested-tait-inference.rs | 3 +- .../nested-tait-inference.stderr | 23 +++++- .../nested-tait-inference2.rs | 3 +- .../nested-tait-inference2.stderr | 23 +++++- 57 files changed, 640 insertions(+), 267 deletions(-) create mode 100644 src/test/ui/impl-trait/cross-return-site-inference.rs create mode 100644 src/test/ui/impl-trait/cross-return-site-inference.stderr create mode 100644 src/test/ui/impl-trait/divergence.rs diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index ba74aa804e336..ce922bca3565c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -510,7 +510,7 @@ impl UseKind { impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] - fn register_hidden_type( + pub fn register_hidden_type( &self, opaque_type_key: OpaqueTypeKey<'tcx>, cause: ObligationCause<'tcx>, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 1a5f118ea505c..ee93a8ce53592 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -3,6 +3,7 @@ use super::compare_method::check_type_bounds; use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; use super::*; +use hir::OpaqueTyOrigin; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed}; use rustc_hir as hir; @@ -12,8 +13,9 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; +use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -95,7 +97,46 @@ pub(super) fn check_fn<'a, 'tcx>( let declared_ret_ty = fn_sig.output(); - fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(declared_ret_ty))); + let ret_ty = declared_ret_ty.fold_with(&mut BottomUpFolder { + tcx: fcx.tcx, + ty_op: |ty| match *ty.kind() { + ty::Opaque(def_id, substs) => { + let span = tcx.def_span(def_id); + if let Some(origin @ OpaqueTyOrigin::FnReturn(_)) = + fcx.infcx.opaque_type_origin(def_id, span) + { + let hidden_ty = fcx.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: span, + }); + + let cause = ObligationCause::misc(span, body.value.hir_id); + match fcx.infcx.register_hidden_type( + ty::OpaqueTypeKey { def_id, substs }, + cause.clone(), + param_env, + hidden_ty, + origin, + ) { + Ok(infer_ok) => { + fcx.register_infer_ok_obligations(infer_ok); + hidden_ty + } + Err(err) => { + fcx.report_mismatched_types(&cause, ty, hidden_ty, err).emit(); + tcx.ty_error() + } + } + } else { + ty + } + } + _ => ty, + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fcx.ret_type_span = Some(decl.output.span()); let span = body.value.span; diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 35f1ddb65aa27..ecbd1e463491b 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -20,6 +20,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use std::mem; +use std::ops::ControlFlow; /////////////////////////////////////////////////////////////////////////// // Entry point @@ -503,7 +504,28 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { 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)) + let ty = self.resolve(decl.hidden_type.ty, &decl.hidden_type.span); + struct RecursionChecker { + def_id: DefId, + } + impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker { + type BreakTy = (); + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if let ty::Opaque(def_id, _) = *t.kind() { + if def_id == self.def_id { + return ControlFlow::Break(()); + } + } + t.super_visit_with(self) + } + } + if ty + .visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id }) + .is_break() + { + return; + } + Some(ty) } hir::OpaqueTyOrigin::TyAlias => None, }; diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs index 30e4c1a3c537b..ef0443034ec43 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs @@ -23,8 +23,9 @@ fn bar() -> impl Bar { } fn baz() -> impl Bar { - bar() //~^ ERROR type mismatch resolving `::Item == i32` + //~| ERROR type mismatch resolving `::Item == i32` + bar() } fn main() { diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 9523a54d954df..b7c49570ca40c 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -1,11 +1,11 @@ error[E0271]: type mismatch resolving `::Item == i32` - --> $DIR/impl-trait-return-missing-constraint.rs:26:5 + --> $DIR/impl-trait-return-missing-constraint.rs:25:13 | LL | fn bar() -> impl Bar { | -------- the expected opaque type ... -LL | bar() - | ^^^^^ expected associated type, found `i32` +LL | fn baz() -> impl Bar { + | ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32` | = note: expected associated type `::Item` found type `i32` @@ -16,6 +16,29 @@ help: consider constraining the associated type `::Item` to `i3 LL | fn bar() -> impl Bar { | ++++++++++++ -error: aborting due to previous error +error[E0271]: type mismatch resolving `::Item == i32` + --> $DIR/impl-trait-return-missing-constraint.rs:25:34 + | +LL | fn bar() -> impl Bar { + | -------- the expected opaque type +... +LL | fn baz() -> impl Bar { + | __________________________________^ +LL | | +LL | | +LL | | bar() +LL | | } + | |_^ expected associated type, found `i32` + | + = note: expected associated type `::Item` + found type `i32` + = help: consider constraining the associated type `::Item` to `i32` or calling a method that returns `::Item` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +help: consider constraining the associated type `::Item` to `i32` + | +LL | fn bar() -> impl Bar { + | ++++++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/async-await/issue-64130-4-async-move.rs b/src/test/ui/async-await/issue-64130-4-async-move.rs index 7cb02e5cf383d..2538f34351e5a 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.rs +++ b/src/test/ui/async-await/issue-64130-4-async-move.rs @@ -13,9 +13,9 @@ impl Client { 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; diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 3a84907e0c04b..d631e6dc7f7e9 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,8 +1,8 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-4-async-move.rs:17:5 + --> $DIR/issue-64130-4-async-move.rs:15:17 | -LL | async move { - | ^^^^^^^^^^ future created by async block is not `Send` +LL | pub fn foo() -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ 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 diff --git a/src/test/ui/async-await/issue-70818.rs b/src/test/ui/async-await/issue-70818.rs index 631389e10f316..019c56eb2fa3e 100644 --- a/src/test/ui/async-await/issue-70818.rs +++ b/src/test/ui/async-await/issue-70818.rs @@ -2,8 +2,8 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { - async { (ty, ty1) } //~^ Error future cannot be sent between threads safely + async { (ty, ty1) } } fn main() {} diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index cb50c70f99847..20109d4d1166a 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -1,11 +1,11 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:5:5 + --> $DIR/issue-70818.rs:4:38 | -LL | async { (ty, ty1) } - | ^^^^^ future created by async block is not `Send` +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | note: captured value is not `Send` - --> $DIR/issue-70818.rs:5:18 + --> $DIR/issue-70818.rs:6:18 | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs index 494561229511e..2965a7e0654a4 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.rs +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -8,8 +8,8 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { } fn foo(tx: std::sync::mpsc::Sender) -> 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; diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index ad61f21741bb5..db3099381196b 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -1,8 +1,8 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70935-complex-spans.rs:11:5 + --> $DIR/issue-70935-complex-spans.rs:10:45 | -LL | async move { - | ^^^^^^^^^^ future created by async block is not `Send` +LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `Sender` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr index 9dc486980aaca..63a4df242f85f 100644 --- a/src/test/ui/conservative_impl_trait.stderr +++ b/src/test/ui/conservative_impl_trait.stderr @@ -1,11 +1,8 @@ error[E0277]: `()` is not an iterator - --> $DIR/conservative_impl_trait.rs:3:60 + --> $DIR/conservative_impl_trait.rs:3:33 | -LL | fn will_ice(something: &u32) -> impl Iterator { - | ____________________________________________________________^ -LL | | -LL | | } - | |_^ `()` is not an iterator +LL | fn will_ice(something: &u32) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs index b3bd88ad7d5d8..24031aa1e61f3 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -4,8 +4,9 @@ trait Trait {} impl Trait for Uwu {} fn rawr() -> impl Trait { - Uwu::<10, 12> //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied + //~| error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied + Uwu::<10, 12> } trait Traitor { } @@ -15,13 +16,15 @@ impl Traitor<1, 2> for u64 {} fn uwu() -> impl Traitor { - 1_u32 //~^ error: the trait bound `u32: Traitor` is not satisfied + //~| error: the trait bound `u32: Traitor` is not satisfied + 1_u32 } fn owo() -> impl Traitor { - 1_u64 //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied + //~| error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied + 1_u64 } fn main() { diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 1cfaf83c5a69e..81cfcb3560661 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -1,32 +1,76 @@ error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:7:5 + --> $DIR/rp_impl_trait_fail.rs:6:14 | -LL | Uwu::<10, 12> - | ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` +LL | fn rawr() -> impl Trait { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | = help: the following implementations were found: as Trait> +error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:6:25 + | +LL | fn rawr() -> impl Trait { + | _________________________^ +LL | | +LL | | +LL | | Uwu::<10, 12> +LL | | } + | |_^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` + | + = help: the following implementations were found: + as Trait> + +error[E0277]: the trait bound `u32: Traitor` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:18:26 + | +LL | fn uwu() -> impl Traitor { + | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` + | + = help: the following implementations were found: + > + > + error[E0277]: the trait bound `u32: Traitor` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:18:5 + --> $DIR/rp_impl_trait_fail.rs:18:42 | -LL | 1_u32 - | ^^^^^ the trait `Traitor` is not implemented for `u32` +LL | fn uwu() -> impl Traitor { + | __________________________________________^ +LL | | +LL | | +LL | | 1_u32 +LL | | } + | |_^ the trait `Traitor` is not implemented for `u32` | = help: the following implementations were found: > > error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:23:5 + --> $DIR/rp_impl_trait_fail.rs:24:13 + | +LL | fn owo() -> impl Traitor { + | ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` + | + = help: the following implementations were found: + > + > + +error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:24:26 | -LL | 1_u64 - | ^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` +LL | fn owo() -> impl Traitor { + | __________________________^ +LL | | +LL | | +LL | | 1_u64 +LL | | } + | |_^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | = help: the following implementations were found: > > -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/issue-88653.rs b/src/test/ui/generator/issue-88653.rs index c4905995a860a..f27956e45950a 100644 --- a/src/test/ui/generator/issue-88653.rs +++ b/src/test/ui/generator/issue-88653.rs @@ -6,10 +6,14 @@ use std::ops::Generator; fn foo(bar: bool) -> impl Generator<(bool,)> { - |bar| { - //~^ NOTE: found signature of `fn(bool) -> _` + //~^ ERROR: type mismatch in generator arguments [E0631] //~| ERROR: type mismatch in generator arguments [E0631] //~| NOTE: expected signature of `fn((bool,)) -> _` + //~| NOTE: expected signature of `fn((bool,)) -> _` + //~| NOTE: in this expansion of desugaring of `impl Trait` + |bar| { + //~^ NOTE: found signature of `fn(bool) -> _` + //~| NOTE: found signature of `fn(bool) -> _` if bar { yield bar; } diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr index eaa90a8e60a23..25357411ce189 100644 --- a/src/test/ui/generator/issue-88653.stderr +++ b/src/test/ui/generator/issue-88653.stderr @@ -1,12 +1,28 @@ error[E0631]: type mismatch in generator arguments - --> $DIR/issue-88653.rs:9:5 + --> $DIR/issue-88653.rs:8:22 | +LL | fn foo(bar: bool) -> impl Generator<(bool,)> { + | ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _` +... LL | |bar| { - | ^^^^^ - | | - | expected signature of `fn((bool,)) -> _` - | found signature of `fn(bool) -> _` + | ----- found signature of `fn(bool) -> _` -error: aborting due to previous error +error[E0631]: type mismatch in generator arguments + --> $DIR/issue-88653.rs:8:46 + | +LL | fn foo(bar: bool) -> impl Generator<(bool,)> { + | ______________________________________________^ +LL | | +LL | | +LL | | +... | +LL | | |bar| { + | | ----- found signature of `fn(bool) -> _` +... | +LL | | } +LL | | } + | |_^ expected signature of `fn((bool,)) -> _` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs index d1b16b6e10da0..77b830783c32a 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.rs +++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs @@ -3,7 +3,9 @@ use std::ops::Generator; fn foo() -> impl Generator { - || { //~ ERROR type mismatch + //~^ ERROR type mismatch + //~| ERROR type mismatch + || { if false { return Ok(6); } diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 3e78e5b53ba1f..6369e7ec4c784 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch-signature-deduction.rs:13:9 + --> $DIR/type-mismatch-signature-deduction.rs:15:9 | LL | 5 | ^ expected enum `Result`, found integer @@ -7,27 +7,37 @@ LL | 5 = note: expected type `Result<{integer}, _>` found type `{integer}` note: return type inferred to be `Result<{integer}, _>` here - --> $DIR/type-mismatch-signature-deduction.rs:8:20 + --> $DIR/type-mismatch-signature-deduction.rs:10:20 | 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:6:5 +error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:8:5: 16:6] as Generator>::Return == i32` + --> $DIR/type-mismatch-signature-deduction.rs:5:13 | -LL | / || { -LL | | if false { -LL | | return Ok(6); -LL | | } +LL | fn foo() -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32` + | + = note: expected enum `Result<{integer}, _>` + found type `i32` + +error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:8:5: 16:6] as Generator>::Return == i32` + --> $DIR/type-mismatch-signature-deduction.rs:5:42 + | +LL | fn foo() -> impl Generator { + | __________________________________________^ +LL | | +LL | | +LL | | || { ... | -LL | | 5 LL | | } - | |_____^ expected enum `Result`, found `i32` +LL | | } + | |_^ expected enum `Result`, found `i32` | = note: expected enum `Result<{integer}, _>` found type `i32` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0271, E0308. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr index f8c89829e1646..72ade5774d749 100644 --- a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr +++ b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr @@ -1,20 +1,18 @@ error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:24:5 + --> $DIR/issue-92096.rs:20:33 | LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send - | - 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 + | - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `C: 'a` error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:24:5 + --> $DIR/issue-92096.rs:20:33 | LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send - | - 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 + | - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `C: 'a` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-92096.rs b/src/test/ui/generic-associated-types/issue-92096.rs index 2bc1af5506ffd..066132a5d98bb 100644 --- a/src/test/ui/generic-associated-types/issue-92096.rs +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -18,12 +18,12 @@ trait Client { } fn call_connect(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() {} diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index 20ddad0547ef2..9f962fa9bbaf5 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -23,8 +23,9 @@ mod impl_trait { /// `T::Assoc` can't be normalized any further here. fn foo_fail() -> impl FooLike { - Foo(()) //~^ ERROR: type mismatch + //~| ERROR: type mismatch + Foo(()) } } @@ -40,8 +41,9 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + //~| ERROR: type mismatch + //~| ERROR: type mismatch Foo(()) - //~^ ERROR: type mismatch } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index 01fb853e1d1f7..0344f416eb7ff 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -1,8 +1,31 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` - --> $DIR/bound-normalization-fail.rs:26:9 + --> $DIR/bound-normalization-fail.rs:25:32 | -LL | Foo(()) - | ^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` +LL | fn foo_fail() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` + | +note: expected this to be `()` + --> $DIR/bound-normalization-fail.rs:14:19 + | +LL | type Output = T; + | ^ + = note: expected unit type `()` + found associated type `::Assoc` +help: consider constraining the associated type `::Assoc` to `()` + | +LL | fn foo_fail>() -> impl FooLike { + | ++++++++++++ + +error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` + --> $DIR/bound-normalization-fail.rs:25:64 + | +LL | fn foo_fail() -> impl FooLike { + | ________________________________________________________________^ +LL | | +LL | | +LL | | Foo(()) +LL | | } + | |_____^ type mismatch resolving ` as FooLike>::Output == ::Assoc` | note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 @@ -17,16 +40,40 @@ LL | fn foo_fail>() -> impl FooLike | ++++++++++++ error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:41:41 + --> $DIR/bound-normalization-fail.rs:42:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` - --> $DIR/bound-normalization-fail.rs:43:9 + --> $DIR/bound-normalization-fail.rs:42:41 + | +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` + | +note: expected this to be `()` + --> $DIR/bound-normalization-fail.rs:14:19 + | +LL | type Output = T; + | ^ + = note: expected unit type `()` + found associated type `>::Assoc` +help: consider constraining the associated type `>::Assoc` to `()` + | +LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { + | ++++++++++++ + +error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` + --> $DIR/bound-normalization-fail.rs:42:73 | -LL | Foo(()) - | ^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | _________________________________________________________________________^ +LL | | +LL | | +LL | | +LL | | Foo(()) +LL | | } + | |_____^ type mismatch resolving ` as FooLike>::Output == >::Assoc` | note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 @@ -40,7 +87,7 @@ help: consider constraining the associated type ` LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { | ++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0271, E0760. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs new file mode 100644 index 0000000000000..ceb8414650f1e --- /dev/null +++ b/src/test/ui/impl-trait/cross-return-site-inference.rs @@ -0,0 +1,45 @@ +// edition:2021 + +fn foo(b: bool) -> impl std::fmt::Debug { + if b { + return vec![42] + } + [].into_iter().collect() +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return [].into_iter().collect() + } + vec![42] +} + +fn bak(b: bool) -> impl std::fmt::Debug { + if b { + return std::iter::empty().collect() + } + vec![42] +} + +fn baa(b: bool) -> impl std::fmt::Debug { + if b { + return [42].into_iter().collect() + } + vec![] +} + +fn muh() -> Result<(), impl std::fmt::Debug> { + Err("whoops")?; //~ ERROR `?` couldn't convert the error to `impl Debug` + Ok(()) +} + +fn muh2() -> Result<(), impl std::fmt::Debug> { + return Err(From::from("foo")); //~ ERROR the trait bound `impl Debug: From<&str>` is not satisfied + Ok(()) +} + +fn muh3() -> Result<(), impl std::fmt::Debug> { + Err(From::from("foo")) //~ ERROR the trait bound `impl Debug: From<&str>` is not satisfied +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr new file mode 100644 index 0000000000000..06afb938c5fad --- /dev/null +++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr @@ -0,0 +1,26 @@ +error[E0277]: `?` couldn't convert the error to `impl Debug` + --> $DIR/cross-return-site-inference.rs:32:18 + | +LL | fn muh() -> Result<(), impl std::fmt::Debug> { + | -------------------------------- expected `impl Debug` because of this +LL | Err("whoops")?; + | ^ the trait `From<&str>` is not implemented for `impl Debug` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required because of the requirements on the impl of `FromResidual>` for `Result<(), impl Debug>` + +error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied + --> $DIR/cross-return-site-inference.rs:37:16 + | +LL | return Err(From::from("foo")); + | ^^^^^^^^^^ the trait `From<&str>` is not implemented for `impl Debug` + +error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied + --> $DIR/cross-return-site-inference.rs:42:9 + | +LL | Err(From::from("foo")) + | ^^^^^^^^^^ the trait `From<&str>` is not implemented for `impl Debug` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/divergence.rs b/src/test/ui/impl-trait/divergence.rs new file mode 100644 index 0000000000000..211f7972dbca8 --- /dev/null +++ b/src/test/ui/impl-trait/divergence.rs @@ -0,0 +1,13 @@ +// check-pass + +fn foo() -> impl MyTrait { + panic!(); + MyStruct +} + +struct MyStruct; +trait MyTrait {} + +impl MyTrait for MyStruct {} + +fn main() {} diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 185a3f53f6557..804ccbcc6c0ab 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -12,13 +12,10 @@ error[E0308]: mismatched types --> $DIR/equality.rs:15:5 | LL | fn two(x: bool) -> impl Foo { - | -------- the expected opaque type + | -------- expected `_` because of return type ... LL | 0_u32 | ^^^^^ expected `i32`, found `u32` - | - = note: expected opaque type `impl Foo` - found type `u32` error[E0277]: cannot add `impl Foo` to `u32` --> $DIR/equality.rs:24:11 diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs index 1a86fa00ed1a0..9cbe33aef5bb9 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -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"); //~ ERROR opaque type's hidden type cannot be another opaque type + return func(&"oof"); //~^^^ ERROR opaque type's hidden type cannot be another opaque type } fn main() { diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr index 7cbd58bdabf2f..2610a19818621 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -13,10 +13,15 @@ LL | Some(Box::new(quux)) found enum `Option fn(&'r (dyn ToString + 'r)) -> FooRet {quux}>>` error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/issue-70877.rs:31:12 + --> $DIR/issue-70877.rs:28:34 | -LL | return func(&"oof"); - | ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope +LL | fn oof() -> impl std::fmt::Debug { + | __________________________________^ +LL | | let mut bar = ham(); +LL | | let func = bar.next().unwrap(); +LL | | return func(&"oof"); +LL | | } + | |_^ 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 diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs index f89ab7fbd364b..af26a1f54c46d 100644 --- a/src/test/ui/impl-trait/issues/issue-88236-2.rs +++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs @@ -14,10 +14,10 @@ impl<'a> Hrtb<'a> for &'a () { 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 + &() //~^ 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 + 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 index 95c4a52803698..45fadcab3f2e1 100644 --- a/src/test/ui/impl-trait/issues/issue-88236-2.stderr +++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr @@ -1,17 +1,20 @@ error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:17:5 + --> $DIR/issue-88236-2.rs:16:38 | -LL | &() - | ^^^ implementation of `Hrtb` is not general enough +LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 + --> $DIR/issue-88236-2.rs:19:82 | -LL | x - | ^ implementation of `Hrtb` is not general enough +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | __________________________________________________________________________________^ +LL | | x +LL | | } + | |_^ 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 `&()` diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index eb38f84d4afec..9589b69491e25 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -80,7 +80,7 @@ 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:39:5 + --> $DIR/must_outlive_least_region_or_bound.rs:41:5 | LL | x | ^ diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 02ea0255912ab..baa42da64468d 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -36,8 +36,9 @@ fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { } fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - x //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough + x } fn main() {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 77ba0bf908763..1272adb35e98c 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -28,10 +28,15 @@ 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 and required to live as long as `'static` here + | ---- ^ ...is used 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 } @@ -45,10 +50,15 @@ 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 and required to live as long as `'static` here + | ------- ^ ...is used 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 } @@ -59,10 +69,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:41 + --> $DIR/must_outlive_least_region_or_bound.rs:13:24 | 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` @@ -85,8 +95,13 @@ 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 and required to live as long as `'static` here + | ------- 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 + | +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 } @@ -110,12 +125,25 @@ 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:39:5 + --> $DIR/must_outlive_least_region_or_bound.rs:38:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | -- help: consider adding an explicit lifetime bound...: `T: 'static +` -LL | x - | ^ ...so that the type `T` will meet its required lifetime bounds + | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `T: 'static +` + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:38:72 + | +LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { + | _________________________________--_____________________________________^ + | | | + | | help: consider adding an explicit lifetime bound...: `T: 'static +` +LL | | +LL | | +LL | | x +LL | | } + | |_^ ...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 @@ -203,7 +231,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } | ~~~~~~~~~~~~ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0310, E0621, E0700, E0759. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index a10e4ec318230..26b48c7cdf718 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -47,18 +47,18 @@ LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { | ^^^^^^^^^^^^^^ error[E0277]: the trait bound `impl Debug: From>` is not satisfied - --> $DIR/nested_impl_trait.rs:5:70 + --> $DIR/nested_impl_trait.rs:5:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` | = note: required because of the requirements on the impl of `Into` for `impl Into` error[E0277]: the trait bound `impl Debug: From>` is not satisfied - --> $DIR/nested_impl_trait.rs:18:58 + --> $DIR/nested_impl_trait.rs:18:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` | = note: required because of the requirements on the impl of `Into` for `impl Into` diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr index b2f7166f0ae3a..5ca01a593761c 100644 --- a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr +++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr @@ -2,25 +2,19 @@ error[E0308]: mismatched types --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5 | LL | fn can() -> impl NotObjectSafe { - | ------------------ the expected opaque type + | ------------------ expected `_` because of return type ... LL | B | ^ expected struct `A`, found struct `B` - | - = 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 { - | --------------- the expected opaque type + | --------------- expected `_` because of return type ... LL | B | ^ expected struct `A`, found struct `B` - | - = note: expected opaque type `impl ObjectSafe` - found struct `B` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs index 9f9a6c784e638..fa7664a83eee0 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs @@ -14,10 +14,10 @@ fn bar() -> impl std::fmt::Display { } fn baz() -> impl std::fmt::Display { - if false { //~ ERROR mismatched types + if false { return 0i32; } else { - 1u32 + 1u32 //~ ERROR mismatched types } } @@ -30,9 +30,9 @@ fn qux() -> impl std::fmt::Display { } fn bat() -> impl std::fmt::Display { - match 13 { //~ ERROR mismatched types + match 13 { 0 => return 0i32, - _ => 1u32, + _ => 1u32, //~ ERROR mismatched types } } @@ -45,12 +45,12 @@ fn can() -> impl std::fmt::Display { } fn cat() -> impl std::fmt::Display { - match 13 { //~ ERROR mismatched types + match 13 { 0 => { return 0i32; } _ => { - 1u32 + 1u32 //~ ERROR mismatched types } } } diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index db0d446e559a3..0c595f441ba8e 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -2,40 +2,28 @@ error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5 | LL | fn foo() -> impl std::fmt::Display { - | ---------------------- the expected opaque type + | ---------------------- expected `_` because of return type ... LL | 1u32 | ^^^^ 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:12:16 | LL | fn bar() -> impl std::fmt::Display { - | ---------------------- the expected opaque type + | ---------------------- expected `_` because of return type ... LL | return 1u32; | ^^^^ 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:17:5 - | -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` + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9 | - = note: expected opaque type `impl std::fmt::Display` - found type `u32` +LL | fn baz() -> impl std::fmt::Display { + | ---------------------- expected `_` because of return type +... +LL | 1u32 + | ^^^^ expected `i32`, found `u32` error[E0308]: `if` and `else` have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9 @@ -48,63 +36,36 @@ 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 qux() -> Box { - | ~~~~~~~ + -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[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:33:5 - | -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` + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14 | - = note: expected opaque type `impl std::fmt::Display` - found type `u32` +LL | fn bat() -> impl std::fmt::Display { + | ---------------------- expected `_` because of return type +... +LL | _ => 1u32, + | ^^^^ expected `i32`, found `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 { - | ---------------------- the expected opaque type + | ---------------------- expected `_` because of return type LL | / match 13 { LL | | 0 => return 0i32, LL | | 1 => 1u32, LL | | _ => 2u32, 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:48:5 + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13 | -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` +LL | fn cat() -> impl std::fmt::Display { + | ---------------------- expected `_` because of return type +... +LL | 1u32 + | ^^^^ expected `i32`, found `u32` error[E0308]: `match` arms have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14 diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs index 2e7cb21592cb0..b4fd6b3e74364 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs @@ -11,8 +11,8 @@ pub trait Test {} impl Test for T where T: Super {} fn test() -> impl Test { - () //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` + () } fn main() { diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index 5ef1e9abef631..ade0dfa1bb3b3 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` - --> $DIR/projection-mismatch-in-impl-where-clause.rs:14:5 + --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14 | -LL | () - | ^^ type mismatch resolving `<() as Super>::Assoc == ()` +LL | fn test() -> impl Test { + | ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()` | note: expected this to be `u8` --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18 diff --git a/src/test/ui/impl-trait/question_mark.rs b/src/test/ui/impl-trait/question_mark.rs index 211f7972dbca8..495bf5c1d64f2 100644 --- a/src/test/ui/impl-trait/question_mark.rs +++ b/src/test/ui/impl-trait/question_mark.rs @@ -1,13 +1,30 @@ // check-pass -fn foo() -> impl MyTrait { - panic!(); - MyStruct +use std::fmt::Debug; + +#[derive(Debug)] +pub struct Target; + +#[derive(Debug)] +pub struct Source; +impl From for Target { + fn from(_: Source) -> Self { + Self + } +} + +fn maybe_source() -> Result<(), Source> { + todo!() } -struct MyStruct; -trait MyTrait {} +pub fn typaram() -> Result<(), impl Debug> { + maybe_source()?; + Ok::<_, Target>(()) +} -impl MyTrait for MyStruct {} +pub fn direct() -> Result<(), impl Debug> { + maybe_source()?; + Err(Target) +} -fn main() {} +fn main() {} \ No newline at end of file diff --git a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr index e0b77544d439d..b1175a5952e59 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/type_parameters_captured.rs:8:5 + --> $DIR/type_parameters_captured.rs:10:5 | LL | x | ^ diff --git a/src/test/ui/impl-trait/type_parameters_captured.rs b/src/test/ui/impl-trait/type_parameters_captured.rs index 81ee7d3f8a561..bb9cab742a58f 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.rs +++ b/src/test/ui/impl-trait/type_parameters_captured.rs @@ -5,8 +5,9 @@ impl Any for T {} // Check that type parameters are captured and not considered 'static fn foo(x: T) -> impl Any + 'static { - x //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough + x } fn main() {} diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr index c0de4f4b4a0c5..c4ca34a6ed39b 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.stderr @@ -1,11 +1,24 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/type_parameters_captured.rs:8:5 + --> $DIR/type_parameters_captured.rs:7:20 | LL | fn foo(x: T) -> impl Any + 'static { - | - help: consider adding an explicit lifetime bound...: `T: 'static` -LL | x - | ^ ...so that the type `T` will meet its required lifetime bounds + | - ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `T: 'static` -error: aborting due to previous error +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/type_parameters_captured.rs:7:39 + | +LL | fn foo(x: T) -> impl Any + 'static { + | ________-______________________________^ + | | | + | | help: consider adding an explicit lifetime bound...: `T: 'static` +LL | | +LL | | +LL | | x +LL | | } + | |_^ ...so that the type `T` will meet its required lifetime bounds + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs index 89e07037afd42..14b6c0f35812f 100644 --- a/src/test/ui/issues-71798.rs +++ b/src/test/ui/issues-71798.rs @@ -1,6 +1,6 @@ fn test_ref(x: &u32) -> impl std::future::Future + '_ { - *x //~^ ERROR `u32` is not a future + *x } fn main() { diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index 1efa886436e0d..ab72c3e41af97 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -5,10 +5,10 @@ LL | let _ = test_ref & u; | ^ not found in this scope error[E0277]: `u32` is not a future - --> $DIR/issues-71798.rs:2:5 + --> $DIR/issues-71798.rs:1:25 | -LL | *x - | ^^ `u32` is not a future +LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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 diff --git a/src/test/ui/lang-items/lang-item-missing-generator.stderr b/src/test/ui/lang-items/lang-item-missing-generator.stderr index e5f26822f2670..fa13bf0b12719 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-items/lang-item-missing-generator.stderr @@ -1,8 +1,8 @@ error: requires `generator` lang_item - --> $DIR/lang-item-missing-generator.rs:15:22 + --> $DIR/lang-item-missing-generator.rs:15:17 | LL | pub fn abc() -> impl FnOnce(f32) { - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index fd49b4842a74f..133679f30f8fb 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -6,8 +6,9 @@ trait Future { use std::error::Error; fn foo() -> impl Future> { - Ok(()) //~^ ERROR not satisfied + //~| ERROR not satisfied + Ok(()) } fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 7f8384d7eca8d..a3badd7b25add 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -1,9 +1,20 @@ error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied - --> $DIR/lifetime-elision-return-type-trait.rs:9:5 + --> $DIR/lifetime-elision-return-type-trait.rs:8:13 | -LL | Ok(()) - | ^^^^^^ the trait `Future` is not implemented for `Result<(), _>` +LL | fn foo() -> impl Future> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>` -error: aborting due to previous error +error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied + --> $DIR/lifetime-elision-return-type-trait.rs:8:56 + | +LL | fn foo() -> impl Future> { + | ________________________________________________________^ +LL | | +LL | | +LL | | Ok(()) +LL | | } + | |_^ the trait `Future` is not implemented for `Result<(), _>` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs index e72a2d8ccc629..cad7d76c6ab5f 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs @@ -2,6 +2,7 @@ trait Bar {} impl Bar for u8 {} fn foo() -> impl Bar { 5; //~^ ERROR the trait bound `(): Bar` is not satisfied + //~| ERROR the trait bound `(): Bar` is not satisfied } fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index 07c1d8bccbaba..ba6967e78e163 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -1,12 +1,21 @@ +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/impl-trait-return-trailing-semicolon.rs:3:13 + | +LL | fn foo() -> impl Bar { + | ^^^^^^^^ the trait `Bar` is not implemented for `()` +LL | 5; + | - consider removing this semicolon + error[E0277]: the trait bound `(): Bar` is not satisfied --> $DIR/impl-trait-return-trailing-semicolon.rs:3:22 | LL | fn foo() -> impl Bar { | ______________________^ LL | | 5; +LL | | LL | | } | |_^ the trait `Bar` is not implemented for `()` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-81098.rs b/src/test/ui/suggestions/issue-81098.rs index a601b5866f43e..7ca7380a7befd 100644 --- a/src/test/ui/suggestions/issue-81098.rs +++ b/src/test/ui/suggestions/issue-81098.rs @@ -1,12 +1,14 @@ // Don't suggest removing a semicolon if the last statement isn't an expression with semicolon // (#81098) fn wat() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display` + //~^ ERROR: `()` doesn't implement `std::fmt::Display` fn why() {} } // Do it if the last statement is an expression with semicolon // (#54771) fn ok() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display` + //~^ ERROR: `()` doesn't implement `std::fmt::Display` 1; } diff --git a/src/test/ui/suggestions/issue-81098.stderr b/src/test/ui/suggestions/issue-81098.stderr index f13e653cb06bd..d62526442e9af 100644 --- a/src/test/ui/suggestions/issue-81098.stderr +++ b/src/test/ui/suggestions/issue-81098.stderr @@ -1,8 +1,18 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/issue-81098.rs:3:13 + | +LL | fn wat() -> impl core::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` 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:3:37 | LL | fn wat() -> impl core::fmt::Display { | _____________________________________^ +LL | | LL | | fn why() {} LL | | } | |_^ `()` cannot be formatted with the default formatter @@ -11,10 +21,23 @@ LL | | } = 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:36 + --> $DIR/issue-81098.rs:10:12 + | +LL | fn ok() -> impl core::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter +LL | +LL | 1; + | - consider removing this semicolon + | + = 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:10:36 | LL | fn ok() -> impl core::fmt::Display { | ____________________________________^ +LL | | LL | | 1; LL | | } | |_^ `()` cannot be formatted with the default formatter @@ -22,6 +45,6 @@ LL | | } = 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: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index c7f1215c8cc44..a5b50634c71ea 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -7,18 +7,13 @@ LL | fn iter(&self) -> impl Iterator> { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used and required to live as long as `'static` here + | ...is used here... | -note: `'static` lifetime requirement introduced by the return type +note: ...and is required to live as long as `'static` here --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 | -LL | fn iter(&self) -> impl Iterator> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type -LL | / Iter { -LL | | current: None, -LL | | remaining: self.0.iter(), -LL | | } - | |_________- because of this returned expression +LL | fn iter(&self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + '_ { @@ -37,18 +32,13 @@ LL | fn iter(&self) -> impl Iterator> + '_ { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used and required to live as long as `'static` here + | ...is used here... | -note: `'static` lifetime requirement introduced by the return type +note: ...and is required to live as long as `'static` here --> $DIR/trait-object-nested-in-impl-trait.rs:38:23 | -LL | fn iter(&self) -> impl Iterator> + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type -LL | / Iter { -LL | | current: None, -LL | | remaining: self.0.iter(), -LL | | } - | |_________- because of this returned expression +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + '_ { @@ -63,18 +53,13 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used and required to live as long as `'static` here + | ...is used here... | -note: `'static` lifetime requirement introduced by the return type +note: ...and is required to live as long as `'static` here --> $DIR/trait-object-nested-in-impl-trait.rs:49:30 | -LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type -LL | / Iter { -LL | | current: None, -LL | | remaining: self.0.iter(), -LL | | } - | |_________- because of this returned expression +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + 'a { @@ -89,18 +74,13 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used and required to live as long as `'static` here + | ...is used here... | -note: `'static` lifetime requirement introduced by the return type +note: ...and is required to live as long as `'static` here --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 | -LL | fn iter<'a>(&'a self) -> impl Iterator> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type -LL | / Iter { -LL | | current: None, -LL | | remaining: self.0.iter(), -LL | | } - | |_________- because of this returned expression +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> + 'a { diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs index 784a6c75886d4..314e5362a8f2c 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -10,9 +10,10 @@ trait Foo { } impl Foo<()> for () { } fn foo() -> impl Foo { + //~^ ERROR: the trait bound `(): Foo` is not satisfied + //~| ERROR: the trait bound `(): Foo` is not satisfied // FIXME(type-alias-impl-trait): We could probably make this work. () - //~^ ERROR: the trait bound `(): Foo` 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 index 9472cac63554e..eb72e88769100 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -1,12 +1,27 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference.rs:14:5 + --> $DIR/nested-tait-inference.rs:12:13 | -LL | () - | ^^ the trait `Foo` is not implemented for `()` +LL | fn foo() -> impl Foo { + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | = help: the following implementations were found: <() as Foo<()>> -error: aborting due to previous error +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference.rs:12:28 + | +LL | fn foo() -> impl Foo { + | ____________________________^ +LL | | +LL | | +LL | | // FIXME(type-alias-impl-trait): We could probably make this work. +LL | | () +LL | | } + | |_^ the trait `Foo` is not implemented for `()` + | + = help: the following implementations were found: + <() as Foo<()>> + +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/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs index 00bd44c493c83..4dc30d9257bed 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -11,8 +11,9 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - () //~^ ERROR: the trait bound `(): Foo` is not satisfied + //~| ERROR: the trait bound `(): Foo` is not satisfied + () } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index ec1b4642d0822..1372a018667c2 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -1,13 +1,28 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:14:5 + --> $DIR/nested-tait-inference2.rs:13:13 | -LL | () - | ^^ the trait `Foo` is not implemented for `()` +LL | fn foo() -> impl Foo { + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | = help: the following implementations were found: <() as Foo<()>> <() as Foo> -error: aborting due to previous error +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference2.rs:13:28 + | +LL | fn foo() -> impl Foo { + | ____________________________^ +LL | | +LL | | +LL | | () +LL | | } + | |_^ the trait `Foo` is not implemented for `()` + | + = help: the following implementations were found: + <() as Foo<()>> + <() as Foo> + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. From 1163aa7e72bc69b76cb68177fa4f83a66a6034cc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 13:28:06 +0000 Subject: [PATCH 09/26] Remove opaque type obligation and just register opaque types as they are encountered. This also registers obligations for the hidden type immediately. --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- .../src/type_check/relate_tys.rs | 21 ++-- .../src/infer/canonical/query_response.rs | 23 ++-- compiler/rustc_infer/src/infer/equate.rs | 18 +-- compiler/rustc_infer/src/infer/lattice.rs | 12 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 9 +- .../rustc_infer/src/infer/opaque_types.rs | 112 ++++++------------ .../rustc_infer/src/infer/outlives/mod.rs | 1 - compiler/rustc_infer/src/infer/sub.rs | 12 +- compiler/rustc_infer/src/traits/util.rs | 3 - compiler/rustc_lint/src/builtin.rs | 1 - compiler/rustc_middle/src/ty/flags.rs | 4 - compiler/rustc_middle/src/ty/mod.rs | 7 -- compiler/rustc_middle/src/ty/print/pretty.rs | 3 - .../rustc_middle/src/ty/structural_impls.rs | 6 - .../rustc_trait_selection/src/opaque_types.rs | 1 - .../src/traits/auto_trait.rs | 1 - .../src/traits/error_reporting/mod.rs | 4 - .../src/traits/fulfill.rs | 17 --- .../src/traits/object_safety.rs | 2 - .../src/traits/select/mod.rs | 13 -- .../rustc_trait_selection/src/traits/wf.rs | 4 - compiler/rustc_traits/src/chalk/lowering.rs | 4 - .../src/implied_outlives_bounds.rs | 1 - .../src/normalize_erasing_regions.rs | 1 - compiler/rustc_typeck/src/check/closure.rs | 13 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 1 - .../rustc_typeck/src/check/method/probe.rs | 1 - .../src/impl_wf_check/min_specialization.rs | 1 - .../rustc_typeck/src/outlives/explicit.rs | 1 - src/librustdoc/clean/mod.rs | 1 - .../ui/async-await/suggest-missing-await.rs | 1 + .../async-await/suggest-missing-await.stderr | 27 ++--- src/test/ui/cast/casts-differing-anon.rs | 2 +- src/test/ui/cast/casts-differing-anon.stderr | 16 +-- src/test/ui/conservative_impl_trait.rs | 1 + src/test/ui/conservative_impl_trait.stderr | 14 ++- src/test/ui/impl-trait/autoderef.rs | 19 +++ .../impl-trait/cross-return-site-inference.rs | 2 +- src/test/ui/impl-trait/equality2.stderr | 4 +- src/test/ui/impl-trait/issues/issue-70877.rs | 2 +- .../ui/impl-trait/issues/issue-70877.stderr | 11 +- src/test/ui/impl-trait/projection.rs | 2 +- src/test/ui/impl-trait/question_mark.rs | 2 +- ...alias-impl-trait-declaration-too-subtle.rs | 1 + ...s-impl-trait-declaration-too-subtle.stderr | 9 +- .../two_tait_defining_each_other2.rs | 2 +- .../two_tait_defining_each_other2.stderr | 10 +- src/test/ui/issues-71798.rs | 1 + src/test/ui/issues-71798.stderr | 18 ++- src/test/ui/parser/fn-header-semantic-fail.rs | 2 + .../ui/parser/fn-header-semantic-fail.stderr | 82 ++++++++----- ...ue-70736-async-fn-no-body-def-collector.rs | 1 + ...0736-async-fn-no-body-def-collector.stderr | 14 ++- .../match-prev-arm-needing-semi.rs | 9 +- .../match-prev-arm-needing-semi.stderr | 27 ++--- .../ui/suggestions/opaque-type-error.stderr | 7 +- .../declared_but_not_defined_in_scope.stderr | 4 +- ...o_revealing_outside_defining_module.stderr | 8 +- .../clippy_utils/src/qualify_min_const_fn.rs | 1 - 60 files changed, 290 insertions(+), 311 deletions(-) create mode 100644 src/test/ui/impl-trait/autoderef.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3ee0aafebfd84..9d7dcc5379c5d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2646,7 +2646,7 @@ impl NormalizeLocation for Location { pub(super) struct InstantiateOpaqueType<'tcx> { pub base_universe: Option, pub region_constraints: Option>, - pub obligation: PredicateObligation<'tcx>, + pub obligations: Vec>, } impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { @@ -2660,7 +2660,7 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible> { let (mut output, region_constraints) = scrape_region_constraints(infcx, || { - Ok(InferOk { value: (), obligations: vec![self.obligation.clone()] }) + Ok(InferOk { value: (), obligations: self.obligations.clone() }) })?; self.region_constraints = Some(region_constraints); output.error_info = Some(self); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index a032095bf981e..8a757636087df 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -2,6 +2,7 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRe use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::traits::ObligationCause; use rustc_middle::mir::ConstraintCategory; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::{self, Const, Ty}; use rustc_span::Span; @@ -136,7 +137,12 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> true } - fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + fn register_opaque_type( + &mut self, + a: Ty<'tcx>, + b: Ty<'tcx>, + a_is_expected: bool, + ) -> Result<(), TypeError<'tcx>> { let param_env = self.param_env(); let span = self.span(); let def_id = self.type_checker.body.source.def_id().expect_local(); @@ -147,18 +153,17 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> self.locations, self.category, InstantiateOpaqueType { - obligation: self.type_checker.infcx.opaque_ty_obligation( - a, - b, - a_is_expected, - param_env, - cause, - ), + obligations: self + .type_checker + .infcx + .handle_opaque_type(a, b, a_is_expected, &cause, param_env)? + .obligations, // These fields are filled in during exectuion of the operation base_universe: None, region_constraints: None, }, ) .unwrap(); + Ok(()) } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 20f65962db4f7..750643acdda3b 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -22,6 +22,7 @@ use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; use rustc_middle::arena::ArenaAllocatable; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; @@ -499,7 +500,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { 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); + obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -718,13 +719,17 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { 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(), - )); + fn register_opaque_type( + &mut self, + a: Ty<'tcx>, + b: Ty<'tcx>, + a_is_expected: bool, + ) -> Result<(), TypeError<'tcx>> { + self.obligations.extend( + self.infcx + .handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)? + .obligations, + ); + Ok(()) } } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index c1c075e9a4cad..65c0eba4b3d5c 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -98,13 +98,17 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { (&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.obligations.extend( + infcx + .handle_opaque_type( + a, + b, + self.a_is_expected(), + &self.fields.trace.cause, + self.param_env(), + )? + .obligations, + ); } _ => { diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index f4c749492d3bc..b77245c2592f9 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -111,13 +111,11 @@ where (&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(), - )]); + this.add_obligations( + infcx + .handle_opaque_type(a, b, this.a_is_expected(), this.cause(), this.param_env())? + .obligations, + ); Ok(a) } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 2c7f3adafdc96..cc0114d7538e0 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -91,7 +91,12 @@ pub trait TypeRelatingDelegate<'tcx> { ); fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); - fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); + fn register_opaque_type( + &mut self, + a: Ty<'tcx>, + b: Ty<'tcx>, + a_is_expected: bool, + ) -> Result<(), TypeError<'tcx>>; /// Creates a new universe index. Used when instantiating placeholders. fn create_next_universe(&mut self) -> ty::UniverseIndex; @@ -590,7 +595,7 @@ where (_, &ty::Opaque(..)) => (generalize(a, true)?, b), _ => unreachable!(), }; - self.delegate.register_opaque_type(a, b, true); + self.delegate.register_opaque_type(a, b, true)?; trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index ce922bca3565c..b2f62637cf238 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,5 +1,5 @@ use crate::infer::{InferCtxt, InferOk}; -use crate::traits::{self, PredicateObligation}; +use crate::traits; use hir::def_id::{DefId, LocalDefId}; use hir::OpaqueTyOrigin; use rustc_data_structures::sync::Lrc; @@ -42,25 +42,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, a: Ty<'tcx>, b: Ty<'tcx>, + a_is_expected: bool, cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> 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 { 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 + let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; + 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 { 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, @@ -76,13 +76,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "opaque type being used as hidden type", ) .emit(); - } } - Some(self.register_hidden_type( - OpaqueTypeKey { def_id, substs }, - cause.clone(), - param_env, - b, + } + Some(self.register_hidden_type( + OpaqueTypeKey { def_id, substs }, + cause.clone(), + param_env, + b, + if self.defining_use_anchor.is_some() { // 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 @@ -117,47 +118,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 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.kind(), b.kind()) - ), - Err(e) => Err(e), - } + self.opaque_type_origin(def_id, cause.span)? + } else { + self.opaque_ty_origin_unchecked(def_id, cause.span) + }, + )) } + _ => None, + }; + if let Some(res) = process(a, b) { + res + } else if let Some(res) = process(b, a) { + res } else { - let (opaque_type, hidden_ty) = match (a.kind(), b.kind()) { - (ty::Opaque(..), _) => (a, b), - (_, ty::Opaque(..)) => (b, a), - types => span_bug!( + // 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 type obligations only work for opaque types: {:#?}", - types + "opaque types are never equal to anything but themselves: {:#?}", + (a.kind(), b.kind()) ), - }; - 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![] }), + Err(e) => Err(e), } } } @@ -363,22 +345,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }); } - 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 { let def_id = opaque_def_id.as_local()?; diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index b60ffc1878be4..03d6c45a65345 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -28,7 +28,6 @@ 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)) diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 85bae8b823b06..3600b54a27104 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -146,13 +146,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { (_, &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(), - )); + self.fields.obligations.extend( + infcx + .handle_opaque_type(a, b, true, &self.fields.trace.cause, self.param_env())? + .obligations, + ); Ok(a) } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 6600d5e4d0279..674c75fdee561 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -167,9 +167,6 @@ impl<'tcx> Elaborator<'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. diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index cec32823ee2e3..50a3df21a3bc9 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1675,7 +1675,6 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Coerce(..) | ConstEvaluatable(..) | ConstEquate(..) | - OpaqueType(..) | TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 06ac21e5d5794..7a3d615862cba 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -265,10 +265,6 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } - ty::PredicateKind::OpaqueType(opaque, ty) => { - self.add_ty(opaque); - self.add_ty(ty); - } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 069cf32e51589..44c190e459c3d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -632,11 +632,6 @@ 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 @@ -1004,7 +999,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) - | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1023,7 +1017,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) - | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d5f5a1572b89e..fecc5d805fcac 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2654,9 +2654,6 @@ define_print_and_forward_display! { 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) ,"`") - } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 576f4121c42e3..5c7910db362d2 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -198,9 +198,6 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } - ty::PredicateKind::OpaqueType(a, b) => { - write!(f, "OpaqueType({:?}, {:?})", a.kind(), b.kind()) - } } } } @@ -474,9 +471,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { 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)?)) - } } } } diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index eb70de48368dc..06287f00faddb 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -352,7 +352,6 @@ crate fn required_region_bounds<'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 diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index ee8b3a6245316..ee9983ee8b8d8 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -865,7 +865,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} }; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 218abdd573df2..468c7a3c55b36 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -797,10 +797,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, "TypeWellFormedFromEnv predicate should only exist in the environment" ), - - ty::PredicateKind::OpaqueType(..) => { - todo!("{:#?}", obligation); - } } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index d55d06ebbf409..1b8628344671d 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -413,9 +413,6 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::OpaqueType(..) => { - todo!("{:#?}", obligation); - } }, Some(pred) => match pred { ty::PredicateKind::Trait(data) => { @@ -665,20 +662,6 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { 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, - )), - } - } }, } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index eab207600ab58..6cceec8621304 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -313,7 +313,6 @@ fn predicate_references_self<'tcx>( | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -345,7 +344,6 @@ 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, } }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 76526df646159..42f17721f9b54 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -673,19 +673,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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), - } - } } }); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2ac68cea5448f..b4ed5b95b1047 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -148,10 +148,6 @@ 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") } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 1d5b5c6c3cd63..e3c865ce9e632 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -110,7 +110,6 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; @@ -203,7 +202,6 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) } @@ -623,7 +621,6 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } @@ -753,7 +750,6 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 1535a46a01b47..90c698db8fb54 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -105,7 +105,6 @@ 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); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 1d26f6a12a36d..a4aa965ec9533 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -69,7 +69,6 @@ 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, } } diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 83ef76a48cd2c..709622edb76bb 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -661,13 +661,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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, - )]); + self.register_predicates( + self.infcx + .handle_opaque_type(ty, ty_var, true, &cause, self.param_env) + .unwrap() + .obligations, + ); ty_var } _ => ty, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 83587951f2532..6e3013cde7b6c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -732,7 +732,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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)) diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 26119e5a06407..abdce9f586638 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -858,7 +858,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 737e6002005a7..6cef3e9d9409e 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -425,7 +425,6 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs index 7839ce5e4ff48..bbf31de527eb3 100644 --- a/compiler/rustc_typeck/src/outlives/explicit.rs +++ b/compiler/rustc_typeck/src/outlives/explicit.rs @@ -59,7 +59,6 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5256fe762484e..1e3260ce9ae2b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -306,7 +306,6 @@ impl<'a> Clean> for ty::Predicate<'a> { | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } } diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index 046f1dfea3238..796f82e779c2b 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -22,6 +22,7 @@ async fn suggest_await_in_async_fn_return() { dummy() //~^ ERROR mismatched types [E0308] //~| HELP consider `await`ing on the `Future` + //~| HELP consider using a semicolon here //~| SUGGESTION .await } diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 07d6f8986fa60..76073c4c87996 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -33,9 +33,13 @@ 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:34:9 + --> $DIR/suggest-missing-await.rs:35:9 | LL | let _x = if true { | ______________- @@ -49,20 +53,15 @@ LL | | LL | | }; | |_____- `if` and `else` have incompatible types | -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` - found unit type `()` + = note: expected type `impl Future` + 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:44:14 + --> $DIR/suggest-missing-await.rs:45:14 | LL | let _x = match 0usize { | ______________- @@ -90,7 +89,7 @@ LL ~ 1 => dummy().await, | error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:52:9 + --> $DIR/suggest-missing-await.rs:53:9 | LL | let _x = match dummy() { | ------- this expression has type `impl Future` @@ -110,7 +109,7 @@ LL | let _x = match dummy().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:66:9 + --> $DIR/suggest-missing-await.rs:67:9 | LL | match dummy_result() { | -------------- this expression has type `impl Future>` @@ -119,7 +118,7 @@ LL | Ok(_) => {} | ^^^^^ expected opaque type, found enum `Result` | note: while checking the return type of the `async fn` - --> $DIR/suggest-missing-await.rs:56:28 + --> $DIR/suggest-missing-await.rs:57:28 | LL | async fn dummy_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type @@ -131,7 +130,7 @@ LL | match dummy_result().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:68:9 + --> $DIR/suggest-missing-await.rs:69:9 | LL | match dummy_result() { | -------------- this expression has type `impl Future>` @@ -140,7 +139,7 @@ LL | Err(_) => {} | ^^^^^^ expected opaque type, found enum `Result` | note: while checking the return type of the `async fn` - --> $DIR/suggest-missing-await.rs:56:28 + --> $DIR/suggest-missing-await.rs:57:28 | LL | async fn dummy_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type diff --git a/src/test/ui/cast/casts-differing-anon.rs b/src/test/ui/cast/casts-differing-anon.rs index ccf41adce6bd8..d4a0f9613055e 100644 --- a/src/test/ui/cast/casts-differing-anon.rs +++ b/src/test/ui/cast/casts-differing-anon.rs @@ -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 mismatched types + b_raw = f_raw as *mut _; //~ ERROR is invalid } diff --git a/src/test/ui/cast/casts-differing-anon.stderr b/src/test/ui/cast/casts-differing-anon.stderr index 2d08903c5ef69..f9abfb5225f91 100644 --- a/src/test/ui/cast/casts-differing-anon.stderr +++ b/src/test/ui/cast/casts-differing-anon.stderr @@ -1,19 +1,11 @@ -error[E0308]: mismatched types +error[E0606]: casting `*mut impl Debug + ?Sized` as `*mut impl Debug + ?Sized` is invalid --> $DIR/casts-differing-anon.rs:21:13 | -LL | fn foo() -> Box { - | ---------------------- the found opaque type -... -LL | fn bar() -> Box { - | ---------------------- the expected opaque type -... LL | b_raw = f_raw as *mut _; - | ^^^^^ expected opaque type, found a different opaque type + | ^^^^^^^^^^^^^^^ | - = 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 + = note: vtable kinds may not match error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0606`. diff --git a/src/test/ui/conservative_impl_trait.rs b/src/test/ui/conservative_impl_trait.rs index b7f795eadb760..b8488d83998e8 100644 --- a/src/test/ui/conservative_impl_trait.rs +++ b/src/test/ui/conservative_impl_trait.rs @@ -2,6 +2,7 @@ fn will_ice(something: &u32) -> impl Iterator { //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator } fn main() {} diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr index 63a4df242f85f..2348f2f52978f 100644 --- a/src/test/ui/conservative_impl_trait.stderr +++ b/src/test/ui/conservative_impl_trait.stderr @@ -6,6 +6,18 @@ LL | fn will_ice(something: &u32) -> impl Iterator { | = help: the trait `Iterator` is not implemented for `()` -error: aborting due to previous error +error[E0277]: `()` is not an iterator + --> $DIR/conservative_impl_trait.rs:3:60 + | +LL | fn will_ice(something: &u32) -> impl Iterator { + | ____________________________________________________________^ +LL | | +LL | | +LL | | } + | |_^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/autoderef.rs b/src/test/ui/impl-trait/autoderef.rs new file mode 100644 index 0000000000000..5e4f4995447e1 --- /dev/null +++ b/src/test/ui/impl-trait/autoderef.rs @@ -0,0 +1,19 @@ +// check-pass + +use std::path::Path; +use std::ffi::OsStr; +use std::ops::Deref; + +fn frob(path: &str) -> impl Deref + '_ { + OsStr::new(path).as_ref() +} + +fn open_parent<'path>(_path: &'path Path) { + todo!() +} + +fn main() { + let old_path = frob("hello"); + + open_parent(&old_path); +} diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs index ceb8414650f1e..c27b5ca9f6689 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.rs +++ b/src/test/ui/impl-trait/cross-return-site-inference.rs @@ -42,4 +42,4 @@ fn muh3() -> Result<(), impl std::fmt::Debug> { Err(From::from("foo")) //~ ERROR the trait bound `impl Debug: From<&str>` is not satisfied } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index fd33fa7c674f1..46053c6e7c119 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -15,7 +15,9 @@ LL | fn hide(x: T) -> impl Foo { | -------- the found opaque type ... LL | let _: u32 = hide(0_u32); - | ^^^^^^^^^^^ expected `u32`, found opaque type + | --- ^^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this | = note: expected type `u32` found opaque type `impl Foo` diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs index 9cbe33aef5bb9..1a86fa00ed1a0 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -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"); //~^^^ ERROR opaque type's hidden type cannot be another opaque type + return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type } fn main() { diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr index 2610a19818621..7cbd58bdabf2f 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -13,15 +13,10 @@ LL | Some(Box::new(quux)) found enum `Option fn(&'r (dyn ToString + 'r)) -> FooRet {quux}>>` error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/issue-70877.rs:28:34 + --> $DIR/issue-70877.rs:31:12 | -LL | fn oof() -> impl std::fmt::Debug { - | __________________________________^ -LL | | let mut bar = ham(); -LL | | let func = bar.next().unwrap(); -LL | | return func(&"oof"); -LL | | } - | |_^ one of the two opaque types used here has to be outside its defining scope +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 diff --git a/src/test/ui/impl-trait/projection.rs b/src/test/ui/impl-trait/projection.rs index 21fc6591e97bf..b33802e2bc8da 100644 --- a/src/test/ui/impl-trait/projection.rs +++ b/src/test/ui/impl-trait/projection.rs @@ -26,4 +26,4 @@ fn run(f: F) fn main() { run(|_| {}); -} \ No newline at end of file +} diff --git a/src/test/ui/impl-trait/question_mark.rs b/src/test/ui/impl-trait/question_mark.rs index 495bf5c1d64f2..7bd5cff31bbdf 100644 --- a/src/test/ui/impl-trait/question_mark.rs +++ b/src/test/ui/impl-trait/question_mark.rs @@ -27,4 +27,4 @@ pub fn direct() -> Result<(), impl Debug> { Err(Target) } -fn main() {} \ No newline at end of file +fn main() {} 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 index a60e34c17b671..6aa832cde71ee 100644 --- 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 @@ -21,6 +21,7 @@ mod b { impl PartialEq<(Foo, i32)> for Bar { fn eq(&self, _other: &(Bar, i32)) -> bool { + //~^ ERROR impl has stricter requirements than trait true } } 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 index eae7d38d1162b..19d5cdb9d0ac6 100644 --- 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 @@ -14,5 +14,12 @@ 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 +error[E0276]: impl has stricter requirements than trait + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:23:9 + | +LL | fn eq(&self, _other: &(Bar, i32)) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `b::Bar: PartialEq<(b::Bar, i32)>` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0276`. 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 index 3b16d0f5e047f..05b09668016c4 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs @@ -1,6 +1,6 @@ #![feature(type_alias_impl_trait)] -type A = impl Foo; +type A = impl Foo; //~ ERROR unconstrained opaque type type B = impl Foo; trait Foo {} 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 index ef2089a6c5b17..4d8f96de1626c 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr @@ -1,3 +1,11 @@ +error: unconstrained opaque type + --> $DIR/two_tait_defining_each_other2.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + | + = note: `A` must be used in combination with a concrete type within the same module + error: opaque type's hidden type cannot be another opaque type from the same scope --> $DIR/two_tait_defining_each_other2.rs:9:5 | @@ -15,5 +23,5 @@ note: opaque type being used as hidden type LL | type A = impl Foo; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs index 14b6c0f35812f..fde59f39b1cd9 100644 --- a/src/test/ui/issues-71798.rs +++ b/src/test/ui/issues-71798.rs @@ -1,5 +1,6 @@ fn test_ref(x: &u32) -> impl std::future::Future + '_ { //~^ ERROR `u32` is not a future + //~| ERROR `u32` is not a future *x } diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index ab72c3e41af97..63669c0513d64 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `u` in this scope - --> $DIR/issues-71798.rs:7:24 + --> $DIR/issues-71798.rs:8:24 | LL | let _ = test_ref & u; | ^ not found in this scope @@ -13,7 +13,21 @@ LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { = help: the trait `Future` is not implemented for `u32` = note: u32 must be a future or must implement `IntoFuture` to be awaited -error: aborting due to 2 previous errors +error[E0277]: `u32` is not a future + --> $DIR/issues-71798.rs:1:69 + | +LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { + | _____________________________________________________________________^ +LL | | +LL | | +LL | | *x +LL | | } + | |_^ `u32` is not a future + | + = help: the trait `Future` is not implemented for `u32` + = note: u32 must be a future or must implement `IntoFuture` to be awaited + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index cf5d3dab4aada..c2954868f78e4 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -27,6 +27,7 @@ fn main() { struct Y; impl X for Y { async fn ft1() {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR impl has stricter requirements than trait unsafe fn ft2() {} // OK. const fn ft3() {} //~ ERROR functions in traits cannot be declared const extern "C" fn ft4() {} @@ -35,6 +36,7 @@ fn main() { //~| ERROR functions in traits cannot be declared const //~| ERROR functions cannot be both `const` and `async` //~| ERROR cycle detected + //~| ERROR impl has stricter requirements than trait } impl Y { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 1d7460b8d3605..bd3b9181123bb 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -62,19 +62,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:31:9 + --> $DIR/fn-header-semantic-fail.rs:32: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:33:9 + --> $DIR/fn-header-semantic-fail.rs:34: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:33:9 + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,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:33:9 + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^-^^^^^------------------------------ @@ -94,7 +94,7 @@ LL | const async unsafe extern "C" fn ft5() {} | `const` because of this error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:45:9 + --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^-^^^^^------------------------------ @@ -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:51:18 + --> $DIR/fn-header-semantic-fail.rs:53: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:52:19 + --> $DIR/fn-header-semantic-fail.rs:54: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:53:18 + --> $DIR/fn-header-semantic-fail.rs:55: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:54:23 + --> $DIR/fn-header-semantic-fail.rs:56: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:55:42 + --> $DIR/fn-header-semantic-fail.rs:57: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:55:9 + --> $DIR/fn-header-semantic-fail.rs:57:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^-^^^^^---------------------------- @@ -216,30 +216,48 @@ LL | | } LL | | } | |_^ -error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:33:48 +error[E0276]: impl has stricter requirements than trait + --> $DIR/fn-header-semantic-fail.rs:29:9 + | +LL | async fn ft1(); + | --------------- definition of `ft1` from trait +... +LL | async fn ft1() {} + | ^^^^^^^^^^^^^^ impl has extra requirement `(): Future` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/fn-header-semantic-fail.rs:34:9 + | +LL | const async unsafe extern "C" fn ft5(); + | --------------------------------------- definition of `ft5` from trait +... +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future` + +error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:34:48 | LL | const async unsafe extern "C" fn ft5() {} | ^ | -note: ...which requires borrow-checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:33:9 +note: ...which requires borrow-checking `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:33:9 +note: ...which requires processing `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:33:9 +note: ...which requires const checking `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... - = note: ...which again requires computing type of `main::::ft5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::::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 | @@ -252,30 +270,30 @@ LL | | } LL | | } | |_^ -error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:45:48 +error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:47:48 | LL | const async unsafe extern "C" fn fi5() {} | ^ | -note: ...which requires borrow-checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:45:9 +note: ...which requires borrow-checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:45:9 +note: ...which requires processing `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:45:9 +note: ...which requires const checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... - = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::::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 | @@ -288,7 +306,7 @@ LL | | } LL | | } | |_^ -error: aborting due to 21 previous errors +error: aborting due to 23 previous errors -Some errors have detailed explanations: E0379, E0391, E0706. -For more information about an error, try `rustc --explain E0379`. +Some errors have detailed explanations: E0276, E0379, E0391, E0706. +For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs index 49462f52fb4c2..6facc467f7a6f 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -14,6 +14,7 @@ trait B { impl B for A { async fn associated(); //~ ERROR without body //~^ ERROR cannot be declared `async` + //~| ERROR impl has stricter requirements than trait } fn main() {} diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index a473f42fc2cf8..c144060a8597d 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -44,6 +44,16 @@ 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: aborting due to 5 previous errors +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 + | +LL | async fn associated(); + | ---------------------- definition of `associated` from trait +... +LL | async fn associated(); + | ^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0706`. +Some errors have detailed explanations: E0276, E0706. +For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index a02664ad7ca69..6aa93a24d2f04 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -16,9 +16,6 @@ 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` @@ -34,7 +31,7 @@ async fn async_extra_semicolon_same() { } false => async_dummy(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type - //~| NOTE expected unit type `()` + //~| NOTE expected type `()` //~| HELP consider `await`ing on the `Future` }; } @@ -47,7 +44,7 @@ async fn async_extra_semicolon_different() { } false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type - //~| NOTE expected unit type `()` + //~| NOTE expected type `()` //~| HELP consider `await`ing on the `Future` }; } @@ -58,7 +55,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 opaque type `impl Future` + //~| NOTE expected type `impl Future` //~| NOTE distinct uses of `impl Trait` result in different opaque types }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index 4c4b782bd6fb1..b55c51b92809a 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -1,5 +1,5 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:35:18 + --> $DIR/match-prev-arm-needing-semi.rs:32: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 unit type `()` - found opaque type `impl Future` + = note: expected type `()` + found opaque type `impl Future` 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:48:18 + --> $DIR/match-prev-arm-needing-semi.rs:45: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:22:25 + --> $DIR/match-prev-arm-needing-semi.rs:19:25 | LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected unit type `()` - found opaque type `impl Future` + = note: expected type `()` + found opaque type `impl Future` 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:59:18 + --> $DIR/match-prev-arm-needing-semi.rs:56:18 | LL | let _ = match true { | _____________- @@ -84,17 +84,12 @@ LL | | }; | |_____- `match` arms have incompatible types | note: while checking the return type of the `async fn` - --> $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 + --> $DIR/match-prev-arm-needing-semi.rs:19:25 | LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) - found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>) + = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) = 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/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index 133ffb0587392..e065e0aaa8e06 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -1,9 +1,6 @@ error[E0308]: `if` and `else` have incompatible types --> $DIR/opaque-type-error.rs:20:9 | -LL | fn thing_one() -> impl Future> { - | ------------------------------------ the expected opaque type -... LL | fn thing_two() -> impl Future> { | ------------------------------------ the found opaque type ... @@ -16,8 +13,8 @@ LL | | thing_two() LL | | }.await | |_____- `if` and `else` have incompatible types | - = note: expected opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) - found opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: expected type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future>` (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/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr index 26308c6ff6b15..fbfa0ccf1e8d9 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -12,11 +12,13 @@ error[E0308]: mismatched types LL | pub type Boo = impl ::std::fmt::Debug; | ---------------------- the expected opaque type ... +LL | fn bomp() -> boo::Boo { + | -------- expected `Boo` because of return type LL | "" | ^^ expected opaque type, found `&str` | = note: expected opaque type `Boo` - found reference `&str` + found reference `&'static str` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr index e691d8781c0f1..ae03a5b3e37bf 100644 --- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr +++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -5,7 +5,9 @@ LL | pub type Boo = impl ::std::fmt::Debug; | ---------------------- the found opaque type ... LL | let _: &str = bomp(); - | ^^^^^^ expected `&str`, found opaque type + | ---- ^^^^^^ expected `&str`, found opaque type + | | + | expected due to this | = note: expected reference `&str` found opaque type `Boo` @@ -16,11 +18,13 @@ error[E0308]: mismatched types LL | pub type Boo = impl ::std::fmt::Debug; | ---------------------- the expected opaque type ... +LL | fn bomp() -> boo::Boo { + | -------- expected `Boo` because of return type LL | "" | ^^ expected opaque type, found `&str` | = note: expected opaque type `Boo` - found reference `&str` + found reference `&'static str` error: aborting due to 2 previous errors diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index f099d2c07d18f..891531951c1a0 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -33,7 +33,6 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Trait(..) - | 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), From 2bf63a50115efad7a474e50b7a4330b506da2578 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 13:55:58 +0000 Subject: [PATCH 10/26] Add regression tests --- src/test/ui/impl-trait/issues/issue-54895.rs | 23 ++++++++ src/test/ui/impl-trait/issues/issue-62742.rs | 32 +++++++++++ .../ui/impl-trait/issues/issue-62742.stderr | 54 +++++++++++++++++++ .../impl-trait/issues/issue-67830.nll.stderr | 20 +++++++ src/test/ui/impl-trait/issues/issue-67830.rs | 26 +++++++++ .../ui/impl-trait/issues/issue-67830.stderr | 15 ++++++ src/test/ui/impl-trait/issues/issue-74282.rs | 11 ++++ .../ui/impl-trait/issues/issue-74282.stderr | 33 ++++++++++++ src/test/ui/impl-trait/issues/issue-77987.rs | 21 ++++++++ src/test/ui/impl-trait/issues/issue-82139.rs | 19 +++++++ .../ui/impl-trait/issues/issue-82139.stderr | 9 ++++ src/test/ui/impl-trait/issues/issue-83919.rs | 31 +++++++++++ .../ui/impl-trait/issues/issue-83919.stderr | 17 ++++++ src/test/ui/impl-trait/issues/issue-84073.rs | 33 ++++++++++++ .../ui/impl-trait/issues/issue-84073.stderr | 9 ++++ src/test/ui/impl-trait/issues/issue-86719.rs | 12 +++++ .../ui/impl-trait/issues/issue-86719.stderr | 24 +++++++++ src/test/ui/impl-trait/issues/issue-86800.rs | 48 +++++++++++++++++ .../ui/impl-trait/issues/issue-86800.stderr | 10 ++++ src/test/ui/impl-trait/issues/issue-87340.rs | 14 +++++ .../ui/impl-trait/issues/issue-87340.stderr | 9 ++++ src/test/ui/impl-trait/issues/issue-89312.rs | 24 +++++++++ 22 files changed, 494 insertions(+) create mode 100644 src/test/ui/impl-trait/issues/issue-54895.rs create mode 100644 src/test/ui/impl-trait/issues/issue-62742.rs create mode 100644 src/test/ui/impl-trait/issues/issue-62742.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-67830.nll.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-67830.rs create mode 100644 src/test/ui/impl-trait/issues/issue-67830.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-74282.rs create mode 100644 src/test/ui/impl-trait/issues/issue-74282.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-77987.rs create mode 100644 src/test/ui/impl-trait/issues/issue-82139.rs create mode 100644 src/test/ui/impl-trait/issues/issue-82139.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-83919.rs create mode 100644 src/test/ui/impl-trait/issues/issue-83919.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-84073.rs create mode 100644 src/test/ui/impl-trait/issues/issue-84073.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-86719.rs create mode 100644 src/test/ui/impl-trait/issues/issue-86719.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-86800.rs create mode 100644 src/test/ui/impl-trait/issues/issue-86800.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-87340.rs create mode 100644 src/test/ui/impl-trait/issues/issue-87340.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-89312.rs diff --git a/src/test/ui/impl-trait/issues/issue-54895.rs b/src/test/ui/impl-trait/issues/issue-54895.rs new file mode 100644 index 0000000000000..a70166e03a7b1 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54895.rs @@ -0,0 +1,23 @@ +// check-pass + +trait Trait<'a> { + type Out; + fn call(&'a self) -> Self::Out; +} + +struct X(()); + +impl<'a> Trait<'a> for X { + type Out = (); + fn call(&'a self) -> Self::Out { + () + } +} + +fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + X(()) +} + +fn main() { + let _ = f(); +} diff --git a/src/test/ui/impl-trait/issues/issue-62742.rs b/src/test/ui/impl-trait/issues/issue-62742.rs new file mode 100644 index 0000000000000..041bd0e3855ec --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-62742.rs @@ -0,0 +1,32 @@ +use std::marker::PhantomData; + +fn _alias_check() { + WrongImpl::foo(0i32); + //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied + WrongImpl::<()>::foo(0i32); + //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied + //~| ERROR trait bounds were not satisfied + CorrectImpl::foo(0i32); +} + +pub trait Raw { + type Value; +} + +pub type WrongImpl = SafeImpl>; + +pub type CorrectImpl = SafeImpl<[T], RawImpl>; + +pub struct RawImpl(PhantomData); + +impl Raw<[T]> for RawImpl { + type Value = T; +} + +pub struct SafeImpl>(PhantomData<(A, T)>); + +impl> SafeImpl { + pub fn foo(value: A::Value) {} +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr new file mode 100644 index 0000000000000..28068b7548ce5 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-62742.stderr @@ -0,0 +1,54 @@ +error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied + --> $DIR/issue-62742.rs:4:5 + | +LL | WrongImpl::foo(0i32); + | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | + = help: the following implementations were found: + as Raw<[T]>> +note: required by a bound in `SafeImpl` + --> $DIR/issue-62742.rs:26:35 + | +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ^^^^^^ required by this bound in `SafeImpl` + +error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied + --> $DIR/issue-62742.rs:6:22 + | +LL | WrongImpl::<()>::foo(0i32); + | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds +... +LL | pub struct RawImpl(PhantomData); + | -------------------------------------- doesn't satisfy `RawImpl<()>: Raw<()>` +... +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | --------------------------------------------------------------- function or associated item `foo` not found for this + | + = note: the following trait bounds were not satisfied: + `RawImpl<()>: Raw<()>` +note: the following trait must be implemented + --> $DIR/issue-62742.rs:12:1 + | +LL | / pub trait Raw { +LL | | type Value; +LL | | } + | |_^ + +error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied + --> $DIR/issue-62742.rs:6:5 + | +LL | WrongImpl::<()>::foo(0i32); + | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` + | + = help: the following implementations were found: + as Raw<[T]>> +note: required by a bound in `SafeImpl` + --> $DIR/issue-62742.rs:26:35 + | +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ^^^^^^ required by this bound in `SafeImpl` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issues/issue-67830.nll.stderr b/src/test/ui/impl-trait/issues/issue-67830.nll.stderr new file mode 100644 index 0000000000000..17fbe046e3ac9 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-67830.nll.stderr @@ -0,0 +1,20 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-67830.rs:23:5 + | +LL | Wrap(|a| Some(a).into_iter()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-67830.rs:23:5 + | +LL | Wrap(|a| Some(a).into_iter()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/impl-trait/issues/issue-67830.rs b/src/test/ui/impl-trait/issues/issue-67830.rs new file mode 100644 index 0000000000000..a308d975b4395 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-67830.rs @@ -0,0 +1,26 @@ +trait MyFn { + type Output; + fn call(&self, arg: Arg) -> Self::Output; +} + +struct Wrap(F); + +impl MyFn for Wrap +where + F: Fn(A) -> B +{ + type Output = B; + + fn call(&self, arg: A) -> Self::Output { + (self.0)(arg) + } +} + + +struct A; +fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { + //~^ ERROR implementation of `FnOnce` is not general enough + Wrap(|a| Some(a).into_iter()) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-67830.stderr b/src/test/ui/impl-trait/issues/issue-67830.stderr new file mode 100644 index 0000000000000..74e2f99cd33f9 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-67830.stderr @@ -0,0 +1,15 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-67830.rs:21:66 + | +LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { + | __________________________________________________________________^ +LL | | +LL | | Wrap(|a| Some(a).into_iter()) +LL | | } + | |_^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2` + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/issues/issue-74282.rs b/src/test/ui/impl-trait/issues/issue-74282.rs new file mode 100644 index 0000000000000..654de0cd0253c --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-74282.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +type Closure = impl Fn() -> u64; +struct Anonymous(Closure); + +fn main() { + let y = || -> Closure { || 3 }; + Anonymous(|| { //~ ERROR mismatched types + 3 //~^ ERROR mismatched types + }) +} diff --git a/src/test/ui/impl-trait/issues/issue-74282.stderr b/src/test/ui/impl-trait/issues/issue-74282.stderr new file mode 100644 index 0000000000000..6e02a6b2b87b4 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-74282.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/issue-74282.rs:8:15 + | +LL | type Closure = impl Fn() -> u64; + | ---------------- the expected opaque type +... +LL | Anonymous(|| { + | _______________^ +LL | | 3 +LL | | }) + | |_____^ expected closure, found a different closure + | + = note: expected opaque type `Closure` + found closure `[closure@$DIR/issue-74282.rs:8:15: 10:6]` + = note: no two closures, even if identical, have the same type + = help: consider boxing your closure and/or using it as a trait object + +error[E0308]: mismatched types + --> $DIR/issue-74282.rs:8:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | let y = || -> Closure { || 3 }; +LL | / Anonymous(|| { +LL | | 3 +LL | | }) + | | ^- help: consider using a semicolon here: `;` + | |______| + | expected `()`, found struct `Anonymous` + +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-77987.rs b/src/test/ui/impl-trait/issues/issue-77987.rs new file mode 100644 index 0000000000000..d29710b6f54ca --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-77987.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Foo {} +impl Foo for U {} + +type Scope = impl Foo<()>; + +#[allow(unused)] +fn infer_scope() -> Scope { + () +} + +#[allow(unused)] +fn ice() -> impl Foo +{ + loop {} +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-82139.rs b/src/test/ui/impl-trait/issues/issue-82139.rs new file mode 100644 index 0000000000000..cc9167b340ad7 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-82139.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +trait Trait { + type Associated; + fn func() -> Self::Associated; +} + +trait Bound {} +pub struct Struct; + +impl Trait for Struct { + type Associated = impl Bound; + + fn func() -> Self::Associated { + Some(42).map(|_| j) //~ ERROR cannot find value `j` in this scope + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-82139.stderr b/src/test/ui/impl-trait/issues/issue-82139.stderr new file mode 100644 index 0000000000000..0adcd4a7a2f5c --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-82139.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `j` in this scope + --> $DIR/issue-82139.rs:15:26 + | +LL | Some(42).map(|_| j) + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/impl-trait/issues/issue-83919.rs b/src/test/ui/impl-trait/issues/issue-83919.rs new file mode 100644 index 0000000000000..58aca77fdf19f --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-83919.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +// edition:2021 + +use std::future::Future; + +trait Foo { + type T; + type Fut2: Future; // ICE got triggered with traits other than Future here + type Fut: Future; + fn get_fut(&self) -> Self::Fut; +} + +struct Implementor; + +impl Foo for Implementor { + type T = u64; + type Fut2 = impl Future; + type Fut = impl Future; + + fn get_fut(&self) -> Self::Fut { + async move { + 42 //~^ ERROR `{integer}` is not a future + // 42 does not impl Future and rustc does actually point out the error, + // but rustc used to panic. + // Putting a valid Future here always worked fine. + } + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-83919.stderr b/src/test/ui/impl-trait/issues/issue-83919.stderr new file mode 100644 index 0000000000000..ebd0130be8d06 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-83919.stderr @@ -0,0 +1,17 @@ +error[E0277]: `{integer}` is not a future + --> $DIR/issue-83919.rs:22:9 + | +LL | / async move { +LL | | 42 +LL | | // 42 does not impl Future and rustc does actually point out the error, +LL | | // but rustc used to panic. +LL | | // Putting a valid Future here always worked fine. +LL | | } + | |_________^ `{integer}` is not a future + | + = help: the trait `Future` is not implemented for `{integer}` + = note: {integer} must be a future or must implement `IntoFuture` to be awaited + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issues/issue-84073.rs b/src/test/ui/impl-trait/issues/issue-84073.rs new file mode 100644 index 0000000000000..49a34ccfa3b4b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-84073.rs @@ -0,0 +1,33 @@ +use std::marker::PhantomData; + +pub trait StatefulFuture {} +pub struct Never(PhantomData); +impl StatefulFuture for Never {} + +pub struct RaceBuilder { + future: F, + _phantom: PhantomData, +} + +impl RaceBuilder +where + F: StatefulFuture>, +{ + pub fn when(self) {} +} + +pub struct Race { + race: R, + _phantom: PhantomData, +} + +impl Race +where + R: Fn(RaceBuilder>), +{ + pub fn new(race: R) {} +} + +fn main() { + Race::new(|race| race.when()); //~ ERROR type annotations needed +} diff --git a/src/test/ui/impl-trait/issues/issue-84073.stderr b/src/test/ui/impl-trait/issues/issue-84073.stderr new file mode 100644 index 0000000000000..36047d23fedda --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-84073.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed for `RaceBuilder>` + --> $DIR/issue-84073.rs:32:16 + | +LL | Race::new(|race| race.when()); + | ^^^^ consider giving this closure parameter the explicit type `RaceBuilder>`, where the type parameter `T` is specified + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/issues/issue-86719.rs b/src/test/ui/impl-trait/issues/issue-86719.rs new file mode 100644 index 0000000000000..f4b0b3f33fcd3 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86719.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +trait Bar { + type E; +} +impl Bar for S { + type E = impl ; //~ ERROR at least one trait must be specified + fn foo() -> Self::E { //~ ERROR `foo` is not a member + |_| true //~ ERROR type annotations needed + } +} +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-86719.stderr b/src/test/ui/impl-trait/issues/issue-86719.stderr new file mode 100644 index 0000000000000..e2abf71c110b9 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86719.stderr @@ -0,0 +1,24 @@ +error: at least one trait must be specified + --> $DIR/issue-86719.rs:7:14 + | +LL | type E = impl ; + | ^^^^ + +error[E0407]: method `foo` is not a member of trait `Bar` + --> $DIR/issue-86719.rs:8:5 + | +LL | / fn foo() -> Self::E { +LL | | |_| true +LL | | } + | |_____^ not a member of trait `Bar` + +error[E0282]: type annotations needed + --> $DIR/issue-86719.rs:9:10 + | +LL | |_| true + | ^ consider giving this closure parameter a type + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0282, E0407. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/issues/issue-86800.rs b/src/test/ui/impl-trait/issues/issue-86800.rs new file mode 100644 index 0000000000000..e8cef42f208ca --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86800.rs @@ -0,0 +1,48 @@ +#![feature(type_alias_impl_trait)] + +// edition:2021 + +use std::future::Future; + +struct Connection { +} + +trait Transaction { +} + +struct TestTransaction<'conn> { + conn: &'conn Connection +} + +impl<'conn> Transaction for TestTransaction<'conn> { +} + +struct Context { +} + +type TransactionResult = Result; + +type TransactionFuture<'__, O> = impl '__ + Future>; +//~^ ERROR unconstrained opaque type + +fn execute_transaction_fut<'f, F, O>( + f: F, +) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture +where + F: FnOnce(&mut dyn Transaction) -> TransactionFuture + 'f +{ + f +} + +impl Context { + async fn do_transaction( + &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture + ) -> TransactionResult + { + let mut conn = Connection {}; + let mut transaction = TestTransaction { conn: &mut conn }; + f(&mut transaction).await + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-86800.stderr b/src/test/ui/impl-trait/issues/issue-86800.stderr new file mode 100644 index 0000000000000..787aecc5b84bf --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86800.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-86800.rs:25:34 + | +LL | type TransactionFuture<'__, O> = impl '__ + Future>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `TransactionFuture` 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/impl-trait/issues/issue-87340.rs b/src/test/ui/impl-trait/issues/issue-87340.rs new file mode 100644 index 0000000000000..f0f6d2bb61c71 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-87340.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +trait X { + type I; + fn f() -> Self::I; +} + +impl X for () { +//~^ ERROR `T` is not constrained by the impl trait, self type, or predicates + type I = impl Sized; + fn f() -> Self::I {} +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-87340.stderr b/src/test/ui/impl-trait/issues/issue-87340.stderr new file mode 100644 index 0000000000000..2ab1e6a031248 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-87340.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-87340.rs:8:6 + | +LL | impl X for () { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/impl-trait/issues/issue-89312.rs b/src/test/ui/impl-trait/issues/issue-89312.rs new file mode 100644 index 0000000000000..d685a6f120109 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-89312.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait T { type Item; } + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} From 7f933de1946b49960e6522d6520d9a065fdb8a8d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 14:49:45 +0000 Subject: [PATCH 11/26] Merge two duplicates of the same logic into a common function --- .../rustc_infer/src/infer/opaque_types.rs | 45 ++++++++++++++++- compiler/rustc_typeck/src/check/check.rs | 50 +++---------------- compiler/rustc_typeck/src/check/closure.rs | 37 ++------------ 3 files changed, 56 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index b2f62637cf238..5920d12a93c8e 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,7 +1,7 @@ use crate::infer::{InferCtxt, InferOk}; use crate::traits; use hir::def_id::{DefId, LocalDefId}; -use hir::OpaqueTyOrigin; +use hir::{HirId, OpaqueTyOrigin}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; @@ -21,6 +21,7 @@ mod table; pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; +use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::InferResult; /// Information about the opaque types whose values we @@ -38,6 +39,48 @@ pub struct OpaqueTypeDecl<'tcx> { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { + pub fn replace_opaque_types_with_inference_vars( + &self, + ty: Ty<'tcx>, + body_id: HirId, + span: Span, + param_env: ty::ParamEnv<'tcx>, + ) -> InferOk<'tcx, Ty<'tcx>> { + let mut obligations = vec![]; + let value = ty.fold_with(&mut ty::fold::BottomUpFolder { + tcx: self.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.opaque_type_origin(def_id, span), + Some(OpaqueTyOrigin::FnReturn(..)) + ) => + { + let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span }; + let cause = ObligationCause::misc(span, body_id); + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: cause.span, + }); + obligations.extend( + self.handle_opaque_type(ty, ty_var, true, &cause, param_env) + .unwrap() + .obligations, + ); + ty_var + } + _ => ty, + }, + }); + InferOk { value, obligations } + } + pub fn handle_opaque_type( &self, a: Ty<'tcx>, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ee93a8ce53592..5362ca8d71978 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -3,7 +3,6 @@ use super::compare_method::check_type_bounds; use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; use super::*; -use hir::OpaqueTyOrigin; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed}; use rustc_hir as hir; @@ -13,9 +12,8 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; -use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -97,45 +95,13 @@ pub(super) fn check_fn<'a, 'tcx>( let declared_ret_ty = fn_sig.output(); - let ret_ty = declared_ret_ty.fold_with(&mut BottomUpFolder { - tcx: fcx.tcx, - ty_op: |ty| match *ty.kind() { - ty::Opaque(def_id, substs) => { - let span = tcx.def_span(def_id); - if let Some(origin @ OpaqueTyOrigin::FnReturn(_)) = - fcx.infcx.opaque_type_origin(def_id, span) - { - let hidden_ty = fcx.infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: span, - }); - - let cause = ObligationCause::misc(span, body.value.hir_id); - match fcx.infcx.register_hidden_type( - ty::OpaqueTypeKey { def_id, substs }, - cause.clone(), - param_env, - hidden_ty, - origin, - ) { - Ok(infer_ok) => { - fcx.register_infer_ok_obligations(infer_ok); - hidden_ty - } - Err(err) => { - fcx.report_mismatched_types(&cause, ty, hidden_ty, err).emit(); - tcx.ty_error() - } - } - } else { - ty - } - } - _ => ty, - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }); + let ret_ty = + fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars( + declared_ret_ty, + body.value.hir_id, + DUMMY_SP, + param_env, + )); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fcx.ret_type_span = Some(decl.output.span()); diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 709622edb76bb..2f5f804c56f78 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -4,14 +4,12 @@ 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}; @@ -641,37 +639,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } 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( - self.infcx - .handle_opaque_type(ty, ty_var, true, &cause, self.param_env) - .unwrap() - .obligations, - ); - ty_var - } - _ => ty, - }, - }) + let InferOk { value, obligations } = + self.replace_opaque_types_with_inference_vars(ty, body_id, span, self.param_env); + self.register_predicates(obligations); + value } /// Invoked when we are translating the generator that results From 02536fe18b78c0bbda2543617d75a4873e1016dd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 15:02:17 +0000 Subject: [PATCH 12/26] The hack isn't necessary for back compat anymore --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 6e3013cde7b6c..97935efd4f069 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -759,7 +759,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let formal_ret = self.resolve_vars_with_obligations(formal_ret); let Some(ret_ty) = expected_ret.only_has_type(self) else { return Vec::new() }; - // HACK(oli-obk): This is a backwards compatibility hack. Without it, the inference + // HACK(oli-obk): This is a hack to keep RPIT and TAIT in sync wrt their behaviour. + // Without it, the inference // variable will get instantiated with the opaque type. The inference variable often // has various helpful obligations registered for it that help closures figure out their // signature. If we infer the inference var to the opaque type, the closure won't be able From 1f46f771a6b579c1330976c1638ccc4a03e8863f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 15:23:28 +0000 Subject: [PATCH 13/26] Remove some special code handling TAIT being passed through if and match This is not necessary for RPIT anymore, since we reverted that to using inference vars. --- .../rustc_typeck/src/check/expectation.rs | 28 ++----------------- .../ui/lazy-type-alias-impl-trait/branches.rs | 14 ++++++++++ .../branches.stderr | 16 +++++++++++ .../lazy-type-alias-impl-trait/branches2.rs | 28 +++++++++++++++++++ .../type-alias-impl-trait/issue-63279.stderr | 4 ++- .../type-alias-impl-trait/issue-74280.stderr | 5 +++- 6 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/lazy-type-alias-impl-trait/branches.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/branches.stderr create mode 100644 src/test/ui/lazy-type-alias-impl-trait/branches2.rs diff --git a/compiler/rustc_typeck/src/check/expectation.rs b/compiler/rustc_typeck/src/check/expectation.rs index 9e1a70b7dfb92..e9e810344776b 100644 --- a/compiler/rustc_typeck/src/check/expectation.rs +++ b/compiler/rustc_typeck/src/check/expectation.rs @@ -1,6 +1,5 @@ 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::*; @@ -44,7 +43,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.strip_opaque(fcx) { + match *self { ExpectHasType(ety) => { let ety = fcx.shallow_resolve(ety); if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation } @@ -105,35 +104,14 @@ impl<'a, 'tcx> Expectation<'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> { - match self.strip_opaque(fcx) { - ExpectHasType(ty) => Some(ty), + match self { + ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(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> { diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.rs b/src/test/ui/lazy-type-alias-impl-trait/branches.rs new file mode 100644 index 0000000000000..aa172f3f19b6b --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/branches.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + vec![42_i32] + } else { + std::iter::empty().collect() + //~^ ERROR `Foo` cannot be built from an iterator over elements of type `_` + } +} + +fn main() {} diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr new file mode 100644 index 0000000000000..c3902f34706bd --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr @@ -0,0 +1,16 @@ +error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_` + --> $DIR/branches.rs:9:28 + | +LL | std::iter::empty().collect() + | ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `Foo` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches2.rs b/src/test/ui/lazy-type-alias-impl-trait/branches2.rs new file mode 100644 index 0000000000000..af605e4d8062d --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/branches2.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +// run-pass + +type Foo = impl std::iter::FromIterator + PartialEq> + std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + vec![42_i32] + } else { + std::iter::empty().collect() + } +} + +fn bar(b: bool) -> impl PartialEq> + std::fmt::Debug { + if b { + vec![42_i32] + } else { + std::iter::empty().collect() + } +} + +fn main() { + assert_eq!(foo(true), vec![42]); + assert_eq!(foo(false), vec![]); + assert_eq!(bar(true), vec![42]); + assert_eq!(bar(false), vec![]); +} diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 4b7dbbd6a56cc..bcc9c57f91ce6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -21,7 +21,9 @@ error[E0308]: mismatched types | LL | type Closure = impl FnOnce(); | ------------- the expected opaque type -... +LL | +LL | fn c() -> Closure { + | ------- expected `Closure` because of return type LL | || -> Closure { || () } | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | diff --git a/src/test/ui/type-alias-impl-trait/issue-74280.stderr b/src/test/ui/type-alias-impl-trait/issue-74280.stderr index 38591e37f5358..7a22b360a31d0 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -3,7 +3,10 @@ error[E0308]: mismatched types | LL | type Test = impl Copy; | --------- the expected opaque type -... +LL | +LL | fn test() -> Test { + | ---- expected `Test` because of return type +LL | let y = || -> Test { () }; LL | 7 | ^ expected `()`, found integer | From 53c96ed528257489f5537c69a33b27ffce6fee6f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 15:42:53 +0000 Subject: [PATCH 14/26] Add some tests around recursion and "revealing" --- .../lazy-type-alias-impl-trait/recursion.rs | 23 +++++++++++++++ .../lazy-type-alias-impl-trait/recursion2.rs | 21 ++++++++++++++ .../recursion2.stderr | 16 ++++++++++ .../lazy-type-alias-impl-trait/recursion3.rs | 21 ++++++++++++++ .../recursion3.stderr | 19 ++++++++++++ .../lazy-type-alias-impl-trait/recursion4.rs | 23 +++++++++++++++ .../recursion4.stderr | 29 +++++++++++++++++++ 7 files changed, 152 insertions(+) create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion2.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion3.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion4.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion.rs new file mode 100644 index 0000000000000..cf7cd5d26ca2f --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return 42 + } + let x: u32 = foo(false); + 99 +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return 42 + } + let x: u32 = bar(false); + 99 +} + +fn main() {} diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion2.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion2.rs new file mode 100644 index 0000000000000..1cc64ea17e79e --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion2.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return vec![]; + } + let x: Vec = foo(false); + std::iter::empty().collect() //~ ERROR `Foo` cannot be built from an iterator +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return vec![] + } + let x: Vec = bar(false); + std::iter::empty().collect() +} + +fn main() {} diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr new file mode 100644 index 0000000000000..1f6201a8300c6 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr @@ -0,0 +1,16 @@ +error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_` + --> $DIR/recursion2.rs:10:24 + | +LL | std::iter::empty().collect() + | ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `Foo` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion3.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion3.rs new file mode 100644 index 0000000000000..7f1cedae068f0 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion3.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return 42 + } + let x: u32 = foo(false) + 42; //~ ERROR cannot add + 99 +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return 42 + } + let x: u32 = bar(false) + 42; //~ ERROR cannot add + 99 +} + +fn main() {} diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr new file mode 100644 index 0000000000000..e1d5cafedc808 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr @@ -0,0 +1,19 @@ +error[E0369]: cannot add `{integer}` to `Foo` + --> $DIR/recursion3.rs:9:29 + | +LL | let x: u32 = foo(false) + 42; + | ---------- ^ -- {integer} + | | + | Foo + +error[E0369]: cannot add `{integer}` to `impl Debug` + --> $DIR/recursion3.rs:17:29 + | +LL | let x: u32 = bar(false) + 42; + | ---------- ^ -- {integer} + | | + | impl Debug + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion4.rs new file mode 100644 index 0000000000000..57dd7fb067c6d --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return vec![]; + } + let mut x = foo(false); + x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator + vec![] +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return vec![]; + } + let mut x = bar(false); + x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator + vec![] +} + +fn main() {} diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr new file mode 100644 index 0000000000000..42a1f782d299d --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr @@ -0,0 +1,29 @@ +error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_` + --> $DIR/recursion4.rs:10:28 + | +LL | x = std::iter::empty().collect(); + | ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `Foo` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_` + --> $DIR/recursion4.rs:19:28 + | +LL | x = std::iter::empty().collect(); + | ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `impl Debug` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 6596e9dfcf15a76203ec12d64966f5b54eb7849c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 15:54:28 +0000 Subject: [PATCH 15/26] Test that TAIT and RPIT are in sync --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 ++ src/test/ui/impl-trait/hidden-type-is-opaque-2.rs | 11 +++++++++++ .../ui/impl-trait/hidden-type-is-opaque-2.stderr | 12 ++++++++++-- src/test/ui/impl-trait/hidden-type-is-opaque.rs | 10 ++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 97935efd4f069..bb3bfbb7dd11a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -772,6 +772,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Note: this check is pessimistic, as the inference type could be matched with something other // than the opaque type, but then we need a new `TypeRelation` just for this specific case and // can't re-use `sup` below. + // See src/test/ui/impl-trait/hidden-type-is-opaque.rs and + // src/test/ui/impl-trait/hidden-type-is-opaque-2.rs for examples that hit this path. if formal_ret.has_infer_types() { for ty in ret_ty.walk() { if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() { diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs index 1b65685a6c06f..7876add5aa6cb 100644 --- a/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs @@ -2,6 +2,8 @@ // into function arguments via the function's generic parameters // FIXME(oli-obk): make `expected_inputs_for_expected_output` support this +#![feature(type_alias_impl_trait)] + fn reify_as() -> Thunk Continuation> { Thunk::new(|mut cont| { //~ ERROR type annotations needed cont.reify_as(); @@ -9,6 +11,15 @@ fn reify_as() -> Thunk Continuation> { }) } +type Tait = impl FnOnce(Continuation) -> Continuation; + +fn reify_as_tait() -> Thunk { + Thunk::new(|mut cont| { //~ ERROR type annotations needed + cont.reify_as(); + cont + }) +} + #[must_use] struct Thunk(F); diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr index e538aaeb4c5ed..dcf1982312f29 100644 --- a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr @@ -1,11 +1,19 @@ error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:6:17 + --> $DIR/hidden-type-is-opaque-2.rs:8:17 | LL | Thunk::new(|mut cont| { | ^^^^^^^^ consider giving this closure parameter a type | = note: type must be known at this point -error: aborting due to previous error +error[E0282]: type annotations needed + --> $DIR/hidden-type-is-opaque-2.rs:17:17 + | +LL | Thunk::new(|mut cont| { + | ^^^^^^^^ consider giving this closure parameter a type + | + = note: type must be known at this point + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque.rs b/src/test/ui/impl-trait/hidden-type-is-opaque.rs index b302ae36ef42c..72b4028d854f8 100644 --- a/src/test/ui/impl-trait/hidden-type-is-opaque.rs +++ b/src/test/ui/impl-trait/hidden-type-is-opaque.rs @@ -1,4 +1,5 @@ // check-pass +#![feature(type_alias_impl_trait)] fn reify_as() -> Thunk { Thunk::new(|mut cont| { @@ -7,6 +8,15 @@ fn reify_as() -> Thunk { }) } +type Tait = impl ContFn; + +fn reify_as_tait() -> Thunk { + Thunk::new(|mut cont| { + cont.reify_as(); + cont + }) +} + #[must_use] struct Thunk(F); From 3cce66c54434d0e5ef960dd40500f1f45d9158e5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Feb 2022 15:59:04 +0000 Subject: [PATCH 16/26] Add another regression test --- src/test/ui/impl-trait/issues/issue-93788.rs | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/ui/impl-trait/issues/issue-93788.rs diff --git a/src/test/ui/impl-trait/issues/issue-93788.rs b/src/test/ui/impl-trait/issues/issue-93788.rs new file mode 100644 index 0000000000000..6924931cda5db --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-93788.rs @@ -0,0 +1,27 @@ +// check-pass + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { None } +} + +fn run(f: F) + where for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} From 4f6e27d4cf783e4a10326b16596e444dc325cf3d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 22 Feb 2022 15:38:58 +0000 Subject: [PATCH 17/26] Add regression test --- src/test/ui/impl-trait/nested-return-type2.rs | 28 ++++++++++++++++ .../ui/impl-trait/nested-return-type2.stderr | 32 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/test/ui/impl-trait/nested-return-type2.rs create mode 100644 src/test/ui/impl-trait/nested-return-type2.stderr diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs new file mode 100644 index 0000000000000..77a395afba7d9 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2.rs @@ -0,0 +1,28 @@ +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +// The `impl Send` here is then later compared against the inference var +// created, causing the inference var to be set to `impl Send` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. So we error out. +fn foo() -> impl Trait { + //~^ ERROR `impl Send: Duh` is not satisfied + //~| ERROR `impl Send: Duh` is not satisfied + || 42 +} + +fn main() { +} diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr new file mode 100644 index 0000000000000..be6c19795ae7b --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `impl Send: Duh` is not satisfied + --> $DIR/nested-return-type2.rs:21:13 + | +LL | fn foo() -> impl Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send` + | +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:24:5: 24:10]` + --> $DIR/nested-return-type2.rs:12:31 + | +LL | impl R> Trait for F { + | ^^^^^ ^ + +error[E0277]: the trait bound `impl Send: Duh` is not satisfied + --> $DIR/nested-return-type2.rs:21:43 + | +LL | fn foo() -> impl Trait { + | ___________________________________________^ +LL | | +LL | | +LL | | || 42 +LL | | } + | |_^ the trait `Duh` is not implemented for `impl Send` + | +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:24:5: 24:10]` + --> $DIR/nested-return-type2.rs:12:31 + | +LL | impl R> Trait for F { + | ^^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 2aa49d4005d00e7f3b6ee1c596f0c5875d74d90a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 22 Feb 2022 17:09:25 +0000 Subject: [PATCH 18/26] Fix mixing lazy TAIT and RPIT in their defining scopes --- .../rustc_infer/src/infer/opaque_types.rs | 79 ++++++++++--------- src/test/ui/impl-trait/async_scope_creep.rs | 28 +++++++ 2 files changed, 68 insertions(+), 39 deletions(-) create mode 100644 src/test/ui/impl-trait/async_scope_creep.rs diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 5920d12a93c8e..59aea2b20306a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -95,6 +95,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Opaque(def_id, substs) => { + let origin = if self.defining_use_anchor.is_some() { + // 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)? + } else { + self.opaque_ty_origin_unchecked(def_id, cause.span) + }; 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 @@ -126,45 +165,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause.clone(), param_env, b, - if self.defining_use_anchor.is_some() { - // 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)? - } else { - self.opaque_ty_origin_unchecked(def_id, cause.span) - }, + origin, )) } _ => None, diff --git a/src/test/ui/impl-trait/async_scope_creep.rs b/src/test/ui/impl-trait/async_scope_creep.rs new file mode 100644 index 0000000000000..7a9d64d339feb --- /dev/null +++ b/src/test/ui/impl-trait/async_scope_creep.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] +// edition:2021 +// check-pass + +struct Pending {} + +struct CantOpen {} + +trait AsyncRead {} + +impl AsyncRead for i32 {} + +type PendingReader<'a> = impl AsyncRead + 'a; + +type OpeningReadFuture<'a> = + impl std::future::Future, CantOpen>>; + +impl Pending { + async fn read(&mut self) -> Result { + Ok(42) + } + + fn read_fut(&mut self) -> OpeningReadFuture<'_> { + self.read() + } +} + +fn main() {} From 7b4f715979f53f8aaecafa7c9f3330817e054665 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 22 Feb 2022 17:10:38 +0000 Subject: [PATCH 19/26] Added another folder to the `ui` dir --- src/tools/tidy/src/ui_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 0e5e0c2616e5c..63a8909c6627a 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -7,7 +7,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 985; +const ROOT_ENTRY_LIMIT: usize = 986; const ISSUES_ENTRY_LIMIT: usize = 2310; fn check_entries(path: &Path, bad: &mut bool) { From e82b0cde4ef5c8f7dfd451eb8ea1c57d4c153bf8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 22 Feb 2022 17:20:58 +0000 Subject: [PATCH 20/26] Add a test showing that a similar example compiles --- src/test/ui/impl-trait/nested-return-type3.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/ui/impl-trait/nested-return-type3.rs diff --git a/src/test/ui/impl-trait/nested-return-type3.rs b/src/test/ui/impl-trait/nested-return-type3.rs new file mode 100644 index 0000000000000..74b4dae22ebfd --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type3.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +fn foo() -> impl Trait { + 42 +} + +fn main() { +} From dc35d584a971e9a2d7a0c54be6abac779f2bf9b5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 23 Feb 2022 13:14:59 +0000 Subject: [PATCH 21/26] Show that the behaviour is the same for RPIT and TAIT --- .../ui/impl-trait/nested-return-type2-tait.rs | 32 +++++++++++++++++++ .../nested-return-type2-tait.stderr | 32 +++++++++++++++++++ .../impl-trait/nested-return-type2-tait2.rs | 32 +++++++++++++++++++ .../nested-return-type2-tait2.stderr | 15 +++++++++ .../impl-trait/nested-return-type2-tait3.rs | 31 ++++++++++++++++++ .../nested-return-type2-tait3.stderr | 15 +++++++++ .../ui/impl-trait/nested-return-type3-tait.rs | 24 ++++++++++++++ .../impl-trait/nested-return-type3-tait2.rs | 25 +++++++++++++++ .../impl-trait/nested-return-type3-tait3.rs | 24 ++++++++++++++ 9 files changed, 230 insertions(+) create mode 100644 src/test/ui/impl-trait/nested-return-type2-tait.rs create mode 100644 src/test/ui/impl-trait/nested-return-type2-tait.stderr create mode 100644 src/test/ui/impl-trait/nested-return-type2-tait2.rs create mode 100644 src/test/ui/impl-trait/nested-return-type2-tait2.stderr create mode 100644 src/test/ui/impl-trait/nested-return-type2-tait3.rs create mode 100644 src/test/ui/impl-trait/nested-return-type2-tait3.stderr create mode 100644 src/test/ui/impl-trait/nested-return-type3-tait.rs create mode 100644 src/test/ui/impl-trait/nested-return-type3-tait2.rs create mode 100644 src/test/ui/impl-trait/nested-return-type3-tait3.rs diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.rs b/src/test/ui/impl-trait/nested-return-type2-tait.rs new file mode 100644 index 0000000000000..f2217f699fbbd --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2-tait.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +type Sendable = impl Send; + +// The `Sendable` here is then later compared against the inference var +// created, causing the inference var to be set to `Sendable` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. So we error out. +fn foo() -> impl Trait { + //~^ ERROR `Sendable: Duh` is not satisfied + //~| ERROR `Sendable: Duh` is not satisfied + || 42 +} + +fn main() { +} diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr new file mode 100644 index 0000000000000..776c06b20dfc2 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2-tait.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `Sendable: Duh` is not satisfied + --> $DIR/nested-return-type2-tait.rs:25:13 + | +LL | fn foo() -> impl Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `Sendable` + | +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]` + --> $DIR/nested-return-type2-tait.rs:14:31 + | +LL | impl R> Trait for F { + | ^^^^^ ^ + +error[E0277]: the trait bound `Sendable: Duh` is not satisfied + --> $DIR/nested-return-type2-tait.rs:25:42 + | +LL | fn foo() -> impl Trait { + | __________________________________________^ +LL | | +LL | | +LL | | || 42 +LL | | } + | |_^ the trait `Duh` is not implemented for `Sendable` + | +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]` + --> $DIR/nested-return-type2-tait.rs:14:31 + | +LL | impl R> Trait for F { + | ^^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.rs b/src/test/ui/impl-trait/nested-return-type2-tait2.rs new file mode 100644 index 0000000000000..af8e066305471 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2-tait2.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +type Sendable = impl Send; +type Traitable = impl Trait; + +// The `impl Send` here is then later compared against the inference var +// created, causing the inference var to be set to `impl Send` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. So we error out. +fn foo() -> Traitable { + || 42 + //~^ ERROR `Sendable: Duh` is not satisfied +} + +fn main() { +} diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr new file mode 100644 index 0000000000000..4993202e2532e --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Sendable: Duh` is not satisfied + --> $DIR/nested-return-type2-tait2.rs:27:5 + | +LL | || 42 + | ^^^^^ the trait `Duh` is not implemented for `Sendable` + | +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:10]` + --> $DIR/nested-return-type2-tait2.rs:14:31 + | +LL | impl R> Trait for F { + | ^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.rs b/src/test/ui/impl-trait/nested-return-type2-tait3.rs new file mode 100644 index 0000000000000..74fd8a9dda0bf --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2-tait3.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +type Traitable = impl Trait; + +// The `impl Send` here is then later compared against the inference var +// created, causing the inference var to be set to `impl Send` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. So we error out. +fn foo() -> Traitable { + || 42 + //~^ ERROR `impl Send: Duh` is not satisfied +} + +fn main() { +} diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr new file mode 100644 index 0000000000000..efeaf059a3bb2 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `impl Send: Duh` is not satisfied + --> $DIR/nested-return-type2-tait3.rs:26:5 + | +LL | || 42 + | ^^^^^ the trait `Duh` is not implemented for `impl Send` + | +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:10]` + --> $DIR/nested-return-type2-tait3.rs:14:31 + | +LL | impl R> Trait for F { + | ^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/nested-return-type3-tait.rs b/src/test/ui/impl-trait/nested-return-type3-tait.rs new file mode 100644 index 0000000000000..3936f4dbbb426 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type3-tait.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +type Sendable = impl Send; + +fn foo() -> impl Trait { + 42 +} + +fn main() { +} diff --git a/src/test/ui/impl-trait/nested-return-type3-tait2.rs b/src/test/ui/impl-trait/nested-return-type3-tait2.rs new file mode 100644 index 0000000000000..56778ed90dc7b --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type3-tait2.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +type Sendable = impl Send; +type Traitable = impl Trait; + +fn foo() -> Traitable { + 42 +} + +fn main() { +} diff --git a/src/test/ui/impl-trait/nested-return-type3-tait3.rs b/src/test/ui/impl-trait/nested-return-type3-tait3.rs new file mode 100644 index 0000000000000..04c6c92b1a3c5 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type3-tait3.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +type Traitable = impl Trait; + +fn foo() -> Traitable { + 42 +} + +fn main() { +} From 360edd611d3de389c09685097cd9944d61bc8f07 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 23 Feb 2022 13:34:39 +0000 Subject: [PATCH 22/26] Also use the RPIT back compat hack in trait projection --- .../rustc_infer/src/infer/opaque_types.rs | 13 +++++--- .../src/traits/project.rs | 19 ++++++++--- src/test/ui/impl-trait/nested-return-type2.rs | 8 +++-- .../ui/impl-trait/nested-return-type2.stderr | 32 ------------------- 4 files changed, 29 insertions(+), 43 deletions(-) delete mode 100644 src/test/ui/impl-trait/nested-return-type2.stderr diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 59aea2b20306a..e8cd5988b96ec 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -39,15 +39,20 @@ pub struct OpaqueTypeDecl<'tcx> { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - pub fn replace_opaque_types_with_inference_vars( + /// This is a backwards compatibility hack to prevent breaking changes from + /// lazy TAIT around RPIT handling. + pub fn replace_opaque_types_with_inference_vars>( &self, - ty: Ty<'tcx>, + value: T, body_id: HirId, span: Span, param_env: ty::ParamEnv<'tcx>, - ) -> InferOk<'tcx, Ty<'tcx>> { + ) -> InferOk<'tcx, T> { + if !value.has_opaque_types() { + return InferOk { value, obligations: vec![] }; + } let mut obligations = vec![]; - let value = ty.fold_with(&mut ty::fold::BottomUpFolder { + let value = value.fold_with(&mut ty::fold::BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, ct_op: |ct| ct, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b61e68735712b..d4ec677a0b1c5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -214,10 +214,21 @@ fn project_and_unify_type<'cx, 'tcx>( Err(InProgress) => return Ok(Err(InProgress)), }; debug!(?normalized, ?obligations, "project_and_unify_type result"); - match infcx - .at(&obligation.cause, obligation.param_env) - .eq(normalized, obligation.predicate.term) - { + let actual = obligation.predicate.term; + // HACK: lazy TAIT would regress src/test/ui/impl-trait/nested-return-type2.rs, so we add + // a back-compat hack hat converts the RPITs into inference vars, just like they were before + // lazy TAIT. + // This does not affect TAITs in general, as tested in the nested-return-type-tait* tests. + let InferOk { value: actual, obligations: new } = + selcx.infcx().replace_opaque_types_with_inference_vars( + actual, + obligation.cause.body_id, + obligation.cause.span, + obligation.param_env, + ); + obligations.extend(new); + + match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); Ok(Ok(Some(obligations))) diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs index 77a395afba7d9..39928d543e15d 100644 --- a/src/test/ui/impl-trait/nested-return-type2.rs +++ b/src/test/ui/impl-trait/nested-return-type2.rs @@ -1,3 +1,5 @@ +// check-pass + trait Duh {} impl Duh for i32 {} @@ -17,10 +19,10 @@ impl R> Trait for F { // created, causing the inference var to be set to `impl Send` instead of // the hidden type. We already have obligations registered on the inference // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque -// type does not implement `Duh`, even if its hidden type does. So we error out. +// type does not implement `Duh`, even if its hidden type does. +// Lazy TAIT would error out, but we inserted a hack to make it work again, +// keeping backwards compatibility. fn foo() -> impl Trait { - //~^ ERROR `impl Send: Duh` is not satisfied - //~| ERROR `impl Send: Duh` is not satisfied || 42 } diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr deleted file mode 100644 index be6c19795ae7b..0000000000000 --- a/src/test/ui/impl-trait/nested-return-type2.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error[E0277]: the trait bound `impl Send: Duh` is not satisfied - --> $DIR/nested-return-type2.rs:21:13 - | -LL | fn foo() -> impl Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send` - | -note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:24:5: 24:10]` - --> $DIR/nested-return-type2.rs:12:31 - | -LL | impl R> Trait for F { - | ^^^^^ ^ - -error[E0277]: the trait bound `impl Send: Duh` is not satisfied - --> $DIR/nested-return-type2.rs:21:43 - | -LL | fn foo() -> impl Trait { - | ___________________________________________^ -LL | | -LL | | -LL | | || 42 -LL | | } - | |_^ the trait `Duh` is not implemented for `impl Send` - | -note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:24:5: 24:10]` - --> $DIR/nested-return-type2.rs:12:31 - | -LL | impl R> Trait for F { - | ^^^^^ ^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. From 88296432d346fea918ced16c413378e4d63652e8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 1 Mar 2022 16:03:27 +0000 Subject: [PATCH 23/26] Bless ui tests --- src/test/ui/chalkify/bugs/async.stderr | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr index b5519fc9cd6a6..55c0928885669 100644 --- a/src/test/ui/chalkify/bugs/async.stderr +++ b/src/test/ui/chalkify/bugs/async.stderr @@ -28,6 +28,15 @@ note: required by a bound in `from_generator` LL | T: Generator, | ^^^^^^^^^^ required by this bound in `from_generator` -error: aborting due to 2 previous errors +error[E0280]: the requirement ` as Future>::Output == u32` is not satisfied + --> $DIR/async.rs:7:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________^ +LL | | x +LL | | } + | |_^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. From 5d3941878e664f152347331c69ddd078aa880c0c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Mar 2022 13:28:12 +0000 Subject: [PATCH 24/26] Add some tests showcasing further differences between TAIT and RPIT --- .../closures_in_branches.rs | 31 +++++++++++++++++++ .../closures_in_branches.stderr | 11 +++++++ 2 files changed, 42 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/closures_in_branches.rs create mode 100644 src/test/ui/type-alias-impl-trait/closures_in_branches.stderr diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.rs b/src/test/ui/type-alias-impl-trait/closures_in_branches.rs new file mode 100644 index 0000000000000..a1a9401acc2c4 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::ops::FnOnce(String) -> usize; + +fn foo(b: bool) -> Foo { + if b { + |x| x.len() + } else { + panic!() + } +} + + +type Foo1 = impl std::ops::FnOnce(String) -> usize; +fn foo1(b: bool) -> Foo1 { + |x| x.len() +} + +fn bar(b: bool) -> impl std::ops::FnOnce(String) -> usize { + if b { + |x| x.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + +fn bar1(b: bool) -> impl std::ops::FnOnce(String) -> usize { + |x| x.len() +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr new file mode 100644 index 0000000000000..cfa4a4b9d20ba --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/closures_in_branches.rs:21:10 + | +LL | |x| x.len() + | ^ consider giving this closure parameter a type + | + = note: type must be known at this point + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. From b262c7c2dace54d58557fc79b9320c03593a21be Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 17 Mar 2022 14:27:21 +0000 Subject: [PATCH 25/26] Add test for revealing auto traits in the defining scope --- .../ui/type-alias-impl-trait/reveal_local.rs | 26 ++++++++++ .../type-alias-impl-trait/reveal_local.stderr | 51 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/reveal_local.rs create mode 100644 src/test/ui/type-alias-impl-trait/reveal_local.stderr diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.rs b/src/test/ui/type-alias-impl-trait/reveal_local.rs new file mode 100644 index 0000000000000..145186baa1faa --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/reveal_local.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; +//~^ ERROR cycle detected +//~| ERROR cycle detected + +fn is_send() { } + +fn not_good() { + // Error: this function does not constrain `Foo` to any particular + // hidden type, so it cannot rely on `Send` being true. + is_send::(); +} + +fn not_gooder() { + // Constrain `Foo = u32` + let x: Foo = 22_u32; + + // while we could know this from the hidden type, it would + // need extra roundabout logic to support it. + is_send::(); +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.stderr b/src/test/ui/type-alias-impl-trait/reveal_local.stderr new file mode 100644 index 0000000000000..5d48dd5b2bf73 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/reveal_local.stderr @@ -0,0 +1,51 @@ +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_good`... + --> $DIR/reveal_local.rs:11:1 + | +LL | fn not_good() { + | ^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_gooder`... + --> $DIR/reveal_local.rs:17:1 + | +LL | fn not_gooder() { + | ^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. From 638f84d782e9d8ad4fe5f35fea75088c11986e51 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 28 Mar 2022 17:22:42 +0000 Subject: [PATCH 26/26] rebase fallout --- src/test/ui/chalkify/bugs/async.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr index 55c0928885669..78d78f57955a8 100644 --- a/src/test/ui/chalkify/bugs/async.stderr +++ b/src/test/ui/chalkify/bugs/async.stderr @@ -28,7 +28,7 @@ note: required by a bound in `from_generator` LL | T: Generator, | ^^^^^^^^^^ required by this bound in `from_generator` -error[E0280]: the requirement ` as Future>::Output == u32` is not satisfied +error[E0280]: the requirement `::Output == u32` is not satisfied --> $DIR/async.rs:7:29 | LL | async fn foo(x: u32) -> u32 {