summaryrefslogtreecommitdiffstats
path: root/src/test/ui/impl-trait
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/impl-trait')
-rw-r--r--src/test/ui/impl-trait/associated-impl-trait-type-generic-trait.rs30
-rw-r--r--src/test/ui/impl-trait/associated-impl-trait-type-trivial.rs20
-rw-r--r--src/test/ui/impl-trait/associated-impl-trait-type.rs24
-rw-r--r--src/test/ui/impl-trait/async_scope_creep.rs28
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak-rpass.rs21
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.rs23
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr89
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak2.rs39
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak2.stderr59
-rw-r--r--src/test/ui/impl-trait/auto-trait.rs26
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr24
-rw-r--r--src/test/ui/impl-trait/autoderef.rs19
-rw-r--r--src/test/ui/impl-trait/auxiliary/extra-item.rs1
-rw-r--r--src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs36
-rw-r--r--src/test/ui/impl-trait/auxiliary/xcrate.rs23
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.rs48
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.stderr52
-rw-r--r--src/test/ui/impl-trait/bound-normalization-pass.rs87
-rw-r--r--src/test/ui/impl-trait/bounds_regression.rs24
-rw-r--r--src/test/ui/impl-trait/can-return-unconstrained-closure.rs23
-rw-r--r--src/test/ui/impl-trait/closure-calling-parent-fn.rs12
-rw-r--r--src/test/ui/impl-trait/closure-in-impl-trait-arg.rs7
-rw-r--r--src/test/ui/impl-trait/closure-in-impl-trait.rs14
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.rs45
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.stderr36
-rw-r--r--src/test/ui/impl-trait/deprecated_annotation.rs19
-rw-r--r--src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs15
-rw-r--r--src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr9
-rw-r--r--src/test/ui/impl-trait/divergence.rs13
-rw-r--r--src/test/ui/impl-trait/does-not-live-long-enough.rs11
-rw-r--r--src/test/ui/impl-trait/does-not-live-long-enough.stderr21
-rw-r--r--src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs16
-rw-r--r--src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs11
-rw-r--r--src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs27
-rw-r--r--src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs23
-rw-r--r--src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs74
-rw-r--r--src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr307
-rw-r--r--src/test/ui/impl-trait/equal-hidden-lifetimes.rs49
-rw-r--r--src/test/ui/impl-trait/equal-hidden-lifetimes.stderr10
-rw-r--r--src/test/ui/impl-trait/equality-rpass.rs48
-rw-r--r--src/test/ui/impl-trait/equality-rpass.stderr12
-rw-r--r--src/test/ui/impl-trait/equality.rs43
-rw-r--r--src/test/ui/impl-trait/equality.stderr41
-rw-r--r--src/test/ui/impl-trait/equality2.rs44
-rw-r--r--src/test/ui/impl-trait/equality2.stderr75
-rw-r--r--src/test/ui/impl-trait/example-calendar.rs840
-rw-r--r--src/test/ui/impl-trait/example-st.rs30
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs21
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs5
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr18
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs7
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs7
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs6
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr21
-rw-r--r--src/test/ui/impl-trait/extra-item.rs10
-rw-r--r--src/test/ui/impl-trait/extra-item.stderr9
-rw-r--r--src/test/ui/impl-trait/fallback.rs9
-rw-r--r--src/test/ui/impl-trait/fallback_inference.rs7
-rw-r--r--src/test/ui/impl-trait/fallback_inference.stderr14
-rw-r--r--src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr9
-rw-r--r--src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr22
-rw-r--r--src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs12
-rw-r--r--src/test/ui/impl-trait/hidden-lifetimes.rs63
-rw-r--r--src/test/ui/impl-trait/hidden-lifetimes.stderr29
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque-2.rs45
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr15
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque.rs42
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch-ab.rs12
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr23
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch.rs32
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch.stderr43
-rw-r--r--src/test/ui/impl-trait/impl-trait-in-macro.rs20
-rw-r--r--src/test/ui/impl-trait/impl-trait-in-macro.stderr22
-rw-r--r--src/test/ui/impl-trait/impl-trait-plus-priority.rs49
-rw-r--r--src/test/ui/impl-trait/impl-trait-plus-priority.stderr69
-rw-r--r--src/test/ui/impl-trait/impl_trait_projections.rs39
-rw-r--r--src/test/ui/impl-trait/impl_trait_projections.stderr34
-rw-r--r--src/test/ui/impl-trait/issue-100187.rs12
-rw-r--r--src/test/ui/impl-trait/issue-46959.rs9
-rw-r--r--src/test/ui/impl-trait/issue-49579.rs14
-rw-r--r--src/test/ui/impl-trait/issue-49685.rs13
-rw-r--r--src/test/ui/impl-trait/issue-51185.rs8
-rw-r--r--src/test/ui/impl-trait/issue-54966.rs6
-rw-r--r--src/test/ui/impl-trait/issue-54966.stderr9
-rw-r--r--src/test/ui/impl-trait/issue-55872-1.rs20
-rw-r--r--src/test/ui/impl-trait/issue-55872-1.stderr37
-rw-r--r--src/test/ui/impl-trait/issue-55872-2.rs19
-rw-r--r--src/test/ui/impl-trait/issue-55872-2.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.rs20
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.stderr9
-rw-r--r--src/test/ui/impl-trait/issue-55872.rs18
-rw-r--r--src/test/ui/impl-trait/issue-55872.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-56445.rs25
-rw-r--r--src/test/ui/impl-trait/issue-68532.rs13
-rw-r--r--src/test/ui/impl-trait/issue-72911.rs22
-rw-r--r--src/test/ui/impl-trait/issue-72911.stderr22
-rw-r--r--src/test/ui/impl-trait/issue-86465.rs10
-rw-r--r--src/test/ui/impl-trait/issue-86465.stderr11
-rw-r--r--src/test/ui/impl-trait/issue-87450.rs16
-rw-r--r--src/test/ui/impl-trait/issue-87450.stderr27
-rw-r--r--src/test/ui/impl-trait/issue-99073-2.rs17
-rw-r--r--src/test/ui/impl-trait/issue-99073-2.stderr14
-rw-r--r--src/test/ui/impl-trait/issue-99073.rs8
-rw-r--r--src/test/ui/impl-trait/issue-99073.stderr14
-rw-r--r--src/test/ui/impl-trait/issue-99642-2.rs8
-rw-r--r--src/test/ui/impl-trait/issue-99642.rs7
-rw-r--r--src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs25
-rw-r--r--src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr27
-rw-r--r--src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs22
-rw-r--r--src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr19
-rw-r--r--src/test/ui/impl-trait/issues/issue-42479.rs17
-rw-r--r--src/test/ui/impl-trait/issues/issue-49376.rs23
-rw-r--r--src/test/ui/impl-trait/issues/issue-52128.rs25
-rw-r--r--src/test/ui/impl-trait/issues/issue-53457.rs14
-rw-r--r--src/test/ui/impl-trait/issues/issue-54600.rs7
-rw-r--r--src/test/ui/impl-trait/issues/issue-54600.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-54840.rs7
-rw-r--r--src/test/ui/impl-trait/issues/issue-54840.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-54895.rs22
-rw-r--r--src/test/ui/impl-trait/issues/issue-54895.stderr14
-rw-r--r--src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs22
-rw-r--r--src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs29
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs17
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr12
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs12
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs12
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr12
-rw-r--r--src/test/ui/impl-trait/issues/issue-58504.rs12
-rw-r--r--src/test/ui/impl-trait/issues/issue-58504.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-58956.rs14
-rw-r--r--src/test/ui/impl-trait/issues/issue-58956.stderr15
-rw-r--r--src/test/ui/impl-trait/issues/issue-62742.rs32
-rw-r--r--src/test/ui/impl-trait/issues/issue-62742.stderr50
-rw-r--r--src/test/ui/impl-trait/issues/issue-65581.rs34
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.rs26
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.stderr14
-rw-r--r--src/test/ui/impl-trait/issues/issue-70877.rs36
-rw-r--r--src/test/ui/impl-trait/issues/issue-70877.stderr19
-rw-r--r--src/test/ui/impl-trait/issues/issue-70971.rs4
-rw-r--r--src/test/ui/impl-trait/issues/issue-70971.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-74282.rs11
-rw-r--r--src/test/ui/impl-trait/issues/issue-74282.stderr40
-rw-r--r--src/test/ui/impl-trait/issues/issue-77987.rs21
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.rs20
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.stderr28
-rw-r--r--src/test/ui/impl-trait/issues/issue-79099.rs10
-rw-r--r--src/test/ui/impl-trait/issues/issue-79099.stderr20
-rw-r--r--src/test/ui/impl-trait/issues/issue-82139.rs19
-rw-r--r--src/test/ui/impl-trait/issues/issue-82139.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-83919.rs32
-rw-r--r--src/test/ui/impl-trait/issues/issue-83919.stderr12
-rw-r--r--src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs12
-rw-r--r--src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr15
-rw-r--r--src/test/ui/impl-trait/issues/issue-84073.rs33
-rw-r--r--src/test/ui/impl-trait/issues/issue-84073.stderr14
-rw-r--r--src/test/ui/impl-trait/issues/issue-84919.rs9
-rw-r--r--src/test/ui/impl-trait/issues/issue-84919.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-86201.rs13
-rw-r--r--src/test/ui/impl-trait/issues/issue-86642.rs8
-rw-r--r--src/test/ui/impl-trait/issues/issue-86642.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-86719.rs12
-rw-r--r--src/test/ui/impl-trait/issues/issue-86719.stderr29
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.rs55
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.stderr19
-rw-r--r--src/test/ui/impl-trait/issues/issue-87295.rs18
-rw-r--r--src/test/ui/impl-trait/issues/issue-87295.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-87340.rs14
-rw-r--r--src/test/ui/impl-trait/issues/issue-87340.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.rs28
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.stderr38
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236.rs18
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236.stderr14
-rw-r--r--src/test/ui/impl-trait/issues/issue-89312.rs24
-rw-r--r--src/test/ui/impl-trait/issues/issue-92305.rs15
-rw-r--r--src/test/ui/impl-trait/issues/issue-92305.stderr37
-rw-r--r--src/test/ui/impl-trait/issues/issue-93788.rs27
-rw-r--r--src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs26
-rw-r--r--src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr25
-rw-r--r--src/test/ui/impl-trait/lifetimes.rs123
-rw-r--r--src/test/ui/impl-trait/lifetimes2.rs10
-rw-r--r--src/test/ui/impl-trait/method-suggestion-no-duplication.rs9
-rw-r--r--src/test/ui/impl-trait/method-suggestion-no-duplication.stderr16
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes.rs12
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs26
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr12
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr15
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs26
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr15
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs50
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs25
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs28
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs25
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs42
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs36
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr17
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs39
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr17
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs47
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr126
-rw-r--r--src/test/ui/impl-trait/needs_least_region_or_bound.rs21
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.rs24
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr26
-rw-r--r--src/test/ui/impl-trait/nested-return-type.rs16
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait.rs33
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait2.rs32
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait2.stderr16
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait3.rs31
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait3.stderr16
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.rs30
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait.rs24
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait2.rs25
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait3.rs24
-rw-r--r--src/test/ui/impl-trait/nested-return-type3.rs20
-rw-r--r--src/test/ui/impl-trait/nested-rpit-hrtb.rs64
-rw-r--r--src/test/ui/impl-trait/nested-rpit-hrtb.stderr82
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.rs32
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.stderr70
-rw-r--r--src/test/ui/impl-trait/nesting.rs15
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.rs77
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.stderr284
-rw-r--r--src/test/ui/impl-trait/no-trait.rs3
-rw-r--r--src/test/ui/impl-trait/no-trait.stderr8
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs35
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr47
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs46
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr21
-rw-r--r--src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs101
-rw-r--r--src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr194
-rw-r--r--src/test/ui/impl-trait/printing-binder.rs14
-rw-r--r--src/test/ui/impl-trait/printing-binder.stderr31
-rw-r--r--src/test/ui/impl-trait/private_unused.rs13
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs20
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr20
-rw-r--r--src/test/ui/impl-trait/projection.rs29
-rw-r--r--src/test/ui/impl-trait/question_mark.rs30
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs9
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs96
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr148
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs25
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr47
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs18
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr14
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs28
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr14
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs19
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs18
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs22
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound.rs21
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound.stderr17
-rw-r--r--src/test/ui/impl-trait/return-position-impl-trait-minimal.rs5
-rw-r--r--src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs7
-rw-r--r--src/test/ui/impl-trait/rpit-not-sized.rs6
-rw-r--r--src/test/ui/impl-trait/rpit-not-sized.stderr12
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.rs18
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr55
-rw-r--r--src/test/ui/impl-trait/suggest-calling-rpit-closure.rs12
-rw-r--r--src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr21
-rw-r--r--src/test/ui/impl-trait/trait_resolution.rs30
-rw-r--r--src/test/ui/impl-trait/trait_type.rs24
-rw-r--r--src/test/ui/impl-trait/trait_type.stderr40
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other.rs19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other.stderr19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other2.rs16
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other2.stderr27
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other3.rs19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other3.stderr19
-rw-r--r--src/test/ui/impl-trait/type-alias-generic-param.rs23
-rw-r--r--src/test/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs12
-rw-r--r--src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs16
-rw-r--r--src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr15
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.rs12
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.stderr14
-rw-r--r--src/test/ui/impl-trait/universal-mismatched-type.rs7
-rw-r--r--src/test/ui/impl-trait/universal-mismatched-type.stderr16
-rw-r--r--src/test/ui/impl-trait/universal-two-impl-traits.rs16
-rw-r--r--src/test/ui/impl-trait/universal-two-impl-traits.stderr20
-rw-r--r--src/test/ui/impl-trait/universal_hrtb_anon.rs10
-rw-r--r--src/test/ui/impl-trait/universal_hrtb_named.rs10
-rw-r--r--src/test/ui/impl-trait/universal_in_adt_in_parameters.rs22
-rw-r--r--src/test/ui/impl-trait/universal_in_impl_trait_in_parameters.rs30
-rw-r--r--src/test/ui/impl-trait/universal_in_trait_defn_parameters.rs18
-rw-r--r--src/test/ui/impl-trait/universal_multiple_bounds.rs13
-rw-r--r--src/test/ui/impl-trait/universal_wrong_bounds.rs13
-rw-r--r--src/test/ui/impl-trait/universal_wrong_bounds.stderr25
-rw-r--r--src/test/ui/impl-trait/universal_wrong_hrtb.rs8
-rw-r--r--src/test/ui/impl-trait/universal_wrong_hrtb.stderr14
-rw-r--r--src/test/ui/impl-trait/unsafety-checking-cycle.rs32
-rw-r--r--src/test/ui/impl-trait/wf-eval-order.rs39
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.rs6
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.stderr9
-rw-r--r--src/test/ui/impl-trait/where-allowed.rs251
-rw-r--r--src/test/ui/impl-trait/where-allowed.stderr322
-rw-r--r--src/test/ui/impl-trait/xcrate.rs11
-rw-r--r--src/test/ui/impl-trait/xcrate_simple.rs9
295 files changed, 9214 insertions, 0 deletions
diff --git a/src/test/ui/impl-trait/associated-impl-trait-type-generic-trait.rs b/src/test/ui/impl-trait/associated-impl-trait-type-generic-trait.rs
new file mode 100644
index 000000000..6c7c46b0e
--- /dev/null
+++ b/src/test/ui/impl-trait/associated-impl-trait-type-generic-trait.rs
@@ -0,0 +1,30 @@
+#![feature(type_alias_impl_trait)]
+// build-pass (FIXME(62277): could be check-pass?)
+
+trait Bar {}
+struct Dummy<U>(U);
+impl<V> Bar for Dummy<V> {}
+
+trait Foo<T> {
+ type Assoc: Bar;
+ fn foo(t: T) -> Self::Assoc;
+}
+
+impl<W> Foo<W> for i32 {
+ type Assoc = impl Bar;
+ fn foo(w: W) -> Self::Assoc {
+ Dummy(w)
+ }
+}
+
+struct NonGeneric;
+impl Bar for NonGeneric {}
+
+impl<W> Foo<W> for u32 {
+ type Assoc = impl Bar;
+ fn foo(_: W) -> Self::Assoc {
+ NonGeneric
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/associated-impl-trait-type-trivial.rs b/src/test/ui/impl-trait/associated-impl-trait-type-trivial.rs
new file mode 100644
index 000000000..cdda341ca
--- /dev/null
+++ b/src/test/ui/impl-trait/associated-impl-trait-type-trivial.rs
@@ -0,0 +1,20 @@
+#![feature(type_alias_impl_trait)]
+// build-pass (FIXME(62277): could be check-pass?)
+
+trait Bar {}
+struct Dummy;
+impl Bar for Dummy {}
+
+trait Foo {
+ type Assoc: Bar;
+ fn foo() -> Self::Assoc;
+}
+
+impl Foo for i32 {
+ type Assoc = impl Bar;
+ fn foo() -> Self::Assoc {
+ Dummy
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/associated-impl-trait-type.rs b/src/test/ui/impl-trait/associated-impl-trait-type.rs
new file mode 100644
index 000000000..d0661d66f
--- /dev/null
+++ b/src/test/ui/impl-trait/associated-impl-trait-type.rs
@@ -0,0 +1,24 @@
+#![feature(type_alias_impl_trait)]
+// build-pass (FIXME(62277): could be check-pass?)
+
+trait Bar {}
+struct Dummy;
+impl Bar for Dummy {}
+
+trait Foo {
+ type Assoc: Bar;
+ fn foo() -> Self::Assoc;
+ fn bar() -> Self::Assoc;
+}
+
+impl Foo for i32 {
+ type Assoc = impl Bar;
+ fn foo() -> Self::Assoc {
+ Dummy
+ }
+ fn bar() -> Self::Assoc {
+ Dummy
+ }
+}
+
+fn main() {}
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 000000000..7a9d64d33
--- /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<Output = Result<PendingReader<'a>, CantOpen>>;
+
+impl Pending {
+ async fn read(&mut self) -> Result<impl AsyncRead + '_, CantOpen> {
+ Ok(42)
+ }
+
+ fn read_fut(&mut self) -> OpeningReadFuture<'_> {
+ self.read()
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait-leak-rpass.rs b/src/test/ui/impl-trait/auto-trait-leak-rpass.rs
new file mode 100644
index 000000000..9976a018b
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak-rpass.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+// Fast path, main can see the concrete type returned.
+fn before() -> impl FnMut(i32) {
+ let mut p = Box::new(0);
+ move |x| *p = x
+}
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+ send(before());
+ send(after());
+}
+
+// Deferred path, main has to wait until typeck finishes,
+// to check if the return type of after is Send.
+fn after() -> impl FnMut(i32) {
+ let mut p = Box::new(0);
+ move |x| *p = x
+}
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
new file mode 100644
index 000000000..c2fbbf94f
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -0,0 +1,23 @@
+use std::cell::Cell;
+use std::rc::Rc;
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+}
+
+// Cycles should work as the deferred obligations are
+// independently resolved and only require the concrete
+// return type, which can't depend on the obligation.
+fn cycle1() -> impl Clone {
+ //~^ ERROR cycle detected
+ send(cycle2().clone());
+
+ Rc::new(Cell::new(5))
+}
+
+fn cycle2() -> impl Clone {
+ send(cycle1().clone());
+
+ Rc::new(String::from("foo"))
+}
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
new file mode 100644
index 000000000..634ff1486
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -0,0 +1,89 @@
+error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
+ --> $DIR/auto-trait-leak.rs:12:16
+ |
+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:14:5
+ |
+LL | send(cycle2().clone());
+ | ^^^^
+ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+note: ...which requires computing type of `cycle2::{opaque#0}`...
+ --> $DIR/auto-trait-leak.rs:19:16
+ |
+LL | fn cycle2() -> impl Clone {
+ | ^^^^^^^^^^
+note: ...which requires borrow-checking `cycle2`...
+ --> $DIR/auto-trait-leak.rs:19:1
+ |
+LL | fn cycle2() -> impl Clone {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+ --> $DIR/auto-trait-leak.rs:19:1
+ |
+LL | fn cycle2() -> impl Clone {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing MIR for `cycle2`...
+ --> $DIR/auto-trait-leak.rs:19:1
+ |
+LL | fn cycle2() -> impl Clone {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `cycle2`...
+ --> $DIR/auto-trait-leak.rs:19:1
+ |
+LL | fn cycle2() -> impl Clone {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `cycle2`...
+ --> $DIR/auto-trait-leak.rs:19:1
+ |
+LL | fn cycle2() -> impl Clone {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `cycle2`...
+ --> $DIR/auto-trait-leak.rs:20:5
+ |
+LL | send(cycle1().clone());
+ | ^^^^
+ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+ = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+ --> $DIR/auto-trait-leak.rs:1:1
+ |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+... |
+LL | | Rc::new(String::from("foo"))
+LL | | }
+ | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.rs b/src/test/ui/impl-trait/auto-trait-leak2.rs
new file mode 100644
index 000000000..09450089a
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak2.rs
@@ -0,0 +1,39 @@
+use std::cell::Cell;
+use std::rc::Rc;
+
+// Fast path, main can see the concrete type returned.
+fn before() -> impl Fn(i32) {
+//~^ NOTE within this `impl Fn
+//~| NOTE within the type `impl Fn
+//~| NOTE expansion of desugaring
+ let p = Rc::new(Cell::new(0));
+ move |x| p.set(x) //~ NOTE used within this closure
+}
+
+fn send<T: Send>(_: T) {}
+//~^ NOTE required by a bound
+//~| NOTE required by a bound
+//~| NOTE required by this bound
+//~| NOTE required by this bound
+
+fn main() {
+ send(before());
+ //~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely
+ //~| NOTE `Rc<Cell<i32>>` cannot be sent between threads safely
+ //~| NOTE required by a bound
+
+ send(after());
+ //~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely
+ //~| NOTE `Rc<Cell<i32>>` cannot be sent between threads safely
+ //~| NOTE required by a bound
+}
+
+// Deferred path, main has to wait until typeck finishes,
+// to check if the return type of after is Send.
+fn after() -> impl Fn(i32) {
+//~^ NOTE within this `impl Fn(i32)`
+//~| NOTE in this expansion
+//~| NOTE appears within the type
+ let p = Rc::new(Cell::new(0));
+ move |x| p.set(x) //~ NOTE used within this closure
+}
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
new file mode 100644
index 000000000..52fa28145
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr
@@ -0,0 +1,59 @@
+error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
+ --> $DIR/auto-trait-leak2.rs:20:10
+ |
+LL | fn before() -> impl Fn(i32) {
+ | ------------ within this `impl Fn(i32)`
+...
+LL | send(before());
+ | ---- ^^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
+note: required because it's used within this closure
+ --> $DIR/auto-trait-leak2.rs:10:5
+ |
+LL | move |x| p.set(x)
+ | ^^^^^^^^
+note: required because it appears within the type `impl Fn(i32)`
+ --> $DIR/auto-trait-leak2.rs:5:16
+ |
+LL | fn before() -> impl Fn(i32) {
+ | ^^^^^^^^^^^^
+note: required by a bound in `send`
+ --> $DIR/auto-trait-leak2.rs:13:12
+ |
+LL | fn send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `send`
+
+error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
+ --> $DIR/auto-trait-leak2.rs:25:10
+ |
+LL | send(after());
+ | ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+...
+LL | fn after() -> impl Fn(i32) {
+ | ------------ within this `impl Fn(i32)`
+ |
+ = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
+note: required because it's used within this closure
+ --> $DIR/auto-trait-leak2.rs:38:5
+ |
+LL | move |x| p.set(x)
+ | ^^^^^^^^
+note: required because it appears within the type `impl Fn(i32)`
+ --> $DIR/auto-trait-leak2.rs:33:15
+ |
+LL | fn after() -> impl Fn(i32) {
+ | ^^^^^^^^^^^^
+note: required by a bound in `send`
+ --> $DIR/auto-trait-leak2.rs:13:12
+ |
+LL | fn send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `send`
+
+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/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs
new file mode 100644
index 000000000..afa95645a
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait.rs
@@ -0,0 +1,26 @@
+// Tests that type alias impls traits do not leak auto-traits for
+// the purposes of coherence checking
+#![feature(type_alias_impl_trait)]
+
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
+type OpaqueType = impl OpaqueTrait;
+fn mk_opaque() -> OpaqueType {
+ ()
+}
+
+#[derive(Debug)]
+struct D<T>(T);
+
+trait AnotherTrait {}
+impl<T: Send> AnotherTrait for T {}
+
+// This is in error, because we cannot assume that `OpaqueType: !Send`.
+// (We treat opaque types as "foreign types" that could grow more impls
+// in the future.)
+impl AnotherTrait for D<OpaqueType> {
+ //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+ //~| ERROR cannot implement trait on type alias impl trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
new file mode 100644
index 000000000..5e10272b0
--- /dev/null
+++ b/src/test/ui/impl-trait/auto-trait.stderr
@@ -0,0 +1,24 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+ --> $DIR/auto-trait.rs:21:1
+ |
+LL | impl<T: Send> AnotherTrait for T {}
+ | -------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+
+error: cannot implement trait on type alias impl trait
+ --> $DIR/auto-trait.rs:21:25
+ |
+LL | impl AnotherTrait for D<OpaqueType> {
+ | ^^^^^^^^^^
+ |
+note: type alias impl trait defined here
+ --> $DIR/auto-trait.rs:7:19
+ |
+LL | type OpaqueType = impl OpaqueTrait;
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/autoderef.rs b/src/test/ui/impl-trait/autoderef.rs
new file mode 100644
index 000000000..5e4f49954
--- /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<Target = Path> + '_ {
+ 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/auxiliary/extra-item.rs b/src/test/ui/impl-trait/auxiliary/extra-item.rs
new file mode 100644
index 000000000..8eaeafa52
--- /dev/null
+++ b/src/test/ui/impl-trait/auxiliary/extra-item.rs
@@ -0,0 +1 @@
+pub trait MyTrait {}
diff --git a/src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs b/src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs
new file mode 100644
index 000000000..cefb17e0f
--- /dev/null
+++ b/src/test/ui/impl-trait/auxiliary/no_method_suggested_traits.rs
@@ -0,0 +1,36 @@
+pub use reexport::Reexported;
+
+pub struct Foo;
+pub enum Bar { X }
+
+pub mod foo {
+ pub trait PubPub {
+ fn method(&self) {}
+
+ fn method3(&self) {}
+ }
+
+ impl PubPub for u32 {}
+ impl PubPub for i32 {}
+}
+pub mod bar {
+ trait PubPriv {
+ fn method(&self);
+ }
+}
+mod qux {
+ pub trait PrivPub {
+ fn method(&self);
+ }
+}
+mod quz {
+ trait PrivPriv {
+ fn method(&self);
+ }
+}
+
+mod reexport {
+ pub trait Reexported {
+ fn method(&self);
+ }
+}
diff --git a/src/test/ui/impl-trait/auxiliary/xcrate.rs b/src/test/ui/impl-trait/auxiliary/xcrate.rs
new file mode 100644
index 000000000..ac016258b
--- /dev/null
+++ b/src/test/ui/impl-trait/auxiliary/xcrate.rs
@@ -0,0 +1,23 @@
+// NOTE commented out due to issue #45994
+//pub fn fourway_add(a: i32) -> impl Fn(i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
+// move |b| move |c| move |d| a + b + c + d
+//}
+
+fn some_internal_fn() -> u32 {
+ 1
+}
+
+fn other_internal_fn() -> u32 {
+ 1
+}
+
+// See #40839
+pub fn return_closure_accessing_internal_fn() -> impl Fn() -> u32 {
+ || {
+ some_internal_fn() + 1
+ }
+}
+
+pub fn return_internal_fn() -> impl Fn() -> u32 {
+ other_internal_fn
+}
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs
new file mode 100644
index 000000000..332959247
--- /dev/null
+++ b/src/test/ui/impl-trait/bound-normalization-fail.rs
@@ -0,0 +1,48 @@
+// edition:2018
+
+// See issue 60414
+
+// Reduction to `impl Trait`
+
+struct Foo<T>(T);
+
+trait FooLike {
+ type Output;
+}
+
+impl<T> FooLike for Foo<T> {
+ type Output = T;
+}
+
+mod impl_trait {
+ use super::*;
+
+ trait Trait {
+ type Assoc;
+ }
+
+ /// `T::Assoc` can't be normalized any further here.
+ fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
+ //~^ ERROR: type mismatch
+ Foo(())
+ }
+}
+
+// Same with lifetimes in the trait
+
+mod lifetimes {
+ use super::*;
+
+ trait Trait<'a> {
+ type Assoc;
+ }
+
+ /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
+ fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+ //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+ //~| ERROR: type mismatch
+ Foo(())
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr
new file mode 100644
index 000000000..bd8d3d3d2
--- /dev/null
+++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr
@@ -0,0 +1,52 @@
+error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+ --> $DIR/bound-normalization-fail.rs:25:32
+ |
+LL | fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+LL |
+LL | Foo(())
+ | ------- return type was inferred to be `Foo<()>` here
+ |
+note: expected this to be `()`
+ --> $DIR/bound-normalization-fail.rs:14:19
+ |
+LL | type Output = T;
+ | ^
+ = note: expected unit type `()`
+ found associated type `<T as impl_trait::Trait>::Assoc`
+help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
+ |
+LL | fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
+ | ++++++++++++
+
+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
+ |
+LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
+ --> $DIR/bound-normalization-fail.rs:41:41
+ |
+LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
+...
+LL | Foo(())
+ | ------- return type was inferred to be `Foo<()>` here
+ |
+note: expected this to be `()`
+ --> $DIR/bound-normalization-fail.rs:14:19
+ |
+LL | type Output = T;
+ | ^
+ = note: expected unit type `()`
+ found associated type `<T as lifetimes::Trait<'static>>::Assoc`
+help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
+ |
+LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
+ | ++++++++++++
+
+error: aborting due to 3 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/bound-normalization-pass.rs b/src/test/ui/impl-trait/bound-normalization-pass.rs
new file mode 100644
index 000000000..51718079d
--- /dev/null
+++ b/src/test/ui/impl-trait/bound-normalization-pass.rs
@@ -0,0 +1,87 @@
+// check-pass
+// edition:2018
+// revisions: default sa
+//[sa] compile-flags: -Z save-analysis
+//-^ To make this the regression test for #75962.
+
+#![feature(type_alias_impl_trait)]
+
+// See issue 60414
+
+// Reduction to `impl Trait`
+
+struct Foo<T>(T);
+
+trait FooLike {
+ type Output;
+}
+
+impl<T> FooLike for Foo<T> {
+ type Output = T;
+}
+
+mod impl_trait {
+ use super::*;
+
+ trait Trait {
+ type Assoc;
+ }
+
+ /// `T::Assoc` should be normalized to `()` here.
+ fn foo_pass<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
+ Foo(())
+ }
+}
+
+// Same with lifetimes in the trait
+
+mod lifetimes {
+ use super::*;
+
+ trait Trait<'a> {
+ type Assoc;
+ }
+
+ /// Like above.
+ ///
+ /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here
+ fn foo2_pass<'a, T: Trait<'a, Assoc = ()> + 'a>()
+ -> impl FooLike<Output = <T as Trait<'a>>::Assoc> + 'a {
+ Foo(())
+ }
+
+ /// Normalization to type containing bound region.
+ ///
+ /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here
+ fn foo2_pass2<'a, T: Trait<'a, Assoc = &'a ()> + 'a>()
+ -> impl FooLike<Output = <T as Trait<'a>>::Assoc> + 'a {
+ Foo(&())
+ }
+}
+
+// The same applied to `type Foo = impl Bar`s
+
+mod opaque_types {
+ trait Implemented {
+ type Assoc;
+ }
+ impl<T> Implemented for T {
+ type Assoc = u8;
+ }
+
+ trait Trait {
+ type Out;
+ }
+
+ impl Trait for () {
+ type Out = u8;
+ }
+
+ type Ex = impl Trait<Out = <() as Implemented>::Assoc>;
+
+ fn define() -> Ex {
+ ()
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/bounds_regression.rs b/src/test/ui/impl-trait/bounds_regression.rs
new file mode 100644
index 000000000..31fc46203
--- /dev/null
+++ b/src/test/ui/impl-trait/bounds_regression.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+pub trait FakeGenerator {
+ type Yield;
+ type Return;
+}
+
+pub trait FakeFuture {
+ type Output;
+}
+
+pub fn future_from_generator<
+ T: FakeGenerator<Yield = ()>
+>(x: T) -> impl FakeFuture<Output = T::Return> {
+ GenFuture(x)
+}
+
+struct GenFuture<T: FakeGenerator<Yield = ()>>(#[allow(unused_tuple_struct_fields)] T);
+
+impl<T: FakeGenerator<Yield = ()>> FakeFuture for GenFuture<T> {
+ type Output = T::Return;
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs
new file mode 100644
index 000000000..7ae1ac4f5
--- /dev/null
+++ b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs
@@ -0,0 +1,23 @@
+// Test that we are special casing "outlives" for opaque types.
+//
+// The return type of a closure is not required to outlive the closure. As such
+// the following code would not compile if we used a standard outlives check
+// when checking the return type, because the return type of the closure would
+// be `&ReEmpty i32`, and we don't allow `ReEmpty` to occur in the concrete
+// type used for an opaque type.
+//
+// However, opaque types are special cased to include check all regions in the
+// concrete type against the bound, which forces the return type to be
+// `&'static i32` here.
+
+// build-pass (FIXME(62277): could be check-pass?)
+
+fn make_identity() -> impl Sized {
+ |x: &'static i32| x
+}
+
+fn make_identity_static() -> impl Sized + 'static {
+ |x: &'static i32| x
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/closure-calling-parent-fn.rs b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
new file mode 100644
index 000000000..9dab334a2
--- /dev/null
+++ b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
@@ -0,0 +1,12 @@
+// Regression test for #54593: the MIR type checker was going wrong
+// when a closure returns the `impl Copy` from its parent fn. It was
+// (incorrectly) replacing the `impl Copy` in its return type with the
+// hidden type (`()`) but that type resulted from a recursive call to
+// `foo` and hence is treated opaquely within the closure body. This
+// resulted in a failed subtype relationship.
+//
+// check-pass
+
+fn foo() -> impl Copy { || foo(); }
+fn bar() -> impl Copy { || bar(); }
+fn main() { }
diff --git a/src/test/ui/impl-trait/closure-in-impl-trait-arg.rs b/src/test/ui/impl-trait/closure-in-impl-trait-arg.rs
new file mode 100644
index 000000000..3cfce459e
--- /dev/null
+++ b/src/test/ui/impl-trait/closure-in-impl-trait-arg.rs
@@ -0,0 +1,7 @@
+// run-pass
+#![allow(unused_must_use)]
+fn bug(_: impl Iterator<Item = [(); { |x: u32| { x }; 4 }]>) {}
+
+fn main() {
+ bug(std::iter::empty());
+}
diff --git a/src/test/ui/impl-trait/closure-in-impl-trait.rs b/src/test/ui/impl-trait/closure-in-impl-trait.rs
new file mode 100644
index 000000000..3593a1d5c
--- /dev/null
+++ b/src/test/ui/impl-trait/closure-in-impl-trait.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![allow(unused_must_use)]
+fn bug<T>() -> impl Iterator<Item = [(); { |x: u32| { x }; 4 }]> {
+ std::iter::empty()
+}
+
+fn ok<T>() -> Box<dyn Iterator<Item = [(); { |x: u32| { x }; 4 }]>> {
+ Box::new(std::iter::empty())
+}
+
+fn main() {
+ for _item in ok::<u32>() {}
+ for _item in bug::<u32>() {}
+}
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 000000000..d881af9ed
--- /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")?;
+ Ok(()) //~ ERROR type annotations needed
+}
+
+fn muh2() -> Result<(), impl std::fmt::Debug> {
+ return Err(From::from("foo")); //~ ERROR type annotations needed
+ Ok(())
+}
+
+fn muh3() -> Result<(), impl std::fmt::Debug> {
+ Err(From::from("foo")) //~ ERROR type annotations needed
+}
+
+fn main() {}
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 000000000..1ff777e65
--- /dev/null
+++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr
@@ -0,0 +1,36 @@
+error[E0282]: type annotations needed
+ --> $DIR/cross-return-site-inference.rs:33:5
+ |
+LL | Ok(())
+ | ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+ |
+help: consider specifying the generic arguments
+ |
+LL | Ok::<(), E>(())
+ | +++++++++
+
+error[E0282]: type annotations needed
+ --> $DIR/cross-return-site-inference.rs:37:12
+ |
+LL | return Err(From::from("foo"));
+ | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+ |
+help: consider specifying the generic arguments
+ |
+LL | return Err::<(), E>(From::from("foo"));
+ | +++++++++
+
+error[E0282]: type annotations needed
+ --> $DIR/cross-return-site-inference.rs:42:5
+ |
+LL | Err(From::from("foo"))
+ | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+ |
+help: consider specifying the generic arguments
+ |
+LL | Err::<(), E>(From::from("foo"))
+ | +++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/deprecated_annotation.rs b/src/test/ui/impl-trait/deprecated_annotation.rs
new file mode 100644
index 000000000..f76724c8a
--- /dev/null
+++ b/src/test/ui/impl-trait/deprecated_annotation.rs
@@ -0,0 +1,19 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![deny(warnings)]
+
+#[deprecated]
+trait Deprecated {}
+
+#[deprecated]
+struct DeprecatedTy;
+
+#[allow(deprecated)]
+impl Deprecated for DeprecatedTy {}
+
+#[allow(deprecated)]
+fn foo() -> impl Deprecated { DeprecatedTy }
+
+fn main() {
+ foo();
+}
diff --git a/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs
new file mode 100644
index 000000000..3a47710d5
--- /dev/null
+++ b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs
@@ -0,0 +1,15 @@
+trait Foo<T> {
+ fn foo(self, f: impl FnOnce());
+}
+
+impl<T> Foo<T> for () {
+ fn foo(self, f: impl FnOnce()) {
+ f()
+ }
+}
+
+fn main() {
+ // FIXME: This should ideally use a fully qualified path
+ // without mentioning the generic arguments of `foo`.
+ ().foo(|| ()) //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr
new file mode 100644
index 000000000..a1a629bdd
--- /dev/null
+++ b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/fully-qualified-path-impl-trait.rs:14:8
+ |
+LL | ().foo(|| ())
+ | ^^^ cannot infer type for type parameter `T` declared on the trait `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/divergence.rs b/src/test/ui/impl-trait/divergence.rs
new file mode 100644
index 000000000..211f7972d
--- /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/does-not-live-long-enough.rs b/src/test/ui/impl-trait/does-not-live-long-enough.rs
new file mode 100644
index 000000000..d2a345231
--- /dev/null
+++ b/src/test/ui/impl-trait/does-not-live-long-enough.rs
@@ -0,0 +1,11 @@
+struct List {
+ data: Vec<String>,
+}
+impl List {
+ fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
+ self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
+ //~^ ERROR E0373
+ }
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..750687e23
--- /dev/null
+++ b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
@@ -0,0 +1,21 @@
+error[E0373]: closure may outlive the current function, but it borrows `prefix`, which is owned by the current function
+ --> $DIR/does-not-live-long-enough.rs:6:33
+ |
+LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
+ | ^^^ ------ `prefix` is borrowed here
+ | |
+ | may outlive borrowed value `prefix`
+ |
+note: closure is returned here
+ --> $DIR/does-not-live-long-enough.rs:6:9
+ |
+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())
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs
new file mode 100644
index 000000000..3b7141573
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs
@@ -0,0 +1,16 @@
+// Test that we don't get an error with `dyn Bar` in an impl Trait
+// when there are multiple inputs. The `dyn Bar` should default to `+
+// 'static`. This used to erroneously generate an error (cc #62517).
+//
+// check-pass
+
+trait Foo { type Item: ?Sized; }
+trait Bar { }
+
+impl<T> Foo for T {
+ type Item = dyn Bar;
+}
+
+fn foo(x: &str, y: &str) -> impl Foo<Item = dyn Bar> { () }
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs
new file mode 100644
index 000000000..e8da52aad
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs
@@ -0,0 +1,11 @@
+// Test that we don't get an error with `dyn Object` in an impl Trait
+// when there are multiple inputs. The `dyn Object` should default to `+
+// 'static`. This used to erroneously generate an error (cc #62517).
+//
+// check-pass
+
+trait Alpha<Item: ?Sized> {}
+trait Object {}
+impl<T> Alpha<dyn Object> for T {}
+fn alpha(x: &str, y: &str) -> impl Alpha<dyn Object> { () }
+fn main() { }
diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs
new file mode 100644
index 000000000..aad9d89fe
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs
@@ -0,0 +1,27 @@
+// Test that we don't get an error with `dyn Bar` in an impl Trait
+// when there are multiple inputs. The `dyn Bar` should default to `+
+// 'static`. This used to erroneously generate an error (cc #62517).
+//
+// check-pass
+
+trait Foo {
+ type Item: ?Sized;
+
+ fn item(&self) -> Box<Self::Item> { panic!() }
+}
+
+trait Bar { }
+
+impl<T> Foo for T {
+ type Item = dyn Bar;
+}
+
+fn is_static<T>(_: T) where T: 'static { }
+
+fn bar(x: &str) -> &impl Foo<Item = dyn Bar> { &() }
+
+fn main() {
+ let s = format!("foo");
+ let r = bar(&s);
+ is_static(r.item());
+}
diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs
new file mode 100644
index 000000000..8d34c1b6c
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs
@@ -0,0 +1,23 @@
+// Test that `impl Alpha<dyn Object>` resets the object-lifetime
+// default to `'static`.
+//
+// check-pass
+
+trait Alpha<Item: ?Sized> {
+ fn item(&self) -> Box<Item> {
+ panic!()
+ }
+}
+
+trait Object {}
+impl<T> Alpha<dyn Object> for T {}
+fn alpha(x: &str, y: &str) -> impl Alpha<dyn Object> { () }
+fn is_static<T>(_: T) where T: 'static { }
+
+fn bar(x: &str) -> &impl Alpha<dyn Object> { &() }
+
+fn main() {
+ let s = format!("foo");
+ let r = bar(&s);
+ is_static(r.item());
+}
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
new file mode 100644
index 000000000..cbf1daabe
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
@@ -0,0 +1,74 @@
+#![allow(bare_trait_objects)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn fuz() -> (usize, Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bar() -> (usize, dyn Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bap() -> Trait { Struct }
+//~^ ERROR E0746
+fn ban() -> dyn Trait { Struct }
+//~^ ERROR E0746
+fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0746
+// Suggest using `Box<dyn Trait>`
+fn bal() -> dyn Trait { //~ ERROR E0746
+ if true {
+ return Struct;
+ }
+ 42
+}
+fn bax() -> dyn Trait { //~ ERROR E0746
+ if true {
+ Struct
+ } else {
+ 42 //~ ERROR `if` and `else` have incompatible types
+ }
+}
+fn bam() -> Box<dyn Trait> {
+ if true {
+ return Struct; //~ ERROR mismatched types
+ }
+ 42 //~ ERROR mismatched types
+}
+fn baq() -> Box<dyn Trait> {
+ if true {
+ return 0; //~ ERROR mismatched types
+ }
+ 42 //~ ERROR mismatched types
+}
+fn baz() -> Box<dyn Trait> {
+ if true {
+ Struct //~ ERROR mismatched types
+ } else {
+ 42 //~ ERROR mismatched types
+ }
+}
+fn baw() -> Box<dyn Trait> {
+ if true {
+ 0 //~ ERROR mismatched types
+ } else {
+ 42 //~ ERROR mismatched types
+ }
+}
+
+// Suggest using `impl Trait`
+fn bat() -> dyn Trait { //~ ERROR E0746
+ if true {
+ return 0;
+ }
+ 42
+}
+fn bay() -> dyn Trait { //~ ERROR E0746
+ if true {
+ 0
+ } else {
+ 42
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
new file mode 100644
index 000000000..f90399b6b
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -0,0 +1,307 @@
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
+ |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+ | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+ |
+ = note: expected trait object `(dyn Trait + 'static)`
+ found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
+ |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+ | ^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+ | |
+ | doesn't have a size known at compile-time
+ |
+ = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+ = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+ = note: the return type of a function must have a statically known size
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
+ |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+ | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+ |
+ = note: expected trait object `(dyn Trait + 'static)`
+ found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
+ |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+ | ^^^^^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+ | |
+ | doesn't have a size known at compile-time
+ |
+ = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+ = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+ = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
+ |
+LL | fn bap() -> Trait { Struct }
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+ |
+LL | fn bap() -> impl Trait { Struct }
+ | ~~~~~~~~~~
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
+ |
+LL | fn ban() -> dyn Trait { Struct }
+ | ^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+ |
+LL | fn ban() -> impl Trait { Struct }
+ | ~~~~~~~~~~
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
+ |
+LL | fn bak() -> dyn Trait { unimplemented!() }
+ | ^^^^^^^^^ doesn't have a size known at compile-time
+ |
+help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
+ |
+LL | fn bak() -> T { unimplemented!() }
+ | ~
+help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
+ |
+LL | fn bak() -> impl Trait { unimplemented!() }
+ | ~~~~~~~~~~
+help: use a boxed trait object if all return paths implement trait `Trait`
+ |
+LL | fn bak() -> Box<dyn Trait> { unimplemented!() }
+ | ++++ +
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
+ |
+LL | fn bal() -> dyn Trait {
+ | ^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+ = note: if all the returned values were of the same type you could use `impl Trait` as the return type
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+ = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+ |
+LL | fn bal() -> Box<dyn Trait> {
+ | ++++ +
+help: ... and box this value
+ |
+LL | return Box::new(Struct);
+ | +++++++++ +
+help: ... and box this value
+ |
+LL | Box::new(42)
+ | +++++++++ +
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9
+ |
+LL | / if true {
+LL | | Struct
+ | | ------ expected because of this
+LL | | } else {
+LL | | 42
+ | | ^^ expected struct `Struct`, found integer
+LL | | }
+ | |_____- `if` and `else` have incompatible types
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13
+ |
+LL | fn bax() -> dyn Trait {
+ | ^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+ = note: if all the returned values were of the same type you could use `impl Trait` as the return type
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+ = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+ |
+LL | fn bax() -> Box<dyn Trait> {
+ | ++++ +
+help: ... and box this value
+ |
+LL | Box::new(Struct)
+ | +++++++++ +
+help: ... and box this value
+ |
+LL | Box::new(42)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16
+ |
+LL | fn bam() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL | if true {
+LL | return Struct;
+ | ^^^^^^ expected struct `Box`, found struct `Struct`
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found struct `Struct`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | return Box::new(Struct);
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:5
+ |
+LL | fn bam() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL | 42
+ | ^^ expected struct `Box`, found integer
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found type `{integer}`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | Box::new(42)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:40:16
+ |
+LL | fn baq() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL | if true {
+LL | return 0;
+ | ^ expected struct `Box`, found integer
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found type `{integer}`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | return Box::new(0);
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:5
+ |
+LL | fn baq() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL | 42
+ | ^^ expected struct `Box`, found integer
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found type `{integer}`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | Box::new(42)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9
+ |
+LL | fn baz() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL | if true {
+LL | Struct
+ | ^^^^^^ expected struct `Box`, found struct `Struct`
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found struct `Struct`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | Box::new(Struct)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9
+ |
+LL | fn baz() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL | 42
+ | ^^ expected struct `Box`, found integer
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found type `{integer}`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | Box::new(42)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9
+ |
+LL | fn baw() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL | if true {
+LL | 0
+ | ^ expected struct `Box`, found integer
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found type `{integer}`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | Box::new(0)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9
+ |
+LL | fn baw() -> Box<dyn Trait> {
+ | -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL | 42
+ | ^^ expected struct `Box`, found integer
+ |
+ = note: expected struct `Box<(dyn Trait + 'static)>`
+ found type `{integer}`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL | Box::new(42)
+ | +++++++++ +
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:13
+ |
+LL | fn bat() -> dyn Trait {
+ | ^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+ |
+LL | fn bat() -> impl Trait {
+ | ~~~~~~~~~~
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13
+ |
+LL | fn bay() -> dyn Trait {
+ | ^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+ |
+LL | fn bay() -> impl Trait {
+ | ~~~~~~~~~~
+
+error: aborting due to 20 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0746.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equal-hidden-lifetimes.rs b/src/test/ui/impl-trait/equal-hidden-lifetimes.rs
new file mode 100644
index 000000000..79db88828
--- /dev/null
+++ b/src/test/ui/impl-trait/equal-hidden-lifetimes.rs
@@ -0,0 +1,49 @@
+// Test that we consider equal regions when checking for hidden regions in
+// opaque types
+
+// check-pass
+
+// `'a == 'static` so `&'a i32` is fine as the return type
+fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
+ //~^ WARNING unnecessary lifetime parameter `'a`
+ x
+}
+
+// `'a == 'b` so `&'b i32` is fine as the return type
+fn equal_regions<'a: 'b, 'b: 'a>(x: &'b i32) -> impl Sized + 'a {
+ let y: &'a i32 = x;
+ let z: &'b i32 = y;
+ x
+}
+
+// `'a == 'b` so `&'a i32` is fine as the return type
+fn equal_regions_rev<'a: 'b, 'b: 'a>(x: &'a i32) -> impl Sized + 'b {
+ let y: &'a i32 = x;
+ let z: &'b i32 = y;
+ x
+}
+
+// `'a == 'b` so `*mut &'b i32` is fine as the return type
+fn equal_regions_inv<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a {
+ let y: *mut &'a i32 = x;
+ let z: *mut &'b i32 = y;
+ x
+}
+
+// `'a == 'b` so `*mut &'a i32` is fine as the return type
+fn equal_regions_inv_rev<'a: 'b, 'b: 'a>(x: *mut &'a i32) -> impl Sized + 'b {
+ let y: *mut &'a i32 = x;
+ let z: *mut &'b i32 = y;
+ x
+}
+
+// Should be able to infer `fn(&'static ())` as the return type.
+fn contravariant_lub<'a, 'b: 'a, 'c: 'a, 'd: 'b + 'c>(
+ x: fn(&'b ()),
+ y: fn(&'c ()),
+ c: bool,
+) -> impl Sized + 'a {
+ if c { x } else { y }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr b/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr
new file mode 100644
index 000000000..3e48aef55
--- /dev/null
+++ b/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr
@@ -0,0 +1,10 @@
+warning: unnecessary lifetime parameter `'a`
+ --> $DIR/equal-hidden-lifetimes.rs:7:25
+ |
+LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
+ | ^^
+ |
+ = help: you can use the `'static` lifetime directly, in place of `'a`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/equality-rpass.rs b/src/test/ui/impl-trait/equality-rpass.rs
new file mode 100644
index 000000000..607b4a496
--- /dev/null
+++ b/src/test/ui/impl-trait/equality-rpass.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo: std::fmt::Debug + Eq {}
+
+impl<T: std::fmt::Debug + Eq> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+ x
+}
+
+trait Leak<T>: Sized {
+ fn leak(self) -> T;
+}
+impl<T, U> Leak<T> for U {
+ default fn leak(self) -> T { panic!("type mismatch") }
+}
+impl<T> Leak<T> for T {
+ fn leak(self) -> T { self }
+}
+
+trait CheckIfSend: Sized {
+ type T: Default;
+ fn check(self) -> Self::T { Default::default() }
+}
+impl<T> CheckIfSend for T {
+ default type T = ();
+}
+impl<T: Send> CheckIfSend for T {
+ type T = bool;
+}
+
+fn lucky_seven() -> impl Fn(usize) -> u8 {
+ let a = [1, 2, 3, 4, 5, 6, 7];
+ move |i| a[i]
+}
+
+fn main() {
+ assert_eq!(hide(42), hide(42));
+
+ assert_eq!(std::mem::size_of_val(&hide([0_u8; 5])), 5);
+ assert_eq!(std::mem::size_of_val(&lucky_seven()), 7);
+
+ assert_eq!(Leak::<i32>::leak(hide(5_i32)), 5_i32);
+
+ assert_eq!(CheckIfSend::check(hide(0_i32)), false);
+}
diff --git a/src/test/ui/impl-trait/equality-rpass.stderr b/src/test/ui/impl-trait/equality-rpass.stderr
new file mode 100644
index 000000000..11eeceba0
--- /dev/null
+++ b/src/test/ui/impl-trait/equality-rpass.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/equality-rpass.rs:3:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
new file mode 100644
index 000000000..828b5aac8
--- /dev/null
+++ b/src/test/ui/impl-trait/equality.rs
@@ -0,0 +1,43 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+ x
+}
+
+fn two(x: bool) -> impl Foo {
+ if x {
+ return 1_i32;
+ }
+ 0_u32
+ //~^ ERROR mismatched types
+ //~| expected `i32`, found `u32`
+}
+
+fn sum_to(n: u32) -> impl Foo {
+ if n == 0 {
+ 0
+ } else {
+ n + sum_to(n - 1)
+ //~^ ERROR cannot add `impl Foo` to `u32`
+ }
+}
+
+trait Leak: Sized {
+ type T;
+ fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+ default type T = ();
+ default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+ type T = i32;
+ fn leak(self) -> i32 { self }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
new file mode 100644
index 000000000..f14b447b0
--- /dev/null
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -0,0 +1,41 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/equality.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+
+error[E0308]: mismatched types
+ --> $DIR/equality.rs:15:5
+ |
+LL | fn two(x: bool) -> impl Foo {
+ | -------- expected `_` because of return type
+...
+LL | 0_u32
+ | ^^^^^ expected `i32`, found `u32`
+
+error[E0277]: cannot add `impl Foo` to `u32`
+ --> $DIR/equality.rs:24:11
+ |
+LL | n + sum_to(n - 1)
+ | ^ no implementation for `u32 + impl Foo`
+ |
+ = help: the trait `Add<impl Foo>` is not implemented for `u32`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f32 as Add<f32>>
+ <&'a f64 as Add<f64>>
+ <&'a i128 as Add<i128>>
+ <&'a i16 as Add<i16>>
+ <&'a i32 as Add<i32>>
+ <&'a i64 as Add<i64>>
+ <&'a i8 as Add<i8>>
+ <&'a isize as Add<isize>>
+ and 48 others
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs
new file mode 100644
index 000000000..2e325867d
--- /dev/null
+++ b/src/test/ui/impl-trait/equality2.rs
@@ -0,0 +1,44 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+ x
+}
+
+trait Leak: Sized {
+ type T;
+ fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+ default type T = ();
+ default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+ type T = i32;
+ fn leak(self) -> i32 { self }
+}
+
+fn main() {
+ let _: u32 = hide(0_u32);
+ //~^ ERROR mismatched types
+ //~| expected type `u32`
+ //~| found opaque type `impl Foo`
+ //~| expected `u32`, found opaque type
+
+ let _: i32 = Leak::leak(hide(0_i32));
+ //~^ ERROR mismatched types
+ //~| expected type `i32`
+ //~| found associated type `<impl Foo as Leak>::T`
+ //~| expected `i32`, found associated type
+
+ let mut x = (hide(0_u32), hide(0_i32));
+ x = (x.1,
+ //~^ ERROR mismatched types
+ //~| expected `u32`, found `i32`
+ x.0);
+ //~^ ERROR mismatched types
+ //~| expected `i32`, found `u32`
+}
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
new file mode 100644
index 000000000..46053c6e7
--- /dev/null
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -0,0 +1,75 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/equality2.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+
+error[E0308]: mismatched types
+ --> $DIR/equality2.rs:25:18
+ |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+ | -------- the found opaque type
+...
+LL | let _: u32 = hide(0_u32);
+ | --- ^^^^^^^^^^^ expected `u32`, found opaque type
+ | |
+ | expected due to this
+ |
+ = note: expected type `u32`
+ found opaque type `impl Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/equality2.rs:31:18
+ |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+ | -------- the found opaque type
+...
+LL | let _: i32 = Leak::leak(hide(0_i32));
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
+ | |
+ | expected due to this
+ |
+ = note: expected type `i32`
+ found associated type `<impl Foo as Leak>::T`
+help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32`
+ |
+LL | fn hide<T: Foo>(x: T) -> impl Foo<T = i32> {
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/equality2.rs:38:10
+ |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+ | --------
+ | |
+ | the expected opaque type
+ | the found opaque type
+...
+LL | x = (x.1,
+ | ^^^ expected `u32`, found `i32`
+ |
+ = note: expected opaque type `impl Foo` (`u32`)
+ found opaque type `impl Foo` (`i32`)
+
+error[E0308]: mismatched types
+ --> $DIR/equality2.rs:41:10
+ |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+ | --------
+ | |
+ | the expected opaque type
+ | the found opaque type
+...
+LL | x.0);
+ | ^^^ expected `i32`, found `u32`
+ |
+ = note: expected opaque type `impl Foo` (`i32`)
+ found opaque type `impl Foo` (`u32`)
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/example-calendar.rs b/src/test/ui/impl-trait/example-calendar.rs
new file mode 100644
index 000000000..da45f0d13
--- /dev/null
+++ b/src/test/ui/impl-trait/example-calendar.rs
@@ -0,0 +1,840 @@
+// run-pass
+
+#![feature(fn_traits,
+ step_trait,
+ unboxed_closures,
+)]
+
+//! Derived from: <https://raw.githubusercontent.com/quickfur/dcal/master/dcal.d>.
+//!
+//! Originally converted to Rust by [Daniel Keep](https://github.com/DanielKeep).
+
+use std::fmt::Write;
+
+/// Date representation.
+#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+struct NaiveDate(i32, u32, u32);
+
+impl NaiveDate {
+ pub fn from_ymd(y: i32, m: u32, d: u32) -> NaiveDate {
+ assert!(1 <= m && m <= 12, "m = {:?}", m);
+ assert!(1 <= d && d <= NaiveDate(y, m, 1).days_in_month(), "d = {:?}", d);
+ NaiveDate(y, m, d)
+ }
+
+ pub fn year(&self) -> i32 {
+ self.0
+ }
+
+ pub fn month(&self) -> u32 {
+ self.1
+ }
+
+ pub fn day(&self) -> u32 {
+ self.2
+ }
+
+ pub fn succ(&self) -> NaiveDate {
+ let (mut y, mut m, mut d, n) = (
+ self.year(), self.month(), self.day()+1, self.days_in_month());
+ if d > n {
+ d = 1;
+ m += 1;
+ }
+ if m > 12 {
+ m = 1;
+ y += 1;
+ }
+ NaiveDate::from_ymd(y, m, d)
+ }
+
+ pub fn weekday(&self) -> Weekday {
+ use Weekday::*;
+
+ // 0 = Sunday
+ let year = self.year();
+ let dow_jan_1 = (year*365 + ((year-1) / 4) - ((year-1) / 100) + ((year-1) / 400)) % 7;
+ let dow = (dow_jan_1 + (self.day_of_year() as i32 - 1)) % 7;
+ [Sun, Mon, Tue, Wed, Thu, Fri, Sat][dow as usize]
+ }
+
+ pub fn isoweekdate(&self) -> (i32, u32, Weekday) {
+ let first_dow_mon_0 = self.year_first_day_of_week().num_days_from_monday();
+
+ // Work out this date's DOtY and week number, not including year adjustment.
+ let doy_0 = self.day_of_year() - 1;
+ let mut week_mon_0: i32 = ((first_dow_mon_0 + doy_0) / 7) as i32;
+
+ if self.first_week_in_prev_year() {
+ week_mon_0 -= 1;
+ }
+
+ let weeks_in_year = self.last_week_number();
+
+ // Work out the final result.
+ // If the week is `-1` or `>= weeks_in_year`, we will need to adjust the year.
+ let year = self.year();
+ let wd = self.weekday();
+
+ if week_mon_0 < 0 {
+ (year - 1, NaiveDate::from_ymd(year - 1, 1, 1).last_week_number(), wd)
+ } else if week_mon_0 >= weeks_in_year as i32 {
+ (year + 1, (week_mon_0 + 1 - weeks_in_year as i32) as u32, wd)
+ } else {
+ (year, (week_mon_0 + 1) as u32, wd)
+ }
+ }
+
+ fn first_week_in_prev_year(&self) -> bool {
+ let first_dow_mon_0 = self.year_first_day_of_week().num_days_from_monday();
+
+ // Any day in the year *before* the first Monday of that year
+ // is considered to be in the last week of the previous year,
+ // assuming the first week has *less* than four days in it.
+ // Adjust the week appropriately.
+ ((7 - first_dow_mon_0) % 7) < 4
+ }
+
+ fn year_first_day_of_week(&self) -> Weekday {
+ NaiveDate::from_ymd(self.year(), 1, 1).weekday()
+ }
+
+ fn weeks_in_year(&self) -> u32 {
+ let days_in_last_week = self.year_first_day_of_week().num_days_from_monday() + 1;
+ if days_in_last_week >= 4 { 53 } else { 52 }
+ }
+
+ fn last_week_number(&self) -> u32 {
+ let wiy = self.weeks_in_year();
+ if self.first_week_in_prev_year() { wiy - 1 } else { wiy }
+ }
+
+ fn day_of_year(&self) -> u32 {
+ (1..self.1).map(|m| NaiveDate::from_ymd(self.year(), m, 1).days_in_month())
+ .fold(0, |a,b| a+b) + self.day()
+ }
+
+ fn is_leap_year(&self) -> bool {
+ let year = self.year();
+ if year % 4 != 0 {
+ return false
+ } else if year % 100 != 0 {
+ return true
+ } else if year % 400 != 0 {
+ return false
+ } else {
+ return true
+ }
+ }
+
+ fn days_in_month(&self) -> u32 {
+ match self.month() {
+ /* Jan */ 1 => 31,
+ /* Feb */ 2 => if self.is_leap_year() { 29 } else { 28 },
+ /* Mar */ 3 => 31,
+ /* Apr */ 4 => 30,
+ /* May */ 5 => 31,
+ /* Jun */ 6 => 30,
+ /* Jul */ 7 => 31,
+ /* Aug */ 8 => 31,
+ /* Sep */ 9 => 30,
+ /* Oct */ 10 => 31,
+ /* Nov */ 11 => 30,
+ /* Dec */ 12 => 31,
+ _ => unreachable!()
+ }
+ }
+}
+
+impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate {
+ type Output = NaiveDate;
+
+ fn add(self, other: &'b NaiveDate) -> NaiveDate {
+ assert_eq!(*other, NaiveDate(0, 0, 1));
+ self.succ()
+ }
+}
+
+impl std::iter::Step for NaiveDate {
+ fn steps_between(_: &Self, _: &Self) -> Option<usize> {
+ unimplemented!()
+ }
+
+ fn forward_checked(start: Self, n: usize) -> Option<Self> {
+ Some((0..n).fold(start, |x, _| x.succ()))
+ }
+
+ fn backward_checked(_: Self, _: usize) -> Option<Self> {
+ unimplemented!()
+ }
+}
+
+#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum Weekday {
+ Mon,
+ Tue,
+ Wed,
+ Thu,
+ Fri,
+ Sat,
+ Sun,
+}
+
+impl Weekday {
+ pub fn num_days_from_monday(&self) -> u32 {
+ use Weekday::*;
+ match *self {
+ Mon => 0,
+ Tue => 1,
+ Wed => 2,
+ Thu => 3,
+ Fri => 4,
+ Sat => 5,
+ Sun => 6,
+ }
+ }
+
+ pub fn num_days_from_sunday(&self) -> u32 {
+ use Weekday::*;
+ match *self {
+ Sun => 0,
+ Mon => 1,
+ Tue => 2,
+ Wed => 3,
+ Thu => 4,
+ Fri => 5,
+ Sat => 6,
+ }
+ }
+}
+
+/// `GroupBy` implementation.
+struct GroupBy<It: Iterator, F> {
+ it: std::iter::Peekable<It>,
+ f: F,
+}
+
+impl<It, F> Clone for GroupBy<It, F>
+where
+ It: Iterator + Clone,
+ It::Item: Clone,
+ F: Clone,
+{
+ fn clone(&self) -> Self {
+ GroupBy {
+ it: self.it.clone(),
+ f: self.f.clone(),
+ }
+ }
+}
+
+impl<'a, G, It: 'a, F: 'a> Iterator for GroupBy<It, F>
+where It: Iterator + Clone,
+ It::Item: Clone,
+ F: Clone + FnMut(&It::Item) -> G,
+ G: Eq + Clone
+{
+ type Item = (G, InGroup<std::iter::Peekable<It>, F, G>);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.it.peek().map(&mut self.f).map(|key| {
+ let start = self.it.clone();
+ while let Some(k) = self.it.peek().map(&mut self.f) {
+ if key != k {
+ break;
+ }
+ self.it.next();
+ }
+
+ (key.clone(), InGroup {
+ it: start,
+ f: self.f.clone(),
+ g: key
+ })
+ })
+ }
+}
+
+#[derive(Copy, Clone)]
+struct InGroup<It, F, G> {
+ it: It,
+ f: F,
+ g: G
+}
+
+impl<It: Iterator, F: FnMut(&It::Item) -> G, G: Eq> Iterator for InGroup<It, F, G> {
+ type Item = It::Item;
+
+ fn next(&mut self) -> Option<It::Item> {
+ self.it.next().and_then(|x| {
+ if (self.f)(&x) == self.g { Some(x) } else { None }
+ })
+ }
+}
+
+trait IteratorExt: Iterator + Sized {
+ fn group_by<G, F>(self, f: F) -> GroupBy<Self, F>
+ where F: Clone + FnMut(&Self::Item) -> G,
+ G: Eq
+ {
+ GroupBy { it: self.peekable(), f }
+ }
+
+ fn join(mut self, sep: &str) -> String
+ where Self::Item: std::fmt::Display {
+ let mut s = String::new();
+ if let Some(e) = self.next() {
+ write!(s, "{}", e).unwrap();
+ for e in self {
+ s.push_str(sep);
+ write!(s, "{}", e).unwrap();
+ }
+ }
+ s
+ }
+
+ // HACK(eddyb): only needed because `impl Trait` can't be
+ // used with trait methods: `.foo()` becomes `.__(foo)`.
+ fn __<F, R>(self, f: F) -> R
+ where F: FnOnce(Self) -> R {
+ f(self)
+ }
+}
+
+impl<It> IteratorExt for It where It: Iterator {}
+
+/// Generates an iterator that yields exactly `n` spaces.
+fn spaces(n: usize) -> std::iter::Take<std::iter::Repeat<char>> {
+ std::iter::repeat(' ').take(n)
+}
+
+fn test_spaces() {
+ assert_eq!(spaces(0).collect::<String>(), "");
+ assert_eq!(spaces(10).collect::<String>(), " ")
+}
+
+/// Returns an iterator of dates in a given year.
+fn dates_in_year(year: i32) -> impl Iterator<Item=NaiveDate>+Clone {
+ InGroup {
+ it: NaiveDate::from_ymd(year, 1, 1)..,
+ f: |d: &NaiveDate| d.year(),
+ g: year
+ }
+}
+
+fn test_dates_in_year() {
+ {
+ let mut dates = dates_in_year(2013);
+ assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 1)));
+
+ // Check increment.
+ assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 2)));
+
+ // Check monthly roll-over.
+ for _ in 3..31 {
+ assert!(dates.next() != None);
+ }
+
+ assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 31)));
+ assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 2, 1)));
+ }
+
+ {
+ // Check length of year.
+ let mut dates = dates_in_year(2013);
+ for _ in 0..365 {
+ assert!(dates.next() != None);
+ }
+ assert_eq!(dates.next(), None);
+ }
+
+ {
+ // Check length of leap year.
+ let mut dates = dates_in_year(1984);
+ for _ in 0..366 {
+ assert!(dates.next() != None);
+ }
+ assert_eq!(dates.next(), None);
+ }
+}
+
+/// Convenience trait for verifying that a given type iterates over
+/// `NaiveDate`s.
+trait DateIterator: Iterator<Item=NaiveDate> + Clone {}
+impl<It> DateIterator for It where It: Iterator<Item=NaiveDate> + Clone {}
+
+fn test_group_by() {
+ let input = [
+ [1, 1],
+ [1, 1],
+ [1, 2],
+ [2, 2],
+ [2, 3],
+ [2, 3],
+ [3, 3]
+ ];
+
+ let by_x = input.iter().cloned().group_by(|a| a[0]);
+ let expected_1: &[&[[i32; 2]]] = &[
+ &[[1, 1], [1, 1], [1, 2]],
+ &[[2, 2], [2, 3], [2, 3]],
+ &[[3, 3]]
+ ];
+ for ((_, a), b) in by_x.zip(expected_1.iter().cloned()) {
+ assert_eq!(&a.collect::<Vec<_>>()[..], b);
+ }
+
+ let by_y = input.iter().cloned().group_by(|a| a[1]);
+ let expected_2: &[&[[i32; 2]]] = &[
+ &[[1, 1], [1, 1]],
+ &[[1, 2], [2, 2]],
+ &[[2, 3], [2, 3], [3, 3]]
+ ];
+ for ((_, a), b) in by_y.zip(expected_2.iter().cloned()) {
+ assert_eq!(&a.collect::<Vec<_>>()[..], b);
+ }
+}
+
+/// Groups an iterator of dates by month.
+fn by_month(it: impl Iterator<Item=NaiveDate> + Clone)
+ -> impl Iterator<Item=(u32, impl Iterator<Item=NaiveDate> + Clone)> + Clone
+{
+ it.group_by(|d| d.month())
+}
+
+fn test_by_month() {
+ let mut months = dates_in_year(2013).__(by_month);
+ for (month, (_, mut date)) in (1..13).zip(&mut months) {
+ assert_eq!(date.nth(0).unwrap(), NaiveDate::from_ymd(2013, month, 1));
+ }
+ assert!(months.next().is_none());
+}
+
+/// Groups an iterator of dates by week.
+fn by_week(it: impl DateIterator)
+ -> impl Iterator<Item=(u32, impl DateIterator)> + Clone
+{
+ // We go forward one day because `isoweekdate` considers the week to start on a Monday.
+ it.group_by(|d| d.succ().isoweekdate().1)
+}
+
+fn test_isoweekdate() {
+ fn weeks_uniq(year: i32) -> Vec<((i32, u32), u32)> {
+ let mut weeks = dates_in_year(year).map(|d| d.isoweekdate())
+ .map(|(y,w,_)| (y,w));
+ let mut result = vec![];
+ let mut accum = (weeks.next().unwrap(), 1);
+ for yw in weeks {
+ if accum.0 == yw {
+ accum.1 += 1;
+ } else {
+ result.push(accum);
+ accum = (yw, 1);
+ }
+ }
+ result.push(accum);
+ result
+ }
+
+ let wu_1984 = weeks_uniq(1984);
+ assert_eq!(&wu_1984[..2], &[((1983, 52), 1), ((1984, 1), 7)]);
+ assert_eq!(&wu_1984[wu_1984.len()-2..], &[((1984, 52), 7), ((1985, 1), 1)]);
+
+ let wu_2013 = weeks_uniq(2013);
+ assert_eq!(&wu_2013[..2], &[((2013, 1), 6), ((2013, 2), 7)]);
+ assert_eq!(&wu_2013[wu_2013.len()-2..], &[((2013, 52), 7), ((2014, 1), 2)]);
+
+ let wu_2015 = weeks_uniq(2015);
+ assert_eq!(&wu_2015[..2], &[((2015, 1), 4), ((2015, 2), 7)]);
+ assert_eq!(&wu_2015[wu_2015.len()-2..], &[((2015, 52), 7), ((2015, 53), 4)]);
+}
+
+fn test_by_week() {
+ let mut weeks = dates_in_year(2013).__(by_week);
+ assert_eq!(
+ &*weeks.next().unwrap().1.collect::<Vec<_>>(),
+ &[
+ NaiveDate::from_ymd(2013, 1, 1),
+ NaiveDate::from_ymd(2013, 1, 2),
+ NaiveDate::from_ymd(2013, 1, 3),
+ NaiveDate::from_ymd(2013, 1, 4),
+ NaiveDate::from_ymd(2013, 1, 5),
+ ]
+ );
+ assert_eq!(
+ &*weeks.next().unwrap().1.collect::<Vec<_>>(),
+ &[
+ NaiveDate::from_ymd(2013, 1, 6),
+ NaiveDate::from_ymd(2013, 1, 7),
+ NaiveDate::from_ymd(2013, 1, 8),
+ NaiveDate::from_ymd(2013, 1, 9),
+ NaiveDate::from_ymd(2013, 1, 10),
+ NaiveDate::from_ymd(2013, 1, 11),
+ NaiveDate::from_ymd(2013, 1, 12),
+ ]
+ );
+ assert_eq!(weeks.next().unwrap().1.nth(0).unwrap(), NaiveDate::from_ymd(2013, 1, 13));
+}
+
+/// The number of columns per day in the formatted output.
+const COLS_PER_DAY: u32 = 3;
+
+/// The number of columns per week in the formatted output.
+const COLS_PER_WEEK: u32 = 7 * COLS_PER_DAY;
+
+/// Formats an iterator of weeks into an iterator of strings.
+fn format_weeks(it: impl Iterator<Item = impl DateIterator>) -> impl Iterator<Item=String> {
+ it.map(|week| {
+ let mut buf = String::with_capacity((COLS_PER_DAY * COLS_PER_WEEK + 2) as usize);
+
+ // Format each day into its own cell and append to target string.
+ let mut last_day = 0;
+ let mut first = true;
+ for d in week {
+ last_day = d.weekday().num_days_from_sunday();
+
+ // Insert enough filler to align the first day with its respective day-of-week.
+ if first {
+ buf.extend(spaces((COLS_PER_DAY * last_day) as usize));
+ first = false;
+ }
+
+ write!(buf, " {:>2}", d.day()).unwrap();
+ }
+
+ // Insert more filler at the end to fill up the remainder of the week,
+ // if its a short week (e.g., at the end of the month).
+ buf.extend(spaces((COLS_PER_DAY * (6 - last_day)) as usize));
+ buf
+ })
+}
+
+fn test_format_weeks() {
+ let jan_2013 = dates_in_year(2013)
+ .__(by_month).next() // pick January 2013 for testing purposes
+ // NOTE: This `map` is because `next` returns an `Option<_>`.
+ .map(|(_, month)|
+ month.__(by_week)
+ .map(|(_, weeks)| weeks)
+ .__(format_weeks)
+ .join("\n"));
+
+ assert_eq!(
+ jan_2013.as_ref().map(|s| &**s),
+ Some(" 1 2 3 4 5\n\
+ \x20 6 7 8 9 10 11 12\n\
+ \x2013 14 15 16 17 18 19\n\
+ \x2020 21 22 23 24 25 26\n\
+ \x2027 28 29 30 31 ")
+ );
+}
+
+/// Formats the name of a month, centered on `COLS_PER_WEEK`.
+fn month_title(month: u32) -> String {
+ const MONTH_NAMES: &'static [&'static str] = &[
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ ];
+ assert_eq!(MONTH_NAMES.len(), 12);
+
+ // Determine how many spaces before and after the month name
+ // we need to center it over the formatted weeks in the month.
+ let name = MONTH_NAMES[(month - 1) as usize];
+ assert!(name.len() < COLS_PER_WEEK as usize);
+ let before = (COLS_PER_WEEK as usize - name.len()) / 2;
+ let after = COLS_PER_WEEK as usize - name.len() - before;
+
+ // Note: being slightly more verbose to avoid extra allocations.
+ let mut result = String::with_capacity(COLS_PER_WEEK as usize);
+ result.extend(spaces(before));
+ result.push_str(name);
+ result.extend(spaces(after));
+ result
+}
+
+fn test_month_title() {
+ assert_eq!(month_title(1).len(), COLS_PER_WEEK as usize);
+}
+
+/// Formats a month.
+fn format_month(it: impl DateIterator) -> impl Iterator<Item=String> {
+ let mut month_days = it.peekable();
+ let title = month_title(month_days.peek().unwrap().month());
+
+ Some(title).into_iter()
+ .chain(month_days.__(by_week)
+ .map(|(_, week)| week)
+ .__(format_weeks))
+}
+
+fn test_format_month() {
+ let month_fmt = dates_in_year(2013)
+ .__(by_month).next() // Pick January as a test case
+ .map(|(_, days)| days.into_iter()
+ .__(format_month)
+ .join("\n"));
+
+ assert_eq!(
+ month_fmt.as_ref().map(|s| &**s),
+ Some(" January \n\
+ \x20 1 2 3 4 5\n\
+ \x20 6 7 8 9 10 11 12\n\
+ \x2013 14 15 16 17 18 19\n\
+ \x2020 21 22 23 24 25 26\n\
+ \x2027 28 29 30 31 ")
+ );
+}
+
+/// Formats an iterator of months.
+fn format_months(it: impl Iterator<Item = impl DateIterator>)
+ -> impl Iterator<Item=impl Iterator<Item=String>>
+{
+ it.map(format_month)
+}
+
+/// Takes an iterator of iterators of strings; the sub-iterators are consumed
+/// in lock-step, with their elements joined together.
+trait PasteBlocks: Iterator + Sized
+where Self::Item: Iterator<Item = String> {
+ fn paste_blocks(self, sep_width: usize) -> PasteBlocksIter<Self::Item> {
+ PasteBlocksIter {
+ iters: self.collect(),
+ cache: vec![],
+ col_widths: None,
+ sep_width: sep_width,
+ }
+ }
+}
+
+impl<It> PasteBlocks for It where It: Iterator, It::Item: Iterator<Item=String> {}
+
+struct PasteBlocksIter<StrIt>
+where StrIt: Iterator<Item=String> {
+ iters: Vec<StrIt>,
+ cache: Vec<Option<String>>,
+ col_widths: Option<Vec<usize>>,
+ sep_width: usize,
+}
+
+impl<StrIt> Iterator for PasteBlocksIter<StrIt>
+where StrIt: Iterator<Item=String> {
+ type Item = String;
+
+ fn next(&mut self) -> Option<String> {
+ self.cache.clear();
+
+ // `cache` is now the next line from each iterator.
+ self.cache.extend(self.iters.iter_mut().map(|it| it.next()));
+
+ // If every line in `cache` is `None`, we have nothing further to do.
+ if self.cache.iter().all(|e| e.is_none()) { return None }
+
+ // Get the column widths if we haven't already.
+ let col_widths = match self.col_widths {
+ Some(ref v) => &**v,
+ None => {
+ self.col_widths = Some(self.cache.iter()
+ .map(|ms| ms.as_ref().map(|s| s.len()).unwrap_or(0))
+ .collect());
+ &**self.col_widths.as_ref().unwrap()
+ }
+ };
+
+ // Fill in any `None`s with spaces.
+ let mut parts = col_widths.iter().cloned().zip(self.cache.iter_mut())
+ .map(|(w,ms)| ms.take().unwrap_or_else(|| spaces(w).collect()));
+
+ // Join them all together.
+ let first = parts.next().unwrap_or(String::new());
+ let sep_width = self.sep_width;
+ Some(parts.fold(first, |mut accum, next| {
+ accum.extend(spaces(sep_width));
+ accum.push_str(&next);
+ accum
+ }))
+ }
+}
+
+fn test_paste_blocks() {
+ let row = dates_in_year(2013)
+ .__(by_month).map(|(_, days)| days)
+ .take(3)
+ .__(format_months)
+ .paste_blocks(1)
+ .join("\n");
+ assert_eq!(
+ &*row,
+ " January February March \n\
+ \x20 1 2 3 4 5 1 2 1 2\n\
+ \x20 6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9\n\
+ \x2013 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16\n\
+ \x2020 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23\n\
+ \x2027 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30\n\
+ \x20 31 "
+ );
+}
+
+/// Produces an iterator that yields `n` elements at a time.
+trait Chunks: Iterator + Sized {
+ fn chunks(self, n: usize) -> ChunksIter<Self> {
+ assert!(n > 0);
+ ChunksIter {
+ it: self,
+ n: n,
+ }
+ }
+}
+
+impl<It> Chunks for It where It: Iterator {}
+
+struct ChunksIter<It>
+where It: Iterator {
+ it: It,
+ n: usize,
+}
+
+// Note: `chunks` in Rust is more-or-less impossible without overhead of some kind.
+// Aliasing rules mean you need to add dynamic borrow checking, and the design of
+// `Iterator` means that you need to have the iterator's state kept in an allocation
+// that is jointly owned by the iterator itself and the sub-iterator.
+// As such, I've chosen to cop-out and just heap-allocate each chunk.
+
+impl<It> Iterator for ChunksIter<It>
+where It: Iterator {
+ type Item = Vec<It::Item>;
+
+ fn next(&mut self) -> Option<Vec<It::Item>> {
+ let first = self.it.next()?;
+
+ let mut result = Vec::with_capacity(self.n);
+ result.push(first);
+
+ Some((&mut self.it).take(self.n-1)
+ .fold(result, |mut acc, next| { acc.push(next); acc }))
+ }
+}
+
+fn test_chunks() {
+ let r = &[1, 2, 3, 4, 5, 6, 7];
+ let c = r.iter().cloned().chunks(3).collect::<Vec<_>>();
+ assert_eq!(&*c, &[vec![1, 2, 3], vec![4, 5, 6], vec![7]]);
+}
+
+/// Formats a year.
+fn format_year(year: i32, months_per_row: usize) -> String {
+ const COL_SPACING: usize = 1;
+
+ // Start by generating all dates for the given year.
+ dates_in_year(year)
+
+ // Group them by month and throw away month number.
+ .__(by_month).map(|(_, days)| days)
+
+ // Group the months into horizontal rows.
+ .chunks(months_per_row)
+
+ // Format each row...
+ .map(|r| r.into_iter()
+ // ... by formatting each month ...
+ .__(format_months)
+
+ // ... and horizontally pasting each respective month's lines together.
+ .paste_blocks(COL_SPACING)
+ .join("\n")
+ )
+
+ // Insert a blank line between each row.
+ .join("\n\n")
+}
+
+fn test_format_year() {
+ const MONTHS_PER_ROW: usize = 3;
+
+ macro_rules! assert_eq_cal {
+ ($lhs:expr, $rhs:expr) => {
+ if $lhs != $rhs {
+ println!("got:\n```\n{}\n```\n", $lhs.replace(" ", "."));
+ println!("expected:\n```\n{}\n```", $rhs.replace(" ", "."));
+ panic!("calendars didn't match!");
+ }
+ }
+ }
+
+ assert_eq_cal!(&format_year(1984, MONTHS_PER_ROW), "\
+\x20 January February March \n\
+\x20 1 2 3 4 5 6 7 1 2 3 4 1 2 3\n\
+\x20 8 9 10 11 12 13 14 5 6 7 8 9 10 11 4 5 6 7 8 9 10\n\
+\x2015 16 17 18 19 20 21 12 13 14 15 16 17 18 11 12 13 14 15 16 17\n\
+\x2022 23 24 25 26 27 28 19 20 21 22 23 24 25 18 19 20 21 22 23 24\n\
+\x2029 30 31 26 27 28 29 25 26 27 28 29 30 31\n\
+\n\
+\x20 April May June \n\
+\x20 1 2 3 4 5 6 7 1 2 3 4 5 1 2\n\
+\x20 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9\n\
+\x2015 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16\n\
+\x2022 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23\n\
+\x2029 30 27 28 29 30 31 24 25 26 27 28 29 30\n\
+\n\
+\x20 July August September \n\
+\x20 1 2 3 4 5 6 7 1 2 3 4 1\n\
+\x20 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8\n\
+\x2015 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15\n\
+\x2022 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22\n\
+\x2029 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29\n\
+\x20 30 \n\
+\n\
+\x20 October November December \n\
+\x20 1 2 3 4 5 6 1 2 3 1\n\
+\x20 7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8\n\
+\x2014 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15\n\
+\x2021 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22\n\
+\x2028 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29\n\
+\x20 30 31 ");
+
+ assert_eq_cal!(&format_year(2015, MONTHS_PER_ROW), "\
+\x20 January February March \n\
+\x20 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7\n\
+\x20 4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14\n\
+\x2011 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21\n\
+\x2018 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28\n\
+\x2025 26 27 28 29 30 31 29 30 31 \n\
+\n\
+\x20 April May June \n\
+\x20 1 2 3 4 1 2 1 2 3 4 5 6\n\
+\x20 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13\n\
+\x2012 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20\n\
+\x2019 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27\n\
+\x2026 27 28 29 30 24 25 26 27 28 29 30 28 29 30 \n\
+\x20 31 \n\
+\n\
+\x20 July August September \n\
+\x20 1 2 3 4 1 1 2 3 4 5\n\
+\x20 5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12\n\
+\x2012 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19\n\
+\x2019 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26\n\
+\x2026 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30 \n\
+\x20 30 31 \n\
+\n\
+\x20 October November December \n\
+\x20 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5\n\
+\x20 4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12\n\
+\x2011 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19\n\
+\x2018 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26\n\
+\x2025 26 27 28 29 30 31 29 30 27 28 29 30 31 ");
+}
+
+fn main() {
+ // Run tests.
+ test_spaces();
+ test_dates_in_year();
+ test_group_by();
+ test_by_month();
+ test_isoweekdate();
+ test_by_week();
+ test_format_weeks();
+ test_month_title();
+ test_format_month();
+ test_paste_blocks();
+ test_chunks();
+ test_format_year();
+}
diff --git a/src/test/ui/impl-trait/example-st.rs b/src/test/ui/impl-trait/example-st.rs
new file mode 100644
index 000000000..4e1aa3a08
--- /dev/null
+++ b/src/test/ui/impl-trait/example-st.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+struct State;
+type Error = ();
+
+trait Bind<F> {
+ type Output;
+ fn bind(self, f: F) -> Self::Output;
+}
+
+fn bind<T, U, A, B, F>(mut a: A, mut f: F)
+ -> impl FnMut(&mut State) -> Result<U, Error>
+where F: FnMut(T) -> B,
+ A: FnMut(&mut State) -> Result<T, Error>,
+ B: FnMut(&mut State) -> Result<U, Error>
+{
+ move |state | {
+ let r = a(state)?;
+ f(r)(state)
+ }
+}
+
+fn atom<T>(x: T) -> impl FnMut(&mut State) -> Result<T, Error> {
+ let mut x = Some(x);
+ move |_| x.take().map_or(Err(()), Ok)
+}
+
+fn main() {
+ assert_eq!(bind(atom(5), |x| atom(x > 4))(&mut State), Ok(true));
+}
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs
new file mode 100644
index 000000000..1aa23c608
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Usizer {
+ fn m(self) -> usize;
+}
+
+fn f<const N: usize>(u: impl Usizer) -> usize {
+ N + u.m()
+}
+
+struct Usizable;
+
+impl Usizer for Usizable {
+ fn m(self) -> usize {
+ 16
+ }
+}
+
+fn main() {
+ assert_eq!(f::<4usize>(Usizable), 20usize);
+}
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs
new file mode 100644
index 000000000..3b1024d61
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs
@@ -0,0 +1,5 @@
+fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
+
+fn main() {
+ foo::<str, String>("".to_string()); //~ ERROR E0107
+}
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr
new file mode 100644
index 000000000..c8b82783e
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr
@@ -0,0 +1,18 @@
+error[E0107]: this function takes 1 generic argument but 2 generic arguments were supplied
+ --> $DIR/explicit-generic-args-for-impl.rs:4:5
+ |
+LL | foo::<str, String>("".to_string());
+ | ^^^ ------ help: remove this generic argument
+ | |
+ | expected 1 generic argument
+ |
+note: function defined here, with 1 generic parameter: `T`
+ --> $DIR/explicit-generic-args-for-impl.rs:1:4
+ |
+LL | fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
+ | ^^^ -
+ = note: `impl Trait` cannot be explicitly specified as a generic argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs
new file mode 100644
index 000000000..99e0931ab
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
+
+fn main() {
+ foo::<str>("".to_string());
+}
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs
new file mode 100644
index 000000000..987df4997
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+fn f<T: ?Sized>(_: impl AsRef<T>, _: impl AsRef<T>) {}
+
+fn main() {
+ f::<[u8]>("a", b"a");
+}
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs
new file mode 100644
index 000000000..7249a36f5
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs
@@ -0,0 +1,6 @@
+fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {}
+
+fn main() {
+ f::<[u8]>("a", b"a");
+ //~^ ERROR: this function takes 2 generic arguments but 1 generic argument was supplied
+}
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr
new file mode 100644
index 000000000..9d6db88d3
--- /dev/null
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr
@@ -0,0 +1,21 @@
+error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+ --> $DIR/not-enough-args.rs:4:5
+ |
+LL | f::<[u8]>("a", b"a");
+ | ^ ---- supplied 1 generic argument
+ | |
+ | expected 2 generic arguments
+ |
+note: function defined here, with 2 generic parameters: `T`, `U`
+ --> $DIR/not-enough-args.rs:1:4
+ |
+LL | fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {}
+ | ^ - -
+help: add missing generic argument
+ |
+LL | f::<[u8], U>("a", b"a");
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/impl-trait/extra-item.rs b/src/test/ui/impl-trait/extra-item.rs
new file mode 100644
index 000000000..d82237cce
--- /dev/null
+++ b/src/test/ui/impl-trait/extra-item.rs
@@ -0,0 +1,10 @@
+// aux-build:extra-item.rs
+// compile-flags:--extern extra_item
+
+struct S;
+
+impl extra_item::MyTrait for S {
+ fn extra() {} //~ ERROR method `extra` is not a member of trait `extra_item::MyTrait`
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/extra-item.stderr b/src/test/ui/impl-trait/extra-item.stderr
new file mode 100644
index 000000000..728bcc0aa
--- /dev/null
+++ b/src/test/ui/impl-trait/extra-item.stderr
@@ -0,0 +1,9 @@
+error[E0407]: method `extra` is not a member of trait `extra_item::MyTrait`
+ --> $DIR/extra-item.rs:7:5
+ |
+LL | fn extra() {}
+ | ^^^^^^^^^^^^^ not a member of trait `extra_item::MyTrait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0407`.
diff --git a/src/test/ui/impl-trait/fallback.rs b/src/test/ui/impl-trait/fallback.rs
new file mode 100644
index 000000000..1e6eb5bb3
--- /dev/null
+++ b/src/test/ui/impl-trait/fallback.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+fn take_edge_counters(
+ x: &mut Option<Vec<i32>>,
+) -> Option<impl Iterator<Item = i32>> {
+ x.take().map_or(None, |m| Some(m.into_iter()))
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/fallback_inference.rs b/src/test/ui/impl-trait/fallback_inference.rs
new file mode 100644
index 000000000..98f0bd1af
--- /dev/null
+++ b/src/test/ui/impl-trait/fallback_inference.rs
@@ -0,0 +1,7 @@
+use std::marker::PhantomData;
+
+fn weird() -> PhantomData<impl Sized> {
+ PhantomData //~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/fallback_inference.stderr b/src/test/ui/impl-trait/fallback_inference.stderr
new file mode 100644
index 000000000..4ac3c238f
--- /dev/null
+++ b/src/test/ui/impl-trait/fallback_inference.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+ --> $DIR/fallback_inference.rs:4:5
+ |
+LL | PhantomData
+ | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData`
+ |
+help: consider specifying the generic argument
+ |
+LL | PhantomData::<T>
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr
new file mode 100644
index 000000000..fd2e454e7
--- /dev/null
+++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied
+ --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13
+ |
+LL | fn ice() -> impl AsRef<Fn(&())> {
+ | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` 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/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr
new file mode 100644
index 000000000..c01c33a89
--- /dev/null
+++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr
@@ -0,0 +1,22 @@
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24
+ |
+LL | fn ice() -> impl AsRef<Fn(&())> {
+ | ^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL - fn ice() -> impl AsRef<Fn(&())> {
+LL + fn ice() -> impl AsRef<dyn Fn(&())> {
+ |
+
+error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied
+ --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13
+ |
+LL | fn ice() -> impl AsRef<Fn(&())> {
+ | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0782.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs
new file mode 100644
index 000000000..856dc7a3f
--- /dev/null
+++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs
@@ -0,0 +1,12 @@
+// revisions: edition2015 edition2021
+//[edition2021]edition:2021
+
+#![allow(warnings)]
+
+fn ice() -> impl AsRef<Fn(&())> {
+ //~^ ERROR: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied [E0277]
+ //[edition2021]~| ERROR: trait objects must include the `dyn` keyword [E0782]
+ todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.rs b/src/test/ui/impl-trait/hidden-lifetimes.rs
new file mode 100644
index 000000000..ae07c8927
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-lifetimes.rs
@@ -0,0 +1,63 @@
+// Test to show what happens if we were not careful and allowed invariant
+// lifetimes to escape though an impl trait.
+//
+// Specifically we swap a long lived and short lived reference, giving us a
+// dangling pointer.
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+trait Swap: Sized {
+ fn swap(self, other: Self);
+}
+
+impl<T> Swap for &mut T {
+ fn swap(self, other: Self) {
+ std::mem::swap(self, other);
+ }
+}
+
+impl<T> Swap for Rc<RefCell<T>> {
+ fn swap(self, other: Self) {
+ <RefCell<T>>::swap(&self, &other);
+ }
+}
+
+// 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 {
+ x
+ //~^ ERROR hidden type
+}
+
+fn dangle_ref() -> &'static [i32; 3] {
+ let mut res = &[4, 5, 6];
+ let x = [1, 2, 3];
+ hide_ref(&mut res).swap(hide_ref(&mut &x));
+ res
+}
+
+// Here we are hiding `'b` making the caller believe that `Rc<RefCell<&'s T>>`
+// and `Rc<RefCell<&'l T>>` are the same type.
+//
+// This is different to the previous example because the concrete return type
+// only has a single lifetime.
+fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
+ x
+ //~^ ERROR hidden type
+}
+
+fn dangle_rc_refcell() -> &'static [i32; 3] {
+ let long = Rc::new(RefCell::new(&[4, 5, 6]));
+ let x = [1, 2, 3];
+ let short = Rc::new(RefCell::new(&x));
+ hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short));
+ let res: &'static [i32; 3] = *long.borrow();
+ res
+}
+
+fn main() {
+ // both will print nonsense values.
+ println!("{:?}", dangle_ref());
+ println!("{:?}", dangle_rc_refcell())
+}
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr
new file mode 100644
index 000000000..efc228de5
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr
@@ -0,0 +1,29 @@
+error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
+ --> $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
+LL | x
+ | ^
+ |
+help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+ |
+LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
+ | ++++
+
+error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
+ --> $DIR/hidden-lifetimes.rs:46:5
+ |
+LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
+ | -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+LL | x
+ | ^
+ |
+help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+ |
+LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
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 000000000..970d84120
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs
@@ -0,0 +1,45 @@
+// 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
+
+#![feature(type_alias_impl_trait)]
+
+fn reify_as() -> Thunk<impl FnOnce(Continuation) -> Continuation> {
+ Thunk::new(|mut cont| {
+ cont.reify_as(); //~ ERROR type annotations needed
+ cont
+ })
+}
+
+type Tait = impl FnOnce(Continuation) -> Continuation;
+
+fn reify_as_tait() -> Thunk<Tait> {
+ Thunk::new(|mut cont| {
+ cont.reify_as(); //~ ERROR type annotations needed
+ cont
+ })
+}
+
+#[must_use]
+struct Thunk<F>(F);
+
+impl<F> Thunk<F> {
+ fn new(f: F) -> Self
+ where
+ F: ContFn,
+ {
+ Thunk(f)
+ }
+}
+
+trait ContFn {}
+
+impl<F: FnOnce(Continuation) -> 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 000000000..957052feb
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+ --> $DIR/hidden-type-is-opaque-2.rs:9:9
+ |
+LL | cont.reify_as();
+ | ^^^^ cannot infer type
+
+error[E0282]: type annotations needed
+ --> $DIR/hidden-type-is-opaque-2.rs:18:9
+ |
+LL | cont.reify_as();
+ | ^^^^ cannot infer type
+
+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
new file mode 100644
index 000000000..72b4028d8
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque.rs
@@ -0,0 +1,42 @@
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+fn reify_as() -> Thunk<impl ContFn> {
+ Thunk::new(|mut cont| {
+ cont.reify_as();
+ cont
+ })
+}
+
+type Tait = impl ContFn;
+
+fn reify_as_tait() -> Thunk<Tait> {
+ Thunk::new(|mut cont| {
+ cont.reify_as();
+ cont
+ })
+}
+
+#[must_use]
+struct Thunk<F>(F);
+
+impl<F> Thunk<F> {
+ fn new(f: F) -> Self
+ where
+ F: FnOnce(Continuation) -> Continuation,
+ {
+ Thunk(f)
+ }
+}
+
+trait ContFn {}
+
+impl<F: FnOnce(Continuation) -> Continuation> ContFn for F {}
+
+struct Continuation;
+
+impl Continuation {
+ fn reify_as(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.rs b/src/test/ui/impl-trait/impl-generic-mismatch-ab.rs
new file mode 100644
index 000000000..6c9b119de
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.rs
@@ -0,0 +1,12 @@
+use std::fmt::Debug;
+
+trait Foo {
+ fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
+}
+
+impl Foo for () {
+ fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
+ //~^ ERROR method `foo` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
new file mode 100644
index 000000000..acf768d57
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
@@ -0,0 +1,23 @@
+error[E0053]: method `foo` has an incompatible type for trait
+ --> $DIR/impl-generic-mismatch-ab.rs:8:32
+ |
+LL | fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
+ | - ^^^^^^^^^^^
+ | | |
+ | | expected type parameter `B`, found type parameter `impl Debug`
+ | | help: change the parameter type to match the trait: `&B`
+ | expected type parameter
+ |
+note: type in trait
+ --> $DIR/impl-generic-mismatch-ab.rs:4:32
+ |
+LL | fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
+ | ^^
+ = note: expected fn pointer `fn(&(), &B, &impl Debug)`
+ found fn pointer `fn(&(), &impl Debug, &B)`
+ = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+ = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.rs b/src/test/ui/impl-trait/impl-generic-mismatch.rs
new file mode 100644
index 000000000..ba678bb03
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.rs
@@ -0,0 +1,32 @@
+use std::fmt::Debug;
+
+trait Foo {
+ fn foo(&self, _: &impl Debug);
+}
+
+impl Foo for () {
+ fn foo<U: Debug>(&self, _: &U) { }
+ //~^ Error method `foo` has incompatible signature for trait
+}
+
+trait Bar {
+ fn bar<U: Debug>(&self, _: &U);
+}
+
+impl Bar for () {
+ fn bar(&self, _: &impl Debug) { }
+ //~^ Error method `bar` has incompatible signature for trait
+}
+
+// With non-local trait (#49841):
+
+use std::hash::{Hash, Hasher};
+
+struct X;
+
+impl Hash for X {
+ fn hash(&self, hasher: &mut impl Hasher) {}
+ //~^ Error method `hash` has incompatible signature for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.stderr b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
new file mode 100644
index 000000000..489afd761
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
@@ -0,0 +1,43 @@
+error[E0643]: method `foo` has incompatible signature for trait
+ --> $DIR/impl-generic-mismatch.rs:8:12
+ |
+LL | fn foo(&self, _: &impl Debug);
+ | ---------- declaration in trait here
+...
+LL | fn foo<U: Debug>(&self, _: &U) { }
+ | ^ expected `impl Trait`, found generic parameter
+ |
+help: try removing the generic parameter and using `impl Trait` instead
+ |
+LL - fn foo<U: Debug>(&self, _: &U) { }
+LL + fn foo(&self, _: &impl Debug) { }
+ |
+
+error[E0643]: method `bar` has incompatible signature for trait
+ --> $DIR/impl-generic-mismatch.rs:17:23
+ |
+LL | fn bar<U: Debug>(&self, _: &U);
+ | - declaration in trait here
+...
+LL | fn bar(&self, _: &impl Debug) { }
+ | ^^^^^^^^^^ expected generic parameter, found `impl Trait`
+ |
+help: try changing the `impl Trait` argument to a generic parameter
+ |
+LL | fn bar<U: Debug>(&self, _: &U) { }
+ | ++++++++++ ~
+
+error[E0643]: method `hash` has incompatible signature for trait
+ --> $DIR/impl-generic-mismatch.rs:28:33
+ |
+LL | fn hash(&self, hasher: &mut impl Hasher) {}
+ | ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+ |
+ ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
+ |
+LL | fn hash<H: Hasher>(&self, state: &mut H);
+ | - declaration in trait here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0643`.
diff --git a/src/test/ui/impl-trait/impl-trait-in-macro.rs b/src/test/ui/impl-trait/impl-trait-in-macro.rs
new file mode 100644
index 000000000..3165c9b99
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-trait-in-macro.rs
@@ -0,0 +1,20 @@
+use std::fmt::Debug;
+
+macro_rules! i {
+ ($($tr:tt)*) => { impl $($tr)* };
+}
+
+fn foo(x: i!(Debug), y: i!(Debug)) -> String {
+ let mut a = x;
+ a = y; //~ ERROR mismatched
+ format!("{:?}", a)
+}
+
+trait S<T> {}
+
+fn much_universe<T: S<i!(Debug)>, U: IntoIterator<Item = i!(Iterator<Item = i!(Clone)>)>>(
+ _: i!(Debug + Clone),
+) {
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-trait-in-macro.stderr b/src/test/ui/impl-trait/impl-trait-in-macro.stderr
new file mode 100644
index 000000000..7cfbe3447
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-trait-in-macro.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+ --> $DIR/impl-trait-in-macro.rs:9:9
+ |
+LL | ($($tr:tt)*) => { impl $($tr)* };
+ | ----
+ | |
+ | expected type parameter
+ | found type parameter
+...
+LL | let mut a = x;
+ | - expected due to this value
+LL | a = y;
+ | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
+ |
+ = note: expected type parameter `impl Debug` (type parameter `impl Debug`)
+ found type parameter `impl Debug` (type parameter `impl Debug`)
+ = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+ = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.rs b/src/test/ui/impl-trait/impl-trait-plus-priority.rs
new file mode 100644
index 000000000..dfac9c0f1
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-trait-plus-priority.rs
@@ -0,0 +1,49 @@
+// compile-flags: -Z parse-only
+
+fn f() -> impl A + {} // OK
+fn f() -> impl A + B {} // OK
+fn f() -> dyn A + B {} // OK
+fn f() -> A + B {} // OK
+
+impl S {
+ fn f(self) -> impl A + { // OK
+ let _ = |a, b| -> impl A + {}; // OK
+ }
+ fn f(self) -> impl A + B { // OK
+ let _ = |a, b| -> impl A + B {}; // OK
+ }
+ fn f(self) -> dyn A + B { // OK
+ let _ = |a, b| -> dyn A + B {}; // OK
+ }
+ fn f(self) -> A + B { // OK
+ let _ = |a, b| -> A + B {}; // OK
+ }
+}
+
+type A = fn() -> impl A +;
+//~^ ERROR ambiguous `+` in a type
+type A = fn() -> impl A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = fn() -> dyn A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = fn() -> A + B;
+//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A`
+
+type A = Fn() -> impl A +;
+//~^ ERROR ambiguous `+` in a type
+type A = Fn() -> impl A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = Fn() -> dyn A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = Fn() -> A + B; // OK, interpreted as `(Fn() -> A) + B` for compatibility
+
+type A = &impl A +;
+//~^ ERROR ambiguous `+` in a type
+type A = &impl A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = &dyn A + B;
+//~^ ERROR ambiguous `+` in a type
+type A = &A + B;
+//~^ ERROR expected a path on the left-hand side of `+`, not `&A`
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.stderr b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr
new file mode 100644
index 000000000..205d9b0b7
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr
@@ -0,0 +1,69 @@
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:23:18
+ |
+LL | type A = fn() -> impl A +;
+ | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:25:18
+ |
+LL | type A = fn() -> impl A + B;
+ | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:27:18
+ |
+LL | type A = fn() -> dyn A + B;
+ | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A`
+ --> $DIR/impl-trait-plus-priority.rs:29:10
+ |
+LL | type A = fn() -> A + B;
+ | ^^^^^^^^^^^^^ perhaps you forgot parentheses?
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:32:18
+ |
+LL | type A = Fn() -> impl A +;
+ | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:34:18
+ |
+LL | type A = Fn() -> impl A + B;
+ | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:36:18
+ |
+LL | type A = Fn() -> dyn A + B;
+ | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:40:11
+ |
+LL | type A = &impl A +;
+ | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:42:11
+ |
+LL | type A = &impl A + B;
+ | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)`
+
+error: ambiguous `+` in a type
+ --> $DIR/impl-trait-plus-priority.rs:44:11
+ |
+LL | type A = &dyn A + B;
+ | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `&A`
+ --> $DIR/impl-trait-plus-priority.rs:46:10
+ |
+LL | type A = &A + B;
+ | ^^^^^^ help: try adding parentheses: `&(A + B)`
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0178`.
diff --git a/src/test/ui/impl-trait/impl_trait_projections.rs b/src/test/ui/impl-trait/impl_trait_projections.rs
new file mode 100644
index 000000000..fd0986d7c
--- /dev/null
+++ b/src/test/ui/impl-trait/impl_trait_projections.rs
@@ -0,0 +1,39 @@
+use std::fmt::Debug;
+use std::option;
+
+fn parametrized_type_is_allowed() -> Option<impl Debug> {
+ Some(5i32)
+}
+
+fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> {
+ Some(5i32)
+}
+
+fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+//~^ ERROR `impl Trait` is not allowed in path parameters
+//~^^ ERROR ambiguous associated type
+ x.next().unwrap()
+}
+
+fn projection_with_named_trait_is_disallowed(x: impl Iterator)
+ -> <impl Iterator as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+ x.next().unwrap()
+}
+
+fn projection_with_named_trait_inside_path_is_disallowed()
+ -> <::std::ops::Range<impl Debug> as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+ (1i32..100).next().unwrap()
+}
+
+fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
+ -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
+//~^ ERROR `impl Trait` is not allowed in path parameters
+{
+ panic!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl_trait_projections.stderr b/src/test/ui/impl-trait/impl_trait_projections.stderr
new file mode 100644
index 000000000..82d2422c4
--- /dev/null
+++ b/src/test/ui/impl-trait/impl_trait_projections.stderr
@@ -0,0 +1,34 @@
+error[E0667]: `impl Trait` is not allowed in path parameters
+ --> $DIR/impl_trait_projections.rs:12:51
+ |
+LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+ | ^^^^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+ --> $DIR/impl_trait_projections.rs:19:9
+ |
+LL | -> <impl Iterator as Iterator>::Item
+ | ^^^^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+ --> $DIR/impl_trait_projections.rs:26:27
+ |
+LL | -> <::std::ops::Range<impl Debug> as Iterator>::Item
+ | ^^^^^^^^^^
+
+error[E0667]: `impl Trait` is not allowed in path parameters
+ --> $DIR/impl_trait_projections.rs:33:29
+ |
+LL | -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
+ | ^^^^^^^^^^
+
+error[E0223]: ambiguous associated type
+ --> $DIR/impl_trait_projections.rs:12:50
+ |
+LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
+ | ^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<impl Iterator as Trait>::Item`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0223, E0667.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/src/test/ui/impl-trait/issue-100187.rs b/src/test/ui/impl-trait/issue-100187.rs
new file mode 100644
index 000000000..fc541c696
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-100187.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+trait Trait<T> {
+ type Ty;
+}
+impl Trait<&u8> for () {
+ type Ty = ();
+}
+
+fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-46959.rs b/src/test/ui/impl-trait/issue-46959.rs
new file mode 100644
index 000000000..3611a9568
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-46959.rs
@@ -0,0 +1,9 @@
+// check-pass
+#![deny(non_camel_case_types)]
+
+#[allow(dead_code)]
+fn qqq(lol: impl Iterator<Item=u32>) -> impl Iterator<Item=u64> {
+ lol.map(|x|x as u64)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-49579.rs b/src/test/ui/impl-trait/issue-49579.rs
new file mode 100644
index 000000000..98de014e9
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-49579.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+ (0 .. n)
+ .scan((0, 1), |st, _| {
+ *st = (st.1, st.0 + st.1);
+ Some(*st)
+ })
+ .map(&|(f, _)| f)
+}
+
+fn main() {
+ println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/impl-trait/issue-49685.rs b/src/test/ui/impl-trait/issue-49685.rs
new file mode 100644
index 000000000..fb328d67b
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-49685.rs
@@ -0,0 +1,13 @@
+// run-pass
+// Regression test for #49685: drop elaboration was not revealing the
+// value of `impl Trait` returns, leading to an ICE.
+
+fn main() {
+ let _ = Some(())
+ .into_iter()
+ .flat_map(|_| Some(()).into_iter().flat_map(func));
+}
+
+fn func(_: ()) -> impl Iterator<Item = ()> {
+ Some(()).into_iter().flat_map(|_| vec![])
+}
diff --git a/src/test/ui/impl-trait/issue-51185.rs b/src/test/ui/impl-trait/issue-51185.rs
new file mode 100644
index 000000000..52a2b2553
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-51185.rs
@@ -0,0 +1,8 @@
+// run-pass
+fn foo() -> impl Into<for<'a> fn(&'a ())> {
+ (|_| {}) as for<'a> fn(&'a ())
+}
+
+fn main() {
+ foo().into()(&());
+}
diff --git a/src/test/ui/impl-trait/issue-54966.rs b/src/test/ui/impl-trait/issue-54966.rs
new file mode 100644
index 000000000..0ed3c4b3c
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-54966.rs
@@ -0,0 +1,6 @@
+// issue-54966: ICE returning an unknown type with impl FnMut
+
+fn generate_duration() -> Oper<impl FnMut()> {}
+//~^ ERROR cannot find type `Oper` in this scope
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-54966.stderr b/src/test/ui/impl-trait/issue-54966.stderr
new file mode 100644
index 000000000..aa9a61cb5
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-54966.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Oper` in this scope
+ --> $DIR/issue-54966.rs:3:27
+ |
+LL | fn generate_duration() -> Oper<impl FnMut()> {}
+ | ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs
new file mode 100644
index 000000000..22ff7ffa2
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-1.rs
@@ -0,0 +1,20 @@
+#![feature(type_alias_impl_trait)]
+
+pub trait Bar {
+ type E: Copy;
+
+ fn foo<T>() -> Self::E;
+}
+
+impl<S: Default> Bar for S {
+ type E = impl Copy;
+
+ fn foo<T: Default>() -> Self::E {
+ //~^ 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]
+ (S::default(), T::default())
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr
new file mode 100644
index 000000000..8912cce1b
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-1.stderr
@@ -0,0 +1,37 @@
+error[E0276]: impl has stricter requirements than trait
+ --> $DIR/issue-55872-1.rs:12:15
+ |
+LL | fn foo<T>() -> Self::E;
+ | ----------------------- definition of `foo` from trait
+...
+LL | fn foo<T: Default>() -> Self::E {
+ | ^^^^^^^ impl has extra requirement `T: Default`
+
+error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
+ --> $DIR/issue-55872-1.rs:12:29
+ |
+LL | fn foo<T: Default>() -> Self::E {
+ | ^^^^^^^ 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
+ |
+LL | impl<S: Default + std::marker::Copy> Bar for S {
+ | +++++++++++++++++++
+
+error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
+ --> $DIR/issue-55872-1.rs:12:29
+ |
+LL | fn foo<T: Default>() -> Self::E {
+ | ^^^^^^^ 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
+ |
+LL | fn foo<T: Default + std::marker::Copy>() -> Self::E {
+ | +++++++++++++++++++
+
+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
new file mode 100644
index 000000000..4443d3c4d
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-2.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Bar {
+ type E: Send;
+
+ fn foo<T>() -> Self::E;
+}
+
+impl<S> Bar for S {
+ type E = impl std::marker::Send;
+ fn foo<T>() -> Self::E {
+ async {}
+ //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr
new file mode 100644
index 000000000..11b8485c8
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-2.stderr
@@ -0,0 +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-2.rs:14:9
+ |
+LL | async {}
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
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 000000000..3ffce85e6
--- /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<T>() -> Self::E;
+}
+
+impl<S> Bar for S {
+ type E = impl std::marker::Copy;
+ fn foo<T>() -> Self::E {
+ //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied [E0277]
+ async {}
+ }
+}
+
+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 000000000..6ab540e87
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-3.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+ --> $DIR/issue-55872-3.rs:14:20
+ |
+LL | fn foo<T>() -> Self::E {
+ | ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+
+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
new file mode 100644
index 000000000..c4e6f6436
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872.rs
@@ -0,0 +1,18 @@
+#![feature(type_alias_impl_trait)]
+
+pub trait Bar {
+ type E: Copy;
+
+ fn foo<T>() -> Self::E;
+}
+
+impl<S> Bar for S {
+ type E = impl Copy;
+
+ fn foo<T>() -> Self::E {
+ || ()
+ //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55872.stderr b/src/test/ui/impl-trait/issue-55872.stderr
new file mode 100644
index 000000000..cb370fbe1
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872.stderr
@@ -0,0 +1,8 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/issue-55872.rs:13:9
+ |
+LL | || ()
+ | ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-56445.rs b/src/test/ui/impl-trait/issue-56445.rs
new file mode 100644
index 000000000..6dd1648c9
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-56445.rs
@@ -0,0 +1,25 @@
+// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-629426939
+// check-pass
+
+#![crate_type = "lib"]
+
+use std::marker::PhantomData;
+
+pub struct S<'a> {
+ pub m1: PhantomData<&'a u8>,
+ pub m2: [u8; S::size()],
+}
+
+impl<'a> S<'a>
+{
+ pub const fn size() -> usize { 1 }
+
+ pub fn new() -> Self
+ {
+ Self
+ {
+ m1: PhantomData,
+ m2: [0; Self::size()],
+ }
+ }
+}
diff --git a/src/test/ui/impl-trait/issue-68532.rs b/src/test/ui/impl-trait/issue-68532.rs
new file mode 100644
index 000000000..01a7af0ae
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-68532.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+pub struct A<'a>(&'a ());
+
+impl<'a> A<'a> {
+ const N: usize = 68;
+
+ pub fn foo(&self) {
+ let _b = [0; Self::N];
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs
new file mode 100644
index 000000000..be9c643b2
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-72911.rs
@@ -0,0 +1,22 @@
+// Regression test for #72911.
+
+pub struct Lint {}
+
+impl Lint {}
+
+pub fn gather_all() -> impl Iterator<Item = Lint> {
+ //~^ ERROR type annotations needed
+ lint_files().flat_map(|f| gather_from_file(&f))
+}
+
+fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
+ //~^ ERROR: failed to resolve
+ unimplemented!()
+}
+
+fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
+ //~^ ERROR: failed to resolve
+ unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr
new file mode 100644
index 000000000..fc7200c75
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-72911.stderr
@@ -0,0 +1,22 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `foo`
+ --> $DIR/issue-72911.rs:12:33
+ |
+LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
+ | ^^^ use of undeclared crate or module `foo`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `foo`
+ --> $DIR/issue-72911.rs:17:41
+ |
+LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
+ | ^^^ use of undeclared crate or module `foo`
+
+error[E0282]: type annotations needed
+ --> $DIR/issue-72911.rs:7:24
+ |
+LL | pub fn gather_all() -> impl Iterator<Item = Lint> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0433.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs
new file mode 100644
index 000000000..a79bb6474
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-86465.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+type X<'a, 'b> = impl std::fmt::Debug;
+
+fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
+ (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
new file mode 100644
index 000000000..90d6904ed
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-86465.stderr
@@ -0,0 +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`
+ | this expression supplies two conflicting concrete types for the same opaque type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-87450.rs b/src/test/ui/impl-trait/issue-87450.rs
new file mode 100644
index 000000000..983ef7cfb
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-87450.rs
@@ -0,0 +1,16 @@
+fn bar() -> impl Fn() {
+ wrap(wrap(wrap(wrap(foo()))))
+}
+
+fn foo() -> impl Fn() {
+ //~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion]
+ //~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720]
+ wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
+}
+
+fn wrap(f: impl Fn()) -> impl Fn() {
+ move || f()
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/issue-87450.stderr b/src/test/ui/impl-trait/issue-87450.stderr
new file mode 100644
index 000000000..5019e544b
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-87450.stderr
@@ -0,0 +1,27 @@
+warning: function cannot return without recursing
+ --> $DIR/issue-87450.rs:5:1
+ |
+LL | fn foo() -> impl Fn() {
+ | ^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+...
+LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
+ | ----- recursive call site
+ |
+ = note: `#[warn(unconditional_recursion)]` on by default
+ = help: a `loop` may express intention better if this is on purpose
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/issue-87450.rs:5:13
+ |
+LL | fn foo() -> impl Fn() {
+ | ^^^^^^^^^ recursive opaque type
+...
+LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
+ | ----------------------------------------------- returning here with type `impl Fn()`
+...
+LL | fn wrap(f: impl Fn()) -> impl Fn() {
+ | --------- returning this opaque type `impl Fn()`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issue-99073-2.rs b/src/test/ui/impl-trait/issue-99073-2.rs
new file mode 100644
index 000000000..14ac68880
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073-2.rs
@@ -0,0 +1,17 @@
+use std::fmt::Display;
+
+fn main() {
+ test("hi", true);
+}
+
+fn test<T: Display>(t: T, recurse: bool) -> impl Display {
+ let f = || {
+ let i: u32 = test::<i32>(-1, false);
+ //~^ ERROR concrete type differs from previous defining opaque type use
+ println!("{i}");
+ };
+ if recurse {
+ f();
+ }
+ t
+}
diff --git a/src/test/ui/impl-trait/issue-99073-2.stderr b/src/test/ui/impl-trait/issue-99073-2.stderr
new file mode 100644
index 000000000..913bc8f56
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073-2.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/issue-99073-2.rs:9:22
+ |
+LL | let i: u32 = test::<i32>(-1, false);
+ | ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32`
+ |
+note: previous use here
+ --> $DIR/issue-99073-2.rs:16:5
+ |
+LL | t
+ | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-99073.rs b/src/test/ui/impl-trait/issue-99073.rs
new file mode 100644
index 000000000..7798e247d
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let _ = fix(|_: &dyn Fn()| {});
+}
+
+fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
+ move || f(fix(&f))
+ //~^ ERROR concrete type differs from previous defining opaque type use
+}
diff --git a/src/test/ui/impl-trait/issue-99073.stderr b/src/test/ui/impl-trait/issue-99073.stderr
new file mode 100644
index 000000000..546367953
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/issue-99073.rs:6:11
+ |
+LL | move || f(fix(&f))
+ | ^^^^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G`
+ |
+note: previous use here
+ --> $DIR/issue-99073.rs:6:3
+ |
+LL | move || f(fix(&f))
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-99642-2.rs b/src/test/ui/impl-trait/issue-99642-2.rs
new file mode 100644
index 000000000..0e88b3633
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99642-2.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+type Opq = impl Sized;
+fn test() -> impl Iterator<Item = Opq> {
+ Box::new(0..) as Box<dyn Iterator<Item = _>>
+}
+fn main(){}
diff --git a/src/test/ui/impl-trait/issue-99642.rs b/src/test/ui/impl-trait/issue-99642.rs
new file mode 100644
index 000000000..75af60491
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99642.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+fn test() -> impl Iterator<Item = impl Sized> {
+ Box::new(0..) as Box<dyn Iterator<Item = _>>
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
new file mode 100644
index 000000000..451ddb3cc
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
@@ -0,0 +1,25 @@
+// Test that attempts to construct infinite types via impl trait fail
+// in a graceful way.
+//
+// Regression test for #38064.
+
+trait Quux {}
+
+fn foo() -> impl Quux { //~ ERROR cannot resolve opaque type
+ struct Foo<T>(T);
+ impl<T> Quux for Foo<T> {}
+ Foo(bar())
+}
+
+fn bar() -> impl Quux { //~ ERROR cannot resolve opaque type
+ struct Bar<T>(T);
+ impl<T> Quux for Bar<T> {}
+ Bar(foo())
+}
+
+// effectively:
+// struct Foo(Bar);
+// struct Bar(Foo);
+// should produce an error about infinite size
+
+fn main() { foo(); }
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
new file mode 100644
index 000000000..16a1262ec
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
@@ -0,0 +1,27 @@
+error[E0720]: cannot resolve opaque type
+ --> $DIR/infinite-impl-trait-issue-38064.rs:8:13
+ |
+LL | fn foo() -> impl Quux {
+ | ^^^^^^^^^ recursive opaque type
+...
+LL | Foo(bar())
+ | ---------- returning here with type `Foo<impl Quux>`
+...
+LL | fn bar() -> impl Quux {
+ | --------- returning this opaque type `Foo<impl Quux>`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/infinite-impl-trait-issue-38064.rs:14:13
+ |
+LL | fn foo() -> impl Quux {
+ | --------- returning this opaque type `Bar<impl Quux>`
+...
+LL | fn bar() -> impl Quux {
+ | ^^^^^^^^^ recursive opaque type
+...
+LL | Bar(foo())
+ | ---------- returning here with type `Bar<impl Quux>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
new file mode 100644
index 000000000..41f48cb56
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
@@ -0,0 +1,22 @@
+trait Foo<A> {
+ fn foo(&self, a: A) -> A {
+ a
+ }
+}
+
+trait NotRelevant<A> {
+ fn nr(&self, a: A) -> A {
+ a
+ }
+}
+
+struct Bar;
+
+impl NotRelevant<usize> for Bar {}
+
+fn main() {
+ let f1 = Bar;
+
+ f1.foo(1usize);
+ //~^ error: method named `foo` found for struct `Bar` in the current scope
+}
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
new file mode 100644
index 000000000..9150d957d
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `foo` found for struct `Bar` in the current scope
+ --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8
+ |
+LL | struct Bar;
+ | ---------- method `foo` not found for this struct
+...
+LL | f1.foo(1usize);
+ | ^^^ method not found in `Bar`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Foo` defines an item `foo`, perhaps you need to implement it
+ --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:1:1
+ |
+LL | trait Foo<A> {
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/issues/issue-42479.rs b/src/test/ui/impl-trait/issues/issue-42479.rs
new file mode 100644
index 000000000..efc1f975d
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-42479.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+use std::iter::once;
+
+struct Foo {
+ x: i32,
+}
+
+impl Foo {
+ fn inside(&self) -> impl Iterator<Item = &i32> {
+ once(&self.x)
+ }
+}
+
+fn main() {
+ println!("hi");
+}
diff --git a/src/test/ui/impl-trait/issues/issue-49376.rs b/src/test/ui/impl-trait/issues/issue-49376.rs
new file mode 100644
index 000000000..e4472fcc1
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-49376.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+// Tests for nested self-reference which caused a stack overflow.
+
+use std::fmt::Debug;
+use std::ops::*;
+
+fn gen() -> impl PartialOrd + PartialEq + Debug { }
+
+struct Bar {}
+trait Foo<T = Self> {}
+trait FooNested<T = Option<Self>> {}
+impl Foo for Bar {}
+impl FooNested for Bar {}
+
+fn foo() -> impl Foo + FooNested {
+ Bar {}
+}
+
+fn test_impl_ops() -> impl Add + Sub + Mul + Div { 1 }
+fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign { 1 }
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-52128.rs b/src/test/ui/impl-trait/issues/issue-52128.rs
new file mode 100644
index 000000000..5afd380dd
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-52128.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+#![deny(warnings)]
+
+use std::collections::BTreeMap;
+
+pub struct RangeMap {
+ map: BTreeMap<Range, u8>,
+}
+
+#[derive(Eq, PartialEq, Ord, PartialOrd)]
+struct Range;
+
+impl RangeMap {
+ fn iter_with_range<'a>(&'a self) -> impl Iterator<Item = (&'a Range, &'a u8)> + 'a {
+ self.map.range(Range..Range)
+ }
+
+ pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a u8> + 'a {
+ self.iter_with_range().map(|(_, data)| data)
+ }
+
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-53457.rs b/src/test/ui/impl-trait/issues/issue-53457.rs
new file mode 100644
index 000000000..7b9c2c53a
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-53457.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+type X = impl Clone;
+
+fn bar<F: Fn(&i32) + Clone>(f: F) -> F {
+ f
+}
+
+fn foo() -> X {
+ bar(|_| ())
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-54600.rs b/src/test/ui/impl-trait/issues/issue-54600.rs
new file mode 100644
index 000000000..3024fedf7
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54600.rs
@@ -0,0 +1,7 @@
+use std::fmt::Debug;
+
+fn main() {
+ let x: Option<impl Debug> = Some(44_u32);
+ //~^ `impl Trait` only allowed in function and inherent method return types
+ println!("{:?}", x);
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54600.stderr b/src/test/ui/impl-trait/issues/issue-54600.stderr
new file mode 100644
index 000000000..316566a57
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54600.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-54600.rs:4:19
+ |
+LL | let x: Option<impl Debug> = Some(44_u32);
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-54840.rs b/src/test/ui/impl-trait/issues/issue-54840.rs
new file mode 100644
index 000000000..8f1e0ece0
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54840.rs
@@ -0,0 +1,7 @@
+use std::ops::Add;
+
+fn main() {
+ let i: i32 = 0;
+ let j: &impl Add = &i;
+ //~^ `impl Trait` only allowed in function and inherent method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54840.stderr b/src/test/ui/impl-trait/issues/issue-54840.stderr
new file mode 100644
index 000000000..8d82133ac
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54840.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-54840.rs:5:13
+ |
+LL | let j: &impl Add = &i;
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-54895.rs b/src/test/ui/impl-trait/issues/issue-54895.rs
new file mode 100644
index 000000000..8d7a1d56f
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54895.rs
@@ -0,0 +1,22 @@
+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> {
+ //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+ X(())
+}
+
+fn main() {
+ let _ = f();
+}
diff --git a/src/test/ui/impl-trait/issues/issue-54895.stderr b/src/test/ui/impl-trait/issues/issue-54895.stderr
new file mode 100644
index 000000000..7d22f027a
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54895.stderr
@@ -0,0 +1,14 @@
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/issue-54895.rs:15:53
+ |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/issue-54895.rs:15:20
+ |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+ | ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs
new file mode 100644
index 000000000..0c34c97e2
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs
@@ -0,0 +1,22 @@
+// This used to ICE because it creates an `impl Trait` that captures a
+// hidden empty region.
+
+// check-pass
+
+fn server() -> impl FilterBase2 {
+ segment2(|| { loop { } }).map2(|| "")
+}
+
+trait FilterBase2 {
+ fn map2<F>(self, _fn: F) -> Map2<F> where Self: Sized { loop { } }
+}
+
+struct Map2<F> { _func: F }
+
+impl<F> FilterBase2 for Map2<F> { }
+
+fn segment2<F>(_fn: F) -> Map2<F> where F: Fn() -> Result<(), ()> {
+ loop { }
+}
+
+fn main() { server(); }
diff --git a/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs b/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs
new file mode 100644
index 000000000..c4f738a34
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs
@@ -0,0 +1,29 @@
+// Regression test for issue 57464.
+//
+// Closure are (surprisingly) allowed to outlive their signature. As such it
+// was possible to end up with `ReScope`s appearing in the concrete type of an
+// opaque type. As all regions are now required to outlive the bound in an
+// opaque type we avoid the issue here.
+
+// check-pass
+
+struct A<F>(F);
+
+unsafe impl <'a, 'b, F: Fn(&'a i32) -> &'b i32> Send for A<F> {}
+
+fn wrapped_closure() -> impl Sized {
+ let f = |x| x;
+ f(&0);
+ A(f)
+}
+
+fn wrapped_closure_with_bound() -> impl Sized + 'static {
+ let f = |x| x;
+ f(&0);
+ A(f)
+}
+
+fn main() {
+ let x: Box<dyn Send> = Box::new(wrapped_closure());
+ let y: Box<dyn Send> = Box::new(wrapped_closure_with_bound());
+}
diff --git a/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs b/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs
new file mode 100644
index 000000000..0daec3305
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs
@@ -0,0 +1,17 @@
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection,
+// but it did catch *some cases*. This is checking that we continue to
+// properly emit errors for those.
+//
+// issue-57979-nested-impl-trait-in-assoc-proj.rs shows the main case
+// that we were previously failing to catch.
+
+struct Deeper<T>(T);
+
+pub trait Foo<T> { }
+pub trait Bar { }
+pub trait Quux { type Assoc; }
+pub fn demo(_: impl Quux<Assoc=Deeper<impl Foo<impl Bar>>>) { }
+//~^ ERROR nested `impl Trait` is not allowed
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr b/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr
new file mode 100644
index 000000000..6bebbc01f
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr
@@ -0,0 +1,12 @@
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:14:48
+ |
+LL | pub fn demo(_: impl Quux<Assoc=Deeper<impl Foo<impl Bar>>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0666`.
diff --git a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs
new file mode 100644
index 000000000..c5ecd1caa
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs
@@ -0,0 +1,12 @@
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection.
+// Here we test behavior of occurrences of `impl Trait` within a path
+// component in that context.
+
+pub trait Bar { }
+pub trait Quux<T> { type Assoc; }
+pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+//~^ ERROR `impl Trait` is not allowed in path parameters
+impl<T> Quux<T> for () { type Assoc = u32; }
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
new file mode 100644
index 000000000..e31393181
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
@@ -0,0 +1,9 @@
+error[E0667]: `impl Trait` is not allowed in path parameters
+ --> $DIR/issue-57979-impl-trait-in-path.rs:8:48
+ |
+LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0667`.
diff --git a/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs b/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs
new file mode 100644
index 000000000..5a444d3df
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs
@@ -0,0 +1,12 @@
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection.
+// Here we test behavior of occurrences of `impl Trait` within an
+// `impl Trait` in that context.
+
+pub trait Foo<T> { }
+pub trait Bar { }
+pub trait Quux { type Assoc; }
+pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+//~^ ERROR nested `impl Trait` is not allowed
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr b/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr
new file mode 100644
index 000000000..8d3d4b5e2
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr
@@ -0,0 +1,12 @@
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:9:41
+ |
+LL | pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0666`.
diff --git a/src/test/ui/impl-trait/issues/issue-58504.rs b/src/test/ui/impl-trait/issues/issue-58504.rs
new file mode 100644
index 000000000..e5865d0df
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-58504.rs
@@ -0,0 +1,12 @@
+#![feature(generators, generator_trait, never_type)]
+
+use std::ops::Generator;
+
+fn mk_gen() -> impl Generator<Return=!, Yield=()> {
+ || { loop { yield; } }
+}
+
+fn main() {
+ let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+ //~^ `impl Trait` only allowed in function and inherent method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-58504.stderr b/src/test/ui/impl-trait/issues/issue-58504.stderr
new file mode 100644
index 000000000..6656e9fc3
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-58504.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-58504.rs:10:16
+ |
+LL | let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-58956.rs b/src/test/ui/impl-trait/issues/issue-58956.rs
new file mode 100644
index 000000000..68cfcd9ba
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-58956.rs
@@ -0,0 +1,14 @@
+trait Lam {}
+
+pub struct B;
+impl Lam for B {}
+pub struct Wrap<T>(T);
+
+const _A: impl Lam = {
+ //~^ `impl Trait` only allowed in function and inherent method return types
+ let x: Wrap<impl Lam> = Wrap(B);
+ //~^ `impl Trait` only allowed in function and inherent method return types
+ x.0
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-58956.stderr b/src/test/ui/impl-trait/issues/issue-58956.stderr
new file mode 100644
index 000000000..123fb4df4
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-58956.stderr
@@ -0,0 +1,15 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/issue-58956.rs:7:11
+ |
+LL | const _A: impl Lam = {
+ | ^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-58956.rs:9:17
+ |
+LL | let x: Wrap<impl Lam> = Wrap(B);
+ | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-62742.rs b/src/test/ui/impl-trait/issues/issue-62742.rs
new file mode 100644
index 000000000..041bd0e38
--- /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<T: ?Sized> {
+ type Value;
+}
+
+pub type WrongImpl<T> = SafeImpl<T, RawImpl<T>>;
+
+pub type CorrectImpl<T> = SafeImpl<[T], RawImpl<T>>;
+
+pub struct RawImpl<T>(PhantomData<T>);
+
+impl<T> Raw<[T]> for RawImpl<T> {
+ type Value = T;
+}
+
+pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+
+impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
+ 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 000000000..34f4dc2ce
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-62742.stderr
@@ -0,0 +1,50 @@
+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 trait `Raw<[T]>` is implemented for `RawImpl<T>`
+note: required by a bound in `SafeImpl`
+ --> $DIR/issue-62742.rs:26:35
+ |
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(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<T>(PhantomData<T>);
+ | --------------------- doesn't satisfy `RawImpl<()>: Raw<()>`
+...
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+ | ----------------------------------------- function or associated item `foo` not found for this struct
+ |
+ = 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<T: ?Sized> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+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 trait `Raw<[T]>` is implemented for `RawImpl<T>`
+note: required by a bound in `SafeImpl`
+ --> $DIR/issue-62742.rs:26:35
+ |
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(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-65581.rs b/src/test/ui/impl-trait/issues/issue-65581.rs
new file mode 100644
index 000000000..b947fc1d2
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-65581.rs
@@ -0,0 +1,34 @@
+// check-pass
+// ignore-compare-mode-chalk
+
+#![allow(dead_code)]
+
+trait Trait1<T, U> {
+ fn f1(self) -> U;
+}
+
+trait Trait2 {
+ type T;
+ type U: Trait2<T = Self::T>;
+ fn f2(f: impl FnOnce(&Self::U));
+}
+
+fn f3<T: Trait2>() -> impl Trait1<T, T::T> {
+ Struct1
+}
+
+struct Struct1;
+
+impl<T: Trait2> Trait1<T, T::T> for Struct1 {
+ fn f1(self) -> T::T {
+ unimplemented!()
+ }
+}
+
+fn f4<T: Trait2>() {
+ T::f2(|_| {
+ f3::<T::U>().f1();
+ });
+}
+
+fn main() {}
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 000000000..92f7e005d
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-67830.rs
@@ -0,0 +1,26 @@
+trait MyFn<Arg> {
+ type Output;
+ fn call(&self, arg: Arg) -> Self::Output;
+}
+
+struct Wrap<F>(F);
+
+impl<A, B, F> MyFn<A> for Wrap<F>
+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 higher kinded lifetime bounds on nested opaque types are not supported yet
+ 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 000000000..d3ea8cb03
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-67830.stderr
@@ -0,0 +1,14 @@
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/issue-67830.rs:21:62
+ |
+LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/issue-67830.rs:21:23
+ |
+LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+ | ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs
new file mode 100644
index 000000000..8169cfafa
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-70877.rs
@@ -0,0 +1,36 @@
+#![feature(type_alias_impl_trait)]
+
+type FooArg<'a> = &'a dyn ToString;
+type FooRet = impl std::fmt::Debug;
+
+type FooItem = Box<dyn Fn(FooArg) -> FooRet>;
+type Foo = impl Iterator<Item = FooItem>;
+
+#[repr(C)]
+struct Bar(u8);
+
+impl Iterator for Bar {
+ type Item = FooItem;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ Some(Box::new(quux))
+ }
+}
+
+fn quux(st: FooArg) -> FooRet {
+ Some(st.to_string())
+}
+
+fn ham() -> Foo {
+ Bar(1)
+}
+
+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
+}
+
+fn main() {
+ let _ = oof();
+}
diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr
new file mode 100644
index 000000000..8813bff3c
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-70877.stderr
@@ -0,0 +1,19 @@
+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 | 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
+
diff --git a/src/test/ui/impl-trait/issues/issue-70971.rs b/src/test/ui/impl-trait/issues/issue-70971.rs
new file mode 100644
index 000000000..f8ae18bac
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-70971.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x : (impl Copy,) = (true,);
+ //~^ `impl Trait` only allowed in function and inherent method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-70971.stderr b/src/test/ui/impl-trait/issues/issue-70971.stderr
new file mode 100644
index 000000000..4dda4c22a
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-70971.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-70971.rs:2:14
+ |
+LL | let x : (impl Copy,) = (true,);
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-74282.rs b/src/test/ui/impl-trait/issues/issue-74282.rs
new file mode 100644
index 000000000..654de0cd0
--- /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 000000000..5b05fb281
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-74282.stderr
@@ -0,0 +1,40 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-74282.rs:8:15
+ |
+LL | type Closure = impl Fn() -> u64;
+ | ---------------- the expected opaque type
+...
+LL | Anonymous(|| {
+ | _____---------_^
+ | | |
+ | | arguments to this struct are incorrect
+LL | | 3
+LL | | })
+ | |_____^ expected closure, found a different closure
+ |
+ = note: expected opaque type `Closure`
+ found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]`
+ = 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: tuple struct defined here
+ --> $DIR/issue-74282.rs:4:8
+ |
+LL | struct Anonymous(Closure);
+ | ^^^^^^^^^
+
+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 000000000..d29710b6f
--- /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<T> {}
+impl<T, U> Foo<T> for U {}
+
+type Scope = impl Foo<()>;
+
+#[allow(unused)]
+fn infer_scope() -> Scope {
+ ()
+}
+
+#[allow(unused)]
+fn ice() -> impl Foo<Scope>
+{
+ loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs
new file mode 100644
index 000000000..002e4cde4
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-78722.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+type F = impl core::future::Future<Output = u8>;
+
+struct Bug {
+ V1: [(); {
+ fn concrete_use() -> F {
+ //~^ ERROR type mismatch
+ async {}
+ }
+ let f: F = async { 1 };
+ //~^ ERROR `async` blocks are not allowed in constants
+ //~| ERROR destructors cannot be evaluated at compile-time
+ 1
+ }],
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr
new file mode 100644
index 000000000..690d6abc7
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-78722.stderr
@@ -0,0 +1,28 @@
+error[E0658]: `async` blocks are not allowed in constants
+ --> $DIR/issue-78722.rs:13:20
+ |
+LL | let f: F = async { 1 };
+ | ^^^^^^^^^^^
+ |
+ = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
+ = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/issue-78722.rs:13:13
+ |
+LL | let f: F = async { 1 };
+ | ^ constants cannot evaluate destructors
+...
+LL | }],
+ | - value is dropped here
+
+error[E0271]: type mismatch resolving `<impl Future<Output = ()> as Future>::Output == u8`
+ --> $DIR/issue-78722.rs:9:30
+ |
+LL | fn concrete_use() -> F {
+ | ^ expected `()`, found `u8`
+
+error: aborting due to 3 previous errors
+
+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-79099.rs b/src/test/ui/impl-trait/issues/issue-79099.rs
new file mode 100644
index 000000000..da53594f3
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-79099.rs
@@ -0,0 +1,10 @@
+struct Bug {
+ V1: [(); {
+ let f: impl core::future::Future<Output = u8> = async { 1 };
+ //~^ `impl Trait` only allowed in function and inherent method return types
+ //~| expected identifier
+ 1
+ }],
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-79099.stderr b/src/test/ui/impl-trait/issues/issue-79099.stderr
new file mode 100644
index 000000000..362c67daf
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-79099.stderr
@@ -0,0 +1,20 @@
+error: expected identifier, found `1`
+ --> $DIR/issue-79099.rs:3:65
+ |
+LL | let f: impl core::future::Future<Output = u8> = async { 1 };
+ | ----- ^ expected identifier
+ | |
+ | `async` blocks are only allowed in Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-79099.rs:3:16
+ |
+LL | let f: impl core::future::Future<Output = u8> = async { 1 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-82139.rs b/src/test/ui/impl-trait/issues/issue-82139.rs
new file mode 100644
index 000000000..cc9167b34
--- /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 000000000..0adcd4a7a
--- /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 000000000..e76443a65
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-83919.rs
@@ -0,0 +1,32 @@
+#![feature(type_alias_impl_trait)]
+
+// edition:2021
+
+use std::future::Future;
+
+trait Foo {
+ type T;
+ type Fut2: Future<Output=Self::T>; // ICE got triggered with traits other than Future here
+ type Fut: Future<Output=Self::Fut2>;
+ fn get_fut(&self) -> Self::Fut;
+}
+
+struct Implementor;
+
+impl Foo for Implementor {
+ type T = u64;
+ type Fut2 = impl Future<Output=u64>;
+ type Fut = impl Future<Output=Self::Fut2>;
+
+ fn get_fut(&self) -> Self::Fut {
+ //~^ ERROR `{integer}` is not a future
+ async move {
+ 42
+ // 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 000000000..d39dcf7fb
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-83919.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `{integer}` is not a future
+ --> $DIR/issue-83919.rs:21:26
+ |
+LL | fn get_fut(&self) -> Self::Fut {
+ | ^^^^^^^^^ `{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-83929-impl-trait-in-generic-default.rs b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs
new file mode 100644
index 000000000..344f35952
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs
@@ -0,0 +1,12 @@
+struct Foo<T = impl Copy>(T);
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// should not cause ICE
+fn x() -> Foo {
+ Foo(0)
+}
+
+fn main() -> Result<()> {}
diff --git a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
new file mode 100644
index 000000000..e635e554e
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
@@ -0,0 +1,15 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16
+ |
+LL | struct Foo<T = impl Copy>(T);
+ | ^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20
+ |
+LL | type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-84073.rs b/src/test/ui/impl-trait/issues/issue-84073.rs
new file mode 100644
index 000000000..49a34ccfa
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-84073.rs
@@ -0,0 +1,33 @@
+use std::marker::PhantomData;
+
+pub trait StatefulFuture<S> {}
+pub struct Never<T>(PhantomData<T>);
+impl<T> StatefulFuture<T> for Never<T> {}
+
+pub struct RaceBuilder<F, S> {
+ future: F,
+ _phantom: PhantomData<S>,
+}
+
+impl<T, F> RaceBuilder<T, F>
+where
+ F: StatefulFuture<Option<T>>,
+{
+ pub fn when(self) {}
+}
+
+pub struct Race<T, R> {
+ race: R,
+ _phantom: PhantomData<T>,
+}
+
+impl<T, R> Race<T, R>
+where
+ R: Fn(RaceBuilder<T, Never<T>>),
+{
+ 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 000000000..3c39aa6ce
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-84073.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `RaceBuilder<T, Never<T>>`
+ --> $DIR/issue-84073.rs:32:16
+ |
+LL | Race::new(|race| race.when());
+ | ^^^^
+ |
+help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified
+ |
+LL | Race::new(|race: RaceBuilder<T, Never<T>>| race.when());
+ | ++++++++++++++++++++++++++
+
+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-84919.rs b/src/test/ui/impl-trait/issues/issue-84919.rs
new file mode 100644
index 000000000..a0b73743a
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-84919.rs
@@ -0,0 +1,9 @@
+trait Trait {}
+impl Trait for () {}
+
+fn foo<'a: 'a>() {
+ let _x: impl Trait = ();
+ //~^ `impl Trait` only allowed in function and inherent method return types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-84919.stderr b/src/test/ui/impl-trait/issues/issue-84919.stderr
new file mode 100644
index 000000000..5abe1bd87
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-84919.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-84919.rs:5:13
+ |
+LL | let _x: impl Trait = ();
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs
new file mode 100644
index 000000000..0786e66ca
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86201.rs
@@ -0,0 +1,13 @@
+#![feature(unboxed_closures)]
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+type FunType = impl Fn<()>;
+static STATIC_FN: FunType = some_fn;
+
+fn some_fn() {}
+
+fn main() {
+ let _: <FunType as FnOnce<()>>::Output = STATIC_FN();
+}
diff --git a/src/test/ui/impl-trait/issues/issue-86642.rs b/src/test/ui/impl-trait/issues/issue-86642.rs
new file mode 100644
index 000000000..e6e957714
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86642.rs
@@ -0,0 +1,8 @@
+static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
+ //~^ `impl Trait` only allowed in function and inherent method return types
+ let res = (move |source| Ok(source))(source);
+ let res = res.or((move |source| Ok(source))(source));
+ res
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-86642.stderr b/src/test/ui/impl-trait/issues/issue-86642.stderr
new file mode 100644
index 000000000..0ec118d5b
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86642.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/issue-86642.rs:1:11
+ |
+LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/issues/issue-86719.rs b/src/test/ui/impl-trait/issues/issue-86719.rs
new file mode 100644
index 000000000..f4b0b3f33
--- /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<S> 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 000000000..09047cdcb
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86719.stderr
@@ -0,0 +1,29 @@
+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
+ | ^
+ |
+help: consider giving this closure parameter an explicit type
+ |
+LL | |_: _| true
+ | +++
+
+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 000000000..351243c67
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86800.rs
@@ -0,0 +1,55 @@
+#![feature(type_alias_impl_trait)]
+
+// edition:2021
+// unset-rustc-env:RUST_BACKTRACE
+// compile-flags:-Z treat-err-as-bug=1
+// error-pattern:stack backtrace:
+// failure-status:101
+// normalize-stderr-test "note: .*" -> ""
+// normalize-stderr-test "thread 'rustc' .*" -> ""
+// normalize-stderr-test " +[0-9]+:.*\n" -> ""
+// normalize-stderr-test " +at .*\n" -> ""
+
+use std::future::Future;
+
+struct Connection {
+}
+
+trait Transaction {
+}
+
+struct TestTransaction<'conn> {
+ conn: &'conn Connection
+}
+
+impl<'conn> Transaction for TestTransaction<'conn> {
+}
+
+struct Context {
+}
+
+type TransactionResult<O> = Result<O, ()>;
+
+type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
+
+fn execute_transaction_fut<'f, F, O>(
+ f: F,
+) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
+where
+ F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f
+{
+ f
+}
+
+impl Context {
+ async fn do_transaction<O>(
+ &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
+ ) -> TransactionResult<O>
+ {
+ 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 000000000..135d06d44
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86800.stderr
@@ -0,0 +1,19 @@
+
+stack backtrace:
+
+error: internal compiler error: unexpected panic
+
+
+
+
+
+
+
+
+
+query stack during panic:
+#0 [mir_borrowck] borrow-checking `execute_transaction_fut`
+#1 [type_of] computing type of `TransactionFuture::{opaque#0}`
+#2 [check_mod_item_types] checking item types in top-level module
+#3 [analysis] running analysis passes on this crate
+end of query stack
diff --git a/src/test/ui/impl-trait/issues/issue-87295.rs b/src/test/ui/impl-trait/issues/issue-87295.rs
new file mode 100644
index 000000000..aeb8f8332
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-87295.rs
@@ -0,0 +1,18 @@
+trait Trait {
+ type Output;
+}
+impl Trait for () {
+ type Output = i32;
+}
+
+struct Struct<F>(F);
+impl<F> Struct<F> {
+ pub fn new(_: F) -> Self {
+ todo!()
+ }
+}
+
+fn main() {
+ let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
+ //~^ `impl Trait` only allowed in function and inherent method return types
+}
diff --git a/src/test/ui/impl-trait/issues/issue-87295.stderr b/src/test/ui/impl-trait/issues/issue-87295.stderr
new file mode 100644
index 000000000..0b043056b
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-87295.stderr
@@ -0,0 +1,9 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/issue-87295.rs:16:31
+ |
+LL | let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
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 000000000..f0f6d2bb6
--- /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<T> 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 000000000..2ab1e6a03
--- /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<T> 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-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs
new file mode 100644
index 000000000..fde8a6704
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs
@@ -0,0 +1,28 @@
+// 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> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+ //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+ &()
+}
+
+fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+ //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+ x
+}
+
+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 000000000..8605d07ab
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
@@ -0,0 +1,38 @@
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/issue-88236-2.rs:15:61
+ |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/issue-88236-2.rs:15:28
+ |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+ | ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/issue-88236-2.rs:18:80
+ |
+LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/issue-88236-2.rs:18:47
+ |
+LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+ | ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/issue-88236-2.rs:23:78
+ |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/issue-88236-2.rs:23:45
+ |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+ | ^^
+
+error: aborting due to 3 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 000000000..36d124173
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236.rs
@@ -0,0 +1,18 @@
+// 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> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-88236.stderr b/src/test/ui/impl-trait/issues/issue-88236.stderr
new file mode 100644
index 000000000..7a4cc57b0
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236.stderr
@@ -0,0 +1,14 @@
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/issue-88236.rs:15:61
+ |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/issue-88236.rs:15:28
+ |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+ | ^^
+
+error: aborting due to previous error
+
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 000000000..d685a6f12
--- /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<Item = &'a ()>;
+
+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(|_| ());
+}
diff --git a/src/test/ui/impl-trait/issues/issue-92305.rs b/src/test/ui/impl-trait/issues/issue-92305.rs
new file mode 100644
index 000000000..1518c116b
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-92305.rs
@@ -0,0 +1,15 @@
+// edition:2021
+
+use std::iter;
+
+fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
+ //~^ ERROR: missing generics for struct `Vec` [E0107]
+ iter::empty() //~ ERROR: type annotations needed [E0282]
+}
+
+fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> {
+ //~^ ERROR: type annotations needed [E0282]
+ f(data).filter(|x| x == target)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-92305.stderr b/src/test/ui/impl-trait/issues/issue-92305.stderr
new file mode 100644
index 000000000..e8575b76b
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-92305.stderr
@@ -0,0 +1,37 @@
+error[E0107]: missing generics for struct `Vec`
+ --> $DIR/issue-92305.rs:5:45
+ |
+LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
+ | ^^^ expected at least 1 generic argument
+ |
+note: struct defined here, with at least 1 generic parameter: `T`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ |
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+ | ^^^ -
+help: add missing generic argument
+ |
+LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
+ | ~~~~~~
+
+error[E0282]: type annotations needed
+ --> $DIR/issue-92305.rs:7:5
+ |
+LL | iter::empty()
+ | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
+ |
+help: consider specifying the generic argument
+ |
+LL | iter::empty::<T>()
+ | +++++
+
+error[E0282]: type annotations needed
+ --> $DIR/issue-92305.rs:10:35
+ |
+LL | fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0107, E0282.
+For more information about an error, try `rustc --explain E0107`.
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 000000000..6924931cd
--- /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<Self::It>;
+}
+
+impl<'a> Tr for &'a D {
+ type It = ();
+ fn foo(self) -> Option<()> { None }
+}
+
+fn run<F>(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(|_| {});
+}
diff --git a/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
new file mode 100644
index 000000000..b05579f21
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+
+struct Concrete;
+
+type Tait = impl Sized;
+
+impl Foo for Concrete {
+ type Item = Concrete;
+ //~^ type mismatch resolving
+}
+
+impl Bar for Concrete {
+ type Other = Tait;
+}
+
+trait Foo {
+ type Item: Bar<Other = Self>;
+}
+
+trait Bar {
+ type Other;
+}
+
+fn tait() -> Tait {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr
new file mode 100644
index 000000000..f0dceb1b1
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr
@@ -0,0 +1,25 @@
+error[E0271]: type mismatch resolving `<Concrete as Bar>::Other == Concrete`
+ --> $DIR/issue-99348-impl-compatibility.rs:8:17
+ |
+LL | type Tait = impl Sized;
+ | ---------- the found opaque type
+...
+LL | type Item = Concrete;
+ | ^^^^^^^^ type mismatch resolving `<Concrete as Bar>::Other == Concrete`
+ |
+note: expected this to be `Concrete`
+ --> $DIR/issue-99348-impl-compatibility.rs:13:18
+ |
+LL | type Other = Tait;
+ | ^^^^
+ = note: expected struct `Concrete`
+ found opaque type `Tait`
+note: required by a bound in `Foo::Item`
+ --> $DIR/issue-99348-impl-compatibility.rs:17:20
+ |
+LL | type Item: Bar<Other = Self>;
+ | ^^^^^^^^^^^^ required by this bound in `Foo::Item`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/lifetimes.rs b/src/test/ui/impl-trait/lifetimes.rs
new file mode 100644
index 000000000..9a9843375
--- /dev/null
+++ b/src/test/ui/impl-trait/lifetimes.rs
@@ -0,0 +1,123 @@
+// run-pass
+
+#![allow(warnings)]
+#![feature(generators)]
+
+use std::fmt::Debug;
+
+fn any_lifetime<'a>() -> &'a u32 { &5 }
+
+fn static_lifetime() -> &'static u32 { &5 }
+
+fn any_lifetime_as_static_impl_trait() -> impl Debug {
+ any_lifetime()
+}
+
+fn lifetimes_as_static_impl_trait() -> impl Debug {
+ static_lifetime()
+}
+
+fn no_params_or_lifetimes_is_static() -> impl Debug + 'static {
+ lifetimes_as_static_impl_trait()
+}
+
+fn static_input_type_is_static<T: Debug + 'static>(x: T) -> impl Debug + 'static { x }
+
+fn type_outlives_reference_lifetime<'a, T: Debug>(x: &'a T) -> impl Debug + 'a { x }
+fn type_outlives_reference_lifetime_elided<T: Debug>(x: &T) -> impl Debug + '_ { x }
+
+trait SingleRegionTrait<'a> {}
+impl<'a> SingleRegionTrait<'a> for u32 {}
+impl<'a> SingleRegionTrait<'a> for &'a u32 {}
+struct SingleRegionStruct<'a>(&'a u32);
+
+fn simple_type_hrtb<'b>() -> impl for<'a> SingleRegionTrait<'a> { 5 }
+fn elision_single_region_trait(x: &u32) -> impl SingleRegionTrait { x }
+fn elision_single_region_struct(x: SingleRegionStruct) -> impl Into<SingleRegionStruct> { x }
+
+fn closure_hrtb() -> impl for<'a> Fn(&'a u32) { |_| () }
+fn closure_hr_elided() -> impl Fn(&u32) { |_| () }
+fn closure_hr_elided_return() -> impl Fn(&u32) -> &u32 { |x| x }
+fn closure_pass_through_elided_return(x: impl Fn(&u32) -> &u32) -> impl Fn(&u32) -> &u32 { x }
+fn closure_pass_through_reference_elided(x: &impl Fn(&u32) -> &u32) -> &impl Fn(&u32) -> &u32 { x }
+
+fn nested_lifetime<'a>(input: &'a str)
+ -> impl Iterator<Item = impl Iterator<Item = i32> + 'a> + 'a
+{
+ input.lines().map(|line| {
+ line.split_whitespace().map(|cell| cell.parse().unwrap())
+ })
+}
+
+fn pass_through_elision(x: &u32) -> impl Into<&u32> { x }
+fn pass_through_elision_with_fn_ptr(x: &fn(&u32) -> &u32) -> impl Into<&fn(&u32) -> &u32> { x }
+
+fn pass_through_elision_with_fn_path<T: Fn(&u32) -> &u32>(
+ x: &T
+) -> &impl Fn(&u32) -> &u32 { x }
+
+fn foo(x: &impl Debug) -> &impl Debug { x }
+fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> &'a impl Debug { x }
+fn foo_explicit_arg<T: Debug>(x: &T) -> &impl Debug { x }
+
+fn mixed_lifetimes<'a>() -> impl for<'b> Fn(&'b &'a u32) { |_| () }
+fn mixed_as_static() -> impl Fn(&'static &'static u32) { mixed_lifetimes() }
+
+trait MultiRegionTrait<'a, 'b>: Debug {}
+
+#[derive(Debug)]
+struct MultiRegionStruct<'a, 'b>(&'a u32, &'b u32);
+impl<'a, 'b> MultiRegionTrait<'a, 'b> for MultiRegionStruct<'a, 'b> {}
+
+#[derive(Debug)]
+struct NoRegionStruct;
+impl<'a, 'b> MultiRegionTrait<'a, 'b> for NoRegionStruct {}
+
+fn finds_least_region<'a: 'b, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
+ MultiRegionStruct(x, y)
+}
+
+fn finds_explicit_bound<'a: 'b, 'b>
+ (x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> + 'b
+{
+ MultiRegionStruct(x, y)
+}
+
+fn finds_explicit_bound_even_without_least_region<'a, 'b>
+ (x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> + 'b
+{
+ NoRegionStruct
+}
+
+/* FIXME: `impl Trait<'a> + 'b` should live as long as 'b, even if 'b outlives 'a
+fn outlives_bounds_even_with_contained_regions<'a, 'b>
+ (x: &'a u32, y: &'b u32) -> impl Debug + 'b
+{
+ finds_explicit_bound_even_without_least_region(x, y)
+}
+*/
+
+fn unnamed_lifetimes_arent_contained_in_impl_trait_and_will_unify<'a, 'b>
+ (x: &'a u32, y: &'b u32) -> impl Debug
+{
+ fn deref<'lt>(x: &'lt u32) -> impl Debug { *x }
+
+ if true { deref(x) } else { deref(y) }
+}
+
+fn can_add_region_bound_to_static_type<'a, 'b>(_: &'a u32) -> impl Debug + 'a { 5 }
+
+struct MyVec(Vec<Vec<u8>>);
+
+impl<'unnecessary_lifetime> MyVec {
+ fn iter_doesnt_capture_unnecessary_lifetime<'s>(&'s self) -> impl Iterator<Item = &'s u8> {
+ self.0.iter().flat_map(|inner_vec| inner_vec.iter())
+ }
+
+ fn generator_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized {
+ || yield
+ }
+}
+
+
+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 000000000..834f2dc6c
--- /dev/null
+++ b/src/test/ui/impl-trait/lifetimes2.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+pub fn keys<'a>(x: &'a Result<u32, u32>) -> impl std::fmt::Debug + 'a {
+ match x {
+ Ok(map) => Ok(map),
+ Err(map) => Err(map),
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.rs b/src/test/ui/impl-trait/method-suggestion-no-duplication.rs
new file mode 100644
index 000000000..c5c966a95
--- /dev/null
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.rs
@@ -0,0 +1,9 @@
+// issue #21405
+struct Foo;
+
+fn foo<F>(f: F) where F: FnMut(Foo) {}
+
+fn main() {
+ foo(|s| s.is_empty());
+ //~^ ERROR no method named `is_empty` found
+}
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
new file mode 100644
index 000000000..b727b2ca0
--- /dev/null
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `is_empty` found for struct `Foo` in the current scope
+ --> $DIR/method-suggestion-no-duplication.rs:7:15
+ |
+LL | struct Foo;
+ | ---------- method `is_empty` not found for this struct
+...
+LL | foo(|s| s.is_empty());
+ | ^^^^^^^^ method not found in `Foo`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `is_empty`, perhaps you need to implement it:
+ candidate #1: `ExactSizeIterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/multiple-lifetimes.rs b/src/test/ui/impl-trait/multiple-lifetimes.rs
new file mode 100644
index 000000000..5407fb6dd
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes.rs
@@ -0,0 +1,12 @@
+// Test that multiple lifetimes are allowed in impl trait types.
+// build-pass (FIXME(62277): could be check-pass?)
+
+trait X<'x>: Sized {}
+
+impl<U> X<'_> for U {}
+
+fn multiple_lifeteimes<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl X<'b> + 'a {
+ x
+}
+
+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
new file mode 100644
index 000000000..2a2be6b74
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+
+#[derive(Clone)]
+struct CopyIfEq<T, U>(T, U);
+
+impl<T: Copy> Copy for CopyIfEq<T, T> {}
+
+type E<'a, 'b> = impl Sized;
+
+fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+ let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y);
+
+ // This assignment requires that `x` and `y` have the same type due to the
+ // `Copy` impl. The reason why we are using a copy to create a constraint
+ // is that only borrow checking (not regionck in type checking) enforces
+ // this bound.
+ let u = v;
+ let _: *mut &'a i32 = u.1;
+ unsafe {
+ let _: &'b i32 = *u.0;
+ }
+ u.0
+ //~^ ERROR hidden type for `E<'b, 'c>` 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
new file mode 100644
index 000000000..908757080
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
@@ -0,0 +1,12 @@
+error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
+ --> $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
+...
+LL | u.0
+ | ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr
new file mode 100644
index 000000000..ccd004003
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/error-handling.rs:22:16
+ |
+LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'b i32 = *u.0;
+ | ^^^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs
new file mode 100644
index 000000000..367e7f4e6
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+
+#[derive(Clone)]
+struct CopyIfEq<T, U>(T, U);
+
+impl<T: Copy> Copy for CopyIfEq<T, T> {}
+
+type E<'a, 'b> = impl Sized;
+
+fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+ let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y);
+
+ // This assignment requires that `x` and `y` have the same type due to the
+ // `Copy` impl. The reason why we are using a copy to create a constraint
+ // is that only borrow checking (not regionck in type checking) enforces
+ // this bound.
+ let u = v;
+ let _: *mut &'a i32 = u.1;
+ unsafe {
+ let _: &'b i32 = *u.0;
+ //~^ ERROR lifetime may not live long enough
+ }
+ u.0
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
new file mode 100644
index 000000000..01d9f506a
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/error-handling.rs:20:16
+ |
+LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _: &'b i32 = *u.0;
+ | ^^^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
new file mode 100644
index 000000000..5251eeee8
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
@@ -0,0 +1,50 @@
+// edition:2018
+// check-pass
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Invert<'a> <: Invert<'b>` if `'b: 'a`, unlike most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Invert<'a>(fn(&'a u8));
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e>
+where
+ 'c: 'a,
+ 'c: 'b,
+ 'd: 'c,
+{
+ // Representing the where clauses as a graph, where `A: B` is an
+ // edge `B -> A`:
+ //
+ // ```
+ // 'a -> 'c -> 'd
+ // ^
+ // |
+ // 'b
+ // ```
+ //
+ // Meanwhile we return a value &'0 u8 where we have the constraints:
+ //
+ // ```
+ // '0: 'a
+ // '0: 'b
+ // '0 in ['d, 'e]
+ // ```
+ //
+ // Here, ignoring the "in" constraint, the minimal choice for `'0`
+ // is `'c`, but that is not in the "in set". Still, that reduces
+ // the range of options in the "in set" to just `'d` (`'e: 'c`
+ // does not hold).
+ let p = if condition() { a } else { b };
+ p
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs
new file mode 100644
index 000000000..0bddce49b
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs
@@ -0,0 +1,25 @@
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// Test case where we have elision in the impl trait and we have to
+// pick the right region.
+
+// Ultimately `Trait<'x, 'static>`.
+fn upper_bounds1(a: &u8) -> impl Trait<'_, 'static> {
+ (a, a)
+}
+
+// Ultimately `Trait<'x, 'x>`, so not really multiple bounds.
+fn upper_bounds2(a: &u8) -> impl Trait<'_, '_> {
+ (a, a)
+}
+
+// Kind of a weird annoying case.
+fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> {
+ (a, a)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs
new file mode 100644
index 000000000..e363fdb36
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// Here we wind up selecting `'a` and `'b` in the hidden type because
+// those are the types that appear in the original values.
+
+type Foo<'a, 'b> = impl Trait<'a, 'b>;
+
+fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> {
+ // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['a, 'b]
+ // '1 in ['a, 'b]
+ // ```
+ //
+ // We use the fact that `'a: 0'` must hold (combined with the in
+ // constraint) to determine that `'0 = 'a` must be the answer.
+ (a, b)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs
new file mode 100644
index 000000000..0f21dd5ff
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs
@@ -0,0 +1,25 @@
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?)
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// Here we wind up selecting `'a` and `'b` in the hidden type because
+// those are the types that appear in the original values.
+
+fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+ // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['a, 'b]
+ // '1 in ['a, 'b]
+ // ```
+ //
+ // We use the fact that `'a: 0'` must hold (combined with the in
+ // constraint) to determine that `'0 = 'a` must be the answer.
+ (a, b)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs
new file mode 100644
index 000000000..13ad1f721
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs
@@ -0,0 +1,42 @@
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?)
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we wind up selecting `'e` in the hidden type because
+// we need something outlived by both `'a` and `'b` and only `'e` applies.
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+where
+ 'a: 'e,
+ 'b: 'e,
+ 'a: 'd,
+{
+ // We return a value:
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['d, 'e]
+ // ```
+ //
+ // but we don't have it.
+ //
+ // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
+ let p = if condition() { a } else { b };
+ p
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..c6eea5323
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
@@ -0,0 +1,36 @@
+// edition:2018
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we get an error because none of our choices (either `'d` nor `'e`) are outlived
+// by both `'a` and `'b`.
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+where
+ 'a: 'e,
+ 'b: 'd,
+{
+ // Hidden type `Ordinary<'0>` with constraints:
+ //
+ // ```
+ // 'a: '0
+ // 'b: '0
+ // 'a in ['d, 'e]
+ // ```
+ if condition() { a } else { b }
+ //~^ ERROR hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..cb1dc0b7d
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -0,0 +1,17 @@
+error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds
+ --> $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
+...
+LL | if condition() { a } else { b }
+ | ^
+ |
+help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+ |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
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
new file mode 100644
index 000000000..adcbca2a4
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
@@ -0,0 +1,39 @@
+// edition:2018
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we need something outlived by `'a` *and* outlived by `'b`, but
+// we can only name `'a` and `'b` (and neither suits). So we get an
+// error. Somewhat unfortunate, though, since the caller would have to
+// consider the loans for both `'a` and `'b` alive.
+
+fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+{
+ // We return a value:
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['a, 'b]
+ // ```
+ //
+ // but we don't have it.
+ //
+ // 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<'a, 'b>` captures lifetime that does not appear in bounds
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..4388e6601
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -0,0 +1,17 @@
+error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds
+ --> $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
+...
+LL | if condition() { a } else { b }
+ | ^
+ |
+help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+ |
+LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
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
new file mode 100644
index 000000000..18404f986
--- /dev/null
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -0,0 +1,47 @@
+use std::fmt::Debug;
+
+fn elided(x: &i32) -> impl Copy { x }
+//~^ ERROR: captures lifetime that does not appear in bounds
+
+fn explicit<'a>(x: &'a i32) -> impl Copy { x }
+//~^ ERROR: captures lifetime that does not appear in bounds
+
+fn elided2(x: &i32) -> impl Copy + 'static { x }
+//~^ ERROR lifetime may not live long enough
+
+fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+//~^ ERROR lifetime may not live long enough
+
+fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+//~^ ERROR explicit lifetime required in the type of `x`
+
+fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+
+fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
+
+fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+
+fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+
+fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
+//~^ ERROR lifetime may not live long enough
+
+trait LifetimeTrait<'a> {}
+impl<'a> LifetimeTrait<'a> for &'a i32 {}
+
+fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+//~^ ERROR lifetime may not live long enough
+
+// 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) {
+ move |_| println!("{}", y)
+ //~^ ERROR: captures lifetime that does not appear in bounds
+}
+
+fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+ 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
new file mode 100644
index 000000000..16767abd7
--- /dev/null
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -0,0 +1,126 @@
+error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds
+ --> $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
+ |
+help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn elided(x: &i32) -> impl Copy + '_ { x }
+ | ++++
+
+error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds
+ --> $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
+ |
+help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+ |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
+ | ++++
+
+error: lifetime may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+ |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+ | - ^ returning this value requires that `'1` must outlive `'static`
+ | |
+ | let's call the lifetime of this reference `'1`
+ |
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+ |
+LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
+ | ~~~~~~~~~~~~
+
+error: lifetime may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+ |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+ | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
+ |
+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 }
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+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:15:41
+ |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+ | ---- ^ lifetime `'a` required
+ | |
+ | help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error: lifetime may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:26:55
+ |
+LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
+ | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+ | |
+ | let's call the lifetime of this reference `'1`
+ |
+help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
+ | ++++
+help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
+ | ++++
+
+error: lifetime may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:32:69
+ |
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+ | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
+ |
+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 }
+ | ~~
+help: alternatively, add an explicit `'static` bound to this reference
+ |
+LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
+ | ~~~~~~~~~~~~
+
+error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not appear in bounds
+ --> $DIR/must_outlive_least_region_or_bound.rs:38: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:38:5: 38:13]` 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
+ |
+LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
+ | ++++
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:43:5
+ |
+LL | x
+ | ^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn ty_param_wont_outlive_static<T:Debug + 'static>(x: T) -> impl Debug + 'static {
+ | +++++++++
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0310, E0621, E0700.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.rs b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
new file mode 100644
index 000000000..c4bcfe5b2
--- /dev/null
+++ b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait MultiRegionTrait<'a, 'b> {}
+impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}
+
+fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
+ // Here we have a constraint that:
+ //
+ // (x, y) has type (&'0 u32, &'1 u32)
+ //
+ // where
+ //
+ // 'a: '0
+ //
+ // then we require that `('0 u32, &'1 u32): MultiRegionTrait<'a,
+ // 'b>`, which winds up imposing a requirement that `'0 = 'a` and
+ // `'1 = 'b`.
+ (x, y)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs
new file mode 100644
index 000000000..da69bb349
--- /dev/null
+++ b/src/test/ui/impl-trait/negative-reasoning.rs
@@ -0,0 +1,24 @@
+// Tests that we cannot assume that an opaque type does *not* implement some
+// other trait
+#![feature(type_alias_impl_trait)]
+
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
+type OpaqueType = impl OpaqueTrait;
+fn mk_opaque() -> OpaqueType {
+ ()
+}
+
+#[derive(Debug)]
+struct D<T>(T);
+
+trait AnotherTrait {}
+impl<T: std::fmt::Debug> AnotherTrait for T {}
+
+// This is in error, because we cannot assume that `OpaqueType: !Debug`
+impl AnotherTrait for D<OpaqueType> {
+ //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+ //~| ERROR cannot implement trait on type alias impl trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
new file mode 100644
index 000000000..479b45185
--- /dev/null
+++ b/src/test/ui/impl-trait/negative-reasoning.stderr
@@ -0,0 +1,26 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+ --> $DIR/negative-reasoning.rs:19:1
+ |
+LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
+ | ------------------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+ |
+ = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
+
+error: cannot implement trait on type alias impl trait
+ --> $DIR/negative-reasoning.rs:19:25
+ |
+LL | impl AnotherTrait for D<OpaqueType> {
+ | ^^^^^^^^^^
+ |
+note: type alias impl trait defined here
+ --> $DIR/negative-reasoning.rs:7:19
+ |
+LL | type OpaqueType = impl OpaqueTrait;
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/nested-return-type.rs b/src/test/ui/impl-trait/nested-return-type.rs
new file mode 100644
index 000000000..7d7a084b8
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type.rs
@@ -0,0 +1,16 @@
+// Check that nested impl Trait items work in functions with generic parameters.
+// check-pass
+
+trait Captures<'a> {}
+
+impl<T> Captures<'_> for T {}
+
+fn nested_assoc_type<'a: 'a, T>() -> impl Iterator<Item = impl Sized> {
+ [1].iter()
+}
+
+fn nested_assoc_lifetime<'a: 'a, T>() -> impl Iterator<Item = impl Captures<'a>> {
+ [1].iter()
+}
+
+fn main() {}
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 000000000..42613d5cc
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait.rs
@@ -0,0 +1,33 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+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: Duh, F: FnMut() -> R> Trait for F {
+ type Assoc = R;
+}
+
+type Sendable = impl Send;
+
+// The `Sendable` here is converted to an inference var and then later compared
+// against the inference var created, causing the inference var to be set to
+// the hidden type of `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`, but if its hidden type does.
+fn foo() -> impl Trait<Assoc = Sendable> {
+ || 42
+}
+
+fn main() {
+}
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 000000000..af8e06630
--- /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: Duh, F: FnMut() -> R> Trait for F {
+ type Assoc = R;
+}
+
+type Sendable = impl Send;
+type Traitable = impl Trait<Assoc = Sendable>;
+
+// 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 000000000..fe1ae4fcb
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
@@ -0,0 +1,16 @@
+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`
+ |
+ = help: the trait `Duh` is implemented for `i32`
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:7]`
+ --> $DIR/nested-return-type2-tait2.rs:14:31
+ |
+LL | impl<R: Duh, F: FnMut() -> 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 000000000..74fd8a9dd
--- /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: Duh, F: FnMut() -> R> Trait for F {
+ type Assoc = R;
+}
+
+type Traitable = impl Trait<Assoc = impl Send>;
+
+// 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 000000000..c0695d627
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
@@ -0,0 +1,16 @@
+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`
+ |
+ = help: the trait `Duh` is implemented for `i32`
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:7]`
+ --> $DIR/nested-return-type2-tait3.rs:14:31
+ |
+LL | impl<R: Duh, F: FnMut() -> 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.rs b/src/test/ui/impl-trait/nested-return-type2.rs
new file mode 100644
index 000000000..39928d543
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+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: Duh, F: FnMut() -> 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.
+// Lazy TAIT would error out, but we inserted a hack to make it work again,
+// keeping backwards compatibility.
+fn foo() -> impl Trait<Assoc = impl Send> {
+ || 42
+}
+
+fn main() {
+}
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 000000000..3936f4dbb
--- /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<F: Duh> Trait for F {
+ type Assoc = F;
+}
+
+type Sendable = impl Send;
+
+fn foo() -> impl Trait<Assoc = Sendable> {
+ 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 000000000..56778ed90
--- /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<F: Duh> Trait for F {
+ type Assoc = F;
+}
+
+type Sendable = impl Send;
+type Traitable = impl Trait<Assoc = Sendable>;
+
+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 000000000..04c6c92b1
--- /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<F: Duh> Trait for F {
+ type Assoc = F;
+}
+
+type Traitable = impl Trait<Assoc = impl Send>;
+
+fn foo() -> Traitable {
+ 42
+}
+
+fn main() {
+}
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 000000000..74b4dae22
--- /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<F: Duh> Trait for F {
+ type Assoc = F;
+}
+
+fn foo() -> impl Trait<Assoc = impl Send> {
+ 42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.rs b/src/test/ui/impl-trait/nested-rpit-hrtb.rs
new file mode 100644
index 000000000..abf6a7e95
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-rpit-hrtb.rs
@@ -0,0 +1,64 @@
+// Test the interaction between rested RPIT and HRTB.
+
+trait Foo<'a> {
+ type Assoc;
+}
+
+impl Foo<'_> for () {
+ type Assoc = ();
+}
+
+// Alternative version of `Foo` whose impl uses `'a`.
+trait Bar<'a> {
+ type Assoc;
+}
+
+impl<'a> Bar<'a> for () {
+ type Assoc = &'a ();
+}
+
+trait Qux<'a> {}
+
+impl Qux<'_> for () {}
+
+// This is not supported.
+fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+// This is not supported.
+fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+// This should pass.
+fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {}
+
+// This should pass.
+fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {}
+
+// This should pass.
+fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
+
+// This should pass.
+fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
+
+// This should pass.
+fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {}
+
+// `'b` is not in scope for the outlives bound.
+fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+//~^ ERROR use of undeclared lifetime name `'b` [E0261]
+
+// This should pass.
+fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
+
+// `'b` is not in scope for the outlives bound.
+fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+//~^ ERROR use of undeclared lifetime name `'b` [E0261]
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.stderr b/src/test/ui/impl-trait/nested-rpit-hrtb.stderr
new file mode 100644
index 000000000..3dbe6ebad
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -0,0 +1,82 @@
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/nested-rpit-hrtb.rs:54:77
+ |
+LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+ | ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | fn two_htrb_outlives() -> impl for<'b, 'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+ | +++
+help: consider introducing lifetime `'b` here
+ |
+LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/nested-rpit-hrtb.rs:61:82
+ |
+LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+ | ^^ undeclared lifetime
+ |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | fn two_htrb_outlives_uses() -> impl for<'b, 'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+ | +++
+help: consider introducing lifetime `'b` here
+ |
+LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+ | ++++
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/nested-rpit-hrtb.rs:25:69
+ |
+LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/nested-rpit-hrtb.rs:25:36
+ |
+LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
+ | ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/nested-rpit-hrtb.rs:29:68
+ |
+LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/nested-rpit-hrtb.rs:29:39
+ |
+LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
+ | ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/nested-rpit-hrtb.rs:32:74
+ |
+LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/nested-rpit-hrtb.rs:32:41
+ |
+LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+ | ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+ --> $DIR/nested-rpit-hrtb.rs:35:73
+ |
+LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/nested-rpit-hrtb.rs:35:44
+ |
+LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
+ | ^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs
new file mode 100644
index 000000000..85c6f8c46
--- /dev/null
+++ b/src/test/ui/impl-trait/nested_impl_trait.rs
@@ -0,0 +1,32 @@
+use std::fmt::Debug;
+
+fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
+
+fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+//~^ ERROR nested `impl Trait` is not allowed
+//~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
+
+fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+//~^ ERROR nested `impl Trait` is not allowed
+//~| `impl Trait` only allowed in function and inherent method return types
+
+fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+//~^ ERROR nested `impl Trait` is not allowed
+
+struct X;
+impl X {
+ fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+ //~^ ERROR nested `impl Trait` is not allowed
+ //~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
+}
+
+fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
+ vec![|| println!("woot")].into_iter()
+}
+
+fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+//~^ `impl Trait` only allowed in function and inherent method return types
+ || 5
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr
new file mode 100644
index 000000000..bb4ae5e82
--- /dev/null
+++ b/src/test/ui/impl-trait/nested_impl_trait.stderr
@@ -0,0 +1,70 @@
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/nested_impl_trait.rs:5:56
+ |
+LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+ | ----------^^^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/nested_impl_trait.rs:9:42
+ |
+LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+ | ----------^^^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/nested_impl_trait.rs:13:37
+ |
+LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
+ | ----------^^^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/nested_impl_trait.rs:18:44
+ |
+LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+ | ----------^^^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | 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:9:32
+ |
+LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/nested_impl_trait.rs:27:42
+ |
+LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
+ | ^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
+ --> $DIR/nested_impl_trait.rs:5:46
+ |
+LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+ | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
+ |
+ = help: the trait `Into<U>` is implemented for `T`
+ = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
+
+error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
+ --> $DIR/nested_impl_trait.rs:18:34
+ |
+LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+ | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
+ |
+ = help: the trait `Into<U>` is implemented for `T`
+ = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
+
+error: aborting due to 8 previous errors
+
+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/nesting.rs b/src/test/ui/impl-trait/nesting.rs
new file mode 100644
index 000000000..27bdd5fa4
--- /dev/null
+++ b/src/test/ui/impl-trait/nesting.rs
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+
+fn foo<T>(t: T) -> impl Into<[T; { const FOO: usize = 1; FOO }]> {
+ [t]
+}
+
+fn bar() -> impl Into<[u8; { const FOO: usize = 1; FOO }]> {
+ [99]
+}
+
+fn main() {
+ println!("{:?}", foo(42).into());
+ println!("{:?}", bar().into());
+}
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.rs b/src/test/ui/impl-trait/no-method-suggested-traits.rs
new file mode 100644
index 000000000..c8abc2d8f
--- /dev/null
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.rs
@@ -0,0 +1,77 @@
+// aux-build:no_method_suggested_traits.rs
+extern crate no_method_suggested_traits;
+
+struct Foo;
+enum Bar { X }
+
+mod foo {
+ pub trait Bar {
+ fn method(&self) {}
+
+ fn method2(&self) {}
+ }
+
+ impl Bar for u32 {}
+
+ impl Bar for char {}
+}
+
+fn main() {
+ // test the values themselves, and autoderef.
+
+
+ 1u32.method();
+ //~^ ERROR no method named
+ //~|items from traits can only be used if the trait is in scope
+ std::rc::Rc::new(&mut Box::new(&1u32)).method();
+ //~^items from traits can only be used if the trait is in scope
+ //~| ERROR no method named `method` found for struct
+
+ 'a'.method();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&'a')).method();
+ //~^ ERROR no method named
+
+ 1i32.method();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&1i32)).method();
+ //~^ ERROR no method named
+
+ Foo.method();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&Foo)).method();
+ //~^ ERROR no method named
+
+ 1u64.method2();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&1u64)).method2();
+ //~^ ERROR no method named
+
+ no_method_suggested_traits::Foo.method2();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
+ //~^ ERROR no method named
+ no_method_suggested_traits::Bar::X.method2();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
+ //~^ ERROR no method named
+
+ Foo.method3();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&Foo)).method3();
+ //~^ ERROR no method named
+ Bar::X.method3();
+ //~^ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
+ //~^ ERROR no method named
+
+ // should have no help:
+ 1_usize.method3(); //~ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); //~ ERROR no method named
+ no_method_suggested_traits::Foo.method3(); //~ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
+ //~^ ERROR no method named
+ no_method_suggested_traits::Bar::X.method3(); //~ ERROR no method named
+ std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
+ //~^ ERROR no method named
+}
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
new file mode 100644
index 000000000..3d4ae11e5
--- /dev/null
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -0,0 +1,284 @@
+error[E0599]: no method named `method` found for type `u32` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:23:10
+ |
+LL | 1u32.method();
+ | ^^^^^^ method not found in `u32`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+ |
+LL | use foo::Bar;
+ |
+LL | use no_method_suggested_traits::Reexported;
+ |
+LL | use no_method_suggested_traits::foo::PubPub;
+ |
+LL | use no_method_suggested_traits::qux::PrivPub;
+ |
+
+error[E0599]: no method named `method` found for struct `Rc<&mut Box<&u32>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:26:44
+ |
+LL | std::rc::Rc::new(&mut Box::new(&1u32)).method();
+ | ^^^^^^ method not found in `Rc<&mut Box<&u32>>`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+ |
+LL | use foo::Bar;
+ |
+LL | use no_method_suggested_traits::Reexported;
+ |
+LL | use no_method_suggested_traits::foo::PubPub;
+ |
+LL | use no_method_suggested_traits::qux::PrivPub;
+ |
+
+error[E0599]: no method named `method` found for type `char` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:30:9
+ |
+LL | fn method(&self) {}
+ | ------ the method is available for `char` here
+...
+LL | 'a'.method();
+ | ^^^^^^ method not found in `char`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use foo::Bar;
+ |
+
+error[E0599]: no method named `method` found for struct `Rc<&mut Box<&char>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:32:43
+ |
+LL | std::rc::Rc::new(&mut Box::new(&'a')).method();
+ | ^^^^^^ method not found in `Rc<&mut Box<&char>>`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use foo::Bar;
+ |
+
+error[E0599]: no method named `method` found for type `i32` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:35:10
+ |
+LL | 1i32.method();
+ | ^^^^^^ method not found in `i32`
+ |
+ ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12
+ |
+LL | fn method(&self) {}
+ | ------ the method is available for `i32` here
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use no_method_suggested_traits::foo::PubPub;
+ |
+
+error[E0599]: no method named `method` found for struct `Rc<&mut Box<&i32>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:37:44
+ |
+LL | std::rc::Rc::new(&mut Box::new(&1i32)).method();
+ | ^^^^^^ method not found in `Rc<&mut Box<&i32>>`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use no_method_suggested_traits::foo::PubPub;
+ |
+
+error[E0599]: no method named `method` found for struct `Foo` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:40:9
+ |
+LL | struct Foo;
+ | ---------- method `method` not found for this struct
+...
+LL | Foo.method();
+ | ^^^^^^ method not found in `Foo`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following traits define an item `method`, perhaps you need to implement one of them:
+ candidate #1: `foo::Bar`
+ candidate #2: `PubPub`
+ candidate #3: `no_method_suggested_traits::qux::PrivPub`
+ candidate #4: `Reexported`
+
+error[E0599]: no method named `method` found for struct `Rc<&mut Box<&Foo>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:42:43
+ |
+LL | std::rc::Rc::new(&mut Box::new(&Foo)).method();
+ | ^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following traits define an item `method`, perhaps you need to implement one of them:
+ candidate #1: `foo::Bar`
+ candidate #2: `PubPub`
+ candidate #3: `no_method_suggested_traits::qux::PrivPub`
+ candidate #4: `Reexported`
+
+error[E0599]: no method named `method2` found for type `u64` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:45:10
+ |
+LL | 1u64.method2();
+ | ^^^^^^^ method not found in `u64`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
+ --> $DIR/no-method-suggested-traits.rs:8:5
+ |
+LL | pub trait Bar {
+ | ^^^^^^^^^^^^^
+
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&u64>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:47:44
+ |
+LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&u64>>`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
+ --> $DIR/no-method-suggested-traits.rs:8:5
+ |
+LL | pub trait Bar {
+ | ^^^^^^^^^^^^^
+
+error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:50:37
+ |
+LL | no_method_suggested_traits::Foo.method2();
+ | ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
+ --> $DIR/no-method-suggested-traits.rs:8:5
+ |
+LL | pub trait Bar {
+ | ^^^^^^^^^^^^^
+
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:52:71
+ |
+LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
+ --> $DIR/no-method-suggested-traits.rs:8:5
+ |
+LL | pub trait Bar {
+ | ^^^^^^^^^^^^^
+
+error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:54:40
+ |
+LL | no_method_suggested_traits::Bar::X.method2();
+ | ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
+ --> $DIR/no-method-suggested-traits.rs:8:5
+ |
+LL | pub trait Bar {
+ | ^^^^^^^^^^^^^
+
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:56:74
+ |
+LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
+ --> $DIR/no-method-suggested-traits.rs:8:5
+ |
+LL | pub trait Bar {
+ | ^^^^^^^^^^^^^
+
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:59:9
+ |
+LL | struct Foo;
+ | ---------- method `method3` not found for this struct
+...
+LL | Foo.method3();
+ | ^^^^^^^ method not found in `Foo`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `method3`, perhaps you need to implement it:
+ candidate #1: `PubPub`
+
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:61:43
+ |
+LL | std::rc::Rc::new(&mut Box::new(&Foo)).method3();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `method3`, perhaps you need to implement it:
+ candidate #1: `PubPub`
+
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:63:12
+ |
+LL | enum Bar { X }
+ | -------- method `method3` not found for this enum
+...
+LL | Bar::X.method3();
+ | ^^^^^^^ method not found in `Bar`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `method3`, perhaps you need to implement it:
+ candidate #1: `PubPub`
+
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:65:46
+ |
+LL | std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `method3`, perhaps you need to implement it:
+ candidate #1: `PubPub`
+
+error[E0599]: no method named `method3` found for type `usize` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:69:13
+ |
+LL | 1_usize.method3();
+ | ^^^^^^^ method not found in `usize`
+
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:70:47
+ |
+LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
+
+error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:71:37
+ |
+LL | no_method_suggested_traits::Foo.method3();
+ | ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:72:71
+ |
+LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+
+error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:74:40
+ |
+LL | no_method_suggested_traits::Bar::X.method3();
+ | ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+ --> $DIR/no-method-suggested-traits.rs:75:74
+ |
+LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
+ | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+
+error: aborting due to 24 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/impl-trait/no-trait.rs b/src/test/ui/impl-trait/no-trait.rs
new file mode 100644
index 000000000..9ce668f46
--- /dev/null
+++ b/src/test/ui/impl-trait/no-trait.rs
@@ -0,0 +1,3 @@
+fn f() -> impl 'static {} //~ ERROR at least one trait must be specified
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/no-trait.stderr b/src/test/ui/impl-trait/no-trait.stderr
new file mode 100644
index 000000000..3a636f252
--- /dev/null
+++ b/src/test/ui/impl-trait/no-trait.stderr
@@ -0,0 +1,8 @@
+error: at least one trait must be specified
+ --> $DIR/no-trait.rs:1:11
+ |
+LL | fn f() -> impl 'static {}
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
new file mode 100644
index 000000000..ab3086c78
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
@@ -0,0 +1,35 @@
+#![allow(bare_trait_objects)]
+trait NotObjectSafe {
+ fn foo() -> Self;
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+ fn foo() -> Self {
+ A
+ }
+}
+
+impl NotObjectSafe for B {
+ fn foo() -> Self {
+ B
+ }
+}
+
+fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object
+ if true {
+ return A;
+ }
+ B
+}
+
+fn cat() -> Box<dyn NotObjectSafe> { //~ ERROR the trait `NotObjectSafe` cannot be made into an
+ if true {
+ return Box::new(A);
+ }
+ Box::new(B)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
new file mode 100644
index 000000000..365ecd9fc
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
@@ -0,0 +1,47 @@
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+ --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:13
+ |
+LL | fn car() -> dyn NotObjectSafe {
+ | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8
+ |
+LL | trait NotObjectSafe {
+ | ------------- this trait cannot be made into an object...
+LL | fn foo() -> Self;
+ | ^^^ ...because associated function `foo` has no `self` parameter
+help: consider turning `foo` into a method by giving it a `&self` argument
+ |
+LL | fn foo(&self) -> Self;
+ | +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+ |
+LL | fn foo() -> Self where Self: Sized;
+ | +++++++++++++++++
+
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+ --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:13
+ |
+LL | fn cat() -> Box<dyn NotObjectSafe> {
+ | ^^^^^^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8
+ |
+LL | trait NotObjectSafe {
+ | ------------- this trait cannot be made into an object...
+LL | fn foo() -> Self;
+ | ^^^ ...because associated function `foo` has no `self` parameter
+help: consider turning `foo` into a method by giving it a `&self` argument
+ |
+LL | fn foo(&self) -> Self;
+ | +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+ |
+LL | fn foo() -> Self where Self: Sized;
+ | +++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
new file mode 100644
index 000000000..503515013
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
@@ -0,0 +1,46 @@
+trait NotObjectSafe {
+ fn foo() -> Self;
+}
+
+trait ObjectSafe {
+ fn bar(&self);
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+ fn foo() -> Self {
+ A
+ }
+}
+
+impl NotObjectSafe for B {
+ fn foo() -> Self {
+ B
+ }
+}
+
+impl ObjectSafe for A {
+ fn bar(&self) {}
+}
+
+impl ObjectSafe for B {
+ fn bar(&self) {}
+}
+
+fn can() -> impl NotObjectSafe {
+ if true {
+ return A;
+ }
+ B //~ ERROR mismatched types
+}
+
+fn cat() -> impl ObjectSafe {
+ if true {
+ return A;
+ }
+ B //~ ERROR mismatched types
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..5ca01a593
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
+ |
+LL | fn can() -> impl NotObjectSafe {
+ | ------------------ expected `_` because of return type
+...
+LL | B
+ | ^ expected struct `A`, 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 of return type
+...
+LL | B
+ | ^ expected struct `A`, found struct `B`
+
+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/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
new file mode 100644
index 000000000..fa7664a83
--- /dev/null
+++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
@@ -0,0 +1,101 @@
+fn foo() -> impl std::fmt::Display {
+ if false {
+ return 0i32;
+ }
+ 1u32 //~ ERROR mismatched types
+}
+
+fn bar() -> impl std::fmt::Display {
+ if false {
+ return 0i32;
+ } else {
+ return 1u32; //~ ERROR mismatched types
+ }
+}
+
+fn baz() -> impl std::fmt::Display {
+ if false {
+ return 0i32;
+ } else {
+ 1u32 //~ ERROR mismatched types
+ }
+}
+
+fn qux() -> impl std::fmt::Display {
+ if false {
+ 0i32
+ } else {
+ 1u32 //~ ERROR `if` and `else` have incompatible types
+ }
+}
+
+fn bat() -> impl std::fmt::Display {
+ match 13 {
+ 0 => return 0i32,
+ _ => 1u32, //~ ERROR mismatched types
+ }
+}
+
+fn can() -> impl std::fmt::Display {
+ match 13 { //~ ERROR mismatched types
+ 0 => return 0i32,
+ 1 => 1u32,
+ _ => 2u32,
+ }
+}
+
+fn cat() -> impl std::fmt::Display {
+ match 13 {
+ 0 => {
+ return 0i32;
+ }
+ _ => {
+ 1u32 //~ ERROR mismatched types
+ }
+ }
+}
+
+fn dog() -> impl std::fmt::Display {
+ match 13 {
+ 0 => 0i32,
+ 1 => 1u32, //~ ERROR `match` arms have incompatible types
+ _ => 2u32,
+ }
+}
+
+fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
+ match 13 {
+ 0 => {
+ return 0i32;
+ }
+ _ => {
+ 1u32
+ }
+ }
+}
+
+fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
+ match 13 {
+ 0 => 0i32,
+ 1 => 1u32, //~ ERROR `match` arms have incompatible types
+ _ => 2u32,
+ }
+}
+
+fn man() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
+ if false {
+ 0i32
+ } else {
+ 1u32 //~ ERROR `if` and `else` have incompatible types
+ }
+}
+
+fn apt() -> impl std::fmt::Display {
+ if let Some(42) = Some(42) {
+ 0i32
+ } else {
+ 1u32 //~ ERROR `if` and `else` have incompatible types
+ }
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..10510c175
--- /dev/null
+++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -0,0 +1,194 @@
+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 of return type
+...
+LL | 1u32
+ | ^^^^ expected `i32`, found `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 of return type
+...
+LL | return 1u32;
+ | ^^^^ expected `i32`, found `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 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
+ |
+LL | / if false {
+LL | | 0i32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 1u32
+ | | ^^^^ expected `i32`, found `u32`
+LL | | }
+ | |_____- `if` and `else` have incompatible types
+
+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 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 {
+ | ---------------------- expected `_` because of return type
+LL | / match 13 {
+LL | | 0 => return 0i32,
+LL | | 1 => 1u32,
+LL | | _ => 2u32,
+LL | | }
+ | |_____^ expected `i32`, found `u32`
+
+error[E0308]: mismatched types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13
+ |
+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
+ |
+LL | / match 13 {
+LL | | 0 => 0i32,
+ | | ---- this is found to be of type `i32`
+LL | | 1 => 1u32,
+ | | ^^^^ expected `i32`, found `u32`
+LL | | _ => 2u32,
+LL | | }
+ | |_____- `match` arms have incompatible types
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9
+ |
+LL | / if let Some(42) = Some(42) {
+LL | | 0i32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 1u32
+ | | ^^^^ expected `i32`, found `u32`
+LL | | }
+ | |_____- `if` and `else` have incompatible types
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13
+ |
+LL | fn hat() -> dyn std::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+ = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+ = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+ |
+LL | fn hat() -> Box<dyn std::fmt::Display> {
+ | ++++ +
+help: ... and box this value
+ |
+LL | return Box::new(0i32);
+ | +++++++++ +
+help: ... and box this value
+ |
+LL | Box::new(1u32)
+ | +++++++++ +
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14
+ |
+LL | / match 13 {
+LL | | 0 => 0i32,
+ | | ---- this is found to be of type `i32`
+LL | | 1 => 1u32,
+ | | ^^^^ expected `i32`, found `u32`
+LL | | _ => 2u32,
+LL | | }
+ | |_____- `match` arms have incompatible types
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
+ |
+LL | fn pug() -> dyn std::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+ = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+ = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+ |
+LL | fn pug() -> Box<dyn std::fmt::Display> {
+ | ++++ +
+help: ... and box this value
+ |
+LL | 0 => Box::new(0i32),
+ | +++++++++ +
+help: ... and box this value
+ |
+LL | 1 => Box::new(1u32),
+ | +++++++++ +
+help: ... and box this value
+ |
+LL | _ => Box::new(2u32),
+ | +++++++++ +
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9
+ |
+LL | / if false {
+LL | | 0i32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 1u32
+ | | ^^^^ expected `i32`, found `u32`
+LL | | }
+ | |_____- `if` and `else` have incompatible types
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13
+ |
+LL | fn man() -> dyn std::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+ = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+ = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+ |
+LL | fn man() -> Box<dyn std::fmt::Display> {
+ | ++++ +
+help: ... and box this value
+ |
+LL | Box::new(0i32)
+ | +++++++++ +
+help: ... and box this value
+ |
+LL | Box::new(1u32)
+ | +++++++++ +
+
+error: aborting due to 14 previous errors
+
+Some errors have detailed explanations: E0308, E0746.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/printing-binder.rs b/src/test/ui/impl-trait/printing-binder.rs
new file mode 100644
index 000000000..273b5dcdb
--- /dev/null
+++ b/src/test/ui/impl-trait/printing-binder.rs
@@ -0,0 +1,14 @@
+trait Trait<'a> {}
+impl<T> Trait<'_> for T {}
+fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {}
+
+fn whatever2() -> impl for<'c> Fn(&'c ()) {
+ |_: &()| {}
+}
+
+fn main() {
+ let x: u32 = whatever();
+ //~^ ERROR mismatched types
+ let x2: u32 = whatever2();
+ //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/impl-trait/printing-binder.stderr b/src/test/ui/impl-trait/printing-binder.stderr
new file mode 100644
index 000000000..5ffec8af1
--- /dev/null
+++ b/src/test/ui/impl-trait/printing-binder.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+ --> $DIR/printing-binder.rs:10:18
+ |
+LL | fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {}
+ | ------------------------------------------ the found opaque type
+...
+LL | let x: u32 = whatever();
+ | --- ^^^^^^^^^^ expected `u32`, found opaque type
+ | |
+ | expected due to this
+ |
+ = note: expected type `u32`
+ found opaque type `impl for<'a> Trait<'a> + for<'b> Trait<'b>`
+
+error[E0308]: mismatched types
+ --> $DIR/printing-binder.rs:12:19
+ |
+LL | fn whatever2() -> impl for<'c> Fn(&'c ()) {
+ | ----------------------- the found opaque type
+...
+LL | let x2: u32 = whatever2();
+ | --- ^^^^^^^^^^^ expected `u32`, found opaque type
+ | |
+ | expected due to this
+ |
+ = note: expected type `u32`
+ found opaque type `impl for<'c> Fn(&'c ())`
+
+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/private_unused.rs b/src/test/ui/impl-trait/private_unused.rs
new file mode 100644
index 000000000..92268f186
--- /dev/null
+++ b/src/test/ui/impl-trait/private_unused.rs
@@ -0,0 +1,13 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#[deny(warnings)]
+
+enum Empty { }
+trait Bar<T> {}
+impl Bar<Empty> for () {}
+
+fn boo() -> impl Bar<Empty> {}
+
+fn main() {
+ boo();
+}
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
new file mode 100644
index 000000000..b4fd6b3e7
--- /dev/null
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
@@ -0,0 +1,20 @@
+pub trait Super {
+ type Assoc;
+}
+
+impl Super for () {
+ type Assoc = u8;
+}
+
+pub trait Test {}
+
+impl<T> Test for T where T: Super<Assoc = ()> {}
+
+fn test() -> impl Test {
+ //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()`
+ ()
+}
+
+fn main() {
+ let a = test();
+}
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
new file mode 100644
index 000000000..ade0dfa1b
--- /dev/null
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
@@ -0,0 +1,20 @@
+error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()`
+ --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14
+ |
+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
+ |
+LL | type Assoc = u8;
+ | ^^
+note: required because of the requirements on the impl of `Test` for `()`
+ --> $DIR/projection-mismatch-in-impl-where-clause.rs:11:9
+ |
+LL | impl<T> Test for T where T: Super<Assoc = ()> {}
+ | ^^^^ ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/projection.rs b/src/test/ui/impl-trait/projection.rs
new file mode 100644
index 000000000..b33802e2b
--- /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<Self::It>;
+}
+
+impl<'a> Tr for &'a D {
+ type It = ();
+ fn foo(self) -> Option<()> { None }
+}
+
+fn run<F>(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(|_| {});
+}
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 000000000..7bd5cff31
--- /dev/null
+++ b/src/test/ui/impl-trait/question_mark.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::fmt::Debug;
+
+#[derive(Debug)]
+pub struct Target;
+
+#[derive(Debug)]
+pub struct Source;
+impl From<Source> for Target {
+ fn from(_: Source) -> Self {
+ Self
+ }
+}
+
+fn maybe_source() -> Result<(), Source> {
+ todo!()
+}
+
+pub fn typaram() -> Result<(), impl Debug> {
+ maybe_source()?;
+ Ok::<_, Target>(())
+}
+
+pub fn direct() -> Result<(), impl Debug> {
+ maybe_source()?;
+ Err(Target)
+}
+
+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
new file mode 100644
index 000000000..540a280f0
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+#![allow(unconditional_recursion)]
+
+fn test() -> impl Sized {
+ test()
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..ffc0cd9d1
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -0,0 +1,96 @@
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden.
+
+#![feature(generators)]
+#![allow(unconditional_recursion)]
+
+fn option(i: i32) -> impl Sized {
+ //~^ ERROR cannot resolve opaque type
+ if i < 0 { None } else { Some((option(i - 1), i)) }
+}
+
+fn tuple() -> impl Sized {
+ //~^ ERROR
+ (tuple(),)
+}
+
+fn array() -> impl Sized {
+ //~^ ERROR
+ [array()]
+}
+
+fn ptr() -> impl Sized {
+ //~^ ERROR
+ &ptr() as *const _
+}
+
+fn fn_ptr() -> impl Sized {
+ //~^ ERROR
+ fn_ptr as fn() -> _
+}
+
+fn closure_capture() -> impl Sized {
+ //~^ ERROR
+ let x = closure_capture();
+ move || {
+ x;
+ }
+}
+
+fn closure_ref_capture() -> impl Sized {
+ //~^ ERROR
+ let x = closure_ref_capture();
+ move || {
+ &x;
+ }
+}
+
+fn closure_sig() -> impl Sized {
+ //~^ ERROR
+ || closure_sig()
+}
+
+fn generator_sig() -> impl Sized {
+ //~^ ERROR
+ || generator_sig()
+}
+
+fn generator_capture() -> impl Sized {
+ //~^ ERROR
+ let x = generator_capture();
+ move || {
+ yield;
+ x;
+ }
+}
+
+fn substs_change<T: 'static>() -> impl Sized {
+ //~^ ERROR
+ (substs_change::<&T>(),)
+}
+
+fn generator_hold() -> impl Sized {
+ //~^ ERROR
+ move || {
+ let x = generator_hold();
+ yield;
+ x;
+ }
+}
+
+fn use_fn_ptr() -> impl Sized {
+ // OK, error already reported
+ fn_ptr()
+}
+
+fn mutual_recursion() -> impl Sync {
+ //~^ ERROR
+ mutual_recursion_b()
+}
+
+fn mutual_recursion_b() -> impl Sized {
+ //~^ ERROR
+ mutual_recursion()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
new file mode 100644
index 000000000..2e34d3d42
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -0,0 +1,148 @@
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:7:22
+ |
+LL | fn option(i: i32) -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | if i < 0 { None } else { Some((option(i - 1), i)) }
+ | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>`
+ | |
+ | returning here with type `Option<(impl Sized, i32)>`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:12:15
+ |
+LL | fn tuple() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | (tuple(),)
+ | ---------- returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:17:15
+ |
+LL | fn array() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | [array()]
+ | --------- returning here with type `[impl Sized; 1]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:22:13
+ |
+LL | fn ptr() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | &ptr() as *const _
+ | ------------------ returning here with type `*const impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:27:16
+ |
+LL | fn fn_ptr() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | fn_ptr as fn() -> _
+ | ------------------- returning here with type `fn() -> impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:32:25
+ |
+LL | fn closure_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | x;
+LL | | }
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 35:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:40:29
+ |
+LL | fn closure_ref_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | &x;
+LL | | }
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 43:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:48:21
+ |
+LL | fn closure_sig() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | || closure_sig()
+ | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:7]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
+ |
+LL | fn generator_sig() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | || generator_sig()
+ | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
+ |
+LL | fn generator_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | yield;
+LL | | x;
+LL | | }
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
+ |
+LL | fn substs_change<T: 'static>() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | (substs_change::<&T>(),)
+ | ------------------------ returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
+ |
+LL | fn generator_hold() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | / move || {
+LL | | let x = generator_hold();
+LL | | yield;
+LL | | x;
+LL | | }
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 74:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
+ |
+LL | fn mutual_recursion() -> impl Sync {
+ | ^^^^^^^^^ recursive opaque type
+LL |
+LL | mutual_recursion_b()
+ | -------------------- returning here with type `impl Sized`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+ | ---------- returning this opaque type `impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:91:28
+ |
+LL | fn mutual_recursion() -> impl Sync {
+ | --------- returning this opaque type `impl Sync`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | mutual_recursion()
+ | ------------------ returning here with type `impl Sync`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
new file mode 100644
index 000000000..818e40365
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
@@ -0,0 +1,25 @@
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden. Even when there's an opaque type in another crate
+// hiding this.
+
+fn id<T>(t: T) -> impl Sized { t }
+
+fn recursive_id() -> impl Sized { //~ ERROR cannot resolve opaque type
+ id(recursive_id2())
+}
+
+fn recursive_id2() -> impl Sized { //~ ERROR cannot resolve opaque type
+ id(recursive_id())
+}
+
+fn wrap<T>(t: T) -> impl Sized { (t,) }
+
+fn recursive_wrap() -> impl Sized { //~ ERROR cannot resolve opaque type
+ wrap(recursive_wrap2())
+}
+
+fn recursive_wrap2() -> impl Sized { //~ ERROR cannot resolve opaque type
+ wrap(recursive_wrap())
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
new file mode 100644
index 000000000..b514e9fef
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
@@ -0,0 +1,47 @@
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22
+ |
+LL | fn id<T>(t: T) -> impl Sized { t }
+ | ---------- returning this opaque type `impl Sized`
+LL |
+LL | fn recursive_id() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL | id(recursive_id2())
+ | ------------------- returning here with type `impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23
+ |
+LL | fn id<T>(t: T) -> impl Sized { t }
+ | ---------- returning this opaque type `impl Sized`
+...
+LL | fn recursive_id2() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL | id(recursive_id())
+ | ------------------ returning here with type `impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24
+ |
+LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
+ | ---------- returning this opaque type `impl Sized`
+LL |
+LL | fn recursive_wrap() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL | wrap(recursive_wrap2())
+ | ----------------------- returning here with type `impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25
+ |
+LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
+ | ---------- returning this opaque type `impl Sized`
+...
+LL | fn recursive_wrap2() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL | wrap(recursive_wrap())
+ | ---------------------- returning here with type `impl Sized`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
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 000000000..621c4ea6e
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
@@ -0,0 +1,18 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl PartialEq<(Foo, i32)>;
+
+struct Bar;
+
+impl PartialEq<(Foo, i32)> for Bar {
+//~^ ERROR cannot implement trait on type alias impl trait
+ fn eq(&self, _other: &(Foo, i32)) -> bool {
+ true
+ }
+}
+
+fn foo() -> Foo {
+ Bar
+}
+
+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 000000000..2ef1697ba
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
@@ -0,0 +1,14 @@
+error: cannot implement trait on type alias impl trait
+ --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:17
+ |
+LL | impl PartialEq<(Foo, i32)> for Bar {
+ | ^^^
+ |
+note: type alias impl trait defined here
+ --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12
+ |
+LL | type Foo = impl PartialEq<(Foo, i32)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
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 000000000..df7966f00
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -0,0 +1,28 @@
+#![feature(type_alias_impl_trait)]
+
+mod a {
+ type Foo = impl PartialEq<(Foo, i32)>;
+
+ struct Bar;
+
+ impl PartialEq<(Bar, i32)> for Bar {
+ fn eq(&self, _other: &(Foo, i32)) -> bool {
+ true
+ }
+ }
+}
+
+mod b {
+ type Foo = impl PartialEq<(Foo, i32)>;
+
+ struct Bar;
+
+ impl PartialEq<(Foo, i32)> for Bar {
+ //~^ ERROR cannot implement trait on type alias impl trait
+ 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 000000000..6cd63dcf8
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -0,0 +1,14 @@
+error: cannot implement trait on type alias impl trait
+ --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:21
+ |
+LL | impl PartialEq<(Foo, i32)> for Bar {
+ | ^^^
+ |
+note: type alias impl trait defined here
+ --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16
+ |
+LL | type Foo = impl PartialEq<(Foo, i32)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
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 000000000..ad0a003e8
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+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-contravariant-closure.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs
new file mode 100644
index 000000000..9f63a8617
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs
@@ -0,0 +1,18 @@
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+
+fn foo<'x, 'y>(x: &'x u32) -> impl Fn() -> &'y u32
+where 'x: 'y
+{
+ move || x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs
new file mode 100644
index 000000000..79319dfe7
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs
@@ -0,0 +1,22 @@
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+
+trait Trait<'a> { }
+
+impl<'a, 'b> Trait<'b> for &'a u32 { }
+
+fn foo<'x, 'y>(x: &'x u32) -> impl Trait<'y>
+where 'x: 'y
+{
+ x
+}
+
+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
new file mode 100644
index 000000000..fe60c76ca
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound.rs
@@ -0,0 +1,21 @@
+// Test that we do not allow the region `'x` to escape in the impl
+// trait **even though** `'y` escapes, which outlives `'x`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+#![allow(dead_code)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a, 'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
+where 'x: 'y
+{
+ x
+ //~^ ERROR hidden type for `impl Trait<'y>` 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
new file mode 100644
index 000000000..fdb2fe022
--- /dev/null
+++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr
@@ -0,0 +1,17 @@
+error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not appear in bounds
+ --> $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
+...
+LL | x
+ | ^
+ |
+help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound
+ |
+LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/return-position-impl-trait-minimal.rs b/src/test/ui/impl-trait/return-position-impl-trait-minimal.rs
new file mode 100644
index 000000000..6d3c06929
--- /dev/null
+++ b/src/test/ui/impl-trait/return-position-impl-trait-minimal.rs
@@ -0,0 +1,5 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+fn main() {}
+
+fn foo() -> impl std::fmt::Debug { "cake" }
diff --git a/src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs
new file mode 100644
index 000000000..a4e603de1
--- /dev/null
+++ b/src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> {
+ v.into_iter()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/rpit-not-sized.rs b/src/test/ui/impl-trait/rpit-not-sized.rs
new file mode 100644
index 000000000..bd2594078
--- /dev/null
+++ b/src/test/ui/impl-trait/rpit-not-sized.rs
@@ -0,0 +1,6 @@
+fn foo() -> impl ?Sized {
+ //~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time
+ ()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/rpit-not-sized.stderr b/src/test/ui/impl-trait/rpit-not-sized.stderr
new file mode 100644
index 000000000..608c94fc0
--- /dev/null
+++ b/src/test/ui/impl-trait/rpit-not-sized.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time
+ --> $DIR/rpit-not-sized.rs:1:13
+ |
+LL | fn foo() -> impl ?Sized {
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `impl ?Sized`
+ = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
new file mode 100644
index 000000000..f940c1949
--- /dev/null
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
@@ -0,0 +1,18 @@
+struct A {
+ x: [(u32, u32); 10]
+}
+
+impl A {
+ fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+ self.x.iter().map(|a| a.0)
+ //~^ ERROR: captures lifetime that does not appear in bounds
+ //~| ERROR: captures lifetime that does not appear in bounds
+ }
+ fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+ self.x.iter().map(|a| a.0)
+ //~^ ERROR: captures lifetime that does not appear in bounds
+ //~| ERROR: captures lifetime that does not appear in bounds
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
new file mode 100644
index 000000000..b86815231
--- /dev/null
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -0,0 +1,55 @@
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
+ --> $DIR/static-return-lifetime-infered.rs:7:9
+ |
+LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+ | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` 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
+ |
+LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
+ | ++++
+
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
+ --> $DIR/static-return-lifetime-infered.rs:7:9
+ |
+LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+ | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` 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
+ |
+LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
+ | ++++
+
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
+ --> $DIR/static-return-lifetime-infered.rs:12:9
+ |
+LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+ | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` 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
+ |
+LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
+ | ++++
+
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
+ --> $DIR/static-return-lifetime-infered.rs:12:9
+ |
+LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+ | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` 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
+ |
+LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
+ | ++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/suggest-calling-rpit-closure.rs b/src/test/ui/impl-trait/suggest-calling-rpit-closure.rs
new file mode 100644
index 000000000..640156291
--- /dev/null
+++ b/src/test/ui/impl-trait/suggest-calling-rpit-closure.rs
@@ -0,0 +1,12 @@
+fn whatever() -> i32 {
+ opaque()
+//~^ ERROR mismatched types
+}
+
+fn opaque() -> impl Fn() -> i32 {
+ || 0
+}
+
+fn main() {
+ let _ = whatever();
+}
diff --git a/src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr b/src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr
new file mode 100644
index 000000000..2a328a0e6
--- /dev/null
+++ b/src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-calling-rpit-closure.rs:2:5
+ |
+LL | fn whatever() -> i32 {
+ | --- expected `i32` because of return type
+LL | opaque()
+ | ^^^^^^^^ expected `i32`, found opaque type
+...
+LL | fn opaque() -> impl Fn() -> i32 {
+ | ---------------- the found opaque type
+ |
+ = note: expected type `i32`
+ found opaque type `impl Fn() -> i32`
+help: use parentheses to call this closure
+ |
+LL | opaque()()
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
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 000000000..8dcbbfd6e
--- /dev/null
+++ b/src/test/ui/impl-trait/trait_resolution.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::fmt::Debug;
+
+pub struct EventStream<S> {
+ stream: S,
+}
+
+impl<S: Debug> EventStream<S> {
+ fn into_stream(self) -> impl Debug {
+ unimplemented!()
+ }
+
+ pub fn into_reader(self) -> impl Debug {
+ ReaderStream::from(self.into_stream())
+ }
+}
+
+#[derive(Debug)]
+pub struct ReaderStream<S> {
+ stream: S,
+}
+
+impl<S> From<S> for ReaderStream<S> {
+ fn from(stream: S) -> Self {
+ ReaderStream { stream }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/trait_type.rs b/src/test/ui/impl-trait/trait_type.rs
new file mode 100644
index 000000000..638fefc46
--- /dev/null
+++ b/src/test/ui/impl-trait/trait_type.rs
@@ -0,0 +1,24 @@
+struct MyType;
+struct MyType2;
+struct MyType3;
+struct MyType4;
+
+impl std::fmt::Display for MyType {
+ fn fmt(&self, x: &str) -> () { }
+ //~^ ERROR method `fmt` has an incompatible type
+}
+
+impl std::fmt::Display for MyType2 {
+ fn fmt(&self) -> () { }
+ //~^ ERROR method `fmt` has 1 parameter
+}
+
+impl std::fmt::Display for MyType3 {
+ fn fmt() -> () { }
+ //~^ ERROR method `fmt` has a `&self` declaration in the trait
+}
+
+impl std::fmt::Display for MyType4 {}
+//~^ ERROR not all trait items
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr
new file mode 100644
index 000000000..bea243398
--- /dev/null
+++ b/src/test/ui/impl-trait/trait_type.stderr
@@ -0,0 +1,40 @@
+error[E0053]: method `fmt` has an incompatible type for trait
+ --> $DIR/trait_type.rs:7:21
+ |
+LL | fn fmt(&self, x: &str) -> () { }
+ | ^^^^
+ | |
+ | types differ in mutability
+ | help: change the parameter type to match the trait: `&mut Formatter<'_>`
+ |
+ = note: expected fn pointer `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
+ found fn pointer `fn(&MyType, &str)`
+
+error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2
+ --> $DIR/trait_type.rs:12:11
+ |
+LL | fn fmt(&self) -> () { }
+ | ^^^^^ expected 2 parameters, found 1
+ |
+ = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
+
+error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in the impl
+ --> $DIR/trait_type.rs:17:4
+ |
+LL | fn fmt() -> () { }
+ | ^^^^^^^^^^^^^^ expected `&self` in impl
+ |
+ = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
+
+error[E0046]: not all trait items implemented, missing: `fmt`
+ --> $DIR/trait_type.rs:21:1
+ |
+LL | impl std::fmt::Display for MyType4 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation
+ |
+ = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0046, E0050, E0053, E0186.
+For more information about an error, try `rustc --explain E0046`.
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 000000000..6eb2a11b2
--- /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 000000000..1a42ac525
--- /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 000000000..05b096680
--- /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; //~ ERROR unconstrained opaque type
+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 000000000..4d8f96de1
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr
@@ -0,0 +1,27 @@
+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
+ |
+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 2 previous errors
+
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 000000000..37f8ae1b8
--- /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 000000000..b06dc16d5
--- /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-alias-generic-param.rs b/src/test/ui/impl-trait/type-alias-generic-param.rs
new file mode 100644
index 000000000..3499b2859
--- /dev/null
+++ b/src/test/ui/impl-trait/type-alias-generic-param.rs
@@ -0,0 +1,23 @@
+// Regression test for issue #59342
+// Checks that we properly detect defining uses of opaque
+// types in 'item' position when generic parameters are involved
+//
+// run-pass
+#![feature(type_alias_impl_trait)]
+
+trait Meow {
+ type MeowType;
+ fn meow(self) -> Self::MeowType;
+}
+
+impl<T, I> Meow for I
+where
+ I: Iterator<Item = T>,
+{
+ type MeowType = impl Iterator<Item = T>;
+ fn meow(self) -> Self::MeowType {
+ self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs b/src/test/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs
new file mode 100644
index 000000000..91be4efd5
--- /dev/null
+++ b/src/test/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs
@@ -0,0 +1,12 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+
+fn main() {
+ type Existential = impl Debug;
+
+ fn f() -> Existential {}
+ println!("{:?}", f());
+}
diff --git a/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs
new file mode 100644
index 000000000..ecfa5c69e
--- /dev/null
+++ b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs
@@ -0,0 +1,16 @@
+trait Foo {
+ type T;
+ fn foo(&self, t: Self::T);
+//~^ NOTE expected 0 type parameters
+}
+
+impl Foo for u32 {
+ type T = ();
+
+ fn foo(&self, t: impl Clone) {}
+//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+//~| NOTE found 1 type parameter
+//~| NOTE `impl Trait` introduces an implicit type parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr
new file mode 100644
index 000000000..30322f88c
--- /dev/null
+++ b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr
@@ -0,0 +1,15 @@
+error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+ --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
+ |
+LL | fn foo(&self, t: Self::T);
+ | - expected 0 type parameters
+...
+LL | fn foo(&self, t: impl Clone) {}
+ | ^^^^^^^^^^
+ | |
+ | found 1 type parameter
+ | `impl Trait` introduces an implicit type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/impl-trait/type_parameters_captured.rs b/src/test/ui/impl-trait/type_parameters_captured.rs
new file mode 100644
index 000000000..81ee7d3f8
--- /dev/null
+++ b/src/test/ui/impl-trait/type_parameters_captured.rs
@@ -0,0 +1,12 @@
+use std::fmt::Debug;
+
+trait Any {}
+impl<T> Any for T {}
+
+// Check that type parameters are captured and not considered 'static
+fn foo<T>(x: T) -> impl Any + 'static {
+ 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
new file mode 100644
index 000000000..fb502cfdd
--- /dev/null
+++ b/src/test/ui/impl-trait/type_parameters_captured.stderr
@@ -0,0 +1,14 @@
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/type_parameters_captured.rs:8:5
+ |
+LL | x
+ | ^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn foo<T: 'static>(x: T) -> impl Any + 'static {
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/universal-mismatched-type.rs b/src/test/ui/impl-trait/universal-mismatched-type.rs
new file mode 100644
index 000000000..e9129bbd7
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-mismatched-type.rs
@@ -0,0 +1,7 @@
+use std::fmt::Debug;
+
+fn foo(x: impl Debug) -> String {
+ x //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/universal-mismatched-type.stderr b/src/test/ui/impl-trait/universal-mismatched-type.stderr
new file mode 100644
index 000000000..817c573c0
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-mismatched-type.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+ --> $DIR/universal-mismatched-type.rs:4:5
+ |
+LL | fn foo(x: impl Debug) -> String {
+ | ---------- ------ expected `String` because of return type
+ | |
+ | this type parameter
+LL | x
+ | ^ expected struct `String`, found type parameter `impl Debug`
+ |
+ = note: expected struct `String`
+ found type parameter `impl Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.rs b/src/test/ui/impl-trait/universal-two-impl-traits.rs
new file mode 100644
index 000000000..689c24012
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-two-impl-traits.rs
@@ -0,0 +1,16 @@
+use std::fmt::Debug;
+
+fn foo(x: impl Debug, y: impl Debug) -> String {
+ let mut a = x;
+ a = y; //~ ERROR mismatched
+ format!("{:?}", a)
+}
+
+trait S<T> {}
+
+fn much_universe<T: S<impl Debug>, U: IntoIterator<Item = impl Iterator<Item = impl Clone>>>(
+ _: impl Debug + Clone,
+) {
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr
new file mode 100644
index 000000000..ab8a53d0d
--- /dev/null
+++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/universal-two-impl-traits.rs:5:9
+ |
+LL | fn foo(x: impl Debug, y: impl Debug) -> String {
+ | ---------- ---------- found type parameter
+ | |
+ | expected type parameter
+LL | let mut a = x;
+ | - expected due to this value
+LL | a = y;
+ | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
+ |
+ = note: expected type parameter `impl Debug` (type parameter `impl Debug`)
+ found type parameter `impl Debug` (type parameter `impl Debug`)
+ = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+ = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/universal_hrtb_anon.rs b/src/test/ui/impl-trait/universal_hrtb_anon.rs
new file mode 100644
index 000000000..30c8d291f
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_hrtb_anon.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+fn hrtb(f: impl Fn(&u32) -> u32) -> u32 {
+ f(&22) + f(&44)
+}
+
+fn main() {
+ let sum = hrtb(|x| x * 2);
+ assert_eq!(sum, 22*2 + 44*2);
+}
diff --git a/src/test/ui/impl-trait/universal_hrtb_named.rs b/src/test/ui/impl-trait/universal_hrtb_named.rs
new file mode 100644
index 000000000..07ff5d23e
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_hrtb_named.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+fn hrtb(f: impl for<'a> Fn(&'a u32) -> &'a u32) -> u32 {
+ f(&22) + f(&44)
+}
+
+fn main() {
+ let sum = hrtb(|x| x);
+ assert_eq!(sum, 22 + 44);
+}
diff --git a/src/test/ui/impl-trait/universal_in_adt_in_parameters.rs b/src/test/ui/impl-trait/universal_in_adt_in_parameters.rs
new file mode 100644
index 000000000..a3829133d
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_in_adt_in_parameters.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+use std::fmt::Display;
+
+fn check_display_eq(iter: &Vec<impl Display>) {
+ let mut collected = String::new();
+ for it in iter {
+ let disp = format!("{} ", it);
+ collected.push_str(&disp);
+ }
+ assert_eq!("0 3 27 823 4891 1 0", collected.trim());
+}
+
+fn main() {
+ let i32_list_vec = vec![0i32, 3, 27, 823, 4891, 1, 0];
+ let u32_list_vec = vec![0u32, 3, 27, 823, 4891, 1, 0];
+ let str_list_vec = vec!["0", "3", "27", "823", "4891", "1", "0"];
+
+ check_display_eq(&i32_list_vec);
+ check_display_eq(&u32_list_vec);
+ check_display_eq(&str_list_vec);
+}
diff --git a/src/test/ui/impl-trait/universal_in_impl_trait_in_parameters.rs b/src/test/ui/impl-trait/universal_in_impl_trait_in_parameters.rs
new file mode 100644
index 000000000..e98912d95
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_in_impl_trait_in_parameters.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+use std::fmt::Display;
+
+fn check_display_eq(iter: impl IntoIterator<Item = impl Display>) {
+ let mut collected = String::new();
+ for it in iter {
+ let disp = format!("{} ", it);
+ collected.push_str(&disp);
+ }
+ assert_eq!("0 3 27 823 4891 1 0", collected.trim());
+}
+
+fn main() {
+ let i32_list = [0i32, 3, 27, 823, 4891, 1, 0];
+ let i32_list_vec = vec![0i32, 3, 27, 823, 4891, 1, 0];
+ let u32_list = [0u32, 3, 27, 823, 4891, 1, 0];
+ let u32_list_vec = vec![0u32, 3, 27, 823, 4891, 1, 0];
+ let u16_list = [0u16, 3, 27, 823, 4891, 1, 0];
+ let str_list = ["0", "3", "27", "823", "4891", "1", "0"];
+ let str_list_vec = vec!["0", "3", "27", "823", "4891", "1", "0"];
+
+ check_display_eq(&i32_list);
+ check_display_eq(i32_list_vec);
+ check_display_eq(&u32_list);
+ check_display_eq(u32_list_vec);
+ check_display_eq(&u16_list);
+ check_display_eq(&str_list);
+ check_display_eq(str_list_vec);
+}
diff --git a/src/test/ui/impl-trait/universal_in_trait_defn_parameters.rs b/src/test/ui/impl-trait/universal_in_trait_defn_parameters.rs
new file mode 100644
index 000000000..23c217a8f
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_in_trait_defn_parameters.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+use std::fmt::Debug;
+
+trait InTraitDefnParameters {
+ fn in_parameters(_: impl Debug) -> String;
+}
+
+impl InTraitDefnParameters for () {
+ fn in_parameters(v: impl Debug) -> String {
+ format!("() + {:?}", v)
+ }
+}
+
+fn main() {
+ let s = <() as InTraitDefnParameters>::in_parameters(22);
+ assert_eq!(s, "() + 22");
+}
diff --git a/src/test/ui/impl-trait/universal_multiple_bounds.rs b/src/test/ui/impl-trait/universal_multiple_bounds.rs
new file mode 100644
index 000000000..40c1405c3
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_multiple_bounds.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+use std::fmt::Display;
+
+fn foo(f: impl Display + Clone) -> String {
+ let g = f.clone();
+ format!("{} + {}", f, g)
+}
+
+fn main() {
+ let sum = foo(format!("22"));
+ assert_eq!(sum, r"22 + 22");
+}
diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.rs b/src/test/ui/impl-trait/universal_wrong_bounds.rs
new file mode 100644
index 000000000..2182506c7
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_wrong_bounds.rs
@@ -0,0 +1,13 @@
+use std::fmt::Display;
+
+fn foo(f: impl Display + Clone) -> String {
+ wants_debug(f);
+ wants_display(f);
+ wants_clone(f);
+}
+
+fn wants_debug(g: impl Debug) { } //~ ERROR expected trait, found derive macro `Debug`
+fn wants_display(g: impl Debug) { } //~ ERROR expected trait, found derive macro `Debug`
+fn wants_clone(g: impl Clone) { }
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.stderr b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
new file mode 100644
index 000000000..3b1a5e5f4
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
@@ -0,0 +1,25 @@
+error[E0404]: expected trait, found derive macro `Debug`
+ --> $DIR/universal_wrong_bounds.rs:9:24
+ |
+LL | fn wants_debug(g: impl Debug) { }
+ | ^^^^^ not a trait
+ |
+help: consider importing this trait instead
+ |
+LL | use std::fmt::Debug;
+ |
+
+error[E0404]: expected trait, found derive macro `Debug`
+ --> $DIR/universal_wrong_bounds.rs:10:26
+ |
+LL | fn wants_display(g: impl Debug) { }
+ | ^^^^^ not a trait
+ |
+help: consider importing this trait instead
+ |
+LL | use std::fmt::Debug;
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/impl-trait/universal_wrong_hrtb.rs b/src/test/ui/impl-trait/universal_wrong_hrtb.rs
new file mode 100644
index 000000000..b9551c2ce
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_wrong_hrtb.rs
@@ -0,0 +1,8 @@
+trait Trait<'a> {
+ type Assoc;
+}
+
+fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
+//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/universal_wrong_hrtb.stderr b/src/test/ui/impl-trait/universal_wrong_hrtb.stderr
new file mode 100644
index 000000000..37eb8dfa1
--- /dev/null
+++ b/src/test/ui/impl-trait/universal_wrong_hrtb.stderr
@@ -0,0 +1,14 @@
+error: `impl Trait` can only mention lifetimes bound at the fn or impl level
+ --> $DIR/universal_wrong_hrtb.rs:5:73
+ |
+LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
+ | ^^
+ |
+note: lifetime declared here
+ --> $DIR/universal_wrong_hrtb.rs:5:39
+ |
+LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
+ | ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/unsafety-checking-cycle.rs b/src/test/ui/impl-trait/unsafety-checking-cycle.rs
new file mode 100644
index 000000000..4a5831c5b
--- /dev/null
+++ b/src/test/ui/impl-trait/unsafety-checking-cycle.rs
@@ -0,0 +1,32 @@
+// Ensure that we don't get a cycle error from trying to determine whether an
+// opaque type implements `Freeze` in safety checking, when it doesn't matter.
+
+// check-pass
+
+#![feature(rustc_attrs)]
+
+struct AnyValue<T>(T);
+
+// No need to check for `Freeze` here, there's no
+// `rustc_layout_scalar_valid_range_start` involved.
+fn not_restricted(c: bool) -> impl Sized {
+ if c {
+ let x = AnyValue(not_restricted(false));
+ &x.0;
+ }
+ 2u32
+}
+
+#[rustc_layout_scalar_valid_range_start(1)]
+struct NonZero<T>(T);
+
+// No need to check for `Freeze` here, we're not borrowing the field.
+fn not_field(c: bool) -> impl Sized {
+ if c {
+ let x = unsafe { NonZero(not_field(false)) };
+ &x;
+ }
+ 5u32
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/wf-eval-order.rs b/src/test/ui/impl-trait/wf-eval-order.rs
new file mode 100644
index 000000000..c7d6bb870
--- /dev/null
+++ b/src/test/ui/impl-trait/wf-eval-order.rs
@@ -0,0 +1,39 @@
+// Check that we handle evaluating `wf` predicates correctly.
+
+// check-pass
+
+struct X<T: B>(T)
+where
+ T::V: Clone;
+
+fn hide<T>(t: T) -> impl Sized {
+ t
+}
+
+trait A {
+ type U;
+}
+
+impl<T> A for T {
+ type U = T;
+}
+
+trait B {
+ type V;
+}
+
+impl<S: A<U = T>, T> B for S {
+ type V = T;
+}
+
+fn main() {
+ // Evaluating `typeof(x): Sized` requires
+ //
+ // - `wf(typeof(x))` because we use a projection candidate.
+ // - `<i32 as B>::V: Clone` because that's a bound on the trait.
+ // - `<i32 as B>::V` normalizes to `_#1` where `<i32 as A>::U == _#1`
+ //
+ // This all works if we evaluate `<i32 as A>::U == _#1` before
+ // `<i32 as B>::V`, but we previously had the opposite order.
+ let x = hide(X(0));
+}
diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs
new file mode 100644
index 000000000..1a1210d00
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed-2.rs
@@ -0,0 +1,6 @@
+use std::fmt::Debug;
+
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
+//~^ ERROR type annotations needed
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
new file mode 100644
index 000000000..2b328c01c
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed-2.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/where-allowed-2.rs:3:30
+ |
+LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
+ | ^^^^^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs
new file mode 100644
index 000000000..c1dd46c7f
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed.rs
@@ -0,0 +1,251 @@
+//! A simple test for testing many permutations of allowedness of
+//! impl Trait
+use std::fmt::Debug;
+
+// Allowed
+fn in_parameters(_: impl Debug) { panic!() }
+
+// Allowed
+fn in_return() -> impl Debug { panic!() }
+
+// Allowed
+fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
+
+// Disallowed
+fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^^ ERROR nested `impl Trait` is not allowed
+
+// Disallowed
+fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR nested `impl Trait` is not allowed
+
+// Disallowed
+fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+
+// Allowed
+fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!() }
+
+// Allowed
+fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
+ vec![vec![0; 10], vec![12; 7], vec![8; 3]]
+}
+
+// Disallowed
+struct InBraceStructField { x: impl Debug }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+struct InAdtInBraceStructField { x: Vec<impl Debug> }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+struct InTupleStructField(impl Debug);
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+enum InEnum {
+ InBraceVariant { x: impl Debug },
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+ InTupleVariant(impl Debug),
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Allowed
+trait InTraitDefnParameters {
+ fn in_parameters(_: impl Debug);
+}
+
+// Disallowed
+trait InTraitDefnReturn {
+ fn in_return() -> impl Debug;
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Allowed and disallowed in trait impls
+trait DummyTrait {
+ type Out;
+ fn in_trait_impl_parameter(_: impl Debug);
+ fn in_trait_impl_return() -> Self::Out;
+}
+impl DummyTrait for () {
+ type Out = impl Debug;
+ //~^ ERROR `impl Trait` in type aliases is unstable
+
+ fn in_trait_impl_parameter(_: impl Debug) { }
+ // Allowed
+
+ fn in_trait_impl_return() -> impl Debug { () }
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Allowed
+struct DummyType;
+impl DummyType {
+ fn in_inherent_impl_parameters(_: impl Debug) { }
+ fn in_inherent_impl_return() -> impl Debug { () }
+}
+
+// Disallowed
+extern "C" {
+ fn in_foreign_parameters(_: impl Debug);
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+ fn in_foreign_return() -> impl Debug;
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Allowed
+extern "C" fn in_extern_fn_parameters(_: impl Debug) {
+}
+
+// Allowed
+extern "C" fn in_extern_fn_return() -> impl Debug {
+ 22
+}
+
+type InTypeAlias<R> = impl Debug;
+//~^ ERROR `impl Trait` in type aliases is unstable
+
+type InReturnInTypeAlias<R> = fn() -> impl Debug;
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR `impl Trait` in type aliases is unstable
+
+// Disallowed in impl headers
+impl PartialEq<impl Debug> for () {
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Disallowed in impl headers
+impl PartialEq<()> for impl Debug {
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Disallowed in inherent impls
+impl impl Debug {
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Disallowed in inherent impls
+struct InInherentImplAdt<T> { t: T }
+impl InInherentImplAdt<impl Debug> {
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
+
+// Disallowed in where clauses
+fn in_fn_where_clause()
+ where impl Debug: Debug
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+{
+}
+
+// Disallowed in where clauses
+fn in_adt_in_fn_where_clause()
+ where Vec<impl Debug>: Debug
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+{
+}
+
+// Disallowed
+fn in_trait_parameter_in_fn_where_clause<T>()
+ where T: PartialEq<impl Debug>
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+{
+}
+
+// Disallowed
+fn in_Fn_parameter_in_fn_where_clause<T>()
+ where T: Fn(impl Debug)
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+{
+}
+
+// Disallowed
+fn in_Fn_return_in_fn_where_clause<T>()
+ where T: Fn() -> impl Debug
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+{
+}
+
+// Disallowed
+struct InStructGenericParamDefault<T = impl Debug>(T);
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+trait InTraitGenericParamDefault<T = impl Debug> {}
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+type InTypeAliasGenericParamDefault<T = impl Debug> = T;
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+
+// Disallowed
+impl <T = impl Debug> T {}
+//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+//~| WARNING this was previously accepted by the compiler but is being phased out
+//~| ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR no nominal type found
+
+// Disallowed
+fn in_method_generic_param_default<T = impl Debug>(_: T) {}
+//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+//~| WARNING this was previously accepted by the compiler but is being phased out
+//~| ERROR `impl Trait` only allowed in function and inherent method return types
+
+fn main() {
+ let _in_local_variable: impl Fn() = || {};
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+ let _in_return_in_local_variable = || -> impl Fn() { || {} };
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+}
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr
new file mode 100644
index 000000000..58a2f79ef
--- /dev/null
+++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -0,0 +1,322 @@
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/where-allowed.rs:47:51
+ |
+LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
+ | --------^^^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/where-allowed.rs:56:57
+ |
+LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
+ | --------^^^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0658]: `impl Trait` in type aliases is unstable
+ --> $DIR/where-allowed.rs:119:16
+ |
+LL | type Out = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+
+error[E0658]: `impl Trait` in type aliases is unstable
+ --> $DIR/where-allowed.rs:154:23
+ |
+LL | type InTypeAlias<R> = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+
+error[E0658]: `impl Trait` in type aliases is unstable
+ --> $DIR/where-allowed.rs:157:39
+ |
+LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param
+ --> $DIR/where-allowed.rs:15:40
+ |
+LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+ --> $DIR/where-allowed.rs:19:42
+ |
+LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param
+ --> $DIR/where-allowed.rs:23:38
+ |
+LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+ --> $DIR/where-allowed.rs:27:40
+ |
+LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+ --> $DIR/where-allowed.rs:31:49
+ |
+LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/where-allowed.rs:35:51
+ |
+LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+ --> $DIR/where-allowed.rs:39:55
+ |
+LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/where-allowed.rs:43:57
+ |
+LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+ --> $DIR/where-allowed.rs:47:51
+ |
+LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/where-allowed.rs:52:53
+ |
+LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+ --> $DIR/where-allowed.rs:56:57
+ |
+LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/where-allowed.rs:61:59
+ |
+LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+ --> $DIR/where-allowed.rs:65:38
+ |
+LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/where-allowed.rs:69:40
+ |
+LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:82:32
+ |
+LL | struct InBraceStructField { x: impl Debug }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path
+ --> $DIR/where-allowed.rs:86:41
+ |
+LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:90:27
+ |
+LL | struct InTupleStructField(impl Debug);
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:95:25
+ |
+LL | InBraceVariant { x: impl Debug },
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:97:20
+ |
+LL | InTupleVariant(impl Debug),
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+ --> $DIR/where-allowed.rs:108:23
+ |
+LL | fn in_return() -> impl Debug;
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
+ --> $DIR/where-allowed.rs:125:34
+ |
+LL | fn in_trait_impl_return() -> impl Debug { () }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param
+ --> $DIR/where-allowed.rs:138:33
+ |
+LL | fn in_foreign_parameters(_: impl Debug);
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return
+ --> $DIR/where-allowed.rs:141:31
+ |
+LL | fn in_foreign_return() -> impl Debug;
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+ --> $DIR/where-allowed.rs:157:39
+ |
+LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait
+ --> $DIR/where-allowed.rs:162:16
+ |
+LL | impl PartialEq<impl Debug> for () {
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:167:24
+ |
+LL | impl PartialEq<()> for impl Debug {
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:172:6
+ |
+LL | impl impl Debug {
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:178:24
+ |
+LL | impl InInherentImplAdt<impl Debug> {
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:184:11
+ |
+LL | where impl Debug: Debug
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:191:15
+ |
+LL | where Vec<impl Debug>: Debug
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound
+ --> $DIR/where-allowed.rs:198:24
+ |
+LL | where T: PartialEq<impl Debug>
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+ --> $DIR/where-allowed.rs:205:17
+ |
+LL | where T: Fn(impl Debug)
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+ --> $DIR/where-allowed.rs:212:22
+ |
+LL | where T: Fn() -> impl Debug
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:218:40
+ |
+LL | struct InStructGenericParamDefault<T = impl Debug>(T);
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:222:36
+ |
+LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:226:38
+ |
+LL | trait InTraitGenericParamDefault<T = impl Debug> {}
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:230:41
+ |
+LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:234:11
+ |
+LL | impl <T = impl Debug> T {}
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/where-allowed.rs:241:40
+ |
+LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
+ | ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+ --> $DIR/where-allowed.rs:247:29
+ |
+LL | let _in_local_variable: impl Fn() = || {};
+ | ^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return
+ --> $DIR/where-allowed.rs:249:46
+ |
+LL | let _in_return_in_local_variable = || -> impl Fn() { || {} };
+ | ^^^^^^^^^
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/where-allowed.rs:234:7
+ |
+LL | impl <T = impl Debug> T {}
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(invalid_type_param_default)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/where-allowed.rs:241:36
+ |
+LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
+ | ^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error[E0118]: no nominal type found for inherent implementation
+ --> $DIR/where-allowed.rs:234:23
+ |
+LL | impl <T = impl Debug> T {}
+ | ^ impl requires a nominal type
+ |
+ = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to 49 previous errors
+
+Some errors have detailed explanations: E0118, E0562, E0658, E0666.
+For more information about an error, try `rustc --explain E0118`.
diff --git a/src/test/ui/impl-trait/xcrate.rs b/src/test/ui/impl-trait/xcrate.rs
new file mode 100644
index 000000000..fe106ff05
--- /dev/null
+++ b/src/test/ui/impl-trait/xcrate.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+// aux-build:xcrate.rs
+
+extern crate xcrate;
+
+fn main() {
+// NOTE line below commented out due to issue #45994
+// assert_eq!(xcrate::fourway_add(1)(2)(3)(4), 10);
+ xcrate::return_closure_accessing_internal_fn()();
+}
diff --git a/src/test/ui/impl-trait/xcrate_simple.rs b/src/test/ui/impl-trait/xcrate_simple.rs
new file mode 100644
index 000000000..2b1fc97e3
--- /dev/null
+++ b/src/test/ui/impl-trait/xcrate_simple.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+// aux-build:xcrate.rs
+
+extern crate xcrate;
+
+fn main() {
+ xcrate::return_internal_fn()();
+}