summaryrefslogtreecommitdiffstats
path: root/tests/ui/async-await
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
commit64d98f8ee037282c35007b64c2649055c56af1db (patch)
tree5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/ui/async-await
parentAdding debian version 1.67.1+dfsg1-1. (diff)
downloadrustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz
rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/async-await')
-rw-r--r--tests/ui/async-await/argument-patterns.rs28
-rw-r--r--tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs23
-rw-r--r--tests/ui/async-await/async-await-let-else.drop-tracking.stderr106
-rw-r--r--tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr90
-rw-r--r--tests/ui/async-await/async-await-let-else.rs56
-rw-r--r--tests/ui/async-await/async-await.rs219
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.rs65
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.stderr81
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-block-error.fixed18
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-block-error.rs18
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-block-error.stderr41
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.rs10
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.stderr21
-rw-r--r--tests/ui/async-await/async-closure-matches-expr.rs12
-rw-r--r--tests/ui/async-await/async-closure.rs100
-rw-r--r--tests/ui/async-await/async-error-span.rs17
-rw-r--r--tests/ui/async-await/async-error-span.stderr25
-rw-r--r--tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs15
-rw-r--r--tests/ui/async-await/async-fn-nonsend.rs74
-rw-r--r--tests/ui/async-await/async-fn-nonsend.stderr49
-rw-r--r--tests/ui/async-await/async-fn-path-elision.rs13
-rw-r--r--tests/ui/async-await/async-fn-path-elision.stderr15
-rw-r--r--tests/ui/async-await/async-fn-send-uses-nonsend.rs57
-rw-r--r--tests/ui/async-await/async-fn-size-moved-locals.rs118
-rw-r--r--tests/ui/async-await/async-fn-size-uninit-locals.rs102
-rw-r--r--tests/ui/async-await/async-fn-size.rs105
-rw-r--r--tests/ui/async-await/async-is-unwindsafe.rs30
-rw-r--r--tests/ui/async-await/async-is-unwindsafe.stderr38
-rw-r--r--tests/ui/async-await/async-matches-expr.rs10
-rw-r--r--tests/ui/async-await/async-trait-fn.rs11
-rw-r--r--tests/ui/async-await/async-trait-fn.stderr42
-rw-r--r--tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr35
-rw-r--r--tests/ui/async-await/async-unsafe-fn-call-in-safe.rs25
-rw-r--r--tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr19
-rw-r--r--tests/ui/async-await/async-with-closure.rs24
-rw-r--r--tests/ui/async-await/auxiliary/arc_wake.rs64
-rw-r--r--tests/ui/async-await/auxiliary/issue-107036.rs12
-rw-r--r--tests/ui/async-await/auxiliary/issue-72470-lib.rs175
-rw-r--r--tests/ui/async-await/await-into-future.rs28
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs38
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr97
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.fixed27
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.rs27
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.stderr61
-rw-r--r--tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs24
-rw-r--r--tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr81
-rw-r--r--tests/ui/async-await/await-keyword/2018-edition-error.rs16
-rw-r--r--tests/ui/async-await/await-keyword/2018-edition-error.stderr63
-rw-r--r--tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs132
-rw-r--r--tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr230
-rw-r--r--tests/ui/async-await/await-keyword/post_expansion_error.rs10
-rw-r--r--tests/ui/async-await/await-keyword/post_expansion_error.stderr8
-rw-r--r--tests/ui/async-await/await-sequence.rs21
-rw-r--r--tests/ui/async-await/await-unsize.rs14
-rw-r--r--tests/ui/async-await/bound-normalization.rs14
-rw-r--r--tests/ui/async-await/conditional-and-guaranteed-initialization.rs16
-rw-r--r--tests/ui/async-await/default-struct-update.rs22
-rw-r--r--tests/ui/async-await/dont-print-desugared-async.rs8
-rw-r--r--tests/ui/async-await/dont-print-desugared-async.stderr9
-rw-r--r--tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs24
-rw-r--r--tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr9
-rw-r--r--tests/ui/async-await/dont-suggest-missing-await.rs19
-rw-r--r--tests/ui/async-await/dont-suggest-missing-await.stderr28
-rw-r--r--tests/ui/async-await/drop-and-assign.rs19
-rw-r--r--tests/ui/async-await/drop-order/auxiliary/arc_wake.rs64
-rw-r--r--tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs270
-rw-r--r--tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs265
-rw-r--r--tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs176
-rw-r--r--tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs98
-rw-r--r--tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs13
-rw-r--r--tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr27
-rw-r--r--tests/ui/async-await/drop-order/drop-order-when-cancelled.rs309
-rw-r--r--tests/ui/async-await/drop-track-bad-field-in-fru.rs10
-rw-r--r--tests/ui/async-await/drop-track-bad-field-in-fru.stderr23
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.rs45
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.stderr25
-rw-r--r--tests/ui/async-await/drop-track-field-assign.rs44
-rw-r--r--tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs106
-rw-r--r--tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr62
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.rs38
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.stderr98
-rw-r--r--tests/ui/async-await/expansion-in-attrs.rs13
-rw-r--r--tests/ui/async-await/feature-async-closure.rs8
-rw-r--r--tests/ui/async-await/feature-async-closure.stderr13
-rw-r--r--tests/ui/async-await/feature-gate-async_fn_in_trait.rs25
-rw-r--r--tests/ui/async-await/feature-gate-async_fn_in_trait.stderr42
-rw-r--r--tests/ui/async-await/feature-self-return-type.rs28
-rw-r--r--tests/ui/async-await/feature-self-return-type.stderr15
-rw-r--r--tests/ui/async-await/futures-api.rs61
-rw-r--r--tests/ui/async-await/generator-desc.rs16
-rw-r--r--tests/ui/async-await/generator-desc.stderr63
-rw-r--r--tests/ui/async-await/generator-not-future.rs45
-rw-r--r--tests/ui/async-await/generator-not-future.stderr81
-rw-r--r--tests/ui/async-await/generics-and-bounds.rs88
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types.rs24
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types2.rs30
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr17
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-extra.rs37
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.rs29
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared.rs20
-rw-r--r--tests/ui/async-await/in-trait/async-example.rs32
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics.rs18
-rw-r--r--tests/ui/async-await/in-trait/async-generics.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs19
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes.rs17
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.stderr12
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.rs21
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.stderr12
-rw-r--r--tests/ui/async-await/in-trait/bad-signatures.rs16
-rw-r--r--tests/ui/async-await/in-trait/bad-signatures.stderr26
-rw-r--r--tests/ui/async-await/in-trait/early-bound-1.rs17
-rw-r--r--tests/ui/async-await/in-trait/early-bound-2.rs15
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err.rs17
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err.stderr11
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.rs19
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.stderr12
-rw-r--r--tests/ui/async-await/in-trait/implied-bounds.rs13
-rw-r--r--tests/ui/async-await/in-trait/issue-102138.rs46
-rw-r--r--tests/ui/async-await/in-trait/issue-102219.rs10
-rw-r--r--tests/ui/async-await/in-trait/issue-102310.rs15
-rw-r--r--tests/ui/async-await/in-trait/issue-104678.rs31
-rw-r--r--tests/ui/async-await/in-trait/lifetime-mismatch.rs20
-rw-r--r--tests/ui/async-await/in-trait/lifetime-mismatch.stderr21
-rw-r--r--tests/ui/async-await/in-trait/missing-send-bound.rs21
-rw-r--r--tests/ui/async-await/in-trait/missing-send-bound.stderr29
-rw-r--r--tests/ui/async-await/in-trait/nested-rpit.rs19
-rw-r--r--tests/ui/async-await/in-trait/object-safety.rs13
-rw-r--r--tests/ui/async-await/in-trait/object-safety.stderr27
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.rs14
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.stderr23
-rw-r--r--tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed8
-rw-r--r--tests/ui/async-await/incorrect-move-async-order-issue-79694.rs8
-rw-r--r--tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr13
-rw-r--r--tests/ui/async-await/interior-with-const-generic-expr.rs26
-rw-r--r--tests/ui/async-await/issue-101715.rs17
-rw-r--r--tests/ui/async-await/issue-101715.stderr16
-rw-r--r--tests/ui/async-await/issue-105501.rs165
-rw-r--r--tests/ui/async-await/issue-107036.rs14
-rw-r--r--tests/ui/async-await/issue-54239-private-type-triggers-lint.rs17
-rw-r--r--tests/ui/async-await/issue-60709.rs28
-rw-r--r--tests/ui/async-await/issue-61076.rs97
-rw-r--r--tests/ui/async-await/issue-61076.stderr82
-rw-r--r--tests/ui/async-await/issue-61452.rs13
-rw-r--r--tests/ui/async-await/issue-61452.stderr26
-rw-r--r--tests/ui/async-await/issue-61793.rs16
-rw-r--r--tests/ui/async-await/issue-61949-self-return-type.rs28
-rw-r--r--tests/ui/async-await/issue-61949-self-return-type.stderr25
-rw-r--r--tests/ui/async-await/issue-62658.rs27
-rw-r--r--tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs19
-rw-r--r--tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs12
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.rs23
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.stderr24
-rw-r--r--tests/ui/async-await/issue-64130-2-send.rs23
-rw-r--r--tests/ui/async-await/issue-64130-2-send.stderr24
-rw-r--r--tests/ui/async-await/issue-64130-3-other.rs26
-rw-r--r--tests/ui/async-await/issue-64130-3-other.stderr27
-rw-r--r--tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr26
-rw-r--r--tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr26
-rw-r--r--tests/ui/async-await/issue-64130-4-async-move.rs32
-rw-r--r--tests/ui/async-await/issue-64130-non-send-future-diags.rs25
-rw-r--r--tests/ui/async-await/issue-64130-non-send-future-diags.stderr24
-rw-r--r--tests/ui/async-await/issue-64391.rs14
-rw-r--r--tests/ui/async-await/issue-66312.rs14
-rw-r--r--tests/ui/async-await/issue-66312.stderr12
-rw-r--r--tests/ui/async-await/issue-66387-if-without-else.rs10
-rw-r--r--tests/ui/async-await/issue-66387-if-without-else.stderr14
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.rs24
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.stderr28
-rw-r--r--tests/ui/async-await/issue-67651.rs20
-rw-r--r--tests/ui/async-await/issue-67651.stderr12
-rw-r--r--tests/ui/async-await/issue-67765-async-diagnostic.rs16
-rw-r--r--tests/ui/async-await/issue-67765-async-diagnostic.stderr12
-rw-r--r--tests/ui/async-await/issue-68112.drop_tracking.stderr79
-rw-r--r--tests/ui/async-await/issue-68112.no_drop_tracking.stderr79
-rw-r--r--tests/ui/async-await/issue-68112.rs69
-rw-r--r--tests/ui/async-await/issue-68523-start.rs9
-rw-r--r--tests/ui/async-await/issue-68523-start.stderr9
-rw-r--r--tests/ui/async-await/issue-68523.rs6
-rw-r--r--tests/ui/async-await/issue-68523.stderr9
-rw-r--r--tests/ui/async-await/issue-69446-fnmut-capture.rs22
-rw-r--r--tests/ui/async-await/issue-69446-fnmut-capture.stderr19
-rw-r--r--tests/ui/async-await/issue-70594.rs11
-rw-r--r--tests/ui/async-await/issue-70594.stderr37
-rw-r--r--tests/ui/async-await/issue-70818.rs9
-rw-r--r--tests/ui/async-await/issue-70818.stderr18
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr34
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr21
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.rs29
-rw-r--r--tests/ui/async-await/issue-71137.rs23
-rw-r--r--tests/ui/async-await/issue-71137.stderr25
-rw-r--r--tests/ui/async-await/issue-72442.rs26
-rw-r--r--tests/ui/async-await/issue-72442.stderr14
-rw-r--r--tests/ui/async-await/issue-72470-llvm-dominate.rs66
-rw-r--r--tests/ui/async-await/issue-72590-type-error-sized.rs22
-rw-r--r--tests/ui/async-await/issue-72590-type-error-sized.stderr34
-rw-r--r--tests/ui/async-await/issue-73050.rs12
-rw-r--r--tests/ui/async-await/issue-73137.rs44
-rw-r--r--tests/ui/async-await/issue-73541-1.rs12
-rw-r--r--tests/ui/async-await/issue-73541-1.stderr14
-rw-r--r--tests/ui/async-await/issue-73541-2.rs20
-rw-r--r--tests/ui/async-await/issue-73541-2.stderr18
-rw-r--r--tests/ui/async-await/issue-73541-3.rs9
-rw-r--r--tests/ui/async-await/issue-73541-3.stderr12
-rw-r--r--tests/ui/async-await/issue-73541.rs9
-rw-r--r--tests/ui/async-await/issue-73541.stderr14
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.rs14
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr11
-rw-r--r--tests/ui/async-await/issue-73741-type-err.rs14
-rw-r--r--tests/ui/async-await/issue-73741-type-err.stderr11
-rw-r--r--tests/ui/async-await/issue-74047.rs17
-rw-r--r--tests/ui/async-await/issue-74047.stderr12
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.rs37
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr51
-rw-r--r--tests/ui/async-await/issue-74497-lifetime-in-opaque.rs19
-rw-r--r--tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr11
-rw-r--r--tests/ui/async-await/issue-75785-confusing-named-region.rs13
-rw-r--r--tests/ui/async-await/issue-75785-confusing-named-region.stderr15
-rw-r--r--tests/ui/async-await/issue-76547.rs38
-rw-r--r--tests/ui/async-await/issue-76547.stderr32
-rw-r--r--tests/ui/async-await/issue-77993-2.rs9
-rw-r--r--tests/ui/async-await/issue-77993-2.stderr8
-rw-r--r--tests/ui/async-await/issue-84841.rs16
-rw-r--r--tests/ui/async-await/issue-84841.stderr26
-rw-r--r--tests/ui/async-await/issue-86507.rs25
-rw-r--r--tests/ui/async-await/issue-86507.stderr23
-rw-r--r--tests/ui/async-await/issue-93197.rs16
-rw-r--r--tests/ui/async-await/issue-93648.rs12
-rw-r--r--tests/ui/async-await/issue-98634.rs50
-rw-r--r--tests/ui/async-await/issue-98634.stderr60
-rw-r--r--tests/ui/async-await/issues/auxiliary/issue-60674.rs12
-rw-r--r--tests/ui/async-await/issues/auxiliary/issue_67893.rs10
-rw-r--r--tests/ui/async-await/issues/issue-102206.rs8
-rw-r--r--tests/ui/async-await/issues/issue-102206.stderr23
-rw-r--r--tests/ui/async-await/issues/issue-51719.rs12
-rw-r--r--tests/ui/async-await/issues/issue-51719.stderr11
-rw-r--r--tests/ui/async-await/issues/issue-51751.rs11
-rw-r--r--tests/ui/async-await/issues/issue-51751.stderr12
-rw-r--r--tests/ui/async-await/issues/issue-53249.rs47
-rw-r--r--tests/ui/async-await/issues/issue-54752-async-block.rs7
-rw-r--r--tests/ui/async-await/issues/issue-54752-async-block.stderr15
-rw-r--r--tests/ui/async-await/issues/issue-54974.rs14
-rw-r--r--tests/ui/async-await/issues/issue-55324.rs11
-rw-r--r--tests/ui/async-await/issues/issue-55809.rs28
-rw-r--r--tests/ui/async-await/issues/issue-58885.rs19
-rw-r--r--tests/ui/async-await/issues/issue-59001.rs14
-rw-r--r--tests/ui/async-await/issues/issue-59972.rs34
-rw-r--r--tests/ui/async-await/issues/issue-60518.rs10
-rw-r--r--tests/ui/async-await/issues/issue-60655-latebound-regions.rs30
-rw-r--r--tests/ui/async-await/issues/issue-60674.rs19
-rw-r--r--tests/ui/async-await/issues/issue-60674.stdout3
-rw-r--r--tests/ui/async-await/issues/issue-61187.rs7
-rw-r--r--tests/ui/async-await/issues/issue-61187.stderr14
-rw-r--r--tests/ui/async-await/issues/issue-61986.rs19
-rw-r--r--tests/ui/async-await/issues/issue-62009-1.rs15
-rw-r--r--tests/ui/async-await/issues/issue-62009-1.stderr43
-rw-r--r--tests/ui/async-await/issues/issue-62009-2.rs10
-rw-r--r--tests/ui/async-await/issues/issue-62009-2.stderr11
-rw-r--r--tests/ui/async-await/issues/issue-62097.rs21
-rw-r--r--tests/ui/async-await/issues/issue-62097.stderr36
-rw-r--r--tests/ui/async-await/issues/issue-62517-1.rs21
-rw-r--r--tests/ui/async-await/issues/issue-62517-2.rs16
-rw-r--r--tests/ui/async-await/issues/issue-63388-1.rs19
-rw-r--r--tests/ui/async-await/issues/issue-63388-1.stderr15
-rw-r--r--tests/ui/async-await/issues/issue-63388-2.rs19
-rw-r--r--tests/ui/async-await/issues/issue-63388-2.stderr30
-rw-r--r--tests/ui/async-await/issues/issue-63388-3.rs17
-rw-r--r--tests/ui/async-await/issues/issue-63388-4.rs10
-rw-r--r--tests/ui/async-await/issues/issue-64391-2.rs20
-rw-r--r--tests/ui/async-await/issues/issue-64433.rs30
-rw-r--r--tests/ui/async-await/issues/issue-64477-2.rs22
-rw-r--r--tests/ui/async-await/issues/issue-64477.rs20
-rw-r--r--tests/ui/async-await/issues/issue-64964.rs23
-rw-r--r--tests/ui/async-await/issues/issue-65159.rs11
-rw-r--r--tests/ui/async-await/issues/issue-65159.stderr16
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs46
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs52
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs25
-rw-r--r--tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr32
-rw-r--r--tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs20
-rw-r--r--tests/ui/async-await/issues/issue-66695-static-refs.rs24
-rw-r--r--tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs15
-rw-r--r--tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr13
-rw-r--r--tests/ui/async-await/issues/issue-67611-static-mut-refs.rs33
-rw-r--r--tests/ui/async-await/issues/issue-67893.rs11
-rw-r--r--tests/ui/async-await/issues/issue-67893.stderr23
-rw-r--r--tests/ui/async-await/issues/issue-69307-nested.rs30
-rw-r--r--tests/ui/async-await/issues/issue-69307.rs23
-rw-r--r--tests/ui/async-await/issues/issue-72312.rs21
-rw-r--r--tests/ui/async-await/issues/issue-72312.stderr23
-rw-r--r--tests/ui/async-await/issues/issue-78600.rs12
-rw-r--r--tests/ui/async-await/issues/issue-78600.stderr14
-rw-r--r--tests/ui/async-await/issues/issue-78654.full.stderr19
-rw-r--r--tests/ui/async-await/issues/issue-78654.min.stderr19
-rw-r--r--tests/ui/async-await/issues/issue-78654.rs15
-rw-r--r--tests/ui/async-await/issues/issue-78938-async-block.rs33
-rw-r--r--tests/ui/async-await/issues/issue-78938-async-block.stderr19
-rw-r--r--tests/ui/async-await/issues/issue-95307.rs13
-rw-r--r--tests/ui/async-await/issues/issue-95307.stderr32
-rw-r--r--tests/ui/async-await/issues/non-async-enclosing-span.rs11
-rw-r--r--tests/ui/async-await/issues/non-async-enclosing-span.stderr12
-rw-r--r--tests/ui/async-await/large_moves.attribute.stderr45
-rw-r--r--tests/ui/async-await/large_moves.option.stderr45
-rw-r--r--tests/ui/async-await/large_moves.rs27
-rw-r--r--tests/ui/async-await/move-part-await-return-rest-struct.rs18
-rw-r--r--tests/ui/async-await/move-part-await-return-rest-tuple.rs12
-rw-r--r--tests/ui/async-await/multiple-lifetimes/elided.rs10
-rw-r--r--tests/ui/async-await/multiple-lifetimes/fn-ptr.rs12
-rw-r--r--tests/ui/async-await/multiple-lifetimes/hrtb.rs14
-rw-r--r--tests/ui/async-await/multiple-lifetimes/named.rs10
-rw-r--r--tests/ui/async-await/multiple-lifetimes/partial-relation.rs13
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs17
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs31
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr35
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-ref.rs44
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-ref.stderr37
-rw-r--r--tests/ui/async-await/multiple-lifetimes/variance.rs15
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs13
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr21
-rw-r--r--tests/ui/async-await/nested-in-impl.rs15
-rw-r--r--tests/ui/async-await/no-async-const.rs5
-rw-r--r--tests/ui/async-await/no-async-const.stderr13
-rw-r--r--tests/ui/async-await/no-const-async.rs6
-rw-r--r--tests/ui/async-await/no-const-async.stderr42
-rw-r--r--tests/ui/async-await/no-move-across-await-struct.rs16
-rw-r--r--tests/ui/async-await/no-move-across-await-struct.stderr13
-rw-r--r--tests/ui/async-await/no-move-across-await-tuple.rs12
-rw-r--r--tests/ui/async-await/no-move-across-await-tuple.stderr14
-rw-r--r--tests/ui/async-await/no-non-guaranteed-initialization.rs12
-rw-r--r--tests/ui/async-await/no-non-guaranteed-initialization.stderr16
-rw-r--r--tests/ui/async-await/no-params-non-move-async-closure.rs8
-rw-r--r--tests/ui/async-await/no-params-non-move-async-closure.stderr11
-rw-r--r--tests/ui/async-await/no-std.rs13
-rw-r--r--tests/ui/async-await/no-unsafe-async.rs11
-rw-r--r--tests/ui/async-await/no-unsafe-async.stderr29
-rw-r--r--tests/ui/async-await/non-trivial-drop.rs36
-rw-r--r--tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr35
-rw-r--r--tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr35
-rw-r--r--tests/ui/async-await/partial-drop-partial-reinit.rs40
-rw-r--r--tests/ui/async-await/partial-initialization-across-await.rs39
-rw-r--r--tests/ui/async-await/partial-initialization-across-await.stderr33
-rw-r--r--tests/ui/async-await/pin-needed-to-poll-2.rs48
-rw-r--r--tests/ui/async-await/pin-needed-to-poll-2.stderr20
-rw-r--r--tests/ui/async-await/pin-needed-to-poll.rs47
-rw-r--r--tests/ui/async-await/pin-needed-to-poll.stderr20
-rw-r--r--tests/ui/async-await/proper-span-for-type-error.fixed12
-rw-r--r--tests/ui/async-await/proper-span-for-type-error.rs11
-rw-r--r--tests/ui/async-await/proper-span-for-type-error.stderr17
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.rs10
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.stderr12
-rw-r--r--tests/ui/async-await/repeat_count_const_in_async_fn.rs10
-rw-r--r--tests/ui/async-await/return-ty-raw-ptr-coercion.rs25
-rw-r--r--tests/ui/async-await/return-ty-unsize-coercion.rs45
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.fixed23
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.rs23
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.stderr28
-rw-r--r--tests/ui/async-await/suggest-missing-await.rs74
-rw-r--r--tests/ui/async-await/suggest-missing-await.stderr167
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs47
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr43
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await.rs45
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await.stderr43
-rw-r--r--tests/ui/async-await/track-caller/async-block.rs9
-rw-r--r--tests/ui/async-await/track-caller/async-block.stderr12
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.rs9
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.stderr12
-rw-r--r--tests/ui/async-await/track-caller/issue-105134.rs11
-rw-r--r--tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr29
-rw-r--r--tests/ui/async-await/track-caller/panic-track-caller.rs113
-rw-r--r--tests/ui/async-await/try-on-option-in-async.rs28
-rw-r--r--tests/ui/async-await/try-on-option-in-async.stderr44
-rw-r--r--tests/ui/async-await/type-parameter-send.rs18
-rw-r--r--tests/ui/async-await/unnecessary-await.rs14
-rw-r--r--tests/ui/async-await/unnecessary-await.stderr24
-rw-r--r--tests/ui/async-await/unreachable-lint-1.rs12
-rw-r--r--tests/ui/async-await/unreachable-lint-1.stderr16
-rw-r--r--tests/ui/async-await/unreachable-lint.rs13
-rw-r--r--tests/ui/async-await/unresolved_type_param.rs24
-rw-r--r--tests/ui/async-await/unresolved_type_param.stderr39
-rw-r--r--tests/ui/async-await/unused-lifetime.rs39
-rw-r--r--tests/ui/async-await/unused-lifetime.stderr48
388 files changed, 12152 insertions, 0 deletions
diff --git a/tests/ui/async-await/argument-patterns.rs b/tests/ui/async-await/argument-patterns.rs
new file mode 100644
index 000000000..b9fc1a88c
--- /dev/null
+++ b/tests/ui/async-await/argument-patterns.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// check-pass
+
+#![deny(unused_mut)]
+
+type A = Vec<u32>;
+
+async fn a(n: u32, mut vec: A) {
+ vec.push(n);
+}
+
+async fn b(n: u32, ref mut vec: A) {
+ vec.push(n);
+}
+
+async fn c(ref vec: A) {
+ vec.contains(&0);
+}
+
+async fn d((a, mut b): (A, A)) {
+ b.push(1);
+}
+
+async fn f((ref mut a, ref b): (A, A)) {}
+
+async fn g(((ref a, ref mut b), (ref mut c, ref d)): ((A, A), (A, A))) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs b/tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs
new file mode 100644
index 000000000..8e08b82b9
--- /dev/null
+++ b/tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs
@@ -0,0 +1,23 @@
+// check-pass
+// Check that the anonymous lifetimes used here aren't considered to shadow one
+// another. Note that `async fn` is different to `fn` here because the lifetimes
+// are numbered by HIR lowering, rather than lifetime resolution.
+
+// edition:2018
+
+struct A<'a, 'b>(&'a &'b i32);
+struct B<'a>(&'a i32);
+
+impl A<'_, '_> {
+ async fn assoc(x: &u32, y: B<'_>) {
+ async fn nested(x: &u32, y: A<'_, '_>) {}
+ }
+
+ async fn assoc2(x: &u32, y: A<'_, '_>) {
+ impl A<'_, '_> {
+ async fn nested_assoc(x: &u32, y: B<'_>) {}
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-await-let-else.drop-tracking.stderr b/tests/ui/async-await/async-await-let-else.drop-tracking.stderr
new file mode 100644
index 000000000..fb83ca90a
--- /dev/null
+++ b/tests/ui/async-await/async-await-let-else.drop-tracking.stderr
@@ -0,0 +1,106 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:48:13
+ |
+LL | is_send(foo(Some(true)));
+ | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:11:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await
+ | ^^^^^^ await occurs here, with `r` maybe used later
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `Rc<()>` cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:50:13
+ |
+LL | async fn foo2(x: Option<bool>) {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_send(foo2(Some(true)));
+ | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: required because it's used within this `async fn` body
+ --> $DIR/async-await-let-else.rs:27:29
+ |
+LL | async fn bar2<T>(_: T) -> ! {
+ | _____________________________^
+LL | | panic!()
+LL | | }
+ | |_^
+ = note: required because it captures the following types: `ResumeTy`, `Option<bool>`, `impl Future<Output = !>`, `()`
+note: required because it's used within this `async fn` body
+ --> $DIR/async-await-let-else.rs:21:32
+ |
+LL | async fn foo2(x: Option<bool>) {
+ | ________________________________^
+LL | | let Some(_) = x else {
+LL | | bar2(Rc::new(())).await
+LL | | };
+LL | | }
+ | |_^
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:52:13
+ |
+LL | is_send(foo3(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:33:28
+ |
+LL | (Rc::new(()), bar().await);
+ | ----------- ^^^^^^ - `Rc::new(())` is later dropped here
+ | | |
+ | | await occurs here, with `Rc::new(())` maybe used later
+ | has type `Rc<()>` which is not `Send`
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:54:13
+ |
+LL | is_send(foo4(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:41:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await;
+ | ^^^^^^ await occurs here, with `r` maybe used later
+...
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr b/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr
new file mode 100644
index 000000000..d3c5e80a3
--- /dev/null
+++ b/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr
@@ -0,0 +1,90 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:48:13
+ |
+LL | is_send(foo(Some(true)));
+ | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:11:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await
+ | ^^^^^^ await occurs here, with `r` maybe used later
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:50:13
+ |
+LL | is_send(foo2(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:23:26
+ |
+LL | bar2(Rc::new(())).await
+ | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
+ | |
+ | has type `Rc<()>` which is not `Send`
+LL | };
+ | - `Rc::new(())` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:52:13
+ |
+LL | is_send(foo3(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:33:28
+ |
+LL | (Rc::new(()), bar().await);
+ | ----------- ^^^^^^ - `Rc::new(())` is later dropped here
+ | | |
+ | | await occurs here, with `Rc::new(())` maybe used later
+ | has type `Rc<()>` which is not `Send`
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:54:13
+ |
+LL | is_send(foo4(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:41:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await;
+ | ^^^^^^ await occurs here, with `r` maybe used later
+...
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/async-await/async-await-let-else.rs b/tests/ui/async-await/async-await-let-else.rs
new file mode 100644
index 000000000..3fb2142b9
--- /dev/null
+++ b/tests/ui/async-await/async-await-let-else.rs
@@ -0,0 +1,56 @@
+// edition:2021
+// revisions: drop-tracking no-drop-tracking
+// [drop-tracking] compile-flags: -Zdrop-tracking=yes
+// [no-drop-tracking] compile-flags: -Zdrop-tracking=no
+
+use std::rc::Rc;
+
+async fn foo(x: Option<bool>) {
+ let Some(_) = x else {
+ let r = Rc::new(());
+ bar().await
+ };
+}
+
+async fn bar() -> ! {
+ panic!()
+}
+
+fn is_send<T: Send>(_: T) {}
+
+async fn foo2(x: Option<bool>) {
+ let Some(_) = x else {
+ bar2(Rc::new(())).await
+ };
+}
+
+async fn bar2<T>(_: T) -> ! {
+ panic!()
+}
+
+async fn foo3(x: Option<bool>) {
+ let Some(_) = x else {
+ (Rc::new(()), bar().await);
+ return;
+ };
+}
+
+async fn foo4(x: Option<bool>) {
+ let Some(_) = x else {
+ let r = Rc::new(());
+ bar().await;
+ println!("{:?}", r);
+ return;
+ };
+}
+
+fn main() {
+ is_send(foo(Some(true)));
+ //~^ ERROR cannot be sent between threads safely
+ is_send(foo2(Some(true)));
+ //~^ ERROR cannot be sent between threads safely
+ is_send(foo3(Some(true)));
+ //~^ ERROR cannot be sent between threads safely
+ is_send(foo4(Some(true)));
+ //~^ ERROR cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/async-await.rs b/tests/ui/async-await/async-await.rs
new file mode 100644
index 000000000..9cabf16f8
--- /dev/null
+++ b/tests/ui/async-await/async-await.rs
@@ -0,0 +1,219 @@
+// run-pass
+
+// revisions: default nomiropt thirunsafeck
+//[nomiropt]compile-flags: -Z mir-opt-level=0
+//[thirunsafeck]compile-flags: -Zthir-unsafeck
+
+#![allow(unused)]
+
+// edition: 2018
+// aux-build:arc_wake.rs
+
+extern crate arc_wake;
+
+use std::pin::Pin;
+use std::future::Future;
+use std::sync::{
+ Arc,
+ atomic::{self, AtomicUsize},
+};
+use std::task::{Context, Poll};
+use arc_wake::ArcWake;
+
+struct Counter {
+ wakes: AtomicUsize,
+}
+
+impl ArcWake for Counter {
+ fn wake(self: Arc<Self>) {
+ Self::wake_by_ref(&self)
+ }
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+ }
+}
+
+struct WakeOnceThenComplete(bool);
+
+fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
+
+impl Future for WakeOnceThenComplete {
+ type Output = ();
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+ if self.0 {
+ Poll::Ready(())
+ } else {
+ cx.waker().wake_by_ref();
+ self.0 = true;
+ Poll::Pending
+ }
+ }
+}
+
+fn async_block(x: u8) -> impl Future<Output = u8> {
+ async move {
+ wake_and_yield_once().await;
+ x
+ }
+}
+
+fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
+ async move {
+ wake_and_yield_once().await;
+ *x
+ }
+}
+
+fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
+ async move {
+ let future = async {
+ wake_and_yield_once().await;
+ x
+ };
+ future.await
+ }
+}
+
+// see async-closure.rs for async_closure + async_closure_in_unsafe_block
+
+async fn async_fn(x: u8) -> u8 {
+ wake_and_yield_once().await;
+ x
+}
+
+async fn generic_async_fn<T>(x: T) -> T {
+ wake_and_yield_once().await;
+ x
+}
+
+async fn async_fn_with_borrow(x: &u8) -> u8 {
+ wake_and_yield_once().await;
+ *x
+}
+
+async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 {
+ wake_and_yield_once().await;
+ *x
+}
+
+fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
+ async move {
+ wake_and_yield_once().await;
+ *x
+ }
+}
+
+async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 {
+ wake_and_yield_once().await;
+ *x
+}
+
+async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 {
+ wake_and_yield_once().await;
+ *x
+}
+
+fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
+ async move {
+ async_fn_with_borrow_named_lifetime(&y).await
+ }
+}
+
+async unsafe fn unsafe_async_fn(x: u8) -> u8 {
+ wake_and_yield_once().await;
+ x
+}
+
+unsafe fn unsafe_fn(x: u8) -> u8 {
+ x
+}
+
+fn async_block_in_unsafe_block(x: u8) -> impl Future<Output = u8> {
+ unsafe {
+ async move {
+ unsafe_fn(unsafe_async_fn(x).await)
+ }
+ }
+}
+
+struct Foo;
+
+trait Bar {
+ fn foo() {}
+}
+
+impl Foo {
+ async fn async_assoc_item(x: u8) -> u8 {
+ unsafe {
+ unsafe_async_fn(x).await
+ }
+ }
+
+ async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 {
+ unsafe_async_fn(x).await
+ }
+}
+
+fn test_future_yields_once_then_returns<F, Fut>(f: F)
+where
+ F: FnOnce(u8) -> Fut,
+ Fut: Future<Output = u8>,
+{
+ let mut fut = Box::pin(f(9));
+ let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
+ let waker = ArcWake::into_waker(counter.clone());
+ let mut cx = Context::from_waker(&waker);
+ assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx));
+ assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx));
+}
+
+fn main() {
+ macro_rules! test {
+ ($($fn_name:expr,)*) => { $(
+ test_future_yields_once_then_returns($fn_name);
+ )* }
+ }
+
+ macro_rules! test_with_borrow {
+ ($($fn_name:expr,)*) => { $(
+ test_future_yields_once_then_returns(|x| {
+ async move {
+ $fn_name(&x).await
+ }
+ });
+ )* }
+ }
+
+ test! {
+ async_block,
+ async_nonmove_block,
+ async_fn,
+ generic_async_fn,
+ async_fn_with_internal_borrow,
+ async_block_in_unsafe_block,
+ Foo::async_assoc_item,
+ |x| {
+ async move {
+ unsafe { unsafe_async_fn(x).await }
+ }
+ },
+ |x| {
+ async move {
+ unsafe { Foo::async_unsafe_assoc_item(x).await }
+ }
+ },
+ }
+ test_with_borrow! {
+ async_block_with_borrow_named_lifetime,
+ async_fn_with_borrow,
+ async_fn_with_borrow_named_lifetime,
+ async_fn_with_impl_future_named_lifetime,
+ |x| {
+ async move {
+ async_fn_multiple_args_named_lifetime(x, x).await
+ }
+ },
+ }
+}
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.rs b/tests/ui/async-await/async-block-control-flow-static-semantics.rs
new file mode 100644
index 000000000..bc9d12793
--- /dev/null
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.rs
@@ -0,0 +1,65 @@
+// Test that `async { .. }` blocks:
+// 1. do not allow `break` expressions.
+// 2. get targeted by `return` and not the parent function.
+// 3. get targeted by `?` and not the parent function.
+//
+// edition:2018
+
+fn main() {}
+
+use core::future::Future;
+
+fn return_targets_async_block_not_fn() -> u8 {
+ //~^ ERROR mismatched types
+ let block = async {
+ return 0u8;
+ };
+ let _: &dyn Future<Output = ()> = &block;
+ //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8`
+}
+
+async fn return_targets_async_block_not_async_fn() -> u8 {
+ //~^ ERROR mismatched types [E0308]
+ let block = async {
+ return 0u8;
+ };
+ let _: &dyn Future<Output = ()> = &block;
+ //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8`
+}
+
+fn no_break_in_async_block() {
+ async {
+ break 0u8; //~ ERROR `break` inside of an `async` block
+ };
+}
+
+fn no_break_in_async_block_even_with_outer_loop() {
+ loop {
+ async {
+ break 0u8; //~ ERROR `break` inside of an `async` block
+ };
+ }
+}
+
+struct MyErr;
+fn err() -> Result<u8, MyErr> {
+ Err(MyErr)
+}
+
+fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
+ //~^ ERROR mismatched types
+ let block = async {
+ err()?;
+ Ok(())
+ };
+ let _: &dyn Future<Output = Result<(), MyErr>> = &block;
+}
+
+fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
+ //~^ ERROR mismatched types
+ let block = async {
+ err()?;
+ Ok(())
+ };
+ let _: &dyn Future<Output = Result<(), MyErr>> = &block;
+}
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
new file mode 100644
index 000000000..c4487eb84
--- /dev/null
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -0,0 +1,81 @@
+error[E0267]: `break` inside of an `async` block
+ --> $DIR/async-block-control-flow-static-semantics.rs:32:9
+ |
+LL | / async {
+LL | | break 0u8;
+ | | ^^^^^^^^^ cannot `break` inside of an `async` block
+LL | | };
+ | |_____- enclosing `async` block
+
+error[E0267]: `break` inside of an `async` block
+ --> $DIR/async-block-control-flow-static-semantics.rs:39:13
+ |
+LL | / async {
+LL | | break 0u8;
+ | | ^^^^^^^^^ cannot `break` inside of an `async` block
+LL | | };
+ | |_________- enclosing `async` block
+
+error[E0308]: mismatched types
+ --> $DIR/async-block-control-flow-static-semantics.rs:21:58
+ |
+LL | async fn return_targets_async_block_not_async_fn() -> u8 {
+ | __________________________________________________________^
+LL | |
+LL | | let block = async {
+LL | | return 0u8;
+... |
+LL | |
+LL | | }
+ | |_^ expected `u8`, found `()`
+
+error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to be a future that resolves to `()`, but it resolves to `u8`
+ --> $DIR/async-block-control-flow-static-semantics.rs:26:39
+ |
+LL | let _: &dyn Future<Output = ()> = &block;
+ | ^^^^^^ expected `()`, found `u8`
+ |
+ = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future<Output = ()>`
+
+error[E0308]: mismatched types
+ --> $DIR/async-block-control-flow-static-semantics.rs:12:43
+ |
+LL | fn return_targets_async_block_not_fn() -> u8 {
+ | --------------------------------- ^^ expected `u8`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+
+error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to be a future that resolves to `()`, but it resolves to `u8`
+ --> $DIR/async-block-control-flow-static-semantics.rs:17:39
+ |
+LL | let _: &dyn Future<Output = ()> = &block;
+ | ^^^^^^ expected `()`, found `u8`
+ |
+ = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future<Output = ()>`
+
+error[E0308]: mismatched types
+ --> $DIR/async-block-control-flow-static-semantics.rs:49:44
+ |
+LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
+ | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected enum `Result<u8, MyErr>`
+ found unit type `()`
+
+error[E0308]: mismatched types
+ --> $DIR/async-block-control-flow-static-semantics.rs:58:50
+ |
+LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
+ | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected enum `Result<u8, MyErr>`
+ found unit type `()`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0267, E0271, E0308.
+For more information about an error, try `rustc --explain E0267`.
diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.fixed b/tests/ui/async-await/async-borrowck-escaping-block-error.fixed
new file mode 100644
index 000000000..605cfdfe7
--- /dev/null
+++ b/tests/ui/async-await/async-borrowck-escaping-block-error.fixed
@@ -0,0 +1,18 @@
+// edition:2018
+// run-rustfix
+
+fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
+ let x = 0u32;
+ Box::new(async move { x } )
+ //~^ ERROR E0373
+}
+
+fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+ async move { *x }
+ //~^ ERROR E0373
+}
+
+fn main() {
+ let _ = test_boxed();
+ let _ = test_ref(&0u32);
+}
diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.rs b/tests/ui/async-await/async-borrowck-escaping-block-error.rs
new file mode 100644
index 000000000..ec752c15f
--- /dev/null
+++ b/tests/ui/async-await/async-borrowck-escaping-block-error.rs
@@ -0,0 +1,18 @@
+// edition:2018
+// run-rustfix
+
+fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
+ let x = 0u32;
+ Box::new(async { x } )
+ //~^ ERROR E0373
+}
+
+fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+ async { *x }
+ //~^ ERROR E0373
+}
+
+fn main() {
+ let _ = test_boxed();
+ let _ = test_ref(&0u32);
+}
diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.stderr b/tests/ui/async-await/async-borrowck-escaping-block-error.stderr
new file mode 100644
index 000000000..190c59e32
--- /dev/null
+++ b/tests/ui/async-await/async-borrowck-escaping-block-error.stderr
@@ -0,0 +1,41 @@
+error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/async-borrowck-escaping-block-error.rs:6:14
+ |
+LL | Box::new(async { x } )
+ | ^^^^^^^^-^^
+ | | |
+ | | `x` is borrowed here
+ | may outlive borrowed value `x`
+ |
+note: async block is returned here
+ --> $DIR/async-borrowck-escaping-block-error.rs:6:5
+ |
+LL | Box::new(async { x } )
+ | ^^^^^^^^^^^^^^^^^^^^^^
+help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | Box::new(async move { x } )
+ | ++++
+
+error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/async-borrowck-escaping-block-error.rs:11:5
+ |
+LL | async { *x }
+ | ^^^^^^^^--^^
+ | | |
+ | | `x` is borrowed here
+ | may outlive borrowed value `x`
+ |
+note: async block is returned here
+ --> $DIR/async-borrowck-escaping-block-error.rs:11:5
+ |
+LL | async { *x }
+ | ^^^^^^^^^^^^
+help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | async move { *x }
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
new file mode 100644
index 000000000..e667b72ae
--- /dev/null
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
@@ -0,0 +1,10 @@
+// edition:2018
+#![feature(async_closure)]
+fn foo() -> Box<dyn std::future::Future<Output = u32>> {
+ let x = 0u32;
+ Box::new((async || x)())
+ //~^ ERROR E0373
+}
+
+fn main() {
+}
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
new file mode 100644
index 000000000..10691aad0
--- /dev/null
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
@@ -0,0 +1,21 @@
+error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/async-borrowck-escaping-closure-error.rs:5:15
+ |
+LL | Box::new((async || x)())
+ | ^^^^^^^^ - `x` is borrowed here
+ | |
+ | may outlive borrowed value `x`
+ |
+note: closure is returned here
+ --> $DIR/async-borrowck-escaping-closure-error.rs:5:5
+ |
+LL | Box::new((async || x)())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | Box::new((async move || x)())
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/tests/ui/async-await/async-closure-matches-expr.rs b/tests/ui/async-await/async-closure-matches-expr.rs
new file mode 100644
index 000000000..d82fbcdc5
--- /dev/null
+++ b/tests/ui/async-await/async-closure-matches-expr.rs
@@ -0,0 +1,12 @@
+// build-pass
+// edition:2018
+
+#![feature(async_closure)]
+
+macro_rules! match_expr {
+ ($x:expr) => {}
+}
+
+fn main() {
+ match_expr!(async || {});
+}
diff --git a/tests/ui/async-await/async-closure.rs b/tests/ui/async-await/async-closure.rs
new file mode 100644
index 000000000..12d66b19e
--- /dev/null
+++ b/tests/ui/async-await/async-closure.rs
@@ -0,0 +1,100 @@
+// run-pass
+
+// revisions: default nomiropt
+//[nomiropt]compile-flags: -Z mir-opt-level=0
+
+// edition:2018
+// aux-build:arc_wake.rs
+
+#![feature(async_closure)]
+
+extern crate arc_wake;
+
+use std::pin::Pin;
+use std::future::Future;
+use std::sync::{
+ Arc,
+ atomic::{self, AtomicUsize},
+};
+use std::task::{Context, Poll};
+use arc_wake::ArcWake;
+
+struct Counter {
+ wakes: AtomicUsize,
+}
+
+impl ArcWake for Counter {
+ fn wake(self: Arc<Self>) {
+ Self::wake_by_ref(&self)
+ }
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+ }
+}
+
+struct WakeOnceThenComplete(bool);
+
+fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
+
+impl Future for WakeOnceThenComplete {
+ type Output = ();
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+ if self.0 {
+ Poll::Ready(())
+ } else {
+ cx.waker().wake_by_ref();
+ self.0 = true;
+ Poll::Pending
+ }
+ }
+}
+
+fn async_closure(x: u8) -> impl Future<Output = u8> {
+ (async move |x: u8| -> u8 {
+ wake_and_yield_once().await;
+ x
+ })(x)
+}
+
+fn async_closure_in_unsafe_block(x: u8) -> impl Future<Output = u8> {
+ (unsafe {
+ async move |x: u8| unsafe_fn(unsafe_async_fn(x).await)
+ })(x)
+}
+
+async unsafe fn unsafe_async_fn(x: u8) -> u8 {
+ wake_and_yield_once().await;
+ x
+}
+
+unsafe fn unsafe_fn(x: u8) -> u8 {
+ x
+}
+
+fn test_future_yields_once_then_returns<F, Fut>(f: F)
+where
+ F: FnOnce(u8) -> Fut,
+ Fut: Future<Output = u8>,
+{
+ let mut fut = Box::pin(f(9));
+ let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
+ let waker = ArcWake::into_waker(counter.clone());
+ let mut cx = Context::from_waker(&waker);
+ assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx));
+ assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx));
+}
+
+fn main() {
+ macro_rules! test {
+ ($($fn_name:expr,)*) => { $(
+ test_future_yields_once_then_returns($fn_name);
+ )* }
+ }
+
+ test! {
+ async_closure,
+ async_closure_in_unsafe_block,
+ }
+}
diff --git a/tests/ui/async-await/async-error-span.rs b/tests/ui/async-await/async-error-span.rs
new file mode 100644
index 000000000..86d459bf0
--- /dev/null
+++ b/tests/ui/async-await/async-error-span.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+// Regression test for issue #62382.
+
+use std::future::Future;
+
+fn get_future() -> impl Future<Output = ()> {
+//~^ ERROR `()` is not a future
+ panic!()
+}
+
+async fn foo() {
+ let a; //~ ERROR type inside `async fn` body must be known in this context
+ get_future().await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.stderr
new file mode 100644
index 000000000..7d4447b6d
--- /dev/null
+++ b/tests/ui/async-await/async-error-span.stderr
@@ -0,0 +1,25 @@
+error[E0277]: `()` is not a future
+ --> $DIR/async-error-span.rs:7:20
+ |
+LL | fn get_future() -> impl Future<Output = ()> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
+ |
+ = help: the trait `Future` is not implemented for `()`
+ = note: () must be a future or must implement `IntoFuture` to be awaited
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/async-error-span.rs:13:9
+ |
+LL | let a;
+ | ^ cannot infer type
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/async-error-span.rs:14:17
+ |
+LL | get_future().await;
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0698.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs b/tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs
new file mode 100644
index 000000000..1c369fd74
--- /dev/null
+++ b/tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs
@@ -0,0 +1,15 @@
+// Check that `async fn` inside of an impl with `'_`
+// in the header compiles correctly.
+//
+// Regression test for #63500.
+//
+// check-pass
+// edition:2018
+
+struct Foo<'a>(&'a u8);
+
+impl Foo<'_> {
+ async fn bar() {}
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/async-fn-nonsend.rs b/tests/ui/async-await/async-fn-nonsend.rs
new file mode 100644
index 000000000..d7f8d7ac5
--- /dev/null
+++ b/tests/ui/async-await/async-fn-nonsend.rs
@@ -0,0 +1,74 @@
+// edition:2018
+// compile-flags: --crate-type lib -Zdrop-tracking
+
+use std::{cell::RefCell, fmt::Debug, rc::Rc};
+
+fn non_sync() -> impl Debug {
+ RefCell::new(())
+}
+
+fn non_send() -> impl Debug {
+ Rc::new(())
+}
+
+fn take_ref<T>(_: &T) {}
+
+async fn fut() {}
+
+async fn fut_arg<T>(_: T) {}
+
+async fn local_dropped_before_await() {
+ // this is okay now because of the drop
+ let x = non_send();
+ drop(x);
+ fut().await;
+}
+
+async fn non_send_temporary_in_match() {
+ // We could theoretically make this work as well (produce a `Send` future)
+ // for scrutinees / temporaries that can or will
+ // be dropped prior to the match body
+ // (e.g. `Copy` types).
+ match Some(non_send()) {
+ Some(_) => fut().await,
+ None => {}
+ }
+}
+
+fn get_formatter() -> std::fmt::Formatter<'static> {
+ panic!()
+}
+
+async fn non_sync_with_method_call() {
+ let f: &mut std::fmt::Formatter = &mut get_formatter();
+ // It would by nice for this to work.
+ if non_sync().fmt(f).unwrap() == () {
+ fut().await;
+ }
+}
+
+async fn non_sync_with_method_call_panic() {
+ let f: &mut std::fmt::Formatter = panic!();
+ if non_sync().fmt(f).unwrap() == () {
+ fut().await;
+ }
+}
+
+async fn non_sync_with_method_call_infinite_loop() {
+ let f: &mut std::fmt::Formatter = loop {};
+ if non_sync().fmt(f).unwrap() == () {
+ fut().await;
+ }
+}
+
+fn assert_send(_: impl Send) {}
+
+pub fn pass_assert() {
+ assert_send(local_dropped_before_await());
+ assert_send(non_send_temporary_in_match());
+ //~^ ERROR future cannot be sent between threads safely
+ assert_send(non_sync_with_method_call());
+ //~^ ERROR future cannot be sent between threads safely
+ assert_send(non_sync_with_method_call_panic());
+ assert_send(non_sync_with_method_call_infinite_loop());
+}
diff --git a/tests/ui/async-await/async-fn-nonsend.stderr b/tests/ui/async-await/async-fn-nonsend.stderr
new file mode 100644
index 000000000..a7b872fe4
--- /dev/null
+++ b/tests/ui/async-await/async-fn-nonsend.stderr
@@ -0,0 +1,49 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:68:17
+ |
+LL | assert_send(non_send_temporary_in_match());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:33:25
+ |
+LL | match Some(non_send()) {
+ | ---------------- has type `Option<impl Debug>` which is not `Send`
+LL | Some(_) => fut().await,
+ | ^^^^^^ await occurs here, with `Some(non_send())` maybe used later
+...
+LL | }
+ | - `Some(non_send())` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:64:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:70:17
+ |
+LL | assert_send(non_sync_with_method_call());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:46:14
+ |
+LL | let f: &mut std::fmt::Formatter = &mut get_formatter();
+ | --------------- has type `Formatter<'_>` which is not `Send`
+...
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `get_formatter()` maybe used later
+LL | }
+LL | }
+ | - `get_formatter()` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:64:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/async-fn-path-elision.rs b/tests/ui/async-await/async-fn-path-elision.rs
new file mode 100644
index 000000000..3f1f51c20
--- /dev/null
+++ b/tests/ui/async-await/async-fn-path-elision.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+struct HasLifetime<'a>(&'a bool);
+
+async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here
+ if *lt.0 {}
+}
+
+fn no_error(lt: HasLifetime) {
+ if *lt.0 {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn-path-elision.stderr b/tests/ui/async-await/async-fn-path-elision.stderr
new file mode 100644
index 000000000..5e0c8c299
--- /dev/null
+++ b/tests/ui/async-await/async-fn-path-elision.stderr
@@ -0,0 +1,15 @@
+error[E0726]: implicit elided lifetime not allowed here
+ --> $DIR/async-fn-path-elision.rs:5:20
+ |
+LL | async fn error(lt: HasLifetime) {
+ | ^^^^^^^^^^^ expected lifetime parameter
+ |
+ = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+ |
+LL | async fn error(lt: HasLifetime<'_>) {
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0726`.
diff --git a/tests/ui/async-await/async-fn-send-uses-nonsend.rs b/tests/ui/async-await/async-fn-send-uses-nonsend.rs
new file mode 100644
index 000000000..35d9cb155
--- /dev/null
+++ b/tests/ui/async-await/async-fn-send-uses-nonsend.rs
@@ -0,0 +1,57 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+// compile-flags: --crate-type lib
+
+use std::{
+ cell::RefCell,
+ fmt::Debug,
+ rc::Rc,
+};
+
+fn non_sync() -> impl Debug { RefCell::new(()) }
+
+fn non_send() -> impl Debug { Rc::new(()) }
+
+fn take_ref<T>(_: &T) {}
+
+async fn fut() {}
+
+async fn fut_arg<T>(_: T) {}
+
+async fn still_send() {
+ fut().await;
+ println!("{:?} {:?}", non_send(), non_sync());
+ fut().await;
+ drop(non_send());
+ drop(non_sync());
+ fut().await;
+ fut_arg(non_sync()).await;
+
+ // Note: all temporaries in `if let` and `match` scrutinee
+ // are dropped at the *end* of the blocks, so using `non_send()`
+ // in either of those positions with an await in the middle will
+ // cause a `!Send` future. It might be nice in the future to allow
+ // this for `Copy` types, since they can be "dropped" early without
+ // affecting the end user.
+ if let Some(_) = Some(non_sync()) {
+ fut().await;
+ }
+ match Some(non_sync()) {
+ Some(_) => fut().await,
+ None => fut().await,
+ }
+
+ let _ = non_send();
+ fut().await;
+
+ {
+ let _x = non_send();
+ }
+ fut().await;
+}
+
+fn assert_send(_: impl Send) {}
+
+pub fn pass_assert() {
+ assert_send(still_send());
+}
diff --git a/tests/ui/async-await/async-fn-size-moved-locals.rs b/tests/ui/async-await/async-fn-size-moved-locals.rs
new file mode 100644
index 000000000..79b7239f3
--- /dev/null
+++ b/tests/ui/async-await/async-fn-size-moved-locals.rs
@@ -0,0 +1,118 @@
+// Test that we don't duplicate storage for futures moved around in .await, and
+// for futures moved into other futures.
+//
+// The exact sizes can change by a few bytes (we'd like to know when they do).
+// What we don't want to see is the wrong multiple of 1024 (the size of BigFut)
+// being reflected in the size.
+//
+// See issue #59123 for a full explanation.
+
+// needs-unwind Size of Futures change on panic=abort
+// run-pass
+
+// edition:2018
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+const BIG_FUT_SIZE: usize = 1024;
+struct BigFut(#[allow(unused_tuple_struct_fields)] [u8; BIG_FUT_SIZE]);
+
+impl BigFut {
+ fn new() -> Self {
+ BigFut([0; BIG_FUT_SIZE])
+ }
+}
+
+impl Drop for BigFut {
+ fn drop(&mut self) {}
+}
+
+impl Future for BigFut {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+#[allow(dead_code)]
+struct Joiner {
+ a: Option<BigFut>,
+ b: Option<BigFut>,
+ c: Option<BigFut>,
+}
+
+impl Future for Joiner {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+fn noop() {}
+
+async fn single() {
+ let x = BigFut::new();
+ x.await;
+}
+
+async fn single_with_noop() {
+ let x = BigFut::new();
+ noop();
+ x.await;
+}
+
+async fn joined() {
+ let a = BigFut::new();
+ let b = BigFut::new();
+ let c = BigFut::new();
+
+ let joiner = Joiner {
+ a: Some(a),
+ b: Some(b),
+ c: Some(c),
+ };
+ joiner.await
+}
+
+async fn joined_with_noop() {
+ let a = BigFut::new();
+ let b = BigFut::new();
+ let c = BigFut::new();
+
+ let joiner = Joiner {
+ a: Some(a),
+ b: Some(b),
+ c: Some(c),
+ };
+ noop();
+ joiner.await
+}
+
+async fn mixed_sizes() {
+ let a = BigFut::new();
+ let b = BigFut::new();
+ let c = BigFut::new();
+ let d = BigFut::new();
+ let e = BigFut::new();
+ let joiner = Joiner {
+ a: Some(a),
+ b: Some(b),
+ c: Some(c),
+ };
+
+ d.await;
+ e.await;
+ joiner.await;
+}
+
+fn main() {
+ assert_eq!(1025, std::mem::size_of_val(&single()));
+ assert_eq!(1026, std::mem::size_of_val(&single_with_noop()));
+ assert_eq!(3076, std::mem::size_of_val(&joined()));
+ assert_eq!(3076, std::mem::size_of_val(&joined_with_noop()));
+ assert_eq!(6157, std::mem::size_of_val(&mixed_sizes()));
+}
diff --git a/tests/ui/async-await/async-fn-size-uninit-locals.rs b/tests/ui/async-await/async-fn-size-uninit-locals.rs
new file mode 100644
index 000000000..546172693
--- /dev/null
+++ b/tests/ui/async-await/async-fn-size-uninit-locals.rs
@@ -0,0 +1,102 @@
+// Test that we don't store uninitialized locals in futures from `async fn`.
+//
+// The exact sizes can change by a few bytes (we'd like to know when they do).
+// What we don't want to see is the wrong multiple of 1024 (the size of `Big`)
+// being reflected in the size.
+
+// ignore-emscripten (sizes don't match)
+// needs-unwind Size of Futures change on panic=abort
+// run-pass
+
+// edition:2018
+
+#![allow(unused_variables, unused_assignments)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+const BIG_FUT_SIZE: usize = 1024;
+struct Big(#[allow(unused_tuple_struct_fields)] [u8; BIG_FUT_SIZE]);
+
+impl Big {
+ fn new() -> Self {
+ Big([0; BIG_FUT_SIZE])
+ }
+}
+
+impl Drop for Big {
+ fn drop(&mut self) {}
+}
+
+#[allow(dead_code)]
+struct Joiner {
+ a: Option<Big>,
+ b: Option<Big>,
+ c: Option<Big>,
+}
+
+impl Future for Joiner {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+fn noop() {}
+async fn fut() {}
+
+async fn single() {
+ let x;
+ fut().await;
+ x = Big::new();
+}
+
+async fn single_with_noop() {
+ let x;
+ fut().await;
+ noop();
+ x = Big::new();
+ noop();
+}
+
+async fn joined() {
+ let joiner;
+ let a = Big::new();
+ let b = Big::new();
+ let c = Big::new();
+
+ fut().await;
+ joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) };
+}
+
+async fn joined_with_noop() {
+ let joiner;
+ let a = Big::new();
+ let b = Big::new();
+ let c = Big::new();
+
+ fut().await;
+ noop();
+ joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) };
+ noop();
+}
+
+async fn join_retval() -> Joiner {
+ let a = Big::new();
+ let b = Big::new();
+ let c = Big::new();
+
+ fut().await;
+ noop();
+ Joiner { a: Some(a), b: Some(b), c: Some(c) }
+}
+
+fn main() {
+ assert_eq!(2, std::mem::size_of_val(&single()));
+ assert_eq!(3, std::mem::size_of_val(&single_with_noop()));
+ assert_eq!(3074, std::mem::size_of_val(&joined()));
+ assert_eq!(3078, std::mem::size_of_val(&joined_with_noop()));
+ assert_eq!(3074, std::mem::size_of_val(&join_retval()));
+}
diff --git a/tests/ui/async-await/async-fn-size.rs b/tests/ui/async-await/async-fn-size.rs
new file mode 100644
index 000000000..0c1f36364
--- /dev/null
+++ b/tests/ui/async-await/async-fn-size.rs
@@ -0,0 +1,105 @@
+// run-pass
+// aux-build:arc_wake.rs
+// edition:2018
+
+extern crate arc_wake;
+
+use std::pin::Pin;
+use std::future::Future;
+use std::sync::{
+ Arc,
+ atomic::{self, AtomicUsize},
+};
+use std::task::{Context, Poll};
+use arc_wake::ArcWake;
+
+struct Counter {
+ wakes: AtomicUsize,
+}
+
+impl ArcWake for Counter {
+ fn wake(self: Arc<Self>) {
+ Self::wake_by_ref(&self)
+ }
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+ }
+}
+
+struct WakeOnceThenComplete(bool, u8);
+
+impl Future for WakeOnceThenComplete {
+ type Output = u8;
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<u8> {
+ if self.0 {
+ Poll::Ready(self.1)
+ } else {
+ cx.waker().wake_by_ref();
+ self.0 = true;
+ Poll::Pending
+ }
+ }
+}
+
+fn wait(fut: impl Future<Output = u8>) -> u8 {
+ let mut fut = Box::pin(fut);
+ let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
+ let waker = ArcWake::into_waker(counter.clone());
+ let mut cx = Context::from_waker(&waker);
+ loop {
+ match fut.as_mut().poll(&mut cx) {
+ Poll::Ready(out) => return out,
+ Poll::Pending => (),
+ }
+ }
+}
+
+fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) }
+
+async fn await1_level1() -> u8 {
+ base().await
+}
+
+async fn await2_level1() -> u8 {
+ base().await + base().await
+}
+
+async fn await3_level1() -> u8 {
+ base().await + base().await + base().await
+}
+
+async fn await3_level2() -> u8 {
+ await3_level1().await + await3_level1().await + await3_level1().await
+}
+
+async fn await3_level3() -> u8 {
+ await3_level2().await + await3_level2().await + await3_level2().await
+}
+
+async fn await3_level4() -> u8 {
+ await3_level3().await + await3_level3().await + await3_level3().await
+}
+
+async fn await3_level5() -> u8 {
+ await3_level4().await + await3_level4().await + await3_level4().await
+}
+
+fn main() {
+ assert_eq!(2, std::mem::size_of_val(&base()));
+ assert_eq!(3, std::mem::size_of_val(&await1_level1()));
+ assert_eq!(4, std::mem::size_of_val(&await2_level1()));
+ assert_eq!(5, std::mem::size_of_val(&await3_level1()));
+ assert_eq!(8, std::mem::size_of_val(&await3_level2()));
+ assert_eq!(11, std::mem::size_of_val(&await3_level3()));
+ assert_eq!(14, std::mem::size_of_val(&await3_level4()));
+ assert_eq!(17, std::mem::size_of_val(&await3_level5()));
+
+ assert_eq!(1, wait(base()));
+ assert_eq!(1, wait(await1_level1()));
+ assert_eq!(2, wait(await2_level1()));
+ assert_eq!(3, wait(await3_level1()));
+ assert_eq!(9, wait(await3_level2()));
+ assert_eq!(27, wait(await3_level3()));
+ assert_eq!(81, wait(await3_level4()));
+ assert_eq!(243, wait(await3_level5()));
+}
diff --git a/tests/ui/async-await/async-is-unwindsafe.rs b/tests/ui/async-await/async-is-unwindsafe.rs
new file mode 100644
index 000000000..56ed28472
--- /dev/null
+++ b/tests/ui/async-await/async-is-unwindsafe.rs
@@ -0,0 +1,30 @@
+// edition:2018
+
+fn is_unwindsafe(_: impl std::panic::UnwindSafe) {}
+
+fn main() {
+ // A normal future created by an async block takes a `&mut Context<'_>` argument.
+ // That should not leak through to the whole async block.
+ is_unwindsafe(async {
+ async {}.await; // this needs an inner await point
+ });
+
+ is_unwindsafe(async {
+ //~^ ERROR the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
+ use std::ptr::null;
+ use std::task::{Context, RawWaker, RawWakerVTable, Waker};
+ let waker = unsafe {
+ Waker::from_raw(RawWaker::new(
+ null(),
+ &RawWakerVTable::new(|_| todo!(), |_| todo!(), |_| todo!(), |_| todo!()),
+ ))
+ };
+ let mut cx = Context::from_waker(&waker);
+ let cx_ref = &mut cx;
+
+ async {}.await; // this needs an inner await point
+
+ // in this case, `&mut Context<'_>` is *truly* alive across an await point
+ drop(cx_ref);
+ });
+}
diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr
new file mode 100644
index 000000000..d6404b30e
--- /dev/null
+++ b/tests/ui/async-await/async-is-unwindsafe.stderr
@@ -0,0 +1,38 @@
+error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
+ --> $DIR/async-is-unwindsafe.rs:12:19
+ |
+LL | is_unwindsafe(async {
+ | ___________________^
+LL | |
+LL | | use std::ptr::null;
+LL | | use std::task::{Context, RawWaker, RawWakerVTable, Waker};
+... |
+LL | | drop(cx_ref);
+LL | | });
+ | | ^
+ | | |
+ | |_____`&mut Context<'_>` may not be safely transferred across an unwind boundary
+ | within this `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]`
+ |
+ = help: within `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`
+ = note: `UnwindSafe` is implemented for `&std::task::Context<'_>`, but not for `&mut std::task::Context<'_>`
+note: future does not implement `UnwindSafe` as this value is used across an await
+ --> $DIR/async-is-unwindsafe.rs:25:17
+ |
+LL | let cx_ref = &mut cx;
+ | ------ has type `&mut Context<'_>` which does not implement `UnwindSafe`
+LL |
+LL | async {}.await; // this needs an inner await point
+ | ^^^^^^ await occurs here, with `cx_ref` maybe used later
+...
+LL | });
+ | - `cx_ref` is later dropped here
+note: required by a bound in `is_unwindsafe`
+ --> $DIR/async-is-unwindsafe.rs:3:26
+ |
+LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-matches-expr.rs b/tests/ui/async-await/async-matches-expr.rs
new file mode 100644
index 000000000..299faa058
--- /dev/null
+++ b/tests/ui/async-await/async-matches-expr.rs
@@ -0,0 +1,10 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+
+macro_rules! match_expr {
+ ($x:expr) => {}
+}
+
+fn main() {
+ match_expr!(async {});
+}
diff --git a/tests/ui/async-await/async-trait-fn.rs b/tests/ui/async-await/async-trait-fn.rs
new file mode 100644
index 000000000..e2062e827
--- /dev/null
+++ b/tests/ui/async-await/async-trait-fn.rs
@@ -0,0 +1,11 @@
+// edition:2018
+trait T {
+ async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
+ async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async`
+ async fn baz() { //~ ERROR functions in traits cannot be declared `async`
+ // Nested item must not ICE.
+ fn a() {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-trait-fn.stderr b/tests/ui/async-await/async-trait-fn.stderr
new file mode 100644
index 000000000..afbe25cf7
--- /dev/null
+++ b/tests/ui/async-await/async-trait-fn.stderr
@@ -0,0 +1,42 @@
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/async-trait-fn.rs:3:5
+ |
+LL | async fn foo() {}
+ | -----^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/async-trait-fn.rs:4:5
+ |
+LL | async fn bar(&self) {}
+ | -----^^^^^^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/async-trait-fn.rs:5:5
+ |
+LL | async fn baz() {
+ | -----^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0706`.
diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr b/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr
new file mode 100644
index 000000000..2114fb59b
--- /dev/null
+++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr
@@ -0,0 +1,35 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/async-unsafe-fn-call-in-safe.rs:14:5
+ |
+LL | S::f();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/async-unsafe-fn-call-in-safe.rs:17:5
+ |
+LL | f();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/async-unsafe-fn-call-in-safe.rs:23:5
+ |
+LL | S::f();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/async-unsafe-fn-call-in-safe.rs:24:5
+ |
+LL | f();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs b/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs
new file mode 100644
index 000000000..c941dc27a
--- /dev/null
+++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs
@@ -0,0 +1,25 @@
+// edition:2018
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+struct S;
+
+impl S {
+ async unsafe fn f() {}
+}
+
+async unsafe fn f() {}
+
+async fn g() {
+ S::f();
+ //[mir]~^ ERROR call to unsafe function is unsafe
+ //[thir]~^^ ERROR call to unsafe function `S::f` is unsafe
+ f();
+ //[mir]~^ ERROR call to unsafe function is unsafe
+ //[thir]~^^ ERROR call to unsafe function `f` is unsafe
+}
+
+fn main() {
+ S::f(); //[mir]~ ERROR call to unsafe function is unsafe
+ f(); //[mir]~ ERROR call to unsafe function is unsafe
+}
diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr b/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr
new file mode 100644
index 000000000..68d97d3fd
--- /dev/null
+++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr
@@ -0,0 +1,19 @@
+error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block
+ --> $DIR/async-unsafe-fn-call-in-safe.rs:14:5
+ |
+LL | S::f();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
+ --> $DIR/async-unsafe-fn-call-in-safe.rs:17:5
+ |
+LL | f();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/async-await/async-with-closure.rs b/tests/ui/async-await/async-with-closure.rs
new file mode 100644
index 000000000..0b2255266
--- /dev/null
+++ b/tests/ui/async-await/async-with-closure.rs
@@ -0,0 +1,24 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+
+trait MyClosure {
+ type Args;
+}
+
+impl<R> MyClosure for dyn FnMut() -> R
+where R: 'static {
+ type Args = ();
+}
+
+struct MyStream<C: ?Sized + MyClosure> {
+ x: C::Args,
+}
+
+async fn get_future<C: ?Sized + MyClosure>(_stream: MyStream<C>) {}
+
+async fn f() {
+ let messages: MyStream<dyn FnMut()> = unimplemented!();
+ get_future(messages).await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/auxiliary/arc_wake.rs b/tests/ui/async-await/auxiliary/arc_wake.rs
new file mode 100644
index 000000000..c21886f26
--- /dev/null
+++ b/tests/ui/async-await/auxiliary/arc_wake.rs
@@ -0,0 +1,64 @@
+// edition:2018
+
+use std::sync::Arc;
+use std::task::{
+ Waker, RawWaker, RawWakerVTable,
+};
+
+macro_rules! waker_vtable {
+ ($ty:ident) => {
+ &RawWakerVTable::new(
+ clone_arc_raw::<$ty>,
+ wake_arc_raw::<$ty>,
+ wake_by_ref_arc_raw::<$ty>,
+ drop_arc_raw::<$ty>,
+ )
+ };
+}
+
+pub trait ArcWake {
+ fn wake(self: Arc<Self>);
+
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.clone().wake()
+ }
+
+ fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
+ {
+ let ptr = Arc::into_raw(wake) as *const ();
+
+ unsafe {
+ Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
+ }
+ }
+}
+
+unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
+ // Retain Arc by creating a copy
+ let arc: Arc<T> = Arc::from_raw(data as *const T);
+ let arc_clone = arc.clone();
+ // Forget the Arcs again, so that the refcount isn't decrased
+ let _ = Arc::into_raw(arc);
+ let _ = Arc::into_raw(arc_clone);
+}
+
+unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
+ increase_refcount::<T>(data);
+ RawWaker::new(data, waker_vtable!(T))
+}
+
+unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
+ // Drop Arc
+ let _: Arc<T> = Arc::from_raw(data as *const T);
+}
+
+unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
+ let arc: Arc<T> = Arc::from_raw(data as *const T);
+ ArcWake::wake(arc);
+}
+
+unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
+ let arc: Arc<T> = Arc::from_raw(data as *const T);
+ ArcWake::wake_by_ref(&arc);
+ let _ = Arc::into_raw(arc);
+}
diff --git a/tests/ui/async-await/auxiliary/issue-107036.rs b/tests/ui/async-await/auxiliary/issue-107036.rs
new file mode 100644
index 000000000..c3f6141b2
--- /dev/null
+++ b/tests/ui/async-await/auxiliary/issue-107036.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+pub trait T {}
+impl T for () {}
+
+pub struct S {}
+
+impl S {
+ pub async fn f<'a>(&self) -> impl T + 'a {
+ ()
+ }
+}
diff --git a/tests/ui/async-await/auxiliary/issue-72470-lib.rs b/tests/ui/async-await/auxiliary/issue-72470-lib.rs
new file mode 100644
index 000000000..8383eba89
--- /dev/null
+++ b/tests/ui/async-await/auxiliary/issue-72470-lib.rs
@@ -0,0 +1,175 @@
+// compile-flags: -C opt-level=3
+// edition:2018
+
+use std::future::Future;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::sync::atomic::AtomicUsize;
+use std::sync::Arc;
+use std::task::Poll::{Pending, Ready};
+use std::task::Waker;
+use std::task::{Context, Poll};
+use std::{
+ ptr,
+ task::{RawWaker, RawWakerVTable},
+};
+
+/// Future for the [`poll_fn`] function.
+pub struct PollFn<F> {
+ f: F,
+}
+
+impl<F> Unpin for PollFn<F> {}
+
+/// Creates a new future wrapping around a function returning [`Poll`].
+pub fn poll_fn<T, F>(f: F) -> PollFn<F>
+where
+ F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+ PollFn { f }
+}
+
+impl<T, F> Future for PollFn<F>
+where
+ F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+ type Output = T;
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
+ (&mut self.f)(cx)
+ }
+}
+pub fn run<F: Future>(future: F) -> F::Output {
+ BasicScheduler.block_on(future)
+}
+
+pub(crate) struct BasicScheduler;
+
+impl BasicScheduler {
+ pub(crate) fn block_on<F>(&mut self, mut future: F) -> F::Output
+ where
+ F: Future,
+ {
+ let waker = unsafe { Waker::from_raw(raw_waker()) };
+ let mut cx = std::task::Context::from_waker(&waker);
+
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+ loop {
+ if let Ready(v) = future.as_mut().poll(&mut cx) {
+ return v;
+ }
+ }
+ }
+}
+
+// ===== impl Spawner =====
+
+fn raw_waker() -> RawWaker {
+ RawWaker::new(ptr::null(), waker_vtable())
+}
+
+fn waker_vtable() -> &'static RawWakerVTable {
+ &RawWakerVTable::new(
+ clone_arc_raw,
+ wake_arc_raw,
+ wake_by_ref_arc_raw,
+ drop_arc_raw,
+ )
+}
+
+unsafe fn clone_arc_raw(_: *const ()) -> RawWaker {
+ raw_waker()
+}
+
+unsafe fn wake_arc_raw(_: *const ()) {}
+
+unsafe fn wake_by_ref_arc_raw(_: *const ()) {}
+
+unsafe fn drop_arc_raw(_: *const ()) {}
+
+struct AtomicWaker {}
+
+impl AtomicWaker {
+ /// Create an `AtomicWaker`
+ fn new() -> AtomicWaker {
+ AtomicWaker {}
+ }
+
+ fn register_by_ref(&self, _waker: &Waker) {}
+}
+
+#[allow(dead_code)]
+struct Tx<T> {
+ inner: Arc<Chan<T>>,
+}
+
+struct Rx<T> {
+ inner: Arc<Chan<T>>,
+}
+
+#[allow(dead_code)]
+struct Chan<T> {
+ tx: PhantomData<T>,
+ semaphore: Sema,
+ rx_waker: AtomicWaker,
+ rx_closed: bool,
+}
+
+fn channel<T>() -> (Tx<T>, Rx<T>) {
+ let chan = Arc::new(Chan {
+ tx: PhantomData,
+ semaphore: Sema(AtomicUsize::new(0)),
+ rx_waker: AtomicWaker::new(),
+ rx_closed: false,
+ });
+
+ (
+ Tx {
+ inner: chan.clone(),
+ },
+ Rx { inner: chan },
+ )
+}
+
+// ===== impl Rx =====
+
+impl<T> Rx<T> {
+ /// Receive the next value
+ fn recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
+ self.inner.rx_waker.register_by_ref(cx.waker());
+
+ if self.inner.rx_closed && self.inner.semaphore.is_idle() {
+ Ready(None)
+ } else {
+ Pending
+ }
+ }
+}
+
+struct Sema(AtomicUsize);
+
+impl Sema {
+ fn is_idle(&self) -> bool {
+ false
+ }
+}
+
+pub struct UnboundedReceiver<T> {
+ chan: Rx<T>,
+}
+
+pub fn unbounded_channel<T>() -> UnboundedReceiver<T> {
+ let (tx, rx) = channel();
+
+ drop(tx);
+ let rx = UnboundedReceiver { chan: rx };
+
+ rx
+}
+
+impl<T> UnboundedReceiver<T> {
+ pub async fn recv(&mut self) -> Option<T> {
+ poll_fn(|cx| self.chan.recv(cx)).await
+ }
+}
diff --git a/tests/ui/async-await/await-into-future.rs b/tests/ui/async-await/await-into-future.rs
new file mode 100644
index 000000000..8bf1385b3
--- /dev/null
+++ b/tests/ui/async-await/await-into-future.rs
@@ -0,0 +1,28 @@
+// run-pass
+// aux-build: issue-72470-lib.rs
+// edition:2021
+extern crate issue_72470_lib;
+use std::{future::{Future, IntoFuture}, pin::Pin};
+
+struct AwaitMe;
+
+impl IntoFuture for AwaitMe {
+ type Output = i32;
+ type IntoFuture = Pin<Box<dyn Future<Output = i32>>>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ Box::pin(me())
+ }
+}
+
+async fn me() -> i32 {
+ 41
+}
+
+async fn run() {
+ assert_eq!(AwaitMe.await, 41);
+}
+
+fn main() {
+ issue_72470_lib::run(run());
+}
diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs
new file mode 100644
index 000000000..50c163999
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs
@@ -0,0 +1,38 @@
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+ pub mod await { //~ ERROR `await` is a keyword in the 2018 edition
+ //~^ WARN this is accepted in the current edition
+ pub struct await; //~ ERROR `await` is a keyword in the 2018 edition
+ //~^ WARN this is accepted in the current edition
+ }
+}
+use outer_mod::await::await; //~ ERROR `await` is a keyword in the 2018 edition
+//~^ ERROR `await` is a keyword in the 2018 edition
+//~^^ WARN this is accepted in the current edition
+//~^^^ WARN this is accepted in the current edition
+
+struct Foo { await: () }
+//~^ ERROR `await` is a keyword in the 2018 edition
+//~^^ WARN this is accepted in the current edition
+
+impl Foo { fn await() {} }
+//~^ ERROR `await` is a keyword in the 2018 edition
+//~^^ WARN this is accepted in the current edition
+
+macro_rules! await {
+//~^ ERROR `await` is a keyword in the 2018 edition
+//~^^ WARN this is accepted in the current edition
+ () => {}
+}
+
+fn main() {
+ await!(); //~ ERROR `await` is a keyword in the 2018 edition
+ //~^ WARN this is accepted in the current edition
+
+ match await { await => {} } //~ ERROR `await` is a keyword in the 2018 edition
+ //~^ ERROR `await` is a keyword in the 2018 edition
+ //~^^ WARN this is accepted in the current edition
+ //~^^^ WARN this is accepted in the current edition
+}
diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
new file mode 100644
index 000000000..d99967eb2
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
@@ -0,0 +1,97 @@
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:5:13
+ |
+LL | pub mod await {
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+note: the lint level is defined here
+ --> $DIR/2015-edition-error-various-positions.rs:2:9
+ |
+LL | #![deny(keyword_idents)]
+ | ^^^^^^^^^^^^^^
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:7:20
+ |
+LL | pub struct await;
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:11:16
+ |
+LL | use outer_mod::await::await;
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:11:23
+ |
+LL | use outer_mod::await::await;
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:16:14
+ |
+LL | struct Foo { await: () }
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:20:15
+ |
+LL | impl Foo { fn await() {} }
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:24:14
+ |
+LL | macro_rules! await {
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:31:5
+ |
+LL | await!();
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:34:11
+ |
+LL | match await { await => {} }
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-error-various-positions.rs:34:19
+ |
+LL | match await { await => {} }
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.fixed b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed
new file mode 100644
index 000000000..117495e13
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+ pub mod r#await {
+//~^ ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+ pub struct r#await;
+//~^ ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+ }
+}
+use outer_mod::r#await::r#await;
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+
+fn main() {
+ match r#await { r#await => {} }
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+}
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.rs b/tests/ui/async-await/await-keyword/2015-edition-warning.rs
new file mode 100644
index 000000000..b3c64895c
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.rs
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![allow(non_camel_case_types)]
+#![deny(keyword_idents)]
+
+mod outer_mod {
+ pub mod await {
+//~^ ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+ pub struct await;
+//~^ ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+ }
+}
+use outer_mod::await::await;
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+
+fn main() {
+ match await { await => {} }
+//~^ ERROR `await` is a keyword
+//~| ERROR `await` is a keyword
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+}
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
new file mode 100644
index 000000000..bf5c4d8d6
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
@@ -0,0 +1,61 @@
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-warning.rs:7:13
+ |
+LL | pub mod await {
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+note: the lint level is defined here
+ --> $DIR/2015-edition-warning.rs:4:9
+ |
+LL | #![deny(keyword_idents)]
+ | ^^^^^^^^^^^^^^
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-warning.rs:10:20
+ |
+LL | pub struct await;
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-warning.rs:15:16
+ |
+LL | use outer_mod::await::await;
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-warning.rs:15:23
+ |
+LL | use outer_mod::await::await;
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-warning.rs:22:11
+ |
+LL | match await { await => {} }
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: `await` is a keyword in the 2018 edition
+ --> $DIR/2015-edition-warning.rs:22:19
+ |
+LL | match await { await => {} }
+ | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
new file mode 100644
index 000000000..9e78f7c51
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
@@ -0,0 +1,24 @@
+// edition:2018
+
+#![allow(non_camel_case_types)]
+
+mod outer_mod {
+ pub mod await { //~ ERROR expected identifier, found keyword `await`
+ pub struct await; //~ ERROR expected identifier, found keyword `await`
+ }
+}
+use self::outer_mod::await::await; //~ ERROR expected identifier, found keyword `await`
+//~^ ERROR expected identifier, found keyword `await`
+
+struct Foo { await: () }
+//~^ ERROR expected identifier, found keyword `await`
+
+impl Foo { fn await() {} }
+//~^ ERROR expected identifier, found keyword `await`
+
+macro_rules! await {
+//~^ ERROR expected identifier, found keyword `await`
+ () => {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
new file mode 100644
index 000000000..6bd8f671d
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
@@ -0,0 +1,81 @@
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:6:13
+ |
+LL | pub mod await {
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | pub mod r#await {
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:7:20
+ |
+LL | pub struct await;
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | pub struct r#await;
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:10:22
+ |
+LL | use self::outer_mod::await::await;
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | use self::outer_mod::r#await::await;
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:10:29
+ |
+LL | use self::outer_mod::await::await;
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | use self::outer_mod::await::r#await;
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:13:14
+ |
+LL | struct Foo { await: () }
+ | --- ^^^^^ expected identifier, found keyword
+ | |
+ | while parsing this struct
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | struct Foo { r#await: () }
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:16:15
+ |
+LL | impl Foo { fn await() {} }
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | impl Foo { fn r#await() {} }
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error-in-non-macro-position.rs:19:14
+ |
+LL | macro_rules! await {
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | macro_rules! r#await {
+ | ++
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/async-await/await-keyword/2018-edition-error.rs b/tests/ui/async-await/await-keyword/2018-edition-error.rs
new file mode 100644
index 000000000..7ce52259a
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2018-edition-error.rs
@@ -0,0 +1,16 @@
+// edition:2018
+#![allow(non_camel_case_types)]
+
+mod outer_mod {
+ pub mod await { //~ ERROR expected identifier
+ pub struct await; //~ ERROR expected identifier
+ }
+}
+use self::outer_mod::await::await; //~ ERROR expected identifier
+ //~^ ERROR expected identifier, found keyword `await`
+
+macro_rules! await { () => {}; } //~ ERROR expected identifier, found keyword `await`
+
+fn main() {
+ await!(); //~ ERROR expected expression, found `)`
+}
diff --git a/tests/ui/async-await/await-keyword/2018-edition-error.stderr b/tests/ui/async-await/await-keyword/2018-edition-error.stderr
new file mode 100644
index 000000000..34bfdfc71
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/2018-edition-error.stderr
@@ -0,0 +1,63 @@
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error.rs:5:13
+ |
+LL | pub mod await {
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | pub mod r#await {
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error.rs:6:20
+ |
+LL | pub struct await;
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | pub struct r#await;
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error.rs:9:22
+ |
+LL | use self::outer_mod::await::await;
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | use self::outer_mod::r#await::await;
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error.rs:9:29
+ |
+LL | use self::outer_mod::await::await;
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | use self::outer_mod::await::r#await;
+ | ++
+
+error: expected identifier, found keyword `await`
+ --> $DIR/2018-edition-error.rs:12:14
+ |
+LL | macro_rules! await { () => {}; }
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `await` to use it as an identifier
+ |
+LL | macro_rules! r#await { () => {}; }
+ | ++
+
+error: expected expression, found `)`
+ --> $DIR/2018-edition-error.rs:15:12
+ |
+LL | await!();
+ | ^ expected expression
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs
new file mode 100644
index 000000000..554ac673d
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs
@@ -0,0 +1,132 @@
+// edition:2018
+
+async fn bar() -> Result<(), ()> {
+ Ok(())
+}
+
+async fn foo1() -> Result<(), ()> {
+ let _ = await bar(); //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo2() -> Result<(), ()> {
+ let _ = await? bar(); //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo3() -> Result<(), ()> {
+ let _ = await bar()?; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo21() -> Result<(), ()> {
+ let _ = await { bar() }; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo22() -> Result<(), ()> {
+ let _ = await(bar()); //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo23() -> Result<(), ()> {
+ let _ = await { bar() }?; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo4() -> Result<(), ()> {
+ let _ = (await bar())?; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo5() -> Result<(), ()> {
+ let _ = bar().await(); //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo6() -> Result<(), ()> {
+ let _ = bar().await()?; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo7() -> Result<(), ()> {
+ let _ = bar().await; // OK
+ Ok(())
+}
+async fn foo8() -> Result<(), ()> {
+ let _ = bar().await?; // OK
+ Ok(())
+}
+fn foo9() -> Result<(), ()> {
+ let _ = await bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks
+ //~^ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo10() -> Result<(), ()> {
+ let _ = await? bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks
+ //~^ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo11() -> Result<(), ()> {
+ let _ = await bar()?; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo12() -> Result<(), ()> {
+ let _ = (await bar())?; //~ ERROR `await` is only allowed inside `async` functions and blocks
+ //~^ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo13() -> Result<(), ()> {
+ let _ = bar().await(); //~ ERROR `await` is only allowed inside `async` functions and blocks
+ //~^ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo14() -> Result<(), ()> {
+ let _ = bar().await()?; //~ ERROR `await` is only allowed inside `async` functions and blocks
+ //~^ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo15() -> Result<(), ()> {
+ let _ = bar().await; //~ ERROR `await` is only allowed inside `async` functions and blocks
+ Ok(())
+}
+fn foo16() -> Result<(), ()> {
+ let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks
+ Ok(())
+}
+fn foo24() -> Result<(), ()> {
+ fn foo() -> Result<(), ()> {
+ let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks
+ Ok(())
+ }
+ foo()
+}
+fn foo25() -> Result<(), ()> {
+ let foo = || {
+ let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks
+ Ok(())
+ };
+ foo()
+}
+
+async fn foo26() -> Result<(), ()> {
+ let _ = await!(bar()); //~ ERROR incorrect use of `await`
+ Ok(())
+}
+async fn foo27() -> Result<(), ()> {
+ let _ = await!(bar())?; //~ ERROR incorrect use of `await`
+ Ok(())
+}
+fn foo28() -> Result<(), ()> {
+ fn foo() -> Result<(), ()> {
+ let _ = await!(bar())?; //~ ERROR incorrect use of `await`
+ //~^ ERROR `await` is only allowed inside `async` functions
+ Ok(())
+ }
+ foo()
+}
+fn foo29() -> Result<(), ()> {
+ let foo = || {
+ let _ = await!(bar())?; //~ ERROR incorrect use of `await`
+ //~^ ERROR `await` is only allowed inside `async` functions
+ Ok(())
+ };
+ foo()
+}
+
+fn main() {
+ match await { await => () }
+ //~^ ERROR expected expression, found `=>`
+ //~| ERROR incorrect use of `await`
+} //~ ERROR expected one of `.`, `?`, `{`, or an operator, found `}`
diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
new file mode 100644
index 000000000..b30f28837
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
@@ -0,0 +1,230 @@
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:8:13
+ |
+LL | let _ = await bar();
+ | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:12:13
+ |
+LL | let _ = await? bar();
+ | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:16:13
+ |
+LL | let _ = await bar()?;
+ | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:20:13
+ |
+LL | let _ = await { bar() };
+ | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:24:13
+ |
+LL | let _ = await(bar());
+ | ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:28:13
+ |
+LL | let _ = await { bar() }?;
+ | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:32:14
+ |
+LL | let _ = (await bar())?;
+ | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:36:24
+ |
+LL | let _ = bar().await();
+ | ^^ help: `await` is not a method call, remove the parentheses
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:40:24
+ |
+LL | let _ = bar().await()?;
+ | ^^ help: `await` is not a method call, remove the parentheses
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:52:13
+ |
+LL | let _ = await bar();
+ | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:57:13
+ |
+LL | let _ = await? bar();
+ | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:62:13
+ |
+LL | let _ = await bar()?;
+ | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:66:14
+ |
+LL | let _ = (await bar())?;
+ | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:71:24
+ |
+LL | let _ = bar().await();
+ | ^^ help: `await` is not a method call, remove the parentheses
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:76:24
+ |
+LL | let _ = bar().await()?;
+ | ^^ help: `await` is not a method call, remove the parentheses
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:104:13
+ |
+LL | let _ = await!(bar());
+ | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:108:13
+ |
+LL | let _ = await!(bar())?;
+ | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:113:17
+ |
+LL | let _ = await!(bar())?;
+ | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:121:17
+ |
+LL | let _ = await!(bar())?;
+ | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
+
+error: expected expression, found `=>`
+ --> $DIR/incorrect-syntax-suggestions.rs:129:25
+ |
+LL | match await { await => () }
+ | ----- ^^ expected expression
+ | |
+ | while parsing this incorrect await expression
+
+error: incorrect use of `await`
+ --> $DIR/incorrect-syntax-suggestions.rs:129:11
+ |
+LL | match await { await => () }
+ | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
+
+error: expected one of `.`, `?`, `{`, or an operator, found `}`
+ --> $DIR/incorrect-syntax-suggestions.rs:132:1
+ |
+LL | match await { await => () }
+ | ----- - expected one of `.`, `?`, `{`, or an operator
+ | |
+ | while parsing this `match` expression
+...
+LL | }
+ | ^ unexpected token
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:52:13
+ |
+LL | fn foo9() -> Result<(), ()> {
+ | ---- this is not `async`
+LL | let _ = await bar();
+ | ^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:57:13
+ |
+LL | fn foo10() -> Result<(), ()> {
+ | ----- this is not `async`
+LL | let _ = await? bar();
+ | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:66:14
+ |
+LL | fn foo12() -> Result<(), ()> {
+ | ----- this is not `async`
+LL | let _ = (await bar())?;
+ | ^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:71:18
+ |
+LL | fn foo13() -> Result<(), ()> {
+ | ----- this is not `async`
+LL | let _ = bar().await();
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:76:18
+ |
+LL | fn foo14() -> Result<(), ()> {
+ | ----- this is not `async`
+LL | let _ = bar().await()?;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:81:18
+ |
+LL | fn foo15() -> Result<(), ()> {
+ | ----- this is not `async`
+LL | let _ = bar().await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:85:18
+ |
+LL | fn foo16() -> Result<(), ()> {
+ | ----- this is not `async`
+LL | let _ = bar().await?;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:90:22
+ |
+LL | fn foo() -> Result<(), ()> {
+ | --- this is not `async`
+LL | let _ = bar().await?;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:97:22
+ |
+LL | let foo = || {
+ | -- this is not `async`
+LL | let _ = bar().await?;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:113:29
+ |
+LL | fn foo() -> Result<(), ()> {
+ | --- this is not `async`
+LL | let _ = await!(bar())?;
+ | ^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/incorrect-syntax-suggestions.rs:121:29
+ |
+LL | let foo = || {
+ | -- this is not `async`
+LL | let _ = await!(bar())?;
+ | ^ only allowed inside `async` functions and blocks
+
+error: aborting due to 33 previous errors
+
+For more information about this error, try `rustc --explain E0728`.
diff --git a/tests/ui/async-await/await-keyword/post_expansion_error.rs b/tests/ui/async-await/await-keyword/post_expansion_error.rs
new file mode 100644
index 000000000..b4c899b0d
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/post_expansion_error.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+macro_rules! r#await {
+ () => { println!("Hello, world!") }
+}
+
+fn main() {
+ await!()
+ //~^ ERROR expected expression, found `)`
+}
diff --git a/tests/ui/async-await/await-keyword/post_expansion_error.stderr b/tests/ui/async-await/await-keyword/post_expansion_error.stderr
new file mode 100644
index 000000000..0996c38b3
--- /dev/null
+++ b/tests/ui/async-await/await-keyword/post_expansion_error.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `)`
+ --> $DIR/post_expansion_error.rs:8:12
+ |
+LL | await!()
+ | ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/await-sequence.rs b/tests/ui/async-await/await-sequence.rs
new file mode 100644
index 000000000..726c4284e
--- /dev/null
+++ b/tests/ui/async-await/await-sequence.rs
@@ -0,0 +1,21 @@
+// edition:2021
+// compile-flags: -Z drop-tracking
+// build-pass
+
+use std::collections::HashMap;
+
+fn main() {
+ let _ = real_main();
+}
+
+async fn nop() {}
+
+async fn real_main() {
+ nop().await;
+ nop().await;
+ nop().await;
+ nop().await;
+
+ let mut map: HashMap<(), ()> = HashMap::new();
+ map.insert((), nop().await);
+}
diff --git a/tests/ui/async-await/await-unsize.rs b/tests/ui/async-await/await-unsize.rs
new file mode 100644
index 000000000..aa09d4bdf
--- /dev/null
+++ b/tests/ui/async-await/await-unsize.rs
@@ -0,0 +1,14 @@
+// Regression test for #62312
+
+// check-pass
+// edition:2018
+
+async fn make_boxed_object() -> Box<dyn Send> {
+ Box::new(()) as _
+}
+
+async fn await_object() {
+ let _ = make_boxed_object().await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/bound-normalization.rs b/tests/ui/async-await/bound-normalization.rs
new file mode 100644
index 000000000..5d260682f
--- /dev/null
+++ b/tests/ui/async-await/bound-normalization.rs
@@ -0,0 +1,14 @@
+// check-pass
+// edition:2018
+
+// See issue 60414
+
+trait Trait {
+ type Assoc;
+}
+
+async fn foo<T: Trait<Assoc=()>>() -> T::Assoc {
+ ()
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/conditional-and-guaranteed-initialization.rs b/tests/ui/async-await/conditional-and-guaranteed-initialization.rs
new file mode 100644
index 000000000..56f4cbbd1
--- /dev/null
+++ b/tests/ui/async-await/conditional-and-guaranteed-initialization.rs
@@ -0,0 +1,16 @@
+// check-pass
+// edition:2018
+// compile-flags: --crate-type lib
+
+async fn conditional_and_guaranteed_initialization(x: usize) -> usize {
+ let y;
+ if x > 5 {
+ y = echo(10).await;
+ } else {
+ y = get_something().await;
+ }
+ y
+}
+
+async fn echo(x: usize) -> usize { x }
+async fn get_something() -> usize { 10 }
diff --git a/tests/ui/async-await/default-struct-update.rs b/tests/ui/async-await/default-struct-update.rs
new file mode 100644
index 000000000..64fb6280d
--- /dev/null
+++ b/tests/ui/async-await/default-struct-update.rs
@@ -0,0 +1,22 @@
+// build-pass
+// edition:2018
+// compile-flags: -Zdrop-tracking=y
+
+fn main() {
+ let _ = foo();
+}
+
+async fn from_config(_: Config) {}
+
+async fn foo() {
+ from_config(Config {
+ nickname: None,
+ ..Default::default()
+ })
+ .await;
+}
+
+#[derive(Default)]
+struct Config {
+ nickname: Option<Box<u8>>,
+}
diff --git a/tests/ui/async-await/dont-print-desugared-async.rs b/tests/ui/async-await/dont-print-desugared-async.rs
new file mode 100644
index 000000000..68341a24c
--- /dev/null
+++ b/tests/ui/async-await/dont-print-desugared-async.rs
@@ -0,0 +1,8 @@
+// Test that we don't show variables with from async fn desugaring
+
+// edition:2018
+
+async fn async_fn(&ref mut s: &[i32]) {}
+//~^ ERROR cannot borrow data in a `&` reference as mutable [E0596]
+
+fn main() {}
diff --git a/tests/ui/async-await/dont-print-desugared-async.stderr b/tests/ui/async-await/dont-print-desugared-async.stderr
new file mode 100644
index 000000000..d80467c7f
--- /dev/null
+++ b/tests/ui/async-await/dont-print-desugared-async.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+ --> $DIR/dont-print-desugared-async.rs:5:20
+ |
+LL | async fn async_fn(&ref mut s: &[i32]) {}
+ | ^^^^^^^^^ cannot borrow as mutable through `&` reference
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs
new file mode 100644
index 000000000..f2f87a908
--- /dev/null
+++ b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs
@@ -0,0 +1,24 @@
+// edition:2021
+
+// Test that we do not suggest `.await` when it doesn't make sense.
+
+struct A;
+
+impl A {
+ fn test(&self) -> i32 {
+ 1
+ }
+}
+
+async fn foo() -> A {
+ A
+}
+
+async fn async_main() {
+ let x: u32 = foo().test();
+ //~^ ERROR no method named `test` found for opaque type `impl Future<Output = A>` in the current scope
+}
+
+fn main() {
+ let _ = async_main();
+}
diff --git a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr
new file mode 100644
index 000000000..e65d9d0e5
--- /dev/null
+++ b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `test` found for opaque type `impl Future<Output = A>` in the current scope
+ --> $DIR/dont-suggest-await-on-method-return-mismatch.rs:18:24
+ |
+LL | let x: u32 = foo().test();
+ | ^^^^ method not found in `impl Future<Output = A>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/async-await/dont-suggest-missing-await.rs b/tests/ui/async-await/dont-suggest-missing-await.rs
new file mode 100644
index 000000000..a8e5b38ec
--- /dev/null
+++ b/tests/ui/async-await/dont-suggest-missing-await.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+// This test ensures we don't make the suggestion in bodies that aren't `async`.
+
+fn take_u32(x: u32) {}
+
+async fn make_u32() -> u32 {
+ 22
+}
+
+async fn dont_suggest_await_in_closure() {
+ || {
+ let x = make_u32();
+ take_u32(x)
+ //~^ ERROR mismatched types [E0308]
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/dont-suggest-missing-await.stderr b/tests/ui/async-await/dont-suggest-missing-await.stderr
new file mode 100644
index 000000000..627bf05bb
--- /dev/null
+++ b/tests/ui/async-await/dont-suggest-missing-await.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+ --> $DIR/dont-suggest-missing-await.rs:14:18
+ |
+LL | take_u32(x)
+ | -------- ^ expected `u32`, found opaque type
+ | |
+ | arguments to this function are incorrect
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/dont-suggest-missing-await.rs:7:24
+ |
+LL | async fn make_u32() -> u32 {
+ | ^^^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected type `u32`
+ found opaque type `impl Future<Output = u32>`
+note: function defined here
+ --> $DIR/dont-suggest-missing-await.rs:5:4
+ |
+LL | fn take_u32(x: u32) {}
+ | ^^^^^^^^ ------
+help: consider `await`ing on the `Future`
+ |
+LL | take_u32(x.await)
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/drop-and-assign.rs b/tests/ui/async-await/drop-and-assign.rs
new file mode 100644
index 000000000..fa3f33036
--- /dev/null
+++ b/tests/ui/async-await/drop-and-assign.rs
@@ -0,0 +1,19 @@
+// edition:2021
+// compile-flags: -Zdrop-tracking
+// build-pass
+
+struct A;
+impl Drop for A { fn drop(&mut self) {} }
+
+pub async fn f() {
+ let mut a = A;
+ a = A;
+ drop(a);
+ async {}.await;
+}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+ let _ = f();
+}
diff --git a/tests/ui/async-await/drop-order/auxiliary/arc_wake.rs b/tests/ui/async-await/drop-order/auxiliary/arc_wake.rs
new file mode 100644
index 000000000..c21886f26
--- /dev/null
+++ b/tests/ui/async-await/drop-order/auxiliary/arc_wake.rs
@@ -0,0 +1,64 @@
+// edition:2018
+
+use std::sync::Arc;
+use std::task::{
+ Waker, RawWaker, RawWakerVTable,
+};
+
+macro_rules! waker_vtable {
+ ($ty:ident) => {
+ &RawWakerVTable::new(
+ clone_arc_raw::<$ty>,
+ wake_arc_raw::<$ty>,
+ wake_by_ref_arc_raw::<$ty>,
+ drop_arc_raw::<$ty>,
+ )
+ };
+}
+
+pub trait ArcWake {
+ fn wake(self: Arc<Self>);
+
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.clone().wake()
+ }
+
+ fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
+ {
+ let ptr = Arc::into_raw(wake) as *const ();
+
+ unsafe {
+ Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
+ }
+ }
+}
+
+unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
+ // Retain Arc by creating a copy
+ let arc: Arc<T> = Arc::from_raw(data as *const T);
+ let arc_clone = arc.clone();
+ // Forget the Arcs again, so that the refcount isn't decrased
+ let _ = Arc::into_raw(arc);
+ let _ = Arc::into_raw(arc_clone);
+}
+
+unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
+ increase_refcount::<T>(data);
+ RawWaker::new(data, waker_vtable!(T))
+}
+
+unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
+ // Drop Arc
+ let _: Arc<T> = Arc::from_raw(data as *const T);
+}
+
+unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
+ let arc: Arc<T> = Arc::from_raw(data as *const T);
+ ArcWake::wake(arc);
+}
+
+unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
+ let arc: Arc<T> = Arc::from_raw(data as *const T);
+ ArcWake::wake_by_ref(&arc);
+ let _ = Arc::into_raw(arc);
+}
diff --git a/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs
new file mode 100644
index 000000000..9817d377a
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs
@@ -0,0 +1,270 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+
+// Test that the drop order for parameters in a fn and async fn matches up. Also test that
+// parameters (used or unused) are not dropped until the async fn completes execution.
+// See also #54716.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::marker::PhantomData;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+/// Check that unused bindings are dropped after the function is polled.
+async fn foo_async(ref mut x: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn foo_sync(ref mut x: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore patterns are dropped after the function is polled.
+async fn bar_async(ref mut x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn bar_sync(ref mut x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore patterns within more complex patterns are dropped after the function
+/// is polled.
+async fn baz_async((ref mut x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn baz_sync((ref mut x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore and unused bindings within and outwith more complex patterns are dropped
+/// after the function is polled.
+async fn foobar_async(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn foobar_sync(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+struct Foo;
+
+impl Foo {
+ /// Check that unused bindings are dropped after the method is polled.
+ async fn foo_async(ref mut x: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foo_sync(ref mut x: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns are dropped after the method is polled.
+ async fn bar_async(ref mut x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn bar_sync(ref mut x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns within more complex patterns are dropped after the method
+ /// is polled.
+ async fn baz_async((ref mut x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn baz_sync((ref mut x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore and unused bindings within and outwith more complex patterns are
+ /// dropped after the method is polled.
+ async fn foobar_async(
+ ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
+ ) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foobar_sync(
+ ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
+ ) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+}
+
+struct Bar<'a>(PhantomData<&'a ()>);
+
+impl<'a> Bar<'a> {
+ /// Check that unused bindings are dropped after the method with self is polled.
+ async fn foo_async(&'a self, ref mut x: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foo_sync(&'a self, ref mut x: D, ref mut _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns are dropped after the method with self is polled.
+ async fn bar_async(&'a self, ref mut x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn bar_sync(&'a self, ref mut x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns within more complex patterns are dropped after the method
+ /// with self is polled.
+ async fn baz_async(&'a self, (ref mut x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn baz_sync(&'a self, (ref mut x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore and unused bindings within and outwith more complex patterns are
+ /// dropped after the method with self is polled.
+ async fn foobar_async(
+ &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
+ ) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foobar_sync(
+ &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
+ ) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+}
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let _ = fut.as_mut().poll(&mut cx);
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ // Free functions (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+ assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| bar_sync(D("x", l.clone()), D("_", l.clone())));
+ assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| baz_sync((D("x", l.clone()), D("_", l.clone()))));
+ assert_drop_order_after_poll(
+ |l| {
+ foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+
+ // Methods w/out self (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())));
+ assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())));
+ assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))));
+ assert_drop_order_after_poll(
+ |l| {
+ Foo::foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ Foo::foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+
+ // Methods (see doc comment on function for what it tests).
+ let b = Bar(Default::default());
+ assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())));
+ assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())));
+ assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))));
+ assert_drop_order_after_poll(
+ |l| {
+ b.foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ b.foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+}
diff --git a/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs
new file mode 100644
index 000000000..6c10ead36
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs
@@ -0,0 +1,265 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+// revisions: default nomiropt
+//[nomiropt]compile-flags: -Z mir-opt-level=0
+
+#![allow(unused_variables)]
+
+// Test that the drop order for parameters in a fn and async fn matches up. Also test that
+// parameters (used or unused) are not dropped until the async fn completes execution.
+// See also #54716.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::marker::PhantomData;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+/// Check that unused bindings are dropped after the function is polled.
+async fn foo_async(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn foo_sync(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore patterns are dropped after the function is polled.
+async fn bar_async(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn bar_sync(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore patterns within more complex patterns are dropped after the function
+/// is polled.
+async fn baz_async((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn baz_sync((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore and unused bindings within and outwith more complex patterns are dropped
+/// after the function is polled.
+async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+struct Foo;
+
+impl Foo {
+ /// Check that unused bindings are dropped after the method is polled.
+ async fn foo_async(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foo_sync(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns are dropped after the method is polled.
+ async fn bar_async(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn bar_sync(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns within more complex patterns are dropped after the method
+ /// is polled.
+ async fn baz_async((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn baz_sync((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore and unused bindings within and outwith more complex patterns are
+ /// dropped after the method is polled.
+ async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+}
+
+struct Bar<'a>(PhantomData<&'a ()>);
+
+impl<'a> Bar<'a> {
+ /// Check that unused bindings are dropped after the method with self is polled.
+ async fn foo_async(&'a self, x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foo_sync(&'a self, x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns are dropped after the method with self is polled.
+ async fn bar_async(&'a self, x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn bar_sync(&'a self, x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns within more complex patterns are dropped after the method
+ /// with self is polled.
+ async fn baz_async(&'a self, (x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn baz_sync(&'a self, (x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore and unused bindings within and outwith more complex patterns are
+ /// dropped after the method with self is polled.
+ async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+}
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let _ = fut.as_mut().poll(&mut cx);
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ // Free functions (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+ assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| bar_sync(D("x", l.clone()), D("_", l.clone())));
+ assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| baz_sync((D("x", l.clone()), D("_", l.clone()))));
+ assert_drop_order_after_poll(
+ |l| {
+ foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+
+ // Methods w/out self (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())));
+ assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())));
+ assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))));
+ assert_drop_order_after_poll(
+ |l| {
+ Foo::foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ Foo::foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+
+ // Methods (see doc comment on function for what it tests).
+ let b = Bar(Default::default());
+ assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())));
+ assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())));
+ assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))));
+ assert_drop_order_after_poll(
+ |l| {
+ b.foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ b.foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+}
diff --git a/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs b/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
new file mode 100644
index 000000000..15cc9fbc8
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
@@ -0,0 +1,176 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![deny(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_must_use)]
+#![allow(path_statements)]
+
+// Test that the drop order for locals in a fn and async fn matches up.
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::pin::Pin;
+use std::rc::Rc;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+struct NeverReady;
+
+impl Future for NeverReady {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+async fn simple_variable_declaration_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ NeverReady.await;
+}
+
+fn simple_variable_declaration_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+}
+
+async fn varable_completely_contained_within_block_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ async {
+ let x = D("x", l.clone());
+ }
+ .await;
+ let y = D("y", l.clone());
+ NeverReady.await;
+}
+
+fn varable_completely_contained_within_block_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ {
+ let x = D("x", l.clone());
+ }
+ let y = D("y", l.clone());
+}
+
+async fn variables_moved_into_separate_blocks_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ async move { x }.await;
+ async move { y }.await;
+ NeverReady.await;
+}
+
+fn variables_moved_into_separate_blocks_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ {
+ x
+ };
+ {
+ y
+ };
+}
+
+async fn variables_moved_into_same_block_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ async move {
+ x;
+ y;
+ };
+ NeverReady.await;
+}
+
+fn variables_moved_into_same_block_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ {
+ x;
+ y;
+ };
+ return;
+}
+
+async fn move_after_current_await_doesnt_affect_order(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ NeverReady.await;
+ async move {
+ x;
+ y;
+ };
+}
+
+fn assert_drop_order_after_cancel<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let _ = fut.as_mut().poll(&mut cx);
+ drop(fut);
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ assert_drop_order_after_cancel(
+ simple_variable_declaration_async,
+ simple_variable_declaration_sync,
+ );
+ assert_drop_order_after_cancel(
+ varable_completely_contained_within_block_async,
+ varable_completely_contained_within_block_sync,
+ );
+ assert_drop_order_after_cancel(
+ variables_moved_into_separate_blocks_async,
+ variables_moved_into_separate_blocks_sync,
+ );
+ assert_drop_order_after_cancel(
+ variables_moved_into_same_block_async,
+ variables_moved_into_same_block_sync,
+ );
+ assert_drop_order_after_cancel(
+ move_after_current_await_doesnt_affect_order,
+ simple_variable_declaration_sync,
+ );
+}
diff --git a/tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
new file mode 100644
index 000000000..edfecb910
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
@@ -0,0 +1,98 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+// revisions: default nomiropt
+//[nomiropt]compile-flags: -Z mir-opt-level=0
+
+#![allow(unused_variables)]
+
+// Test the drop order for parameters relative to local variables and
+// temporaries created in the tail return expression of the function
+// body. In particular, check that this drop order is the same between
+// an `async fn` and an ordinary `fn`. See #64512.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
+///
+/// Expected order:
+/// - `z`
+/// - temp
+/// - `y`
+/// - `x`
+async fn foo_async(x: D, _y: D) {
+ let l = x.1.clone();
+ let z = D("z", l.clone());
+ l.borrow_mut().push(DropOrder::Function);
+ helper_async(&D("temp", l)).await
+}
+
+async fn helper_async(v: &D) { }
+
+fn foo_sync(x: D, _y: D) {
+ let l = x.1.clone();
+ let z = D("z", l.clone());
+ l.borrow_mut().push(DropOrder::Function);
+ helper_sync(&D("temp", l))
+}
+
+fn helper_sync(v: &D) { }
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let r = fut.as_mut().poll(&mut cx);
+
+ assert!(match r {
+ std::task::Poll::Ready(()) => true,
+ _ => false,
+ });
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ // Free functions (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+}
diff --git a/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs
new file mode 100644
index 000000000..79dedb1ba
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) {
+ assert_eq!(__arg1, (1, 2, 3)); //~ ERROR cannot find value `__arg1` in this scope [E0425]
+ assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425]
+}
+
+async fn baz_async(ref mut x: u32, ref y: u32) {
+ assert_eq!(__arg0, 1); //~ ERROR cannot find value `__arg0` in this scope [E0425]
+ assert_eq!(__arg1, 2); //~ ERROR cannot find value `__arg1` in this scope [E0425]
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr
new file mode 100644
index 000000000..aa04a613f
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find value `__arg1` in this scope
+ --> $DIR/drop-order-locals-are-hidden.rs:4:16
+ |
+LL | assert_eq!(__arg1, (1, 2, 3));
+ | ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `__arg2` in this scope
+ --> $DIR/drop-order-locals-are-hidden.rs:5:16
+ |
+LL | assert_eq!(__arg2, 4);
+ | ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `__arg0` in this scope
+ --> $DIR/drop-order-locals-are-hidden.rs:9:16
+ |
+LL | assert_eq!(__arg0, 1);
+ | ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `__arg1` in this scope
+ --> $DIR/drop-order-locals-are-hidden.rs:10:16
+ |
+LL | assert_eq!(__arg1, 2);
+ | ^^^^^^ not found in this scope
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/async-await/drop-order/drop-order-when-cancelled.rs b/tests/ui/async-await/drop-order/drop-order-when-cancelled.rs
new file mode 100644
index 000000000..cfd68bc0d
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-when-cancelled.rs
@@ -0,0 +1,309 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+// revisions: default nomiropt
+//[nomiropt]compile-flags: -Z mir-opt-level=0
+
+// Test that the drop order for parameters in a fn and async fn matches up. Also test that
+// parameters (used or unused) are not dropped until the async fn is cancelled.
+// This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs
+
+#![allow(unused_variables)]
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::rc::Rc;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+struct NeverReady;
+
+impl Future for NeverReady {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+/// Check that unused bindings are dropped after the function is polled.
+async fn foo_async(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+}
+
+fn foo_sync(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore patterns are dropped after the function is polled.
+async fn bar_async(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+}
+
+fn bar_sync(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore patterns within more complex patterns are dropped after the function
+/// is polled.
+async fn baz_async((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+}
+
+fn baz_sync((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+/// Check that underscore and unused bindings within and outwith more complex patterns are dropped
+/// after the function is polled.
+async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+}
+
+fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+}
+
+struct Foo;
+
+impl Foo {
+ /// Check that unused bindings are dropped after the method is polled.
+ async fn foo_async(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn foo_sync(x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns are dropped after the method is polled.
+ async fn bar_async(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn bar_sync(x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns within more complex patterns are dropped after the method
+ /// is polled.
+ async fn baz_async((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn baz_sync((x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore and unused bindings within and outwith more complex patterns are
+ /// dropped after the method is polled.
+ async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+}
+
+struct Bar<'a>(PhantomData<&'a ()>);
+
+impl<'a> Bar<'a> {
+ /// Check that unused bindings are dropped after the method with self is polled.
+ async fn foo_async(&'a self, x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn foo_sync(&'a self, x: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns are dropped after the method with self is polled.
+ async fn bar_async(&'a self, x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn bar_sync(&'a self, x: D, _: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore patterns within more complex patterns are dropped after the method
+ /// with self is polled.
+ async fn baz_async(&'a self, (x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn baz_sync(&'a self, (x, _): (D, D)) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+
+ /// Check that underscore and unused bindings within and outwith more complex patterns are
+ /// dropped after the method with self is polled.
+ async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ NeverReady.await;
+ }
+
+ fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+ x.1.borrow_mut().push(DropOrder::Function);
+ }
+}
+
+fn assert_drop_order_after_cancel<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let _ = fut.as_mut().poll(&mut cx);
+
+ // Parameters are never dropped until the future completes.
+ assert_eq!(*actual_order.borrow(), vec![DropOrder::Function]);
+
+ drop(fut);
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ // Free functions (see doc comment on function for what it tests).
+ assert_drop_order_after_cancel(
+ |l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| foo_sync(D("x", l.clone()), D("_y", l.clone())),
+ );
+ assert_drop_order_after_cancel(
+ |l| bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| bar_sync(D("x", l.clone()), D("_", l.clone())),
+ );
+ assert_drop_order_after_cancel(
+ |l| baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| baz_sync((D("x", l.clone()), D("_", l.clone()))),
+ );
+ assert_drop_order_after_cancel(
+ |l| {
+ foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+
+ // Methods w/out self (see doc comment on function for what it tests).
+ assert_drop_order_after_cancel(
+ |l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())),
+ );
+ assert_drop_order_after_cancel(
+ |l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())),
+ );
+ assert_drop_order_after_cancel(
+ |l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))),
+ );
+ assert_drop_order_after_cancel(
+ |l| {
+ Foo::foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ Foo::foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+
+ // Methods (see doc comment on function for what it tests).
+ let b = Bar(Default::default());
+ assert_drop_order_after_cancel(
+ |l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())),
+ );
+ assert_drop_order_after_cancel(
+ |l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
+ |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())),
+ );
+ assert_drop_order_after_cancel(
+ |l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
+ |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))),
+ );
+ assert_drop_order_after_cancel(
+ |l| {
+ b.foobar_async(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ |l| {
+ b.foobar_sync(
+ D("x", l.clone()),
+ (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+ D("_", l.clone()),
+ D("_y", l.clone()),
+ )
+ },
+ );
+}
diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.rs b/tests/ui/async-await/drop-track-bad-field-in-fru.rs
new file mode 100644
index 000000000..28ad77675
--- /dev/null
+++ b/tests/ui/async-await/drop-track-bad-field-in-fru.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Zdrop-tracking
+// edition: 2021
+
+fn main() {}
+
+async fn foo() {
+ None { value: (), ..Default::default() }.await;
+ //~^ ERROR `Option<_>` is not a future
+ //~| ERROR variant `Option<_>::None` has no field named `value`
+}
diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
new file mode 100644
index 000000000..819b64ad7
--- /dev/null
+++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
@@ -0,0 +1,23 @@
+error[E0559]: variant `Option<_>::None` has no field named `value`
+ --> $DIR/drop-track-bad-field-in-fru.rs:7:12
+ |
+LL | None { value: (), ..Default::default() }.await;
+ | ^^^^^ `Option<_>::None` does not have this field
+
+error[E0277]: `Option<_>` is not a future
+ --> $DIR/drop-track-bad-field-in-fru.rs:7:45
+ |
+LL | None { value: (), ..Default::default() }.await;
+ | ^^^^^^
+ | |
+ | `Option<_>` is not a future
+ | help: remove the `.await`
+ |
+ = help: the trait `Future` is not implemented for `Option<_>`
+ = note: Option<_> must be a future or must implement `IntoFuture` to be awaited
+ = note: required for `Option<_>` to implement `IntoFuture`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0559.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.rs b/tests/ui/async-await/drop-track-field-assign-nonsend.rs
new file mode 100644
index 000000000..b6c0fda15
--- /dev/null
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.rs
@@ -0,0 +1,45 @@
+// Derived from an ICE found in tokio-xmpp during a crater run.
+// edition:2021
+// compile-flags: -Zdrop-tracking
+
+#![allow(dead_code)]
+
+#[derive(Clone)]
+struct InfoResult {
+ node: Option<std::rc::Rc<String>>
+}
+
+struct Agent {
+ info_result: InfoResult
+}
+
+impl Agent {
+ async fn handle(&mut self) {
+ let mut info = self.info_result.clone();
+ info.node = None;
+ let element = parse_info(info);
+ let _ = send_element(element).await;
+ }
+}
+
+struct Element {
+}
+
+async fn send_element(_: Element) {}
+
+fn parse(_: &[u8]) -> Result<(), ()> {
+ Ok(())
+}
+
+fn parse_info(_: InfoResult) -> Element {
+ Element { }
+}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+ let agent = Agent { info_result: InfoResult { node: None } };
+ // FIXME: It would be nice for this to work. See #94067.
+ assert_send(agent.handle());
+ //~^ cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr
new file mode 100644
index 000000000..d95483c81
--- /dev/null
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr
@@ -0,0 +1,25 @@
+error: future cannot be sent between threads safely
+ --> $DIR/drop-track-field-assign-nonsend.rs:43:17
+ |
+LL | assert_send(agent.handle());
+ | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/drop-track-field-assign-nonsend.rs:21:38
+ |
+LL | let mut info = self.info_result.clone();
+ | -------- has type `InfoResult` which is not `Send`
+...
+LL | let _ = send_element(element).await;
+ | ^^^^^^ await occurs here, with `mut info` maybe used later
+LL | }
+ | - `mut info` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/drop-track-field-assign-nonsend.rs:38:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/drop-track-field-assign.rs b/tests/ui/async-await/drop-track-field-assign.rs
new file mode 100644
index 000000000..3a393cd16
--- /dev/null
+++ b/tests/ui/async-await/drop-track-field-assign.rs
@@ -0,0 +1,44 @@
+// Derived from an ICE found in tokio-xmpp during a crater run.
+// edition:2021
+// compile-flags: -Zdrop-tracking
+// build-pass
+
+#![allow(dead_code)]
+
+#[derive(Clone)]
+struct InfoResult {
+ node: Option<String>
+}
+
+struct Agent {
+ info_result: InfoResult
+}
+
+impl Agent {
+ async fn handle(&mut self) {
+ let mut info = self.info_result.clone();
+ info.node = Some("bar".into());
+ let element = parse_info(info);
+ let _ = send_element(element).await;
+ }
+}
+
+struct Element {
+}
+
+async fn send_element(_: Element) {}
+
+fn parse(_: &[u8]) -> Result<(), ()> {
+ Ok(())
+}
+
+fn parse_info(_: InfoResult) -> Element {
+ Element { }
+}
+
+fn main() {
+ let mut agent = Agent {
+ info_result: InfoResult { node: None }
+ };
+ let _ = agent.handle();
+}
diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs
new file mode 100644
index 000000000..7f7294295
--- /dev/null
+++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs
@@ -0,0 +1,106 @@
+// compile-flags: -Zdrop-tracking
+// incremental
+// edition: 2021
+
+use std::future::*;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::task::*;
+
+fn send<T: Send>(_: T) {}
+
+pub trait Stream {
+ type Item;
+
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
+}
+
+struct Empty<T>(PhantomData<fn() -> T>);
+
+impl<T> Stream for Empty<T> {
+ type Item = T;
+
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+ todo!()
+ }
+}
+
+pub trait FnOnce1<A> {
+ type Output;
+ fn call_once(self, arg: A) -> Self::Output;
+}
+
+impl<T, A, R> FnOnce1<A> for T
+where
+ T: FnOnce(A) -> R,
+{
+ type Output = R;
+ fn call_once(self, arg: A) -> R {
+ self(arg)
+ }
+}
+
+pub trait FnMut1<A>: FnOnce1<A> {
+ fn call_mut(&mut self, arg: A) -> Self::Output;
+}
+
+impl<T, A, R> FnMut1<A> for T
+where
+ T: FnMut(A) -> R,
+{
+ fn call_mut(&mut self, arg: A) -> R {
+ self(arg)
+ }
+}
+
+struct Map<St, F>(St, F);
+
+impl<St, F> Stream for Map<St, F>
+where
+ St: Stream,
+ F: FnMut1<St::Item>,
+{
+ type Item = F::Output;
+
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+ todo!()
+ }
+}
+
+struct FuturesOrdered<T: Future>(PhantomData<fn() -> T::Output>);
+
+pub struct Buffered<St: Stream>(St, FuturesOrdered<St::Item>, usize)
+where
+ St::Item: Future;
+
+impl<St> Stream for Buffered<St>
+where
+ St: Stream,
+ St::Item: Future,
+{
+ type Item = <St::Item as Future>::Output;
+
+ fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+ todo!()
+ }
+}
+
+struct Next<'a, T: ?Sized>(&'a T);
+
+impl<St: ?Sized + Stream + Unpin> Future for Next<'_, St> {
+ type Output = Option<St::Item>;
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ todo!()
+ }
+}
+
+fn main() {
+ send(async {
+ //~^ ERROR implementation of `FnOnce` is not general enough
+ //~| ERROR implementation of `FnOnce` is not general enough
+ //~| ERROR implementation of `FnOnce` is not general enough
+ //~| ERROR implementation of `FnOnce` is not general enough
+ Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+ });
+}
diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
new file mode 100644
index 000000000..aa9a22e9e
--- /dev/null
+++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
@@ -0,0 +1,62 @@
+error: implementation of `FnOnce` is not general enough
+ --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+ |
+LL | / send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | | });
+ | |______^ implementation of `FnOnce` is not general enough
+ |
+ = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: implementation of `FnOnce` is not general enough
+ --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+ |
+LL | / send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | | });
+ | |______^ implementation of `FnOnce` is not general enough
+ |
+ = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: implementation of `FnOnce` is not general enough
+ --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+ |
+LL | / send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | | });
+ | |______^ implementation of `FnOnce` is not general enough
+ |
+ = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: implementation of `FnOnce` is not general enough
+ --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5
+ |
+LL | / send(async {
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await
+LL | | });
+ | |______^ implementation of `FnOnce` is not general enough
+ |
+ = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but it actually implements `FnOnce<(&(),)>`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.rs b/tests/ui/async-await/edition-deny-async-fns-2015.rs
new file mode 100644
index 000000000..6bd6d879a
--- /dev/null
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.rs
@@ -0,0 +1,38 @@
+// edition:2015
+
+async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
+
+fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in Rust 2015
+
+async fn async_baz() { //~ ERROR `async fn` is not permitted in Rust 2015
+ async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015
+}
+
+struct Foo {}
+
+impl Foo {
+ async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
+}
+
+trait Bar {
+ async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
+ //~^ ERROR functions in traits cannot be declared `async`
+}
+
+fn main() {
+ macro_rules! accept_item { ($x:item) => {} }
+
+ accept_item! {
+ async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
+ }
+
+ accept_item! {
+ impl Foo {
+ async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015
+ }
+ }
+
+ let inside_closure = || {
+ async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015
+ };
+}
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.stderr
new file mode 100644
index 000000000..ba918eb28
--- /dev/null
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -0,0 +1,98 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:3:1
+ |
+LL | async fn foo() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:5:12
+ |
+LL | fn baz() { async fn foo() {} }
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:7:1
+ |
+LL | async fn async_baz() {
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:8:5
+ |
+LL | async fn bar() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:14:5
+ |
+LL | async fn foo() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:18:5
+ |
+LL | async fn foo() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:36:9
+ |
+LL | async fn bar() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:26:9
+ |
+LL | async fn foo() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/edition-deny-async-fns-2015.rs:31:13
+ |
+LL | async fn bar() {}
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/edition-deny-async-fns-2015.rs:18:5
+ |
+LL | async fn foo() {}
+ | -----^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/tests/ui/async-await/expansion-in-attrs.rs b/tests/ui/async-await/expansion-in-attrs.rs
new file mode 100644
index 000000000..af77c3463
--- /dev/null
+++ b/tests/ui/async-await/expansion-in-attrs.rs
@@ -0,0 +1,13 @@
+// check-pass
+// edition:2018
+
+macro_rules! with_doc {
+ ($doc: expr) => {
+ #[doc = $doc]
+ async fn f() {}
+ };
+}
+
+with_doc!(concat!(""));
+
+fn main() {}
diff --git a/tests/ui/async-await/feature-async-closure.rs b/tests/ui/async-await/feature-async-closure.rs
new file mode 100644
index 000000000..d07116b13
--- /dev/null
+++ b/tests/ui/async-await/feature-async-closure.rs
@@ -0,0 +1,8 @@
+// edition:2018
+// gate-test-async_closure
+
+fn f() {
+ let _ = async || {}; //~ ERROR async closures are unstable
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/feature-async-closure.stderr b/tests/ui/async-await/feature-async-closure.stderr
new file mode 100644
index 000000000..485a838b6
--- /dev/null
+++ b/tests/ui/async-await/feature-async-closure.stderr
@@ -0,0 +1,13 @@
+error[E0658]: async closures are unstable
+ --> $DIR/feature-async-closure.rs:5:13
+ |
+LL | let _ = async || {};
+ | ^^^^^
+ |
+ = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+ = help: add `#![feature(async_closure)]` to the crate attributes to enable
+ = help: to use an async block, remove the `||`: `async {`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/feature-gate-async_fn_in_trait.rs b/tests/ui/async-await/feature-gate-async_fn_in_trait.rs
new file mode 100644
index 000000000..792f378cb
--- /dev/null
+++ b/tests/ui/async-await/feature-gate-async_fn_in_trait.rs
@@ -0,0 +1,25 @@
+// edition:2021
+
+// RPITIT is not enough to allow use of async functions
+#![allow(incomplete_features)]
+#![feature(return_position_impl_trait_in_trait)]
+
+trait T {
+ async fn foo(); //~ ERROR functions in traits cannot be declared `async`
+}
+
+// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also
+// feature-gate-return_position_impl_trait_in_trait.rs)
+trait T2 {
+ async fn foo() -> impl Sized; //~ ERROR functions in traits cannot be declared `async`
+}
+
+trait T3 {
+ fn foo() -> impl std::future::Future<Output = ()>;
+}
+
+impl T3 for () {
+ async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/feature-gate-async_fn_in_trait.stderr b/tests/ui/async-await/feature-gate-async_fn_in_trait.stderr
new file mode 100644
index 000000000..2a5fbd1ec
--- /dev/null
+++ b/tests/ui/async-await/feature-gate-async_fn_in_trait.stderr
@@ -0,0 +1,42 @@
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/feature-gate-async_fn_in_trait.rs:8:5
+ |
+LL | async fn foo();
+ | -----^^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/feature-gate-async_fn_in_trait.rs:14:5
+ |
+LL | async fn foo() -> impl Sized;
+ | -----^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/feature-gate-async_fn_in_trait.rs:22:5
+ |
+LL | async fn foo() {}
+ | -----^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0706`.
diff --git a/tests/ui/async-await/feature-self-return-type.rs b/tests/ui/async-await/feature-self-return-type.rs
new file mode 100644
index 000000000..41f887430
--- /dev/null
+++ b/tests/ui/async-await/feature-self-return-type.rs
@@ -0,0 +1,28 @@
+// edition:2018
+#![feature(impl_trait_projections)]
+
+// This test checks that we emit the correct borrowck error when `Self` is used as a return type.
+// See #61949 for context.
+
+pub struct Foo<'a> {
+ pub bar: &'a i32,
+}
+
+impl<'a> Foo<'a> {
+ pub async fn new(_bar: &'a i32) -> Self {
+ Foo {
+ bar: &22
+ }
+ }
+}
+
+pub async fn foo() {
+ let x = {
+ let bar = 22;
+ Foo::new(&bar).await
+ //~^ ERROR `bar` does not live long enough
+ };
+ drop(x);
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/feature-self-return-type.stderr b/tests/ui/async-await/feature-self-return-type.stderr
new file mode 100644
index 000000000..892468368
--- /dev/null
+++ b/tests/ui/async-await/feature-self-return-type.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `bar` does not live long enough
+ --> $DIR/feature-self-return-type.rs:22:18
+ |
+LL | let x = {
+ | - borrow later stored here
+LL | let bar = 22;
+LL | Foo::new(&bar).await
+ | ^^^^ borrowed value does not live long enough
+LL |
+LL | };
+ | - `bar` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/async-await/futures-api.rs b/tests/ui/async-await/futures-api.rs
new file mode 100644
index 000000000..a7da058de
--- /dev/null
+++ b/tests/ui/async-await/futures-api.rs
@@ -0,0 +1,61 @@
+// run-pass
+
+// aux-build:arc_wake.rs
+
+extern crate arc_wake;
+
+use std::future::Future;
+use std::pin::Pin;
+use std::sync::{
+ Arc,
+ atomic::{self, AtomicUsize},
+};
+use std::task::{
+ Context, Poll,
+};
+use arc_wake::ArcWake;
+
+struct Counter {
+ wakes: AtomicUsize,
+}
+
+impl ArcWake for Counter {
+ fn wake(self: Arc<Self>) {
+ Self::wake_by_ref(&self)
+ }
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+ }
+}
+
+struct MyFuture;
+
+impl Future for MyFuture {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ // Wake twice
+ let waker = cx.waker();
+ waker.wake_by_ref();
+ waker.wake_by_ref();
+ Poll::Ready(())
+ }
+}
+
+fn test_waker() {
+ let counter = Arc::new(Counter {
+ wakes: AtomicUsize::new(0),
+ });
+ let waker = ArcWake::into_waker(counter.clone());
+ assert_eq!(2, Arc::strong_count(&counter));
+ {
+ let mut context = Context::from_waker(&waker);
+ assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&mut context));
+ assert_eq!(2, counter.wakes.load(atomic::Ordering::SeqCst));
+ }
+ drop(waker);
+ assert_eq!(1, Arc::strong_count(&counter));
+}
+
+fn main() {
+ test_waker();
+}
diff --git a/tests/ui/async-await/generator-desc.rs b/tests/ui/async-await/generator-desc.rs
new file mode 100644
index 000000000..500812016
--- /dev/null
+++ b/tests/ui/async-await/generator-desc.rs
@@ -0,0 +1,16 @@
+// edition:2018
+#![feature(async_closure)]
+use std::future::Future;
+
+async fn one() {}
+async fn two() {}
+
+fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+fn main() {
+ fun(async {}, async {});
+ //~^ ERROR mismatched types
+ fun(one(), two());
+ //~^ ERROR mismatched types
+ fun((async || {})(), (async || {})());
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/async-await/generator-desc.stderr b/tests/ui/async-await/generator-desc.stderr
new file mode 100644
index 000000000..963c6ba57
--- /dev/null
+++ b/tests/ui/async-await/generator-desc.stderr
@@ -0,0 +1,63 @@
+error[E0308]: mismatched types
+ --> $DIR/generator-desc.rs:10:19
+ |
+LL | fun(async {}, async {});
+ | -------- ^^^^^^^^
+ | | |
+ | | expected `async` block, found a different `async` block
+ | | arguments to this function are incorrect
+ | the expected `async` block
+ |
+ = note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]`
+ found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
+note: function defined here
+ --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+
+error[E0308]: mismatched types
+ --> $DIR/generator-desc.rs:12:16
+ |
+LL | fun(one(), two());
+ | --- ^^^^^ expected opaque type, found a different opaque type
+ | |
+ | arguments to this function are incorrect
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/generator-desc.rs:5:16
+ |
+LL | async fn one() {}
+ | ^ checked the `Output` of this `async fn`, expected opaque type
+note: while checking the return type of the `async fn`
+ --> $DIR/generator-desc.rs:6:16
+ |
+LL | async fn two() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
+ found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
+ = help: consider `await`ing on both `Future`s
+ = note: distinct uses of `impl Trait` result in different opaque types
+note: function defined here
+ --> $DIR/generator-desc.rs:8:4
+ |
+LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+ | ^^^ -----
+
+error[E0308]: mismatched types
+ --> $DIR/generator-desc.rs:14:26
+ |
+LL | fun((async || {})(), (async || {})());
+ | --- -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
+ | | |
+ | | the expected `async` closure body
+ | arguments to this function are incorrect
+ |
+ = note: expected `async` closure body `[async closure body@$DIR/generator-desc.rs:14:19: 14:21]`
+ found `async` closure body `[async closure body@$DIR/generator-desc.rs:14:36: 14:38]`
+note: function defined here
+ --> $DIR/generator-desc.rs:8:4
+ |
+LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+ | ^^^ -----
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/generator-not-future.rs b/tests/ui/async-await/generator-not-future.rs
new file mode 100644
index 000000000..37d7cfa6f
--- /dev/null
+++ b/tests/ui/async-await/generator-not-future.rs
@@ -0,0 +1,45 @@
+// edition:2018
+#![feature(generators, generator_trait)]
+
+use std::future::Future;
+use std::ops::Generator;
+
+async fn async_fn() {}
+fn returns_async_block() -> impl Future<Output = ()> {
+ async {}
+}
+fn returns_generator() -> impl Generator<(), Yield = (), Return = ()> {
+ || {
+ let _: () = yield ();
+ }
+}
+
+fn takes_future(_f: impl Future<Output = ()>) {}
+fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
+
+fn main() {
+ // okay:
+ takes_future(async_fn());
+ takes_future(returns_async_block());
+ takes_future(async {});
+ takes_generator(returns_generator());
+ takes_generator(|| {
+ let _: () = yield ();
+ });
+
+ // async futures are not generators:
+ takes_generator(async_fn());
+ //~^ ERROR the trait bound
+ takes_generator(returns_async_block());
+ //~^ ERROR the trait bound
+ takes_generator(async {});
+ //~^ ERROR the trait bound
+
+ // generators are not futures:
+ takes_future(returns_generator());
+ //~^ ERROR is not a future
+ takes_future(|ctx| {
+ //~^ ERROR is not a future
+ ctx = yield ();
+ });
+}
diff --git a/tests/ui/async-await/generator-not-future.stderr b/tests/ui/async-await/generator-not-future.stderr
new file mode 100644
index 000000000..1b81b461f
--- /dev/null
+++ b/tests/ui/async-await/generator-not-future.stderr
@@ -0,0 +1,81 @@
+error[E0277]: the trait bound `impl Future<Output = ()>: Generator<_>` is not satisfied
+ --> $DIR/generator-not-future.rs:31:21
+ |
+LL | takes_generator(async_fn());
+ | --------------- ^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future<Output = ()>`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `takes_generator`
+ --> $DIR/generator-not-future.rs:18:39
+ |
+LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
+
+error[E0277]: the trait bound `impl Future<Output = ()>: Generator<_>` is not satisfied
+ --> $DIR/generator-not-future.rs:33:21
+ |
+LL | takes_generator(returns_async_block());
+ | --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future<Output = ()>`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `takes_generator`
+ --> $DIR/generator-not-future.rs:18:39
+ |
+LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
+
+error[E0277]: the trait bound `[async block@$DIR/generator-not-future.rs:35:21: 35:29]: Generator<_>` is not satisfied
+ --> $DIR/generator-not-future.rs:35:21
+ |
+LL | takes_generator(async {});
+ | --------------- ^^^^^^^^ the trait `Generator<_>` is not implemented for `[async block@$DIR/generator-not-future.rs:35:21: 35:29]`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `takes_generator`
+ --> $DIR/generator-not-future.rs:18:39
+ |
+LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
+
+error[E0277]: `impl Generator<Yield = (), Return = ()>` is not a future
+ --> $DIR/generator-not-future.rs:39:18
+ |
+LL | takes_future(returns_generator());
+ | ------------ ^^^^^^^^^^^^^^^^^^^ `impl Generator<Yield = (), Return = ()>` is not a future
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Future` is not implemented for `impl Generator<Yield = (), Return = ()>`
+ = note: impl Generator<Yield = (), Return = ()> must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `takes_future`
+ --> $DIR/generator-not-future.rs:17:26
+ |
+LL | fn takes_future(_f: impl Future<Output = ()>) {}
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
+
+error[E0277]: `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future
+ --> $DIR/generator-not-future.rs:41:18
+ |
+LL | takes_future(|ctx| {
+ | _____------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | | ctx = yield ();
+LL | | });
+ | |_____^ `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future
+ |
+ = help: the trait `Future` is not implemented for `[generator@$DIR/generator-not-future.rs:41:18: 41:23]`
+ = note: [generator@$DIR/generator-not-future.rs:41:18: 41:23] must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `takes_future`
+ --> $DIR/generator-not-future.rs:17:26
+ |
+LL | fn takes_future(_f: impl Future<Output = ()>) {}
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/generics-and-bounds.rs b/tests/ui/async-await/generics-and-bounds.rs
new file mode 100644
index 000000000..963b19b34
--- /dev/null
+++ b/tests/ui/async-await/generics-and-bounds.rs
@@ -0,0 +1,88 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+// compile-flags: --crate-type lib
+
+use std::future::Future;
+
+pub async fn simple_generic<T>() {}
+
+pub trait Foo {
+ fn foo(&self) {}
+}
+
+struct FooType;
+impl Foo for FooType {}
+
+pub async fn call_generic_bound<F: Foo>(f: F) {
+ f.foo()
+}
+
+pub async fn call_where_clause<F>(f: F)
+where
+ F: Foo,
+{
+ f.foo()
+}
+
+pub async fn call_impl_trait(f: impl Foo) {
+ f.foo()
+}
+
+pub async fn call_with_ref(f: &impl Foo) {
+ f.foo()
+}
+
+pub fn async_fn_with_same_generic_params_unifies() {
+ let mut a = call_generic_bound(FooType);
+ a = call_generic_bound(FooType);
+
+ let mut b = call_where_clause(FooType);
+ b = call_where_clause(FooType);
+
+ let mut c = call_impl_trait(FooType);
+ c = call_impl_trait(FooType);
+
+ let f_one = FooType;
+ let f_two = FooType;
+ let mut d = call_with_ref(&f_one);
+ d = call_with_ref(&f_two);
+}
+
+pub fn simple_generic_block<T>() -> impl Future<Output = ()> {
+ async move {}
+}
+
+pub fn call_generic_bound_block<F: Foo>(f: F) -> impl Future<Output = ()> {
+ async move { f.foo() }
+}
+
+pub fn call_where_clause_block<F>(f: F) -> impl Future<Output = ()>
+where
+ F: Foo,
+{
+ async move { f.foo() }
+}
+
+pub fn call_impl_trait_block(f: impl Foo) -> impl Future<Output = ()> {
+ async move { f.foo() }
+}
+
+pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a {
+ async move { f.foo() }
+}
+
+pub fn async_block_with_same_generic_params_unifies() {
+ let mut a = call_generic_bound_block(FooType);
+ a = call_generic_bound_block(FooType);
+
+ let mut b = call_where_clause_block(FooType);
+ b = call_where_clause_block(FooType);
+
+ let mut c = call_impl_trait_block(FooType);
+ c = call_impl_trait_block(FooType);
+
+ let f_one = FooType;
+ let f_two = FooType;
+ let mut d = call_with_ref_block(&f_one);
+ d = call_with_ref_block(&f_two);
+}
diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs
new file mode 100644
index 000000000..974f5aaff
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-associated-types.rs
@@ -0,0 +1,24 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(impl_trait_projections)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b {
+ type MyAssoc;
+
+ async fn foo(&'a self, key: &'b T) -> Self::MyAssoc;
+}
+
+impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
+ type MyAssoc = (&'a U, &'b T);
+
+ async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ (self, key)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-associated-types2.rs b/tests/ui/async-await/in-trait/async-associated-types2.rs
new file mode 100644
index 000000000..e546a0579
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-associated-types2.rs
@@ -0,0 +1,30 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ type Fut<'a>: Future<Output = i32>
+ where
+ Self: 'a;
+
+ fn foo<'a>(&'a self) -> Self::Fut<'a>;
+}
+
+impl MyTrait for i32 {
+ type Fut<'a> = impl Future<Output = i32> + 'a
+ where
+ Self: 'a;
+
+ fn foo<'a>(&'a self) -> Self::Fut<'a> {
+ async {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
new file mode 100644
index 000000000..38ba29718
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+ fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+}
+
+impl MyTrait for i32 {
+ async fn foo(&self) -> i32 {
+ //~^ ERROR method `foo` has an incompatible type for trait
+ *self
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
new file mode 100644
index 000000000..13e722255
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -0,0 +1,17 @@
+error[E0053]: method `foo` has an incompatible type for trait
+ --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
+ |
+LL | async fn foo(&self) -> i32 {
+ | ^^^ expected struct `Pin`, found opaque type
+ |
+note: type in trait
+ --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
+ |
+LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
+ found signature `fn(&i32) -> impl Future<Output = i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
new file mode 100644
index 000000000..1b1b3cffd
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+ //~^ ERROR method `foo` should be async
+ Box::pin(async { *self })
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644
index 000000000..60fa534a6
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+ --> $DIR/async-example-desugared-boxed.rs:15:5
+ |
+LL | async fn foo(&self) -> i32;
+ | --------------------------- required because the trait method is async
+...
+LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
new file mode 100644
index 000000000..81e1e59a3
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
@@ -0,0 +1,37 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::Poll;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+#[derive(Clone)]
+struct MyFuture(i32);
+
+impl Future for MyFuture {
+ type Output = i32;
+ fn poll(
+ self: Pin<&mut Self>,
+ _: &mut std::task::Context<'_>,
+ ) -> Poll<<Self as Future>::Output> {
+ Poll::Ready(self.0)
+ }
+}
+
+impl MyTrait for i32 {
+ // FIXME: this should eventually require `#[refine]` to compile, because it also provides
+ // `Clone`.
+ fn foo(&self) -> impl Future<Output = i32> + Clone {
+ MyFuture(*self)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
new file mode 100644
index 000000000..feeda719e
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
@@ -0,0 +1,21 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ fn foo(&self) -> impl Future<Output = i32> + '_;
+}
+
+impl MyTrait for i32 {
+ // This will break once a PR that implements #102745 is merged
+ async fn foo(&self) -> i32 {
+ *self
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
new file mode 100644
index 000000000..71473e745
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
@@ -0,0 +1,29 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::task::Poll;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+struct MyFuture;
+impl Future for MyFuture {
+ type Output = i32;
+ fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(0)
+ }
+}
+
+impl MyTrait for u32 {
+ fn foo(&self) -> MyFuture {
+ //~^ ERROR method `foo` should be async
+ MyFuture
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644
index 000000000..567a36a86
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+ --> $DIR/async-example-desugared-manual.rs:23:5
+ |
+LL | async fn foo(&self) -> i32;
+ | --------------------------- required because the trait method is async
+...
+LL | fn foo(&self) -> MyFuture {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs
new file mode 100644
index 000000000..fb92ec786
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared.rs
@@ -0,0 +1,20 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ fn foo(&self) -> impl Future<Output = i32> + '_ {
+ async { *self }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs
new file mode 100644
index 000000000..abf94ef74
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example.rs
@@ -0,0 +1,32 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+ async fn bar(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ async fn foo(&self) -> i32 {
+ *self
+ }
+
+ async fn bar(&self) -> i32 {
+ self.foo().await
+ }
+}
+
+fn main() {
+ let x = 5;
+ // Calling from non-async context
+ let _ = x.foo();
+ let _ = x.bar();
+ // Calling from async block in non-async context
+ async {
+ let _: i32 = x.foo().await;
+ let _: i32 = x.bar().await;
+ };
+}
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
new file mode 100644
index 000000000..a73d55adf
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
@@ -0,0 +1,21 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+use std::hash::Hash;
+
+trait MyTrait<T, U> {
+ async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+}
+
+impl<T, U> MyTrait<T, U> for (T, U) {
+ async fn foo(&self) -> &(T, U) {
+ self
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
new file mode 100644
index 000000000..f1f0d7e59
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+ |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+ --> $DIR/async-generics-and-bounds.rs:12:18
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/async-generics-and-bounds.rs:12:18
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs
new file mode 100644
index 000000000..67000e577
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.rs
@@ -0,0 +1,18 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<T, U> {
+ async fn foo(&self) -> &(T, U);
+}
+
+impl<T, U> MyTrait<T, U> for (T, U) {
+ async fn foo(&self) -> &(T, U) {
+ self
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr
new file mode 100644
index 000000000..2f0556456
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+ |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+ --> $DIR/async-generics.rs:9:18
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/async-generics.rs:9:18
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
new file mode 100644
index 000000000..d5481d277
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
@@ -0,0 +1,19 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait MyTrait<'a, 'b, T> {
+ async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
+}
+
+impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
+ async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ (self, key)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs
new file mode 100644
index 000000000..f298e45d2
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-lifetimes.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<'a, 'b, T> {
+ async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
+}
+
+impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
+ async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ (self, key)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs
new file mode 100644
index 000000000..6839abd38
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<T> {
+ async fn foo_recursive(&self, n: usize) -> T;
+}
+
+impl<T> MyTrait<T> for T where T: Copy {
+ async fn foo_recursive(&self, n: usize) -> T {
+ //~^ ERROR recursion in an `async fn` requires boxing
+ if n > 0 {
+ self.foo_recursive(n - 1).await
+ } else {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
new file mode 100644
index 000000000..cab173bdd
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/async-recursive-generic.rs:11:48
+ |
+LL | async fn foo_recursive(&self, n: usize) -> T {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs
new file mode 100644
index 000000000..61119f809
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ async fn foo_recursive(&self, n: usize) -> i32;
+}
+
+impl MyTrait for i32 {
+ async fn foo_recursive(&self, n: usize) -> i32 {
+ //~^ ERROR recursion in an `async fn` requires boxing
+ if n > 0 {
+ self.foo_recursive(n - 1).await
+ } else {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr
new file mode 100644
index 000000000..9feff37b3
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/async-recursive.rs:11:48
+ |
+LL | async fn foo_recursive(&self, n: usize) -> i32 {
+ | ^^^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/in-trait/bad-signatures.rs b/tests/ui/async-await/in-trait/bad-signatures.rs
new file mode 100644
index 000000000..b86f1d1c1
--- /dev/null
+++ b/tests/ui/async-await/in-trait/bad-signatures.rs
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait MyTrait {
+ async fn bar(&abc self);
+ //~^ ERROR expected identifier, found keyword `self`
+ //~| ERROR expected one of `:`, `@`, or `|`, found keyword `self`
+}
+
+impl MyTrait for () {
+ async fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/bad-signatures.stderr b/tests/ui/async-await/in-trait/bad-signatures.stderr
new file mode 100644
index 000000000..e0ba7b53e
--- /dev/null
+++ b/tests/ui/async-await/in-trait/bad-signatures.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `self`
+ --> $DIR/bad-signatures.rs:7:23
+ |
+LL | async fn bar(&abc self);
+ | ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `self`
+ --> $DIR/bad-signatures.rs:7:23
+ |
+LL | async fn bar(&abc self);
+ | -----^^^^
+ | | |
+ | | expected one of `:`, `@`, or `|`
+ | help: declare the type after the parameter binding: `<identifier>: <type>`
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/bad-signatures.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs
new file mode 100644
index 000000000..6b3b14201
--- /dev/null
+++ b/tests/ui/async-await/in-trait/early-bound-1.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+ async fn foo(&mut self);
+}
+
+struct MyFoo<'a>(&'a mut ());
+
+impl<'a> Foo for MyFoo<'a> {
+ async fn foo(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs
new file mode 100644
index 000000000..270443229
--- /dev/null
+++ b/tests/ui/async-await/in-trait/early-bound-2.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+ async fn foo(&mut self);
+}
+
+impl<T: Foo> Foo for &mut T {
+ async fn foo(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs
new file mode 100644
index 000000000..9598d53bc
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs
@@ -0,0 +1,17 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ fn foo(&self) -> i32 {
+ //~^ ERROR: method `foo` should be async
+ *self
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr
new file mode 100644
index 000000000..579801d0f
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+ --> $DIR/fn-not-async-err.rs:11:5
+ |
+LL | async fn foo(&self) -> i32;
+ | --------------------------- required because the trait method is async
+...
+LL | fn foo(&self) -> i32 {
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
new file mode 100644
index 000000000..2c4ed5535
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -0,0 +1,19 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ fn foo(&self) -> impl Future<Output = i32> {
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
+ async { *self }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
new file mode 100644
index 000000000..f591f1847
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
@@ -0,0 +1,12 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
+ --> $DIR/fn-not-async-err2.rs:13:22
+ |
+LL | fn foo(&self) -> impl Future<Output = i32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs
new file mode 100644
index 000000000..52bceb3cc
--- /dev/null
+++ b/tests/ui/async-await/in-trait/implied-bounds.rs
@@ -0,0 +1,13 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait TcpStack {
+ type Connection<'a>: Sized where Self: 'a;
+ fn connect<'a>(&'a self) -> Self::Connection<'a>;
+ async fn async_connect<'a>(&'a self) -> Self::Connection<'a>;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs
new file mode 100644
index 000000000..f61b34ed9
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-102138.rs
@@ -0,0 +1,46 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+async fn yield_now() {}
+
+trait AsyncIterator {
+ type Item;
+ async fn next(&mut self) -> Option<Self::Item>;
+}
+
+struct YieldingRange {
+ counter: u32,
+ stop: u32,
+}
+
+impl AsyncIterator for YieldingRange {
+ type Item = u32;
+
+ async fn next(&mut self) -> Option<Self::Item> {
+ if self.counter == self.stop {
+ None
+ } else {
+ let c = self.counter;
+ self.counter += 1;
+ yield_now().await;
+ Some(c)
+ }
+ }
+}
+
+async fn async_main() {
+ let mut x = YieldingRange { counter: 0, stop: 10 };
+
+ while let Some(v) = x.next().await {
+ println!("Hi: {v}");
+ }
+}
+
+fn main() {
+ let _ = async_main();
+}
diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs
new file mode 100644
index 000000000..9a35f6515
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-102219.rs
@@ -0,0 +1,10 @@
+// compile-flags:--crate-type=lib
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait T {
+ async fn foo();
+}
diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs
new file mode 100644
index 000000000..49c3e9fee
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-102310.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait SpiDevice {
+ async fn transaction<F, R>(&mut self);
+}
+
+impl SpiDevice for () {
+ async fn transaction<F, R>(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs
new file mode 100644
index 000000000..e396df4e5
--- /dev/null
+++ b/tests/ui/async-await/in-trait/issue-104678.rs
@@ -0,0 +1,31 @@
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+pub trait Pool {
+ type Conn;
+
+ async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+ &'a self,
+ callback: F,
+ ) -> ();
+}
+
+pub struct PoolImpl;
+pub struct ConnImpl;
+
+impl Pool for PoolImpl {
+ type Conn = ConnImpl;
+
+ async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+ &'a self,
+ _callback: F,
+ ) -> () {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.rs b/tests/ui/async-await/in-trait/lifetime-mismatch.rs
new file mode 100644
index 000000000..45ede193c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/lifetime-mismatch.rs
@@ -0,0 +1,20 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait MyTrait {
+ async fn foo<'a>(&self);
+ async fn bar(&self);
+}
+
+impl MyTrait for i32 {
+ async fn foo(&self) {}
+ //~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration
+
+ async fn bar(&self) {
+ self.foo();
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr
new file mode 100644
index 000000000..d87adcc78
--- /dev/null
+++ b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr
@@ -0,0 +1,21 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/lifetime-mismatch.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+ --> $DIR/lifetime-mismatch.rs:12:17
+ |
+LL | async fn foo<'a>(&self);
+ | ---- lifetimes in impl do not match this method in trait
+...
+LL | async fn foo(&self) {}
+ | ^ lifetimes do not match method in trait
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/async-await/in-trait/missing-send-bound.rs b/tests/ui/async-await/in-trait/missing-send-bound.rs
new file mode 100644
index 000000000..78922b59b
--- /dev/null
+++ b/tests/ui/async-await/in-trait/missing-send-bound.rs
@@ -0,0 +1,21 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait Foo {
+ async fn bar();
+}
+
+async fn test<T: Foo>() {
+ T::bar().await;
+}
+
+fn test2<T: Foo>() {
+ assert_is_send(test::<T>());
+ //~^ ERROR future cannot be sent between threads safely
+}
+
+fn assert_is_send(_: impl Send) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr
new file mode 100644
index 000000000..5cedf3ddb
--- /dev/null
+++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr
@@ -0,0 +1,29 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/missing-send-bound.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: future cannot be sent between threads safely
+ --> $DIR/missing-send-bound.rs:15:20
+ |
+LL | assert_is_send(test::<T>());
+ | ^^^^^^^^^^^ future returned by `test` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/missing-send-bound.rs:11:5
+ |
+LL | T::bar().await;
+ | ^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
+note: required by a bound in `assert_is_send`
+ --> $DIR/missing-send-bound.rs:19:27
+ |
+LL | fn assert_is_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_is_send`
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs
new file mode 100644
index 000000000..41d72ebb4
--- /dev/null
+++ b/tests/ui/async-await/in-trait/nested-rpit.rs
@@ -0,0 +1,19 @@
+// edition: 2021
+// known-bug: #105197
+// failure-status:101
+// dont-check-compiler-stderr
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::marker::PhantomData;
+
+trait Lockable<K, V> {
+ async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
+}
+
+struct Guard<'a>(PhantomData<&'a ()>);
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/object-safety.rs
new file mode 100644
index 000000000..a8bc35f7e
--- /dev/null
+++ b/tests/ui/async-await/in-trait/object-safety.rs
@@ -0,0 +1,13 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait Foo {
+ async fn foo(&self);
+}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ //~^ ERROR the trait `Foo` cannot be made into an object
+}
diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr
new file mode 100644
index 000000000..0b318f71f
--- /dev/null
+++ b/tests/ui/async-await/in-trait/object-safety.stderr
@@ -0,0 +1,27 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/object-safety.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0038]: the trait `Foo` cannot be made into an object
+ --> $DIR/object-safety.rs:11:12
+ |
+LL | let x: &dyn Foo = todo!();
+ | ^^^^^^^^ `Foo` 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-safety.rs:7:14
+ |
+LL | trait Foo {
+ | --- this trait cannot be made into an object...
+LL | async fn foo(&self);
+ | ^^^ ...because method `foo` is `async`
+ = help: consider moving `foo` to another trait
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs
new file mode 100644
index 000000000..3446761d1
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs
@@ -0,0 +1,14 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait A {
+ async fn e() {
+ Ok(())
+ //~^ ERROR mismatched types
+ //~| HELP consider using a semicolon here
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
new file mode 100644
index 000000000..5a9b15e54
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -0,0 +1,23 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/return-type-suggestion.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+ --> $DIR/return-type-suggestion.rs:8:9
+ |
+LL | Ok(())
+ | ^^^^^^- help: consider using a semicolon here: `;`
+ | |
+ | expected `()`, found enum `Result`
+ |
+ = note: expected unit type `()`
+ found enum `Result<(), _>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed
new file mode 100644
index 000000000..055800d23
--- /dev/null
+++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+// edition:2018
+
+// Regression test for issue 79694
+
+fn main() {
+ let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
+}
diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs
new file mode 100644
index 000000000..e8be16516
--- /dev/null
+++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+// edition:2018
+
+// Regression test for issue 79694
+
+fn main() {
+ let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
+}
diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr b/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr
new file mode 100644
index 000000000..5367b986d
--- /dev/null
+++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr
@@ -0,0 +1,13 @@
+error: the order of `move` and `async` is incorrect
+ --> $DIR/incorrect-move-async-order-issue-79694.rs:7:13
+ |
+LL | let _ = move async { };
+ | ^^^^^^^^^^
+ |
+help: try switching the order
+ |
+LL | let _ = async move { };
+ | ~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/interior-with-const-generic-expr.rs b/tests/ui/async-await/interior-with-const-generic-expr.rs
new file mode 100644
index 000000000..86ba7582d
--- /dev/null
+++ b/tests/ui/async-await/interior-with-const-generic-expr.rs
@@ -0,0 +1,26 @@
+// edition:2018
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+#![allow(unused)]
+
+fn main() {
+ let x = test();
+}
+
+fn concat<const A: usize, const B: usize>(a: [f32; A], b: [f32; B]) -> [f32; A + B] {
+ todo!()
+}
+
+async fn reverse<const A: usize>(x: [f32; A]) -> [f32; A] {
+ todo!()
+}
+
+async fn test() {
+ let a = [0.0];
+ let b = [1.0, 2.0];
+ let ab = concat(a,b);
+ let ba = reverse(ab).await;
+ println!("{:?}", ba);
+}
diff --git a/tests/ui/async-await/issue-101715.rs b/tests/ui/async-await/issue-101715.rs
new file mode 100644
index 000000000..1be5d0248
--- /dev/null
+++ b/tests/ui/async-await/issue-101715.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+struct S;
+
+impl S {
+ fn very_long_method_name_the_longest_method_name_in_the_whole_universe(self) {}
+}
+
+async fn foo() {
+ S.very_long_method_name_the_longest_method_name_in_the_whole_universe()
+ .await
+ //~^ error: `()` is not a future
+ //~| help: remove the `.await`
+ //~| help: the trait `Future` is not implemented for `()`
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr
new file mode 100644
index 000000000..a0e8d2a89
--- /dev/null
+++ b/tests/ui/async-await/issue-101715.stderr
@@ -0,0 +1,16 @@
+error[E0277]: `()` is not a future
+ --> $DIR/issue-101715.rs:11:9
+ |
+LL | .await
+ | ^^^^^^
+ | |
+ | `()` is not a future
+ | help: remove the `.await`
+ |
+ = help: the trait `Future` is not implemented for `()`
+ = note: () must be a future or must implement `IntoFuture` to be awaited
+ = note: required for `()` to implement `IntoFuture`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-105501.rs b/tests/ui/async-await/issue-105501.rs
new file mode 100644
index 000000000..f30d2a9d8
--- /dev/null
+++ b/tests/ui/async-await/issue-105501.rs
@@ -0,0 +1,165 @@
+// check-pass
+// edition:2018
+
+// This is a regression test for https://github.com/rust-lang/rust/issues/105501.
+// It was minified from the published `msf-ice:0.2.1` crate which failed in a crater run.
+// A faulty compiler was triggering a `higher-ranked lifetime error`:
+//
+// > could not prove `[async block@...]: Send`
+
+use mini_futures::Stream;
+
+fn is_send(_: impl Send) {}
+
+pub fn main() {
+ let fut = async {
+ let mut stream = mini_futures::iter([()])
+ .then(|_| async {})
+ .map(|_| async { None })
+ .buffered()
+ .filter_map(std::future::ready);
+
+ stream.next().await
+ };
+
+ is_send(async move {
+ let _: Option<()> = fut.await;
+ });
+}
+
+// this is a simplified subset of `futures::StreamExt` and related types
+mod mini_futures {
+ use std::future::Future;
+ use std::pin::Pin;
+ use std::task::{Context, Poll};
+
+ pub fn iter<I>(_: I) -> Iter<I::IntoIter>
+ where
+ I: IntoIterator,
+ {
+ todo!()
+ }
+
+ pub trait Stream {
+ type Item;
+
+ fn then<Fut, F>(self, _: F) -> Then<Self, Fut, F>
+ where
+ F: FnMut(Self::Item) -> Fut,
+ Fut: Future,
+ Self: Sized,
+ {
+ todo!()
+ }
+
+ fn map<T, F>(self, _: F) -> Map<Self, F>
+ where
+ F: FnMut(Self::Item) -> T,
+ Self: Sized,
+ {
+ todo!()
+ }
+
+ fn buffered(self) -> Buffered<Self>
+ where
+ Self::Item: Future,
+ Self: Sized,
+ {
+ todo!()
+ }
+
+ fn filter_map<Fut, T, F>(self, _: F) -> FilterMap<Self, Fut, F>
+ where
+ F: FnMut(Self::Item) -> Fut,
+ Fut: Future<Output = Option<T>>,
+ Self: Sized,
+ {
+ todo!()
+ }
+
+ fn next(&mut self) -> Next<'_, Self> {
+ todo!()
+ }
+ }
+
+ pub struct Iter<I> {
+ __: I,
+ }
+ impl<I> Stream for Iter<I>
+ where
+ I: Iterator,
+ {
+ type Item = I::Item;
+ }
+
+ pub struct Then<St, Fut, F> {
+ __: (St, Fut, F),
+ }
+ impl<St, Fut, F> Stream for Then<St, Fut, F>
+ where
+ St: Stream,
+ F: FnMut(St::Item) -> Fut,
+ Fut: Future,
+ {
+ type Item = Fut::Output;
+ }
+
+ pub struct Map<St, F> {
+ __: (St, F),
+ }
+ impl<St, F> Stream for Map<St, F>
+ where
+ St: Stream,
+ F: FnMut1<St::Item>,
+ {
+ type Item = F::Output;
+ }
+
+ pub trait FnMut1<A> {
+ type Output;
+ }
+ impl<T, A, R> FnMut1<A> for T
+ where
+ T: FnMut(A) -> R,
+ {
+ type Output = R;
+ }
+
+ pub struct Buffered<St>
+ where
+ St: Stream,
+ St::Item: Future,
+ {
+ __: (St, St::Item),
+ }
+ impl<St> Stream for Buffered<St>
+ where
+ St: Stream,
+ St::Item: Future,
+ {
+ type Item = <St::Item as Future>::Output;
+ }
+
+ pub struct FilterMap<St, Fut, F> {
+ __: (St, Fut, F),
+ }
+ impl<St, Fut, F, T> Stream for FilterMap<St, Fut, F>
+ where
+ St: Stream,
+ F: FnMut1<St::Item, Output = Fut>,
+ Fut: Future<Output = Option<T>>,
+ {
+ type Item = T;
+ }
+
+ pub struct Next<'a, St: ?Sized> {
+ __: &'a mut St,
+ }
+ impl<St: ?Sized + Stream> Future for Next<'_, St> {
+ type Output = Option<St::Item>;
+
+ fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
+ todo!()
+ }
+ }
+}
diff --git a/tests/ui/async-await/issue-107036.rs b/tests/ui/async-await/issue-107036.rs
new file mode 100644
index 000000000..6a22de2c9
--- /dev/null
+++ b/tests/ui/async-await/issue-107036.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-107036.rs
+// edition:2021
+// check-pass
+
+extern crate issue_107036;
+use issue_107036::S;
+
+async fn f() {
+ S{}.f().await;
+}
+
+fn main() {
+ let _ = f();
+}
diff --git a/tests/ui/async-await/issue-54239-private-type-triggers-lint.rs b/tests/ui/async-await/issue-54239-private-type-triggers-lint.rs
new file mode 100644
index 000000000..16cf7ad52
--- /dev/null
+++ b/tests/ui/async-await/issue-54239-private-type-triggers-lint.rs
@@ -0,0 +1,17 @@
+// Regression test for #54239, shouldn't trigger lint.
+// check-pass
+// edition:2018
+
+#![deny(missing_debug_implementations)]
+
+struct DontLookAtMe(i32);
+
+async fn secret() -> DontLookAtMe {
+ DontLookAtMe(41)
+}
+
+pub async fn looking() -> i32 { // Shouldn't trigger lint here.
+ secret().await.0
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs
new file mode 100644
index 000000000..61f6ed1b7
--- /dev/null
+++ b/tests/ui/async-await/issue-60709.rs
@@ -0,0 +1,28 @@
+// This used to compile the future down to ud2, due to uninhabited types being
+// handled incorrectly in generators.
+// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
+
+// run-pass
+// ignore-asmjs wasm2js does not support source maps yet
+
+use std::future::Future;
+use std::task::Poll;
+use std::task::Context;
+use std::pin::Pin;
+use std::rc::Rc;
+
+struct Never();
+impl Future for Never {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+fn main() {
+ let fut = async {
+ let _rc = Rc::new(()); // Also crashes with Arc
+ Never().await;
+ };
+ let _bla = fut; // Moving the future is required.
+}
diff --git a/tests/ui/async-await/issue-61076.rs b/tests/ui/async-await/issue-61076.rs
new file mode 100644
index 000000000..750fad839
--- /dev/null
+++ b/tests/ui/async-await/issue-61076.rs
@@ -0,0 +1,97 @@
+// edition:2018
+
+use core::future::Future;
+use core::pin::Pin;
+use core::task::{Context, Poll};
+
+struct T;
+
+struct Tuple(i32);
+
+struct Struct {
+ a: i32
+}
+
+impl Struct {
+ fn method(&self) {}
+}
+
+impl Future for Struct {
+ type Output = Struct;
+ fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { Poll::Pending }
+}
+
+impl Future for Tuple {
+ type Output = Tuple;
+ fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { Poll::Pending }
+}
+
+impl Future for T {
+ type Output = Result<(), ()>;
+
+ fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+async fn foo() -> Result<(), ()> {
+ Ok(())
+}
+
+async fn bar() -> Result<(), ()> {
+ foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
+ //~^ NOTE the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>`
+ //~| HELP the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>`
+ //~| HELP consider `await`ing on the `Future`
+ //~| NOTE in this expansion of desugaring of operator `?`
+ //~| NOTE in this expansion of desugaring of operator `?`
+ //~| NOTE in this expansion of desugaring of operator `?`
+ Ok(())
+}
+
+async fn struct_() -> Struct {
+ Struct { a: 1 }
+}
+
+async fn tuple() -> Tuple {
+ //~^ NOTE checked the `Output` of this `async fn`, expected opaque type
+ //~| NOTE while checking the return type of the `async fn`
+ //~| NOTE in this expansion of desugaring of `async` block or function
+ Tuple(1i32)
+}
+
+async fn baz() -> Result<(), ()> {
+ let t = T;
+ t?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
+ //~^ NOTE the `?` operator cannot be applied to type `T`
+ //~| HELP the trait `Try` is not implemented for `T`
+ //~| HELP consider `await`ing on the `Future`
+ //~| NOTE in this expansion of desugaring of operator `?`
+ //~| NOTE in this expansion of desugaring of operator `?`
+ //~| NOTE in this expansion of desugaring of operator `?`
+
+
+ let _: i32 = tuple().0; //~ ERROR no field `0`
+ //~^ HELP consider `await`ing on the `Future`
+ //~| NOTE field not available in `impl Future`
+
+ let _: i32 = struct_().a; //~ ERROR no field `a`
+ //~^ HELP consider `await`ing on the `Future`
+ //~| NOTE field not available in `impl Future`
+
+ struct_().method(); //~ ERROR no method named
+ //~^ NOTE method not found in `impl Future<Output = Struct>`
+ //~| HELP consider `await`ing on the `Future`
+ Ok(())
+}
+
+async fn match_() {
+ match tuple() { //~ HELP consider `await`ing on the `Future`
+ //~^ NOTE this expression has type `impl Future<Output = Tuple>`
+ Tuple(_) => {} //~ ERROR mismatched types
+ //~^ NOTE expected opaque type, found struct `Tuple`
+ //~| NOTE expected opaque type `impl Future<Output = Tuple>`
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr
new file mode 100644
index 000000000..33839ea59
--- /dev/null
+++ b/tests/ui/async-await/issue-61076.stderr
@@ -0,0 +1,82 @@
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/issue-61076.rs:42:5
+ |
+LL | foo()?;
+ | ^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>`
+ |
+ = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>`
+help: consider `await`ing on the `Future`
+ |
+LL | foo().await?;
+ | ++++++
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/issue-61076.rs:65:5
+ |
+LL | t?;
+ | ^^ the `?` operator cannot be applied to type `T`
+ |
+ = help: the trait `Try` is not implemented for `T`
+help: consider `await`ing on the `Future`
+ |
+LL | t.await?;
+ | ++++++
+
+error[E0609]: no field `0` on type `impl Future<Output = Tuple>`
+ --> $DIR/issue-61076.rs:74:26
+ |
+LL | let _: i32 = tuple().0;
+ | ^ field not available in `impl Future`, but it is available in its `Output`
+ |
+help: consider `await`ing on the `Future` and access the field of its `Output`
+ |
+LL | let _: i32 = tuple().await.0;
+ | ++++++
+
+error[E0609]: no field `a` on type `impl Future<Output = Struct>`
+ --> $DIR/issue-61076.rs:78:28
+ |
+LL | let _: i32 = struct_().a;
+ | ^ field not available in `impl Future`, but it is available in its `Output`
+ |
+help: consider `await`ing on the `Future` and access the field of its `Output`
+ |
+LL | let _: i32 = struct_().await.a;
+ | ++++++
+
+error[E0599]: no method named `method` found for opaque type `impl Future<Output = Struct>` in the current scope
+ --> $DIR/issue-61076.rs:82:15
+ |
+LL | struct_().method();
+ | ^^^^^^ method not found in `impl Future<Output = Struct>`
+ |
+help: consider `await`ing on the `Future` and calling the method on its `Output`
+ |
+LL | struct_().await.method();
+ | ++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-61076.rs:91:9
+ |
+LL | match tuple() {
+ | ------- this expression has type `impl Future<Output = Tuple>`
+LL |
+LL | Tuple(_) => {}
+ | ^^^^^^^^ expected opaque type, found struct `Tuple`
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-61076.rs:56:21
+ |
+LL | async fn tuple() -> Tuple {
+ | ^^^^^ checked the `Output` of this `async fn`, expected opaque type
+ = note: expected opaque type `impl Future<Output = Tuple>`
+ found struct `Tuple`
+help: consider `await`ing on the `Future`
+ |
+LL | match tuple().await {
+ | ++++++
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0599, E0609.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-61452.rs b/tests/ui/async-await/issue-61452.rs
new file mode 100644
index 000000000..9381251ad
--- /dev/null
+++ b/tests/ui/async-await/issue-61452.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+pub async fn f(x: Option<usize>) {
+ x.take();
+ //~^ ERROR cannot borrow `x` as mutable, as it is not declared as mutable [E0596]
+}
+
+pub async fn g(x: usize) {
+ x += 1;
+ //~^ ERROR cannot assign twice to immutable variable `x` [E0384]
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-61452.stderr b/tests/ui/async-await/issue-61452.stderr
new file mode 100644
index 000000000..bf5044328
--- /dev/null
+++ b/tests/ui/async-await/issue-61452.stderr
@@ -0,0 +1,26 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+ --> $DIR/issue-61452.rs:4:5
+ |
+LL | x.take();
+ | ^^^^^^^^ cannot borrow as mutable
+ |
+help: consider changing this to be mutable
+ |
+LL | pub async fn f(mut x: Option<usize>) {
+ | +++
+
+error[E0384]: cannot assign twice to immutable variable `x`
+ --> $DIR/issue-61452.rs:9:5
+ |
+LL | pub async fn g(x: usize) {
+ | -
+ | |
+ | first assignment to `x`
+ | help: consider making this binding mutable: `mut x`
+LL | x += 1;
+ | ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0384, E0596.
+For more information about an error, try `rustc --explain E0384`.
diff --git a/tests/ui/async-await/issue-61793.rs b/tests/ui/async-await/issue-61793.rs
new file mode 100644
index 000000000..9180e1d81
--- /dev/null
+++ b/tests/ui/async-await/issue-61793.rs
@@ -0,0 +1,16 @@
+// This testcase used to ICE in codegen due to inconsistent field reordering
+// in the generator state, claiming a ZST field was after a non-ZST field,
+// while those two fields were at the same offset (which is impossible).
+// That is, memory ordering of `(X, ())`, but offsets of `((), X)`.
+
+// build-pass
+// edition:2018
+
+async fn foo<F>(_: &(), _: F) {}
+
+fn main() {
+ foo(&(), || {});
+ async {
+ foo(&(), || {}).await;
+ };
+}
diff --git a/tests/ui/async-await/issue-61949-self-return-type.rs b/tests/ui/async-await/issue-61949-self-return-type.rs
new file mode 100644
index 000000000..d73dbc6e8
--- /dev/null
+++ b/tests/ui/async-await/issue-61949-self-return-type.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// gate-test-impl_trait_projections
+
+// This test checks that `Self` is prohibited as a return type. See #61949 for context.
+
+pub struct Foo<'a> {
+ pub bar: &'a i32,
+}
+
+impl<'a> Foo<'a> {
+ pub async fn new(_bar: &'a i32) -> Self {
+ //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+ Foo {
+ bar: &22
+ }
+ }
+}
+
+async fn foo() {
+ let x = {
+ let bar = 22;
+ Foo::new(&bar).await
+ //~^ ERROR `bar` does not live long enough
+ };
+ drop(x);
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issue-61949-self-return-type.stderr b/tests/ui/async-await/issue-61949-self-return-type.stderr
new file mode 100644
index 000000000..638b197bc
--- /dev/null
+++ b/tests/ui/async-await/issue-61949-self-return-type.stderr
@@ -0,0 +1,25 @@
+error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+ --> $DIR/issue-61949-self-return-type.rs:11:40
+ |
+LL | pub async fn new(_bar: &'a i32) -> Self {
+ | ^^^^ help: consider spelling out the type instead: `Foo<'a>`
+ |
+ = note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
+ = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
+
+error[E0597]: `bar` does not live long enough
+ --> $DIR/issue-61949-self-return-type.rs:22:18
+ |
+LL | let x = {
+ | - borrow later stored here
+LL | let bar = 22;
+LL | Foo::new(&bar).await
+ | ^^^^ borrowed value does not live long enough
+LL |
+LL | };
+ | - `bar` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0597, E0658.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/tests/ui/async-await/issue-62658.rs b/tests/ui/async-await/issue-62658.rs
new file mode 100644
index 000000000..d0af01e0c
--- /dev/null
+++ b/tests/ui/async-await/issue-62658.rs
@@ -0,0 +1,27 @@
+// This test created a generator whose size was not rounded to a multiple of its
+// alignment. This caused an assertion error in codegen.
+
+// build-pass
+// edition:2018
+
+async fn noop() {}
+
+async fn foo() {
+ // This suspend should be the largest variant.
+ {
+ let x = [0u8; 17];
+ noop().await;
+ println!("{:?}", x);
+ }
+
+ // Add one variant that's aligned to 8 bytes.
+ {
+ let x = 0u64;
+ noop().await;
+ println!("{:?}", x);
+ }
+}
+
+fn main() {
+ let _ = foo();
+}
diff --git a/tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs
new file mode 100644
index 000000000..54059b29f
--- /dev/null
+++ b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs
@@ -0,0 +1,19 @@
+// check-pass
+// edition:2018
+
+struct Test(String);
+
+impl Test {
+ async fn borrow_async(&self) {}
+
+ fn with(&mut self, s: &str) -> &mut Self {
+ self.0 = s.into();
+ self
+ }
+}
+
+async fn test() {
+ Test("".to_string()).with("123").borrow_async().await;
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs
new file mode 100644
index 000000000..c5ea2b821
--- /dev/null
+++ b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs
@@ -0,0 +1,12 @@
+// check-pass
+// edition:2018
+
+async fn foo(x: &[Vec<u32>]) -> u32 {
+ 0
+}
+
+async fn bar() {
+ foo(&[vec![123]]).await;
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issue-64130-1-sync.rs b/tests/ui/async-await/issue-64130-1-sync.rs
new file mode 100644
index 000000000..1714cec52
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-1-sync.rs
@@ -0,0 +1,23 @@
+#![feature(negative_impls)]
+// edition:2018
+
+// This tests the specialized async-await-specific error when futures don't implement an
+// auto trait (which is specifically Sync) due to some type that was captured.
+
+struct Foo;
+
+impl !Sync for Foo {}
+
+fn is_sync<T: Sync>(t: T) { }
+
+async fn bar() {
+ let x = Foo;
+ baz().await;
+}
+
+async fn baz() { }
+
+fn main() {
+ is_sync(bar());
+ //~^ ERROR future cannot be shared between threads safely
+}
diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr
new file mode 100644
index 000000000..e205de473
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-1-sync.stderr
@@ -0,0 +1,24 @@
+error: future cannot be shared between threads safely
+ --> $DIR/issue-64130-1-sync.rs:21:13
+ |
+LL | is_sync(bar());
+ | ^^^^^ future returned by `bar` is not `Sync`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
+note: future is not `Sync` as this value is used across an await
+ --> $DIR/issue-64130-1-sync.rs:15:10
+ |
+LL | let x = Foo;
+ | - has type `Foo` which is not `Sync`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_sync`
+ --> $DIR/issue-64130-1-sync.rs:11:15
+ |
+LL | fn is_sync<T: Sync>(t: T) { }
+ | ^^^^ required by this bound in `is_sync`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-2-send.rs b/tests/ui/async-await/issue-64130-2-send.rs
new file mode 100644
index 000000000..7a6e5952c
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-2-send.rs
@@ -0,0 +1,23 @@
+#![feature(negative_impls)]
+// edition:2018
+
+// This tests the specialized async-await-specific error when futures don't implement an
+// auto trait (which is specifically Send) due to some type that was captured.
+
+struct Foo;
+
+impl !Send for Foo {}
+
+fn is_send<T: Send>(t: T) { }
+
+async fn bar() {
+ let x = Foo;
+ baz().await;
+}
+
+async fn baz() { }
+
+fn main() {
+ is_send(bar());
+ //~^ ERROR future cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr
new file mode 100644
index 000000000..2225000e2
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-2-send.stderr
@@ -0,0 +1,24 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-2-send.rs:21:13
+ |
+LL | is_send(bar());
+ | ^^^^^ future returned by `bar` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Foo`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-2-send.rs:15:10
+ |
+LL | let x = Foo;
+ | - has type `Foo` which is not `Send`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/issue-64130-2-send.rs:11:15
+ |
+LL | fn is_send<T: Send>(t: T) { }
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-3-other.rs b/tests/ui/async-await/issue-64130-3-other.rs
new file mode 100644
index 000000000..630fb2c41
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-3-other.rs
@@ -0,0 +1,26 @@
+#![feature(auto_traits)]
+#![feature(negative_impls)]
+// edition:2018
+
+// This tests the unspecialized async-await-specific error when futures don't implement an
+// auto trait (which is not Send or Sync) due to some type that was captured.
+
+auto trait Qux {}
+
+struct Foo;
+
+impl !Qux for Foo {}
+
+fn is_qux<T: Qux>(t: T) {}
+
+async fn bar() {
+ let x = Foo;
+ baz().await;
+}
+
+async fn baz() {}
+
+fn main() {
+ is_qux(bar());
+ //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>`
+}
diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr
new file mode 100644
index 000000000..17867a6a3
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-3-other.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>`
+ --> $DIR/issue-64130-3-other.rs:24:12
+ |
+LL | async fn bar() {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_qux(bar());
+ | ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
+ |
+note: future does not implement `Qux` as this value is used across an await
+ --> $DIR/issue-64130-3-other.rs:18:10
+ |
+LL | let x = Foo;
+ | - has type `Foo` which does not implement `Qux`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_qux`
+ --> $DIR/issue-64130-3-other.rs:14:14
+ |
+LL | fn is_qux<T: Qux>(t: T) {}
+ | ^^^ required by this bound in `is_qux`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr
new file mode 100644
index 000000000..f609e3636
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr
@@ -0,0 +1,26 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-4-async-move.rs:19:17
+ |
+LL | pub fn foo() -> impl Future + Send {
+ | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-4-async-move.rs:25:31
+ |
+LL | match client.status() {
+ | ------ has type `&Client` which is not `Send`
+LL | 200 => {
+LL | let _x = get().await;
+ | ^^^^^^ await occurs here, with `client` maybe used later
+...
+LL | }
+ | - `client` is later dropped here
+help: consider moving this into a `let` binding to create a shorter lived borrow
+ --> $DIR/issue-64130-4-async-move.rs:23:15
+ |
+LL | match client.status() {
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr
new file mode 100644
index 000000000..f609e3636
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr
@@ -0,0 +1,26 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-4-async-move.rs:19:17
+ |
+LL | pub fn foo() -> impl Future + Send {
+ | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-4-async-move.rs:25:31
+ |
+LL | match client.status() {
+ | ------ has type `&Client` which is not `Send`
+LL | 200 => {
+LL | let _x = get().await;
+ | ^^^^^^ await occurs here, with `client` maybe used later
+...
+LL | }
+ | - `client` is later dropped here
+help: consider moving this into a `let` binding to create a shorter lived borrow
+ --> $DIR/issue-64130-4-async-move.rs:23:15
+ |
+LL | match client.status() {
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-4-async-move.rs b/tests/ui/async-await/issue-64130-4-async-move.rs
new file mode 100644
index 000000000..a38428fc0
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-4-async-move.rs
@@ -0,0 +1,32 @@
+// edition:2018
+// revisions: no_drop_tracking drop_tracking
+// [drop_tracking] check-pass
+// [drop_tracking] compile-flags: -Zdrop-tracking=yes
+// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+use std::any::Any;
+use std::future::Future;
+
+struct Client(Box<dyn Any + Send>);
+
+impl Client {
+ fn status(&self) -> u16 {
+ 200
+ }
+}
+
+async fn get() {}
+
+pub fn foo() -> impl Future + Send {
+ //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
+ let client = Client(Box::new(true));
+ async move {
+ match client.status() {
+ 200 => {
+ let _x = get().await;
+ }
+ _ => (),
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.rs b/tests/ui/async-await/issue-64130-non-send-future-diags.rs
new file mode 100644
index 000000000..b652d2391
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-non-send-future-diags.rs
@@ -0,0 +1,25 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
+
+// This tests the basic example case for the async-await-specific error.
+
+use std::sync::Mutex;
+
+fn is_send<T: Send>(t: T) { }
+
+async fn foo() {
+ bar(&Mutex::new(22)).await;
+}
+
+async fn bar(x: &Mutex<u32>) {
+ let g = x.lock().unwrap();
+ baz().await;
+}
+
+async fn baz() { }
+
+fn main() {
+ is_send(foo());
+ //~^ ERROR future cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr
new file mode 100644
index 000000000..1da80d98b
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr
@@ -0,0 +1,24 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-non-send-future-diags.rs:23:13
+ |
+LL | is_send(foo());
+ | ^^^^^ future returned by `foo` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-non-send-future-diags.rs:17:10
+ |
+LL | let g = x.lock().unwrap();
+ | - has type `MutexGuard<'_, u32>` which is not `Send`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `g` maybe used later
+LL | }
+ | - `g` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/issue-64130-non-send-future-diags.rs:9:15
+ |
+LL | fn is_send<T: Send>(t: T) { }
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64391.rs b/tests/ui/async-await/issue-64391.rs
new file mode 100644
index 000000000..c6faad3aa
--- /dev/null
+++ b/tests/ui/async-await/issue-64391.rs
@@ -0,0 +1,14 @@
+// Regression test for Issue #64391. The goal here is that this
+// function compiles. In the past, due to incorrect drop order for
+// temporaries in the tail expression, we failed to compile this
+// example. The drop order itself is directly tested in
+// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`.
+//
+// check-pass
+// edition:2018
+
+async fn add(x: u32, y: u32) -> u32 {
+ async { x + y }.await
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issue-66312.rs b/tests/ui/async-await/issue-66312.rs
new file mode 100644
index 000000000..9224971ec
--- /dev/null
+++ b/tests/ui/async-await/issue-66312.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+trait Test<T> {
+ fn is_some(self: T); //~ ERROR invalid `self` parameter type
+}
+
+async fn f() {
+ let x = Some(2);
+ if x.is_some() {
+ println!("Some");
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr
new file mode 100644
index 000000000..80d294a10
--- /dev/null
+++ b/tests/ui/async-await/issue-66312.stderr
@@ -0,0 +1,12 @@
+error[E0307]: invalid `self` parameter type: T
+ --> $DIR/issue-66312.rs:4:22
+ |
+LL | fn is_some(self: T);
+ | ^
+ |
+ = note: type of `self` must be `Self` or a type that dereferences to it
+ = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/async-await/issue-66387-if-without-else.rs b/tests/ui/async-await/issue-66387-if-without-else.rs
new file mode 100644
index 000000000..3ab8220b4
--- /dev/null
+++ b/tests/ui/async-await/issue-66387-if-without-else.rs
@@ -0,0 +1,10 @@
+// edition:2018
+async fn f() -> i32 {
+ if true { //~ ERROR `if` may be missing an `else` clause
+ return 0;
+ }
+ // An `if` block without `else` causes the type table not to have a type for this expr.
+ // Check that we do not unconditionally access the type table and we don't ICE.
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-66387-if-without-else.stderr b/tests/ui/async-await/issue-66387-if-without-else.stderr
new file mode 100644
index 000000000..8155fcb56
--- /dev/null
+++ b/tests/ui/async-await/issue-66387-if-without-else.stderr
@@ -0,0 +1,14 @@
+error[E0317]: `if` may be missing an `else` clause
+ --> $DIR/issue-66387-if-without-else.rs:3:5
+ |
+LL | / if true {
+LL | | return 0;
+LL | | }
+ | |_____^ expected `i32`, found `()`
+ |
+ = note: `if` expressions without `else` evaluate to `()`
+ = help: consider adding an `else` block that evaluates to the expected type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.rs b/tests/ui/async-await/issue-67252-unnamed-future.rs
new file mode 100644
index 000000000..1a7ff6133
--- /dev/null
+++ b/tests/ui/async-await/issue-67252-unnamed-future.rs
@@ -0,0 +1,24 @@
+// edition:2018
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+fn spawn<T: Send>(_: T) {}
+
+pub struct AFuture;
+impl Future for AFuture{
+ type Output = ();
+
+ fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<()> {
+ unimplemented!()
+ }
+}
+
+async fn foo() {
+ spawn(async { //~ ERROR future cannot be sent between threads safely
+ let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+ AFuture.await;
+ });
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr
new file mode 100644
index 000000000..fcba4410b
--- /dev/null
+++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr
@@ -0,0 +1,28 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-67252-unnamed-future.rs:18:11
+ |
+LL | spawn(async {
+ | ___________^
+LL | | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+LL | | AFuture.await;
+LL | | });
+ | |_____^ future created by async block is not `Send`
+ |
+ = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:18:11: 21:6]`, the trait `Send` is not implemented for `*mut ()`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-67252-unnamed-future.rs:20:16
+ |
+LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+ | -- has type `*mut ()` which is not `Send`
+LL | AFuture.await;
+ | ^^^^^^ await occurs here, with `_a` maybe used later
+LL | });
+ | - `_a` is later dropped here
+note: required by a bound in `spawn`
+ --> $DIR/issue-67252-unnamed-future.rs:6:13
+ |
+LL | fn spawn<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `spawn`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-67651.rs b/tests/ui/async-await/issue-67651.rs
new file mode 100644
index 000000000..bd96a3b70
--- /dev/null
+++ b/tests/ui/async-await/issue-67651.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+trait From {
+ fn from();
+}
+
+impl From for () {
+ fn from() {}
+}
+
+impl From for () {
+//~^ ERROR conflicting implementations of trait
+ fn from() {}
+}
+
+fn bar() -> impl core::future::Future<Output = ()> {
+ async move { From::from() }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-67651.stderr b/tests/ui/async-await/issue-67651.stderr
new file mode 100644
index 000000000..89017f6cc
--- /dev/null
+++ b/tests/ui/async-await/issue-67651.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `From` for type `()`
+ --> $DIR/issue-67651.rs:11:1
+ |
+LL | impl From for () {
+ | ---------------- first implementation here
+...
+LL | impl From for () {
+ | ^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.rs b/tests/ui/async-await/issue-67765-async-diagnostic.rs
new file mode 100644
index 000000000..5093916e7
--- /dev/null
+++ b/tests/ui/async-await/issue-67765-async-diagnostic.rs
@@ -0,0 +1,16 @@
+// edition:2018
+//
+// Regression test for issue #67765
+// Tests that we point at the proper location when giving
+// a lifetime error.
+fn main() {}
+
+async fn func<'a>() -> Result<(), &'a str> {
+ let s = String::new();
+
+ let b = &s[..];
+
+ Err(b)?; //~ ERROR cannot return value referencing local variable `s`
+
+ Ok(())
+}
diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.stderr b/tests/ui/async-await/issue-67765-async-diagnostic.stderr
new file mode 100644
index 000000000..492e06fbb
--- /dev/null
+++ b/tests/ui/async-await/issue-67765-async-diagnostic.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local variable `s`
+ --> $DIR/issue-67765-async-diagnostic.rs:13:5
+ |
+LL | let b = &s[..];
+ | - `s` is borrowed here
+LL |
+LL | Err(b)?;
+ | ^^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/async-await/issue-68112.drop_tracking.stderr b/tests/ui/async-await/issue-68112.drop_tracking.stderr
new file mode 100644
index 000000000..f2802698f
--- /dev/null
+++ b/tests/ui/async-await/issue-68112.drop_tracking.stderr
@@ -0,0 +1,79 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:37:18
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/issue-68112.rs:34:17
+ |
+LL | let _ = non_send_fut.await;
+ | ^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send`
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:46:18
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/issue-68112.rs:43:17
+ |
+LL | let _ = make_non_send_future1().await;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send`
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/issue-68112.rs:65:18
+ |
+LL | require_send(send_fut);
+ | ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this `async fn` body
+ --> $DIR/issue-68112.rs:50:31
+ |
+LL | async fn ready2<T>(t: T) -> T {
+ | _______________________________^
+LL | | t
+LL | | }
+ | |_^
+note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:53:31
+ |
+LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
+note: required because it's used within this `async` block
+ --> $DIR/issue-68112.rs:60:20
+ |
+LL | let send_fut = async {
+ | ____________________^
+LL | | let non_send_fut = make_non_send_future2();
+LL | | let _ = non_send_fut.await;
+LL | | ready(0).await;
+LL | | };
+ | |_____^
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-68112.no_drop_tracking.stderr b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr
new file mode 100644
index 000000000..38eb85b30
--- /dev/null
+++ b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr
@@ -0,0 +1,79 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:37:18
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/issue-68112.rs:34:17
+ |
+LL | let _ = non_send_fut.await;
+ | ^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send`
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:46:18
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/issue-68112.rs:43:17
+ |
+LL | let _ = make_non_send_future1().await;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send`
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/issue-68112.rs:65:18
+ |
+LL | require_send(send_fut);
+ | ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this `async fn` body
+ --> $DIR/issue-68112.rs:50:31
+ |
+LL | async fn ready2<T>(t: T) -> T {
+ | _______________________________^
+LL | | t
+LL | | }
+ | |_^
+note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:53:31
+ |
+LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
+note: required because it's used within this `async` block
+ --> $DIR/issue-68112.rs:60:20
+ |
+LL | let send_fut = async {
+ | ____________________^
+LL | | let non_send_fut = make_non_send_future2();
+LL | | let _ = non_send_fut.await;
+LL | | ready(0).await;
+LL | | };
+ | |_____^
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-68112.rs b/tests/ui/async-await/issue-68112.rs
new file mode 100644
index 000000000..9c705137a
--- /dev/null
+++ b/tests/ui/async-await/issue-68112.rs
@@ -0,0 +1,69 @@
+// edition:2018
+// revisions: no_drop_tracking drop_tracking
+// [drop_tracking] compile-flags: -Zdrop-tracking=yes
+// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+
+use std::{
+ cell::RefCell,
+ future::Future,
+ pin::Pin,
+ sync::Arc,
+ task::{Context, Poll},
+};
+
+fn require_send(_: impl Send) {}
+
+struct Ready<T>(Option<T>);
+impl<T> Future for Ready<T> {
+ type Output = T;
+ fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
+ Poll::Ready(self.0.take().unwrap())
+ }
+}
+fn ready<T>(t: T) -> Ready<T> {
+ Ready(Some(t))
+}
+
+fn make_non_send_future1() -> impl Future<Output = Arc<RefCell<i32>>> {
+ ready(Arc::new(RefCell::new(0)))
+}
+
+fn test1() {
+ let send_fut = async {
+ let non_send_fut = make_non_send_future1();
+ let _ = non_send_fut.await;
+ ready(0).await;
+ };
+ require_send(send_fut);
+ //~^ ERROR future cannot be sent between threads
+}
+
+fn test1_no_let() {
+ let send_fut = async {
+ let _ = make_non_send_future1().await;
+ ready(0).await;
+ };
+ require_send(send_fut);
+ //~^ ERROR future cannot be sent between threads
+}
+
+async fn ready2<T>(t: T) -> T {
+ t
+}
+fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
+ ready2(Arc::new(RefCell::new(0)))
+}
+
+// Ideally this test would have diagnostics similar to the test above, but right
+// now it doesn't.
+fn test2() {
+ let send_fut = async {
+ let non_send_fut = make_non_send_future2();
+ let _ = non_send_fut.await;
+ ready(0).await;
+ };
+ require_send(send_fut);
+ //~^ ERROR `RefCell<i32>` cannot be shared between threads safely
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-68523-start.rs b/tests/ui/async-await/issue-68523-start.rs
new file mode 100644
index 000000000..2ced88a16
--- /dev/null
+++ b/tests/ui/async-await/issue-68523-start.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+#![feature(start)]
+
+#[start]
+pub async fn start(_: isize, _: *const *const u8) -> isize {
+//~^ ERROR `start` is not allowed to be `async`
+ 0
+}
diff --git a/tests/ui/async-await/issue-68523-start.stderr b/tests/ui/async-await/issue-68523-start.stderr
new file mode 100644
index 000000000..3a0a3b5de
--- /dev/null
+++ b/tests/ui/async-await/issue-68523-start.stderr
@@ -0,0 +1,9 @@
+error[E0752]: `start` is not allowed to be `async`
+ --> $DIR/issue-68523-start.rs:6:1
+ |
+LL | pub async fn start(_: isize, _: *const *const u8) -> isize {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `start` is not allowed to be `async`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0752`.
diff --git a/tests/ui/async-await/issue-68523.rs b/tests/ui/async-await/issue-68523.rs
new file mode 100644
index 000000000..7a67661a0
--- /dev/null
+++ b/tests/ui/async-await/issue-68523.rs
@@ -0,0 +1,6 @@
+// edition:2018
+
+async fn main() -> Result<i32, ()> {
+//~^ ERROR `main` function is not allowed to be `async`
+ Ok(1)
+}
diff --git a/tests/ui/async-await/issue-68523.stderr b/tests/ui/async-await/issue-68523.stderr
new file mode 100644
index 000000000..dfdf078e3
--- /dev/null
+++ b/tests/ui/async-await/issue-68523.stderr
@@ -0,0 +1,9 @@
+error[E0752]: `main` function is not allowed to be `async`
+ --> $DIR/issue-68523.rs:3:1
+ |
+LL | async fn main() -> Result<i32, ()> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0752`.
diff --git a/tests/ui/async-await/issue-69446-fnmut-capture.rs b/tests/ui/async-await/issue-69446-fnmut-capture.rs
new file mode 100644
index 000000000..842115538
--- /dev/null
+++ b/tests/ui/async-await/issue-69446-fnmut-capture.rs
@@ -0,0 +1,22 @@
+// Regression test for issue #69446 - we should display
+// which variable is captured
+// edition:2018
+
+use core::future::Future;
+
+struct Foo;
+impl Foo {
+ fn foo(&mut self) {}
+}
+
+async fn bar<T>(_: impl FnMut() -> T)
+where
+ T: Future<Output = ()>,
+{}
+
+fn main() {
+ let mut x = Foo;
+ bar(move || async { //~ ERROR captured
+ x.foo();
+ });
+}
diff --git a/tests/ui/async-await/issue-69446-fnmut-capture.stderr b/tests/ui/async-await/issue-69446-fnmut-capture.stderr
new file mode 100644
index 000000000..3d2b0402b
--- /dev/null
+++ b/tests/ui/async-await/issue-69446-fnmut-capture.stderr
@@ -0,0 +1,19 @@
+error: captured variable cannot escape `FnMut` closure body
+ --> $DIR/issue-69446-fnmut-capture.rs:19:17
+ |
+LL | let mut x = Foo;
+ | ----- variable defined here
+LL | bar(move || async {
+ | _______________-_^
+ | | |
+ | | inferred to be a `FnMut` closure
+LL | | x.foo();
+ | | - variable captured here
+LL | | });
+ | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+ |
+ = note: `FnMut` closures only have access to their captured variables while they are executing...
+ = note: ...therefore, they cannot allow references to captured variables to escape
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-70594.rs b/tests/ui/async-await/issue-70594.rs
new file mode 100644
index 000000000..9e7c5847b
--- /dev/null
+++ b/tests/ui/async-await/issue-70594.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+async fn fun() {
+ [1; ().await];
+ //~^ error: `await` is only allowed inside `async` functions and blocks
+ //~| error: `.await` is not allowed in a `const`
+ //~| error: `.await` is not allowed in a `const`
+ //~| error: `()` is not a future
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-70594.stderr b/tests/ui/async-await/issue-70594.stderr
new file mode 100644
index 000000000..d3cf57d3b
--- /dev/null
+++ b/tests/ui/async-await/issue-70594.stderr
@@ -0,0 +1,37 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-70594.rs:4:11
+ |
+LL | async fn fun() {
+ | --- this is not `async`
+LL | [1; ().await];
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0744]: `.await` is not allowed in a `const`
+ --> $DIR/issue-70594.rs:4:9
+ |
+LL | [1; ().await];
+ | ^^^^^^^^
+
+error[E0744]: `.await` is not allowed in a `const`
+ --> $DIR/issue-70594.rs:4:11
+ |
+LL | [1; ().await];
+ | ^^^^^^
+
+error[E0277]: `()` is not a future
+ --> $DIR/issue-70594.rs:4:11
+ |
+LL | [1; ().await];
+ | ^^^^^^
+ | |
+ | `()` is not a future
+ | help: remove the `.await`
+ |
+ = help: the trait `Future` is not implemented for `()`
+ = note: () must be a future or must implement `IntoFuture` to be awaited
+ = note: required for `()` to implement `IntoFuture`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0728, E0744.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs
new file mode 100644
index 000000000..019c56eb2
--- /dev/null
+++ b/tests/ui/async-await/issue-70818.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+use std::future::Future;
+fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ //~^ Error future cannot be sent between threads safely
+ async { (ty, ty1) }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr
new file mode 100644
index 000000000..20109d4d1
--- /dev/null
+++ b/tests/ui/async-await/issue-70818.stderr
@@ -0,0 +1,18 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-70818.rs:4:38
+ |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+note: captured value is not `Send`
+ --> $DIR/issue-70818.rs:6:18
+ |
+LL | async { (ty, ty1) }
+ | ^^^ has type `U` which is not `Send`
+help: consider restricting type parameter `U`
+ |
+LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
new file mode 100644
index 000000000..721234aa4
--- /dev/null
+++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -0,0 +1,34 @@
+error[E0277]: `Sender<i32>` cannot be shared between threads safely
+ --> $DIR/issue-70935-complex-spans.rs:13:45
+ |
+LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
+ | ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Sender<i32>`
+ = note: required for `&Sender<i32>` to implement `Send`
+note: required because it's used within this closure
+ --> $DIR/issue-70935-complex-spans.rs:17:13
+ |
+LL | baz(|| async{
+ | ^^
+note: required because it's used within this `async fn` body
+ --> $DIR/issue-70935-complex-spans.rs:10:67
+ |
+LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
+ | ___________________________________________________________________^
+LL | | }
+ | |_^
+ = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
+note: required because it's used within this `async` block
+ --> $DIR/issue-70935-complex-spans.rs:16:5
+ |
+LL | / async move {
+LL | | baz(|| async{
+LL | | foo(tx.clone());
+LL | | }).await;
+LL | | }
+ | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
new file mode 100644
index 000000000..8036d82da
--- /dev/null
+++ b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
@@ -0,0 +1,21 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-70935-complex-spans.rs:13:45
+ |
+LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
+ | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `Sender<i32>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-70935-complex-spans.rs:19:11
+ |
+LL | baz(|| async{
+ | _____________-
+LL | | foo(tx.clone());
+LL | | }).await;
+ | | - ^^^^^^- the value is later dropped here
+ | | | |
+ | |_________| await occurs here, with the value maybe used later
+ | has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs
new file mode 100644
index 000000000..b6d17f93a
--- /dev/null
+++ b/tests/ui/async-await/issue-70935-complex-spans.rs
@@ -0,0 +1,29 @@
+// edition:2018
+// revisions: no_drop_tracking drop_tracking
+// [no_drop_tracking]compile-flags:-Zdrop-tracking=no
+// [drop_tracking]compile-flags:-Zdrop-tracking
+// #70935: Check if we do not emit snippet
+// with newlines which lead complex diagnostics.
+
+use std::future::Future;
+
+async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
+}
+
+fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
+ //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
+ //[drop_tracking]~^^ ERROR `Sender<i32>` cannot be shared between threads
+ async move {
+ baz(|| async{
+ foo(tx.clone());
+ }).await;
+ }
+}
+
+fn bar(_s: impl Future + Send) {
+}
+
+fn main() {
+ let (tx, _rx) = std::sync::mpsc::channel();
+ bar(foo(tx));
+}
diff --git a/tests/ui/async-await/issue-71137.rs b/tests/ui/async-await/issue-71137.rs
new file mode 100644
index 000000000..7695e0325
--- /dev/null
+++ b/tests/ui/async-await/issue-71137.rs
@@ -0,0 +1,23 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
+
+use std::future::Future;
+use std::sync::Mutex;
+
+fn fake_spawn<F: Future + Send + 'static>(f: F) { }
+
+async fn wrong_mutex() {
+ let m = Mutex::new(1);
+ {
+ let mut guard = m.lock().unwrap();
+ (async { "right"; }).await;
+ *guard += 1;
+ }
+
+ (async { "wrong"; }).await;
+}
+
+fn main() {
+ fake_spawn(wrong_mutex()); //~ Error future cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr
new file mode 100644
index 000000000..eade6aa2d
--- /dev/null
+++ b/tests/ui/async-await/issue-71137.stderr
@@ -0,0 +1,25 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-71137.rs:22:14
+ |
+LL | fake_spawn(wrong_mutex());
+ | ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-71137.rs:14:25
+ |
+LL | let mut guard = m.lock().unwrap();
+ | --------- has type `MutexGuard<'_, i32>` which is not `Send`
+LL | (async { "right"; }).await;
+ | ^^^^^^ await occurs here, with `mut guard` maybe used later
+LL | *guard += 1;
+LL | }
+ | - `mut guard` is later dropped here
+note: required by a bound in `fake_spawn`
+ --> $DIR/issue-71137.rs:8:27
+ |
+LL | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
+ | ^^^^ required by this bound in `fake_spawn`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-72442.rs b/tests/ui/async-await/issue-72442.rs
new file mode 100644
index 000000000..2280154c7
--- /dev/null
+++ b/tests/ui/async-await/issue-72442.rs
@@ -0,0 +1,26 @@
+// edition:2018
+// incremental
+
+use std::fs::File;
+use std::future::Future;
+use std::io::prelude::*;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ block_on(async {
+ {
+ let path = std::path::Path::new(".");
+ let mut f = File::open(path.to_str())?;
+ //~^ ERROR the trait bound
+ let mut src = String::new();
+ f.read_to_string(&mut src)?;
+ Ok(())
+ }
+ })
+}
+
+fn block_on<F>(f: F) -> F::Output
+where
+ F: Future<Output = Result<(), Box<dyn std::error::Error>>>,
+{
+ Ok(())
+}
diff --git a/tests/ui/async-await/issue-72442.stderr b/tests/ui/async-await/issue-72442.stderr
new file mode 100644
index 000000000..4a1705715
--- /dev/null
+++ b/tests/ui/async-await/issue-72442.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `Option<&str>: AsRef<Path>` is not satisfied
+ --> $DIR/issue-72442.rs:12:36
+ |
+LL | let mut f = File::open(path.to_str())?;
+ | ---------- ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `File::open`
+ --> $SRC_DIR/std/src/fs.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-72470-llvm-dominate.rs b/tests/ui/async-await/issue-72470-llvm-dominate.rs
new file mode 100644
index 000000000..5bb69a073
--- /dev/null
+++ b/tests/ui/async-await/issue-72470-llvm-dominate.rs
@@ -0,0 +1,66 @@
+// compile-flags: -C opt-level=3
+// aux-build: issue-72470-lib.rs
+// edition:2018
+// build-pass
+
+// Regression test for issue #72470, using the minimization
+// in https://github.com/jonas-schievink/llvm-error
+
+extern crate issue_72470_lib;
+
+use std::future::Future;
+use std::pin::Pin;
+use std::sync::Mutex;
+use std::task::Poll::{Pending, Ready};
+
+#[allow(dead_code)]
+enum Msg {
+ A(Vec<()>),
+ B,
+}
+
+#[allow(dead_code)]
+enum Out {
+ _0(Option<Msg>),
+ Disabled,
+}
+
+#[allow(unused_must_use)]
+fn main() {
+ let mut rx = issue_72470_lib::unbounded_channel::<Msg>();
+ let entity = Mutex::new(());
+ issue_72470_lib::run(async move {
+ {
+ let output = {
+ let mut fut = rx.recv();
+ issue_72470_lib::poll_fn(|cx| {
+ loop {
+ let fut = unsafe { Pin::new_unchecked(&mut fut) };
+ let out = match fut.poll(cx) {
+ Ready(out) => out,
+ Pending => {
+ break;
+ }
+ };
+ #[allow(unused_variables)]
+ match &out {
+ Some(_msg) => {}
+ _ => break,
+ }
+ return Ready(Out::_0(out));
+ }
+ Ready(Out::_0(None))
+ })
+ .await
+ };
+ match output {
+ Out::_0(Some(_msg)) => {
+ entity.lock();
+ }
+ Out::_0(None) => unreachable!(),
+ _ => unreachable!(),
+ }
+ }
+ entity.lock();
+ });
+}
diff --git a/tests/ui/async-await/issue-72590-type-error-sized.rs b/tests/ui/async-await/issue-72590-type-error-sized.rs
new file mode 100644
index 000000000..00e098d43
--- /dev/null
+++ b/tests/ui/async-await/issue-72590-type-error-sized.rs
@@ -0,0 +1,22 @@
+// Regression test for issue #72590
+// Tests that we don't emit a spurious "size cannot be statically determined" error
+// edition:2018
+
+struct Foo {
+ foo: Nonexistent, //~ ERROR cannot find
+ other: str
+}
+
+struct Bar {
+ test: Missing //~ ERROR cannot find
+}
+
+impl Foo {
+ async fn frob(self) {} //~ ERROR the size
+}
+
+impl Bar {
+ async fn myfn(self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr
new file mode 100644
index 000000000..778423578
--- /dev/null
+++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr
@@ -0,0 +1,34 @@
+error[E0412]: cannot find type `Nonexistent` in this scope
+ --> $DIR/issue-72590-type-error-sized.rs:6:10
+ |
+LL | foo: Nonexistent,
+ | ^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Missing` in this scope
+ --> $DIR/issue-72590-type-error-sized.rs:11:11
+ |
+LL | test: Missing
+ | ^^^^^^^ not found in this scope
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/issue-72590-type-error-sized.rs:15:19
+ |
+LL | async fn frob(self) {}
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `Foo`, the trait `Sized` is not implemented for `str`
+note: required because it appears within the type `Foo`
+ --> $DIR/issue-72590-type-error-sized.rs:5:8
+ |
+LL | struct Foo {
+ | ^^^
+ = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | async fn frob(&self) {}
+ | +
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0412.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-73050.rs b/tests/ui/async-await/issue-73050.rs
new file mode 100644
index 000000000..790f24a23
--- /dev/null
+++ b/tests/ui/async-await/issue-73050.rs
@@ -0,0 +1,12 @@
+// check-pass
+// edition:2018
+
+#[allow(unused)]
+async fn foo<'a>() {
+ let _data = &mut [0u8; { 1 + 4 }];
+ bar().await
+}
+
+async fn bar() {}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-73137.rs b/tests/ui/async-await/issue-73137.rs
new file mode 100644
index 000000000..dcbe7765a
--- /dev/null
+++ b/tests/ui/async-await/issue-73137.rs
@@ -0,0 +1,44 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/73137>
+
+// run-pass
+// edition:2018
+// revisions: normal drop-tracking
+// [normal]compile-flags: -Zdrop-tracking=no
+// [drop-tracking]compile-flags: -Zdrop-tracking
+
+#![allow(dead_code)]
+use std::future::Future;
+use std::task::{Waker, Wake, Context};
+use std::sync::Arc;
+
+struct DummyWaker;
+impl Wake for DummyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+struct Foo {
+ a: usize,
+ b: &'static u32,
+}
+
+#[inline(never)]
+fn nop<T>(_: T) {}
+
+fn main() {
+ let mut fut = Box::pin(async {
+ let action = Foo {
+ b: &42,
+ a: async { 0 }.await,
+ };
+
+ // An error in the generator transform caused `b` to be overwritten with `a` when `b` was
+ // borrowed.
+ nop(&action.b);
+ assert_ne!(0usize, unsafe { std::mem::transmute(action.b) });
+
+ async {}.await;
+ });
+ let waker = Waker::from(Arc::new(DummyWaker));
+ let mut cx = Context::from_waker(&waker);
+ let _ = fut.as_mut().poll(&mut cx);
+}
diff --git a/tests/ui/async-await/issue-73541-1.rs b/tests/ui/async-await/issue-73541-1.rs
new file mode 100644
index 000000000..7fb0d6c39
--- /dev/null
+++ b/tests/ui/async-await/issue-73541-1.rs
@@ -0,0 +1,12 @@
+// edition:2018
+
+fn main() {
+ 'a: loop {
+ async {
+ loop {
+ continue 'a
+ //~^ ERROR use of unreachable label `'a`
+ }
+ };
+ }
+}
diff --git a/tests/ui/async-await/issue-73541-1.stderr b/tests/ui/async-await/issue-73541-1.stderr
new file mode 100644
index 000000000..80c1fdf00
--- /dev/null
+++ b/tests/ui/async-await/issue-73541-1.stderr
@@ -0,0 +1,14 @@
+error[E0767]: use of unreachable label `'a`
+ --> $DIR/issue-73541-1.rs:7:26
+ |
+LL | 'a: loop {
+ | -- unreachable label defined here
+...
+LL | continue 'a
+ | ^^ unreachable label `'a`
+ |
+ = note: labels are unreachable through functions, closures, async blocks and modules
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0767`.
diff --git a/tests/ui/async-await/issue-73541-2.rs b/tests/ui/async-await/issue-73541-2.rs
new file mode 100644
index 000000000..70b4ab253
--- /dev/null
+++ b/tests/ui/async-await/issue-73541-2.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+async fn c() {
+ 'a: loop {
+ macro_rules! b {
+ () => {
+ continue 'a
+ //~^ ERROR use of unreachable label `'a`
+ }
+ }
+
+ async {
+ loop {
+ b!();
+ }
+ };
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issue-73541-2.stderr b/tests/ui/async-await/issue-73541-2.stderr
new file mode 100644
index 000000000..4c9741f6f
--- /dev/null
+++ b/tests/ui/async-await/issue-73541-2.stderr
@@ -0,0 +1,18 @@
+error[E0767]: use of unreachable label `'a`
+ --> $DIR/issue-73541-2.rs:7:26
+ |
+LL | 'a: loop {
+ | -- unreachable label defined here
+...
+LL | continue 'a
+ | ^^ unreachable label `'a`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: labels are unreachable through functions, closures, async blocks and modules
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0767`.
diff --git a/tests/ui/async-await/issue-73541-3.rs b/tests/ui/async-await/issue-73541-3.rs
new file mode 100644
index 000000000..02ca02da8
--- /dev/null
+++ b/tests/ui/async-await/issue-73541-3.rs
@@ -0,0 +1,9 @@
+fn main() {
+ 'aaaaab: loop {
+ || {
+ loop { continue 'aaaaaa }
+ //~^ ERROR use of undeclared label `'aaaaaa`
+ };
+
+ }
+}
diff --git a/tests/ui/async-await/issue-73541-3.stderr b/tests/ui/async-await/issue-73541-3.stderr
new file mode 100644
index 000000000..53487aaca
--- /dev/null
+++ b/tests/ui/async-await/issue-73541-3.stderr
@@ -0,0 +1,12 @@
+error[E0426]: use of undeclared label `'aaaaaa`
+ --> $DIR/issue-73541-3.rs:4:29
+ |
+LL | 'aaaaab: loop {
+ | ------- a label with a similar name exists but is unreachable
+LL | || {
+LL | loop { continue 'aaaaaa }
+ | ^^^^^^^ undeclared label `'aaaaaa`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/tests/ui/async-await/issue-73541.rs b/tests/ui/async-await/issue-73541.rs
new file mode 100644
index 000000000..399a07cd3
--- /dev/null
+++ b/tests/ui/async-await/issue-73541.rs
@@ -0,0 +1,9 @@
+fn main() {
+ 'a: loop {
+ || {
+ loop { continue 'a }
+ //~^ ERROR use of unreachable label `'a`
+ };
+
+ }
+}
diff --git a/tests/ui/async-await/issue-73541.stderr b/tests/ui/async-await/issue-73541.stderr
new file mode 100644
index 000000000..4bb466ff1
--- /dev/null
+++ b/tests/ui/async-await/issue-73541.stderr
@@ -0,0 +1,14 @@
+error[E0767]: use of unreachable label `'a`
+ --> $DIR/issue-73541.rs:4:29
+ |
+LL | 'a: loop {
+ | -- unreachable label defined here
+LL | || {
+LL | loop { continue 'a }
+ | ^^ unreachable label `'a`
+ |
+ = note: labels are unreachable through functions, closures, async blocks and modules
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0767`.
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs
new file mode 100644
index 000000000..c3423ad62
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// compile-flags: -Zdrop-tracking
+// Regression test for issue #73741
+// Ensures that we don't emit spurious errors when
+// a type error ocurrs in an `async fn`
+
+async fn weird() {
+ 1 = 2; //~ ERROR invalid left-hand side
+
+ let mut loop_count = 0;
+ async {}.await
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr
new file mode 100644
index 000000000..d4e3b6c3b
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr
@@ -0,0 +1,11 @@
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/issue-73741-type-err-drop-tracking.rs:8:7
+ |
+LL | 1 = 2;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/async-await/issue-73741-type-err.rs b/tests/ui/async-await/issue-73741-type-err.rs
new file mode 100644
index 000000000..c5b9e34ed
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err.rs
@@ -0,0 +1,14 @@
+// edition:2018
+//
+// Regression test for issue #73741
+// Ensures that we don't emit spurious errors when
+// a type error ocurrs in an `async fn`
+
+async fn weird() {
+ 1 = 2; //~ ERROR invalid left-hand side
+
+ let mut loop_count = 0;
+ async {}.await
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-73741-type-err.stderr b/tests/ui/async-await/issue-73741-type-err.stderr
new file mode 100644
index 000000000..0b5343a98
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err.stderr
@@ -0,0 +1,11 @@
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/issue-73741-type-err.rs:8:7
+ |
+LL | 1 = 2;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/async-await/issue-74047.rs b/tests/ui/async-await/issue-74047.rs
new file mode 100644
index 000000000..2e4f3e675
--- /dev/null
+++ b/tests/ui/async-await/issue-74047.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+use std::convert::{TryFrom, TryInto};
+use std::io;
+
+pub struct MyStream;
+pub struct OtherStream;
+
+pub async fn connect() -> io::Result<MyStream> {
+ let stream: MyStream = OtherStream.try_into()?;
+ Ok(stream)
+}
+
+impl TryFrom<OtherStream> for MyStream {}
+//~^ ERROR: missing
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-74047.stderr b/tests/ui/async-await/issue-74047.stderr
new file mode 100644
index 000000000..28174825d
--- /dev/null
+++ b/tests/ui/async-await/issue-74047.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Error`, `try_from`
+ --> $DIR/issue-74047.rs:14:1
+ |
+LL | impl TryFrom<OtherStream> for MyStream {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Error`, `try_from` in implementation
+ |
+ = help: implement the missing item: `type Error = Type;`
+ = help: implement the missing item: `fn try_from(_: T) -> Result<Self, <Self as TryFrom<T>>::Error> { todo!() }`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
new file mode 100644
index 000000000..95683241a
--- /dev/null
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
@@ -0,0 +1,37 @@
+// edition:2018
+#![feature(async_closure)]
+use std::future::Future;
+
+// test the quality of annotations giving lifetimes names (`'1`) when async constructs are involved
+
+pub async fn async_fn(x: &mut i32) -> &i32 {
+ let y = &*x;
+ *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
+ y
+}
+
+pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
+ (async move || {
+ let y = &*x;
+ *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
+ y
+ })()
+}
+
+pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
+ (async move || -> &i32 {
+ let y = &*x;
+ *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
+ y
+ })()
+}
+
+pub fn async_block(x: &mut i32) -> impl Future<Output=&i32> {
+ async move {
+ let y = &*x;
+ *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
+ y
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
new file mode 100644
index 000000000..b96cab9f0
--- /dev/null
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
@@ -0,0 +1,51 @@
+error[E0506]: cannot assign to `*x` because it is borrowed
+ --> $DIR/issue-74072-lifetime-name-annotations.rs:9:5
+ |
+LL | pub async fn async_fn(x: &mut i32) -> &i32 {
+ | - let's call the lifetime of this reference `'1`
+LL | let y = &*x;
+ | --- borrow of `*x` occurs here
+LL | *x += 1;
+ | ^^^^^^^ assignment to borrowed `*x` occurs here
+LL | y
+ | - returning this value requires that `*x` is borrowed for `'1`
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+ --> $DIR/issue-74072-lifetime-name-annotations.rs:16:9
+ |
+LL | let y = &*x;
+ | --- borrow of `*x` occurs here
+LL | *x += 1;
+ | ^^^^^^^ assignment to borrowed `*x` occurs here
+LL | y
+ | - returning this value requires that `*x` is borrowed for `'1`
+LL | })()
+ | - return type of async closure is &'1 i32
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+ --> $DIR/issue-74072-lifetime-name-annotations.rs:24:9
+ |
+LL | (async move || -> &i32 {
+ | - let's call the lifetime of this reference `'1`
+LL | let y = &*x;
+ | --- borrow of `*x` occurs here
+LL | *x += 1;
+ | ^^^^^^^ assignment to borrowed `*x` occurs here
+LL | y
+ | - returning this value requires that `*x` is borrowed for `'1`
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+ --> $DIR/issue-74072-lifetime-name-annotations.rs:32:9
+ |
+LL | let y = &*x;
+ | --- borrow of `*x` occurs here
+LL | *x += 1;
+ | ^^^^^^^ assignment to borrowed `*x` occurs here
+LL | y
+ | - returning this value requires that `*x` is borrowed for `'1`
+LL | }
+ | - return type of async block is &'1 i32
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/tests/ui/async-await/issue-74497-lifetime-in-opaque.rs b/tests/ui/async-await/issue-74497-lifetime-in-opaque.rs
new file mode 100644
index 000000000..2d765eb41
--- /dev/null
+++ b/tests/ui/async-await/issue-74497-lifetime-in-opaque.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+// test that names give to anonymous lifetimes in opaque types like `impl Future` are correctly
+// introduced in error messages
+
+use std::future::Future;
+
+pub async fn foo<F, T>(_: F)
+where
+ F: Fn(&u8) -> T,
+ T: Future<Output = ()>,
+{
+}
+
+pub async fn bar(_: &u8) {}
+
+fn main() {
+ let _ = foo(|x| bar(x)); //~ ERROR lifetime may not live long enough
+}
diff --git a/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr b/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr
new file mode 100644
index 000000000..4427014ae
--- /dev/null
+++ b/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-74497-lifetime-in-opaque.rs:18:21
+ |
+LL | let _ = foo(|x| bar(x));
+ | -- ^^^^^^ returning this value requires that `'1` must outlive `'2`
+ | ||
+ | |return type of closure `impl Future<Output = ()>` contains a lifetime `'2`
+ | has type `&'1 u8`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-75785-confusing-named-region.rs b/tests/ui/async-await/issue-75785-confusing-named-region.rs
new file mode 100644
index 000000000..452614087
--- /dev/null
+++ b/tests/ui/async-await/issue-75785-confusing-named-region.rs
@@ -0,0 +1,13 @@
+// edition:2018
+//
+// Regression test for issue #75785
+// Tests that we don't point to a confusing named
+// region when emitting a diagnostic
+
+pub async fn async_fn(x: &mut i32) -> (&i32, &i32) {
+ let y = &*x;
+ *x += 1; //~ ERROR cannot assign to
+ (&32, y)
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-75785-confusing-named-region.stderr b/tests/ui/async-await/issue-75785-confusing-named-region.stderr
new file mode 100644
index 000000000..3b731d9c6
--- /dev/null
+++ b/tests/ui/async-await/issue-75785-confusing-named-region.stderr
@@ -0,0 +1,15 @@
+error[E0506]: cannot assign to `*x` because it is borrowed
+ --> $DIR/issue-75785-confusing-named-region.rs:9:5
+ |
+LL | pub async fn async_fn(x: &mut i32) -> (&i32, &i32) {
+ | - let's call the lifetime of this reference `'1`
+LL | let y = &*x;
+ | --- borrow of `*x` occurs here
+LL | *x += 1;
+ | ^^^^^^^ assignment to borrowed `*x` occurs here
+LL | (&32, y)
+ | -------- returning this value requires that `*x` is borrowed for `'1`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/tests/ui/async-await/issue-76547.rs b/tests/ui/async-await/issue-76547.rs
new file mode 100644
index 000000000..587feb624
--- /dev/null
+++ b/tests/ui/async-await/issue-76547.rs
@@ -0,0 +1,38 @@
+// Test for diagnostic improvement issue #76547
+// edition:2018
+
+use std::{
+ future::Future,
+ task::{Context, Poll}
+};
+use std::pin::Pin;
+
+pub struct ListFut<'a>(&'a mut [&'a mut [u8]]);
+impl<'a> Future for ListFut<'a> {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
+ unimplemented!()
+ }
+}
+
+async fn fut(bufs: &mut [&mut [u8]]) {
+ ListFut(bufs).await
+ //~^ ERROR lifetime may not live long enough
+}
+
+pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]);
+impl<'a> Future for ListFut2<'a> {
+ type Output = i32;
+
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
+ unimplemented!()
+ }
+}
+
+async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
+ ListFut2(bufs).await
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-76547.stderr b/tests/ui/async-await/issue-76547.stderr
new file mode 100644
index 000000000..4d96cce82
--- /dev/null
+++ b/tests/ui/async-await/issue-76547.stderr
@@ -0,0 +1,32 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-76547.rs:20:13
+ |
+LL | async fn fut(bufs: &mut [&mut [u8]]) {
+ | - - let's call the lifetime of this reference `'2`
+ | |
+ | let's call the lifetime of this reference `'1`
+LL | ListFut(bufs).await
+ | ^^^^ this usage requires that `'1` must outlive `'2`
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) {
+ | ++++ ++ ++
+
+error: lifetime may not live long enough
+ --> $DIR/issue-76547.rs:34:14
+ |
+LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
+ | - - let's call the lifetime of this reference `'2`
+ | |
+ | let's call the lifetime of this reference `'1`
+LL | ListFut2(bufs).await
+ | ^^^^ this usage requires that `'1` must outlive `'2`
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | async fn fut2<'a>(bufs: &'a mut [&'a mut [u8]]) -> i32 {
+ | ++++ ++ ++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/issue-77993-2.rs b/tests/ui/async-await/issue-77993-2.rs
new file mode 100644
index 000000000..4d554a0a1
--- /dev/null
+++ b/tests/ui/async-await/issue-77993-2.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+async fn test() -> Result<(), Box<dyn std::error::Error>> {
+ macro!();
+ //~^ ERROR expected identifier, found `!`
+ Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-77993-2.stderr b/tests/ui/async-await/issue-77993-2.stderr
new file mode 100644
index 000000000..64b378f83
--- /dev/null
+++ b/tests/ui/async-await/issue-77993-2.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `!`
+ --> $DIR/issue-77993-2.rs:4:10
+ |
+LL | macro!();
+ | ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-84841.rs b/tests/ui/async-await/issue-84841.rs
new file mode 100644
index 000000000..ba3a1617b
--- /dev/null
+++ b/tests/ui/async-await/issue-84841.rs
@@ -0,0 +1,16 @@
+// edition:2018
+
+fn main() {
+
+}
+
+async fn foo() {
+ // Adding an .await here avoids the ICE
+ test()?;
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ //~| ERROR the `?` operator can only be used in an async function that returns
+}
+
+// Removing the const generic parameter here avoids the ICE
+async fn test<const N: usize>() {
+}
diff --git a/tests/ui/async-await/issue-84841.stderr b/tests/ui/async-await/issue-84841.stderr
new file mode 100644
index 000000000..1e22373ba
--- /dev/null
+++ b/tests/ui/async-await/issue-84841.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/issue-84841.rs:9:5
+ |
+LL | test()?;
+ | ^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = ()>`
+ |
+ = help: the trait `Try` is not implemented for `impl Future<Output = ()>`
+
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/issue-84841.rs:9:11
+ |
+LL | async fn foo() {
+ | ________________-
+LL | | // Adding an .await here avoids the ICE
+LL | | test()?;
+ | | ^ cannot use the `?` operator in an async function that returns `()`
+LL | |
+LL | |
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = help: the trait `FromResidual<_>` is not implemented for `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-86507.rs b/tests/ui/async-await/issue-86507.rs
new file mode 100644
index 000000000..317f03176
--- /dev/null
+++ b/tests/ui/async-await/issue-86507.rs
@@ -0,0 +1,25 @@
+// edition:2018
+
+use ::core::pin::Pin;
+use ::core::future::Future;
+use ::core::marker::Send;
+
+trait Foo {
+ fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+ -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
+ where 'me: 'async_trait;
+}
+
+impl Foo for () {
+ fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+ -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
+ where 'me:'async_trait {
+ Box::pin( //~ ERROR future cannot be sent between threads safely
+ async move {
+ let x = x;
+ }
+ )
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr
new file mode 100644
index 000000000..8c2c06da2
--- /dev/null
+++ b/tests/ui/async-await/issue-86507.stderr
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-86507.rs:17:13
+ |
+LL | / Box::pin(
+LL | | async move {
+LL | | let x = x;
+LL | | }
+LL | | )
+ | |_____________^ future created by async block is not `Send`
+ |
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+ --> $DIR/issue-86507.rs:19:29
+ |
+LL | let x = x;
+ | ^ has type `&T` which is not `Send`, because `T` is not `Sync`
+ = note: required for the cast from `[async block@$DIR/issue-86507.rs:18:17: 20:18]` to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting this bound
+ |
+LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-93197.rs b/tests/ui/async-await/issue-93197.rs
new file mode 100644
index 000000000..c627fe17a
--- /dev/null
+++ b/tests/ui/async-await/issue-93197.rs
@@ -0,0 +1,16 @@
+// Regression test for #93197
+// check-pass
+// edition:2021
+// compile-flags: -Zdrop-tracking
+
+#![feature(try_blocks)]
+
+use std::sync::{mpsc, mpsc::SendError};
+
+pub async fn foo() {
+ let (tx, _) = mpsc::channel();
+
+ let _: Result<(), SendError<&str>> = try { tx.send("hello")?; };
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issue-93648.rs b/tests/ui/async-await/issue-93648.rs
new file mode 100644
index 000000000..4ce3ac1e8
--- /dev/null
+++ b/tests/ui/async-await/issue-93648.rs
@@ -0,0 +1,12 @@
+// edition:2021
+// build-pass
+// compile-flags: -Zdrop-tracking
+
+fn main() {
+ let _ = async {
+ let mut s = (String::new(),);
+ s.0.push_str("abc");
+ std::mem::drop(s);
+ async {}.await;
+ };
+}
diff --git a/tests/ui/async-await/issue-98634.rs b/tests/ui/async-await/issue-98634.rs
new file mode 100644
index 000000000..b0d38687f
--- /dev/null
+++ b/tests/ui/async-await/issue-98634.rs
@@ -0,0 +1,50 @@
+// edition: 2021
+
+use std::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, Waker},
+};
+
+pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
+ pub callback: F,
+}
+
+impl<F> Future for StructAsync<F>
+where
+ F: Fn() -> Pin<Box<dyn Future<Output = ()>>>,
+{
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+async fn callback() {}
+
+struct Runtime;
+
+fn waker() -> &'static Waker {
+ todo!()
+}
+
+impl Runtime {
+ #[track_caller]
+ pub fn block_on<F: Future>(&self, mut future: F) -> F::Output {
+ loop {
+ unsafe {
+ Pin::new_unchecked(&mut future).poll(&mut Context::from_waker(waker()));
+ }
+ }
+ }
+}
+
+fn main() {
+ Runtime.block_on(async {
+ StructAsync { callback }.await;
+ //~^ ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ //~| ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ //~| ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ });
+}
diff --git a/tests/ui/async-await/issue-98634.stderr b/tests/ui/async-await/issue-98634.stderr
new file mode 100644
index 000000000..5160e48d8
--- /dev/null
+++ b/tests/ui/async-await/issue-98634.stderr
@@ -0,0 +1,60 @@
+error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ --> $DIR/issue-98634.rs:45:23
+ |
+LL | StructAsync { callback }.await;
+ | ^^^^^^^^ expected struct `Pin`, found opaque type
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-98634.rs:24:21
+ |
+LL | async fn callback() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+ found opaque type `impl Future<Output = ()>`
+note: required by a bound in `StructAsync`
+ --> $DIR/issue-98634.rs:9:35
+ |
+LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
+
+error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ --> $DIR/issue-98634.rs:45:9
+ |
+LL | StructAsync { callback }.await;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-98634.rs:24:21
+ |
+LL | async fn callback() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+ found opaque type `impl Future<Output = ()>`
+note: required by a bound in `StructAsync`
+ --> $DIR/issue-98634.rs:9:35
+ |
+LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
+
+error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ --> $DIR/issue-98634.rs:45:33
+ |
+LL | StructAsync { callback }.await;
+ | ^^^^^^ expected struct `Pin`, found opaque type
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-98634.rs:24:21
+ |
+LL | async fn callback() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+ found opaque type `impl Future<Output = ()>`
+note: required by a bound in `StructAsync`
+ --> $DIR/issue-98634.rs:9:35
+ |
+LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/async-await/issues/auxiliary/issue-60674.rs b/tests/ui/async-await/issues/auxiliary/issue-60674.rs
new file mode 100644
index 000000000..680c6e55e
--- /dev/null
+++ b/tests/ui/async-await/issues/auxiliary/issue-60674.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr(_args: TokenStream, input: TokenStream) -> TokenStream {
+ println!("{}", input);
+ TokenStream::new()
+}
diff --git a/tests/ui/async-await/issues/auxiliary/issue_67893.rs b/tests/ui/async-await/issues/auxiliary/issue_67893.rs
new file mode 100644
index 000000000..387966a50
--- /dev/null
+++ b/tests/ui/async-await/issues/auxiliary/issue_67893.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+use std::sync::{Arc, Mutex};
+
+pub async fn f(_: ()) {}
+
+pub async fn run() {
+ let x: Arc<Mutex<()>> = unimplemented!();
+ f(*x.lock().unwrap()).await;
+}
diff --git a/tests/ui/async-await/issues/issue-102206.rs b/tests/ui/async-await/issues/issue-102206.rs
new file mode 100644
index 000000000..a3a2ebc58
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-102206.rs
@@ -0,0 +1,8 @@
+// edition:2021
+
+async fn foo() {}
+
+fn main() {
+ std::mem::size_of_val(foo());
+ //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/async-await/issues/issue-102206.stderr b/tests/ui/async-await/issues/issue-102206.stderr
new file mode 100644
index 000000000..2ab790ac7
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-102206.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102206.rs:6:27
+ |
+LL | std::mem::size_of_val(foo());
+ | --------------------- ^^^^^
+ | | |
+ | | expected reference, found opaque type
+ | | help: consider borrowing here: `&foo()`
+ | arguments to this function are incorrect
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-102206.rs:3:16
+ |
+LL | async fn foo() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected reference `&_`
+ found opaque type `impl Future<Output = ()>`
+note: function defined here
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/issues/issue-51719.rs b/tests/ui/async-await/issues/issue-51719.rs
new file mode 100644
index 000000000..09241f982
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-51719.rs
@@ -0,0 +1,12 @@
+// edition:2018
+//
+// Tests that the .await syntax can't be used to make a generator
+
+async fn foo() {}
+
+fn make_generator() {
+ let _gen = || foo().await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-51719.stderr b/tests/ui/async-await/issues/issue-51719.stderr
new file mode 100644
index 000000000..f3ce5d1c8
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-51719.stderr
@@ -0,0 +1,11 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-51719.rs:8:24
+ |
+LL | let _gen = || foo().await;
+ | -- ^^^^^^ only allowed inside `async` functions and blocks
+ | |
+ | this is not `async`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0728`.
diff --git a/tests/ui/async-await/issues/issue-51751.rs b/tests/ui/async-await/issues/issue-51751.rs
new file mode 100644
index 000000000..bc85a96ce
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-51751.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+async fn inc(limit: i64) -> i64 {
+ limit + 1
+}
+
+fn main() {
+ let result = inc(10000);
+ let finished = result.await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+}
diff --git a/tests/ui/async-await/issues/issue-51751.stderr b/tests/ui/async-await/issues/issue-51751.stderr
new file mode 100644
index 000000000..8696a5b79
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-51751.stderr
@@ -0,0 +1,12 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-51751.rs:9:26
+ |
+LL | fn main() {
+ | ---- this is not `async`
+LL | let result = inc(10000);
+LL | let finished = result.await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0728`.
diff --git a/tests/ui/async-await/issues/issue-53249.rs b/tests/ui/async-await/issues/issue-53249.rs
new file mode 100644
index 000000000..3a33af2d2
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-53249.rs
@@ -0,0 +1,47 @@
+// check-pass
+// edition:2018
+
+#![feature(arbitrary_self_types)]
+
+use std::task::{self, Poll};
+use std::future::Future;
+use std::marker::Unpin;
+use std::pin::Pin;
+
+// This is a regression test for an ICE/unbounded recursion issue relating to async-await.
+
+#[derive(Debug)]
+#[must_use = "futures do nothing unless polled"]
+pub struct Lazy<F> {
+ f: Option<F>
+}
+
+impl<F> Unpin for Lazy<F> {}
+
+pub fn lazy<F, R>(f: F) -> Lazy<F>
+ where F: FnOnce(&mut task::Context) -> R,
+{
+ Lazy { f: Some(f) }
+}
+
+impl<R, F> Future for Lazy<F>
+ where F: FnOnce(&mut task::Context) -> R,
+{
+ type Output = R;
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<R> {
+ Poll::Ready((self.f.take().unwrap())(cx))
+ }
+}
+
+async fn __receive<WantFn, Fut>(want: WantFn) -> ()
+ where Fut: Future<Output = ()>, WantFn: Fn(&Box<dyn Send + 'static>) -> Fut,
+{
+ lazy(|_| ()).await;
+}
+
+pub fn basic_spawn_receive() {
+ async { __receive(|_| async { () }).await };
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-54752-async-block.rs b/tests/ui/async-await/issues/issue-54752-async-block.rs
new file mode 100644
index 000000000..a8165ae6c
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-54752-async-block.rs
@@ -0,0 +1,7 @@
+// run-pass
+
+// edition:2018
+// pp-exact
+
+fn main() { let _a = (async { }); }
+//~^ WARNING unnecessary parentheses around assigned value
diff --git a/tests/ui/async-await/issues/issue-54752-async-block.stderr b/tests/ui/async-await/issues/issue-54752-async-block.stderr
new file mode 100644
index 000000000..8cc849dd9
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-54752-async-block.stderr
@@ -0,0 +1,15 @@
+warning: unnecessary parentheses around assigned value
+ --> $DIR/issue-54752-async-block.rs:6:22
+ |
+LL | fn main() { let _a = (async { }); }
+ | ^ ^
+ |
+ = note: `#[warn(unused_parens)]` on by default
+help: remove these parentheses
+ |
+LL - fn main() { let _a = (async { }); }
+LL + fn main() { let _a = async { }; }
+ |
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/issues/issue-54974.rs b/tests/ui/async-await/issues/issue-54974.rs
new file mode 100644
index 000000000..b602ef153
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-54974.rs
@@ -0,0 +1,14 @@
+// check-pass
+// edition:2018
+
+use std::sync::Arc;
+
+trait SomeTrait: Send + Sync + 'static {
+ fn do_something(&self);
+}
+
+async fn my_task(obj: Arc<dyn SomeTrait>) {
+ unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-55324.rs b/tests/ui/async-await/issues/issue-55324.rs
new file mode 100644
index 000000000..9ecb3b129
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-55324.rs
@@ -0,0 +1,11 @@
+// check-pass
+// edition:2018
+
+use std::future::Future;
+
+async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 {
+ let y = future.await;
+ *x + y
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-55809.rs b/tests/ui/async-await/issues/issue-55809.rs
new file mode 100644
index 000000000..3b271775a
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-55809.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// run-pass
+
+trait Foo { }
+
+impl Foo for () { }
+
+impl<'a, T> Foo for &'a mut T where T: Foo { }
+
+async fn foo_async<T>(_v: T) -> u8 where T: Foo {
+ 0
+}
+
+async fn bad<T>(v: T) -> u8 where T: Foo {
+ foo_async(v).await
+}
+
+async fn async_main() {
+ let mut v = ();
+
+ let _ = bad(&mut v).await;
+ let _ = foo_async(&mut v).await;
+ let _ = bad(v).await;
+}
+
+fn main() {
+ let _ = async_main();
+}
diff --git a/tests/ui/async-await/issues/issue-58885.rs b/tests/ui/async-await/issues/issue-58885.rs
new file mode 100644
index 000000000..11920b072
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-58885.rs
@@ -0,0 +1,19 @@
+// check-pass
+// edition:2018
+
+struct Xyz {
+ a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+ async fn do_sth<'a>(
+ &'a self, foo: &'a dyn Foo
+ ) -> bool
+ {
+ true
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-59001.rs b/tests/ui/async-await/issues/issue-59001.rs
new file mode 100644
index 000000000..4ddebcf20
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-59001.rs
@@ -0,0 +1,14 @@
+// check-pass
+// edition:2018
+
+use std::future::Future;
+
+async fn enter<'a, F, R>(mut callback: F)
+where
+ F: FnMut(&'a mut i32) -> R,
+ R: Future<Output = ()> + 'a,
+{
+ unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-59972.rs b/tests/ui/async-await/issues/issue-59972.rs
new file mode 100644
index 000000000..c2e24a96b
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-59972.rs
@@ -0,0 +1,34 @@
+// Incorrect handling of uninhabited types could cause us to mark generator
+// types as entirely uninhabited, when they were in fact constructible. This
+// caused us to hit "unreachable" code (illegal instruction on x86).
+
+// run-pass
+
+// compile-flags: --edition=2018 -Aunused
+
+pub enum Uninhabited { }
+
+fn uninhabited_async() -> Uninhabited {
+ unreachable!()
+}
+
+async fn noop() { }
+
+async fn contains_never() {
+ let error = uninhabited_async();
+ noop().await;
+ let error2 = error;
+}
+
+async fn overlap_never() {
+ let error1 = uninhabited_async();
+ noop().await;
+ let error2 = uninhabited_async();
+ drop(error1);
+ noop().await;
+ drop(error2);
+}
+
+#[allow(unused_must_use)]
+fn main() {
+}
diff --git a/tests/ui/async-await/issues/issue-60518.rs b/tests/ui/async-await/issues/issue-60518.rs
new file mode 100644
index 000000000..69bbdd0e8
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-60518.rs
@@ -0,0 +1,10 @@
+// check-pass
+// edition:2018
+
+// This is a regression test to ensure that simple bindings (where replacement arguments aren't
+// created during async fn lowering) that have their DefId used during HIR lowering (such as impl
+// trait) are visited during def collection and thus have a DefId.
+
+async fn foo(ws: impl Iterator<Item = ()>) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-60655-latebound-regions.rs b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
new file mode 100644
index 000000000..66a3b07c3
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
@@ -0,0 +1,30 @@
+// Test that opaque `impl Trait` types are allowed to contain late-bound regions.
+
+// check-pass
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+use std::future::Future;
+
+pub type Func = impl Sized;
+
+// Late bound region should be allowed to escape the function, since it's bound
+// in the type.
+fn null_function_ptr() -> Func {
+ None::<for<'a> fn(&'a ())>
+}
+
+async fn async_nop(_: &u8) {}
+
+pub type ServeFut = impl Future<Output=()>;
+
+// Late bound regions occur in the generator witness type here.
+fn serve() -> ServeFut {
+ async move {
+ let x = 5;
+ async_nop(&x).await
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-60674.rs b/tests/ui/async-await/issues/issue-60674.rs
new file mode 100644
index 000000000..c0e34a8df
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-60674.rs
@@ -0,0 +1,19 @@
+// aux-build:issue-60674.rs
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+
+// This is a regression test that ensures that `mut` patterns are not lost when provided as input
+// to a proc macro.
+
+extern crate issue_60674;
+
+#[issue_60674::attr]
+async fn f(mut x: u8) {}
+
+#[issue_60674::attr]
+async fn g((mut x, y, mut z): (u8, u8, u8)) {}
+
+#[issue_60674::attr]
+async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-60674.stdout b/tests/ui/async-await/issues/issue-60674.stdout
new file mode 100644
index 000000000..6f980e606
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-60674.stdout
@@ -0,0 +1,3 @@
+async fn f(mut x : u8) {}
+async fn g((mut x, y, mut z) : (u8, u8, u8)) {}
+async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) {}
diff --git a/tests/ui/async-await/issues/issue-61187.rs b/tests/ui/async-await/issues/issue-61187.rs
new file mode 100644
index 000000000..8585a4251
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-61187.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+fn main() {}
+
+async fn response(data: Vec<u8>) {
+ data.reverse(); //~ ERROR E0596
+}
diff --git a/tests/ui/async-await/issues/issue-61187.stderr b/tests/ui/async-await/issues/issue-61187.stderr
new file mode 100644
index 000000000..e58f74546
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-61187.stderr
@@ -0,0 +1,14 @@
+error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable
+ --> $DIR/issue-61187.rs:6:5
+ |
+LL | data.reverse();
+ | ^^^^^^^^^^^^^^ cannot borrow as mutable
+ |
+help: consider changing this to be mutable
+ |
+LL | async fn response(mut data: Vec<u8>) {
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/async-await/issues/issue-61986.rs b/tests/ui/async-await/issues/issue-61986.rs
new file mode 100644
index 000000000..879bc6912
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-61986.rs
@@ -0,0 +1,19 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+//
+// Tests that we properly handle StorageDead/StorageLives for temporaries
+// created in async loop bodies.
+
+async fn bar() -> Option<()> {
+ Some(())
+}
+
+async fn listen() {
+ while let Some(_) = bar().await {
+ String::new();
+ }
+}
+
+fn main() {
+ listen();
+}
diff --git a/tests/ui/async-await/issues/issue-62009-1.rs b/tests/ui/async-await/issues/issue-62009-1.rs
new file mode 100644
index 000000000..40ccf2571
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62009-1.rs
@@ -0,0 +1,15 @@
+// edition:2018
+
+async fn print_dur() {}
+
+fn main() {
+ async { let (); }.await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+ async {
+ let task1 = print_dur().await;
+ }.await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+ (|_| 2333).await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+ //~| ERROR is not a future
+}
diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr
new file mode 100644
index 000000000..222afb2c7
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62009-1.stderr
@@ -0,0 +1,43 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-1.rs:6:22
+ |
+LL | fn main() {
+ | ---- this is not `async`
+LL | async { let (); }.await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-1.rs:10:6
+ |
+LL | fn main() {
+ | ---- this is not `async`
+...
+LL | }.await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-1.rs:12:15
+ |
+LL | fn main() {
+ | ---- this is not `async`
+...
+LL | (|_| 2333).await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
+ --> $DIR/issue-62009-1.rs:12:15
+ |
+LL | (|_| 2333).await;
+ | ^^^^^^
+ | |
+ | `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
+ | help: remove the `.await`
+ |
+ = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
+ = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited
+ = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0728.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issues/issue-62009-2.rs b/tests/ui/async-await/issues/issue-62009-2.rs
new file mode 100644
index 000000000..cb7336e61
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62009-2.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+#![feature(async_closure)]
+
+async fn print_dur() {}
+
+fn main() {
+ (async || 2333)().await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+}
diff --git a/tests/ui/async-await/issues/issue-62009-2.stderr b/tests/ui/async-await/issues/issue-62009-2.stderr
new file mode 100644
index 000000000..92e9a8a69
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62009-2.stderr
@@ -0,0 +1,11 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-2.rs:8:22
+ |
+LL | fn main() {
+ | ---- this is not `async`
+LL | (async || 2333)().await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0728`.
diff --git a/tests/ui/async-await/issues/issue-62097.rs b/tests/ui/async-await/issues/issue-62097.rs
new file mode 100644
index 000000000..a24c84cff
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62097.rs
@@ -0,0 +1,21 @@
+// edition:2018
+async fn foo<F>(fun: F)
+where
+ F: FnOnce() + 'static
+{
+ fun()
+}
+
+struct Struct;
+
+impl Struct {
+ pub async fn run_dummy_fn(&self) {
+ foo(|| self.bar()).await;
+ //~^ ERROR closure may outlive the current function
+ //~| ERROR borrowed data escapes outside of associated function
+ }
+
+ pub fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-62097.stderr b/tests/ui/async-await/issues/issue-62097.stderr
new file mode 100644
index 000000000..786f62132
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62097.stderr
@@ -0,0 +1,36 @@
+error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
+ --> $DIR/issue-62097.rs:13:13
+ |
+LL | foo(|| self.bar()).await;
+ | ^^ ---- `self` is borrowed here
+ | |
+ | may outlive borrowed value `self`
+ |
+note: function requires argument type to outlive `'static`
+ --> $DIR/issue-62097.rs:13:9
+ |
+LL | foo(|| self.bar()).await;
+ | ^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
+ |
+LL | foo(move || self.bar()).await;
+ | ++++
+
+error[E0521]: borrowed data escapes outside of associated function
+ --> $DIR/issue-62097.rs:13:9
+ |
+LL | pub async fn run_dummy_fn(&self) {
+ | -----
+ | |
+ | `self` is a reference that is only valid in the associated function body
+ | let's call the lifetime of this reference `'1`
+LL | foo(|| self.bar()).await;
+ | ^^^^^^^^^^^^^^^^^^
+ | |
+ | `self` escapes the associated function body here
+ | argument requires that `'1` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0373, E0521.
+For more information about an error, try `rustc --explain E0373`.
diff --git a/tests/ui/async-await/issues/issue-62517-1.rs b/tests/ui/async-await/issues/issue-62517-1.rs
new file mode 100644
index 000000000..4689ce36a
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62517-1.rs
@@ -0,0 +1,21 @@
+// Regression test for #62517. We used to ICE when you had an `async
+// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no
+// explicit lifetime bound.
+//
+// edition:2018
+// check-pass
+
+trait FirstTrait {}
+trait SecondTrait {
+ type Item: ?Sized;
+}
+
+async fn foo(x: &str) -> impl SecondTrait<Item = dyn FirstTrait> {
+}
+
+
+impl<T> SecondTrait for T {
+ type Item = dyn FirstTrait;
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issues/issue-62517-2.rs b/tests/ui/async-await/issues/issue-62517-2.rs
new file mode 100644
index 000000000..aaf28d6c1
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-62517-2.rs
@@ -0,0 +1,16 @@
+// Regression test for #62517. We used to ICE when you had an `async
+// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no
+// explicit lifetime bound.
+//
+// edition:2018
+// check-pass
+
+trait Object {}
+
+trait Alpha<Param: ?Sized> {}
+
+async fn foo<'a>(_: &'a ()) -> impl Alpha<dyn Object> {}
+
+impl<T> Alpha<dyn Object> for T { }
+
+fn main() { }
diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs
new file mode 100644
index 000000000..32bcbb111
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-63388-1.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+struct Xyz {
+ a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+ async fn do_sth<'a>(
+ &'a self, foo: &dyn Foo
+ ) -> &dyn Foo
+ {
+ //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
+ foo
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr
new file mode 100644
index 000000000..88542315e
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-63388-1.stderr
@@ -0,0 +1,15 @@
+error[E0621]: explicit lifetime required in the type of `foo`
+ --> $DIR/issue-63388-1.rs:13:5
+ |
+LL | &'a self, foo: &dyn Foo
+ | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
+LL | ) -> &dyn Foo
+LL | / {
+LL | |
+LL | | foo
+LL | | }
+ | |_____^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/tests/ui/async-await/issues/issue-63388-2.rs b/tests/ui/async-await/issues/issue-63388-2.rs
new file mode 100644
index 000000000..90b59f96e
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-63388-2.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+struct Xyz {
+ a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+ async fn do_sth<'a>(
+ foo: &dyn Foo, bar: &'a dyn Foo
+ ) -> &dyn Foo //~ ERROR missing lifetime specifier
+ {
+ //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
+ foo
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-63388-2.stderr b/tests/ui/async-await/issues/issue-63388-2.stderr
new file mode 100644
index 000000000..e515f227c
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-63388-2.stderr
@@ -0,0 +1,30 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-63388-2.rs:12:10
+ |
+LL | foo: &dyn Foo, bar: &'a dyn Foo
+ | -------- -----------
+LL | ) -> &dyn Foo
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
+help: consider using the `'a` lifetime
+ |
+LL | ) -> &'a dyn Foo
+ | ++
+
+error[E0621]: explicit lifetime required in the type of `foo`
+ --> $DIR/issue-63388-2.rs:13:5
+ |
+LL | foo: &dyn Foo, bar: &'a dyn Foo
+ | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
+LL | ) -> &dyn Foo
+LL | / {
+LL | |
+LL | | foo
+LL | | }
+ | |_____^ lifetime `'a` required
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0621.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/async-await/issues/issue-63388-3.rs b/tests/ui/async-await/issues/issue-63388-3.rs
new file mode 100644
index 000000000..1a9822e02
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-63388-3.rs
@@ -0,0 +1,17 @@
+// edition:2018
+// check-pass
+
+struct Xyz {
+ a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+ async fn do_sth(
+ &self, foo: &dyn Foo
+ ) {
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-63388-4.rs b/tests/ui/async-await/issues/issue-63388-4.rs
new file mode 100644
index 000000000..58f9dacb3
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-63388-4.rs
@@ -0,0 +1,10 @@
+// check-pass
+// edition:2018
+
+struct A;
+
+impl A {
+ async fn foo(&self, f: &u32) -> &A { self }
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issues/issue-64391-2.rs b/tests/ui/async-await/issues/issue-64391-2.rs
new file mode 100644
index 000000000..eef2c1fb2
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-64391-2.rs
@@ -0,0 +1,20 @@
+// Regression test for #64391
+//
+// As described on the issue, the (spurious) `DROP` inserted for the
+// `"".to_string()` value was causing a (spurious) unwind path that
+// led us to believe that the future might be dropped after `config`
+// had been dropped. This cannot, in fact, happen.
+//
+// check-pass
+// edition:2018
+
+async fn connect() {
+ let config = 666;
+ connect2(&config, "".to_string()).await
+}
+
+async fn connect2(_config: &u32, _tls: String) {
+ unimplemented!()
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issues/issue-64433.rs b/tests/ui/async-await/issues/issue-64433.rs
new file mode 100644
index 000000000..d900f8ed9
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-64433.rs
@@ -0,0 +1,30 @@
+// Regression test for issue #64433.
+//
+// See issue-64391-2.rs for more details, as that was fixed by the
+// same PR.
+//
+// check-pass
+// edition:2018
+
+#[derive(Debug)]
+struct A<'a> {
+ inner: Vec<&'a str>,
+}
+
+struct B {}
+
+impl B {
+ async fn something_with_a(&mut self, a: A<'_>) -> Result<(), String> {
+ println!("{:?}", a);
+ Ok(())
+ }
+}
+
+async fn can_error(some_string: &str) -> Result<(), String> {
+ let a = A { inner: vec![some_string, "foo"] };
+ let mut b = B {};
+ Ok(b.something_with_a(a).await.map(drop)?)
+}
+
+fn main() {
+}
diff --git a/tests/ui/async-await/issues/issue-64477-2.rs b/tests/ui/async-await/issues/issue-64477-2.rs
new file mode 100644
index 000000000..2360b57cc
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-64477-2.rs
@@ -0,0 +1,22 @@
+// Another regression test for #64477.
+//
+// In the past, the code generated by `format!` produced temporaries in the surrounding scope that
+// borrowed the arguments through `&dyn Trait`. These temporaries do not implement `Send`, which
+// meant that when `format!` was used in an async block, the resulting generator was not `Send`.
+// See https://github.com/rust-lang/rust/issues/64477#issuecomment-534669068 for details
+// and https://github.com/rust-lang/rust/issues/64477#issuecomment-531882958 for an example.
+//
+// check-pass
+// edition:2018
+
+async fn foo(_: String) {}
+
+fn bar() -> impl Send {
+ async move {
+ foo(format!("{}:{}", 1, 2)).await;
+ }
+}
+
+fn main() {
+ let _ = bar();
+}
diff --git a/tests/ui/async-await/issues/issue-64477.rs b/tests/ui/async-await/issues/issue-64477.rs
new file mode 100644
index 000000000..5bd52d44a
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-64477.rs
@@ -0,0 +1,20 @@
+// Regression test for #64477.
+//
+// We were incorrectly claiming that the `f(x).await` future captured
+// a value of type `T`, and hence that `T: Send` would have to hold.
+//
+// check-pass
+// edition:2018
+
+use std::future::Future;
+use std::pin::Pin;
+
+fn f<T>(_: &T) -> Pin<Box<dyn Future<Output = ()> + Send>> {
+ unimplemented!()
+}
+
+pub fn g<T: Sync>(x: &'static T) -> impl Future<Output = ()> + Send {
+ async move { f(x).await }
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issues/issue-64964.rs b/tests/ui/async-await/issues/issue-64964.rs
new file mode 100644
index 000000000..6d6eff486
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-64964.rs
@@ -0,0 +1,23 @@
+// check-pass
+// incremental
+// compile-flags: -Z query-dep-graph
+// edition:2018
+
+// Regression test for ICE related to `await`ing in a method + incr. comp. (#64964)
+
+struct Body;
+impl Body {
+ async fn next(&mut self) {
+ async {}.await
+ }
+}
+
+// Another reproduction: `await`ing with a variable from for-loop.
+
+async fn bar() {
+ for x in 0..10 {
+ async { Some(x) }.await.unwrap();
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-65159.rs b/tests/ui/async-await/issues/issue-65159.rs
new file mode 100644
index 000000000..df2ca0257
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65159.rs
@@ -0,0 +1,11 @@
+// Regression test for #65159. We used to ICE.
+//
+// edition:2018
+
+async fn copy() -> Result<()>
+//~^ ERROR this enum takes 2 generic arguments
+{
+ Ok(())
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr
new file mode 100644
index 000000000..40c0e72b2
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65159.stderr
@@ -0,0 +1,16 @@
+error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-65159.rs:5:20
+ |
+LL | async fn copy() -> Result<()>
+ | ^^^^^^ -- supplied 1 generic argument
+ | |
+ | expected 2 generic arguments
+ |
+help: add missing generic argument
+ |
+LL | async fn copy() -> Result<(), E>
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
new file mode 100644
index 000000000..ade386a60
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
@@ -0,0 +1,46 @@
+// issue 65419 - Attempting to run an async fn after completion mentions generators when it should
+// be talking about `async fn`s instead.
+
+// run-fail
+// error-pattern: thread 'main' panicked at '`async fn` resumed after completion'
+// edition:2018
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+
+#![feature(generators, generator_trait)]
+
+async fn foo() {
+}
+
+fn main() {
+ let mut future = Box::pin(foo());
+ executor::block_on(future.as_mut());
+ executor::block_on(future.as_mut());
+}
+
+mod executor {
+ use core::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ };
+
+ pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+ static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ |_| unimplemented!("clone"),
+ |_| unimplemented!("wake"),
+ |_| unimplemented!("wake_by_ref"),
+ |_| (),
+ );
+ let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ let mut context = Context::from_waker(&waker);
+
+ loop {
+ if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ break val;
+ }
+ }
+ }
+}
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
new file mode 100644
index 000000000..b4ea4c9f6
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
@@ -0,0 +1,52 @@
+// issue 65419 - Attempting to run an async fn after completion mentions generators when it should
+// be talking about `async fn`s instead. Should also test what happens when it panics.
+
+// run-fail
+// needs-unwind
+// error-pattern: thread 'main' panicked at '`async fn` resumed after panicking'
+// edition:2018
+// ignore-wasm no panic or subprocess support
+
+#![feature(generators, generator_trait)]
+
+use std::panic;
+
+async fn foo() {
+ panic!();
+}
+
+fn main() {
+ let mut future = Box::pin(foo());
+ panic::catch_unwind(panic::AssertUnwindSafe(|| {
+ executor::block_on(future.as_mut());
+ }));
+
+ executor::block_on(future.as_mut());
+}
+
+mod executor {
+ use core::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ };
+
+ pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+ static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ |_| unimplemented!("clone"),
+ |_| unimplemented!("wake"),
+ |_| unimplemented!("wake_by_ref"),
+ |_| (),
+ );
+ let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ let mut context = Context::from_waker(&waker);
+
+ loop {
+ if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ break val;
+ }
+ }
+ }
+}
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs
new file mode 100644
index 000000000..9fc5667d6
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs
@@ -0,0 +1,25 @@
+// issue 65419 - Attempting to run an `async fn` after completion mentions generators when it should
+// be talking about `async fn`s instead. Regression test added to make sure generators still
+// panic when resumed after completion.
+
+// run-fail
+// error-pattern:generator resumed after completion
+// edition:2018
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+
+#![feature(generators, generator_trait)]
+
+use std::{
+ ops::Generator,
+ pin::Pin,
+};
+
+fn main() {
+ let mut g = || {
+ yield;
+ };
+ Pin::new(&mut g).resume(()); // Yields once.
+ Pin::new(&mut g).resume(()); // Completes here.
+ Pin::new(&mut g).resume(()); // Panics here.
+}
diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
new file mode 100644
index 000000000..1033fa6cc
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
@@ -0,0 +1,32 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:16:17
+ |
+LL | assert_send(async {
+ | _________________^
+LL | |
+LL | | bar(Foo(std::ptr::null())).await;
+LL | | })
+ | |_____^ future created by async block is not `Send`
+ |
+ = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:16:17: 19:6]`, the trait `Send` is not implemented for `*const u8`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
+ |
+LL | bar(Foo(std::ptr::null())).await;
+ | ---------------- ^^^^^^- `std::ptr::null()` is later dropped here
+ | | |
+ | | await occurs here, with `std::ptr::null()` maybe used later
+ | has type `*const u8` which is not `Send`
+help: consider moving this into a `let` binding to create a shorter lived borrow
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13
+ |
+LL | bar(Foo(std::ptr::null())).await;
+ | ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `assert_send`
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:13:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
new file mode 100644
index 000000000..91edbc10d
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// revisions: no_drop_tracking drop_tracking
+// [drop_tracking] check-pass
+// [drop_tracking] compile-flags: -Zdrop-tracking=yes
+// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+
+struct Foo(*const u8);
+
+unsafe impl Send for Foo {}
+
+async fn bar(_: Foo) {}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+ assert_send(async {
+ //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
+ bar(Foo(std::ptr::null())).await;
+ })
+}
diff --git a/tests/ui/async-await/issues/issue-66695-static-refs.rs b/tests/ui/async-await/issues/issue-66695-static-refs.rs
new file mode 100644
index 000000000..f0609713b
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-66695-static-refs.rs
@@ -0,0 +1,24 @@
+// build-pass
+// edition:2018
+
+static A: [i32; 5] = [1, 2, 3, 4, 5];
+
+async fn fun() {
+ let u = A[async { 1 }.await];
+ match A {
+ i if async { true }.await => (),
+ _ => (),
+ }
+}
+
+fn main() {
+ async {
+ let u = A[async { 1 }.await];
+ };
+ async {
+ match A {
+ i if async { true }.await => (),
+ _ => (),
+ }
+ };
+}
diff --git a/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs
new file mode 100644
index 000000000..b7a976a0a
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs
@@ -0,0 +1,15 @@
+// edition:2018
+
+struct Ia<S>(S);
+
+impl<S> Ia<S> {
+ fn partial(_: S) {}
+ fn full(self) {}
+
+ async fn crash(self) {
+ Self::partial(self.0);
+ Self::full(self); //~ ERROR use of partially moved value: `self`
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr
new file mode 100644
index 000000000..e2a735398
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of partially moved value: `self`
+ --> $DIR/issue-66958-non-copy-infered-type-arg.rs:11:20
+ |
+LL | Self::partial(self.0);
+ | ------ value partially moved here
+LL | Self::full(self);
+ | ^^^^ value used here after partial move
+ |
+ = note: partial move occurs because `self.0` has type `S`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
new file mode 100644
index 000000000..dda4a151d
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
@@ -0,0 +1,33 @@
+// build-pass
+// edition:2018
+
+static mut A: [i32; 5] = [1, 2, 3, 4, 5];
+
+fn is_send_sync<T: Send + Sync>(_: T) {}
+
+async fn fun() {
+ let u = unsafe { A[async { 1 }.await] };
+ unsafe {
+ match A {
+ i if async { true }.await => (),
+ _ => (),
+ }
+ }
+}
+
+fn main() {
+ let index_block = async {
+ let u = unsafe { A[async { 1 }.await] };
+ };
+ let match_block = async {
+ unsafe {
+ match A {
+ i if async { true }.await => (),
+ _ => (),
+ }
+ }
+ };
+ is_send_sync(index_block);
+ is_send_sync(match_block);
+ is_send_sync(fun());
+}
diff --git a/tests/ui/async-await/issues/issue-67893.rs b/tests/ui/async-await/issues/issue-67893.rs
new file mode 100644
index 000000000..d73772e5f
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-67893.rs
@@ -0,0 +1,11 @@
+// aux-build: issue_67893.rs
+// edition:2018
+
+extern crate issue_67893;
+
+fn g(_: impl Send) {}
+
+fn main() {
+ g(issue_67893::run())
+ //~^ ERROR future cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr
new file mode 100644
index 000000000..2ce68a782
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-67893.stderr
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-67893.rs:9:7
+ |
+LL | g(issue_67893::run())
+ | ^^^^^^^^^^^^^^^^^^ future is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/auxiliary/issue_67893.rs:9:26
+ |
+LL | f(*x.lock().unwrap()).await;
+ | ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here
+ | | |
+ | | await occurs here, with `x.lock().unwrap()` maybe used later
+ | has type `MutexGuard<'_, ()>` which is not `Send`
+note: required by a bound in `g`
+ --> $DIR/issue-67893.rs:6:14
+ |
+LL | fn g(_: impl Send) {}
+ | ^^^^ required by this bound in `g`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issues/issue-69307-nested.rs b/tests/ui/async-await/issues/issue-69307-nested.rs
new file mode 100644
index 000000000..b7cdf3987
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-69307-nested.rs
@@ -0,0 +1,30 @@
+// Regression test for #69307
+//
+// Having a `async { .. foo.await .. }` block appear inside of a `+=`
+// expression was causing an ICE due to a failure to save/restore
+// state in the AST numbering pass when entering a nested body.
+//
+// check-pass
+// edition:2018
+
+fn block_on<F>(_: F) -> usize {
+ 0
+}
+
+fn main() {}
+
+async fn bar() {
+ let mut sum = 0;
+ sum += {
+ block_on(async {
+ baz().await;
+ let mut inner = 1;
+ inner += block_on(async {
+ baz().await;
+ 0
+ })
+ })
+ };
+}
+
+async fn baz() {}
diff --git a/tests/ui/async-await/issues/issue-69307.rs b/tests/ui/async-await/issues/issue-69307.rs
new file mode 100644
index 000000000..59309a7f2
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-69307.rs
@@ -0,0 +1,23 @@
+// Regression test for #69307
+//
+// Having an `async { .. foo.await .. }` block appear inside of a `+=`
+// expression was causing an ICE due to a failure to save/restore
+// state in the AST numbering pass when entering a nested body.
+//
+// check-pass
+// edition:2018
+
+fn block_on<F>(_: F) -> usize {
+ 0
+}
+
+fn main() {}
+
+async fn bar() {
+ let mut sum = 0;
+ sum += block_on(async {
+ baz().await;
+ });
+}
+
+async fn baz() {}
diff --git a/tests/ui/async-await/issues/issue-72312.rs b/tests/ui/async-await/issues/issue-72312.rs
new file mode 100644
index 000000000..74122cf00
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-72312.rs
@@ -0,0 +1,21 @@
+// edition:2018
+fn require_static<T: 'static>(val: T) -> T {
+ val
+}
+
+struct Problem;
+
+impl Problem {
+ pub async fn start(&self) {
+ //~^ NOTE let's call
+ //~| NOTE `self` is a reference
+ require_static(async move {
+ //~^ ERROR borrowed data escapes
+ //~| NOTE `self` escapes
+ //~| NOTE argument requires
+ &self;
+ });
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr
new file mode 100644
index 000000000..aa947b690
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-72312.stderr
@@ -0,0 +1,23 @@
+error[E0521]: borrowed data escapes outside of associated function
+ --> $DIR/issue-72312.rs:12:9
+ |
+LL | pub async fn start(&self) {
+ | -----
+ | |
+ | `self` is a reference that is only valid in the associated function body
+ | let's call the lifetime of this reference `'1`
+...
+LL | / require_static(async move {
+LL | |
+LL | |
+LL | |
+LL | | &self;
+LL | | });
+ | | ^
+ | | |
+ | |__________`self` escapes the associated function body here
+ | argument requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/async-await/issues/issue-78600.rs b/tests/ui/async-await/issues/issue-78600.rs
new file mode 100644
index 000000000..8aaeaecf3
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78600.rs
@@ -0,0 +1,12 @@
+// edition:2018
+
+struct S<'a>(&'a i32);
+
+impl<'a> S<'a> {
+ async fn new(i: &'a i32) -> Result<Self, ()> {
+ //~^ ERROR: `async fn`
+ Ok(S(&22))
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-78600.stderr b/tests/ui/async-await/issues/issue-78600.stderr
new file mode 100644
index 000000000..37eafa996
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78600.stderr
@@ -0,0 +1,14 @@
+error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+ --> $DIR/issue-78600.rs:6:33
+ |
+LL | async fn new(i: &'a i32) -> Result<Self, ()> {
+ | ^^^^^^^----^^^^^
+ | |
+ | help: consider spelling out the type instead: `S<'a>`
+ |
+ = note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
+ = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/issues/issue-78654.full.stderr b/tests/ui/async-await/issues/issue-78654.full.stderr
new file mode 100644
index 000000000..0d12a948c
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78654.full.stderr
@@ -0,0 +1,19 @@
+error[E0573]: expected type, found built-in attribute `feature`
+ --> $DIR/issue-78654.rs:9:15
+ |
+LL | impl<const H: feature> Foo {
+ | ^^^^^^^ not a type
+
+error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates
+ --> $DIR/issue-78654.rs:9:6
+ |
+LL | impl<const H: feature> Foo {
+ | ^^^^^^^^^^^^^^^^ unconstrained const parameter
+ |
+ = note: expressions using a const parameter must map each value to a distinct output value
+ = note: proving the result of expressions other than the parameter are unique is not supported
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0573.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/async-await/issues/issue-78654.min.stderr b/tests/ui/async-await/issues/issue-78654.min.stderr
new file mode 100644
index 000000000..0d12a948c
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78654.min.stderr
@@ -0,0 +1,19 @@
+error[E0573]: expected type, found built-in attribute `feature`
+ --> $DIR/issue-78654.rs:9:15
+ |
+LL | impl<const H: feature> Foo {
+ | ^^^^^^^ not a type
+
+error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates
+ --> $DIR/issue-78654.rs:9:6
+ |
+LL | impl<const H: feature> Foo {
+ | ^^^^^^^^^^^^^^^^ unconstrained const parameter
+ |
+ = note: expressions using a const parameter must map each value to a distinct output value
+ = note: proving the result of expressions other than the parameter are unique is not supported
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0573.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/async-await/issues/issue-78654.rs b/tests/ui/async-await/issues/issue-78654.rs
new file mode 100644
index 000000000..cc6dc3834
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78654.rs
@@ -0,0 +1,15 @@
+// edition:2018
+// revisions: full min
+
+#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+struct Foo;
+
+impl<const H: feature> Foo {
+//~^ ERROR: expected type, found built-in attribute `feature`
+//~^^ ERROR: the const parameter `H` is not constrained by the impl trait, self type, or predicates
+ async fn biz() {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-78938-async-block.rs b/tests/ui/async-await/issues/issue-78938-async-block.rs
new file mode 100644
index 000000000..36f716019
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78938-async-block.rs
@@ -0,0 +1,33 @@
+// edition:2018
+
+use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}};
+
+async fn f() {
+ let room_ref = Arc::new(Vec::new());
+
+ let gameloop_handle = spawn(async { //~ ERROR E0373
+ game_loop(Arc::clone(&room_ref))
+ });
+ gameloop_handle.await;
+}
+
+fn game_loop(v: Arc<Vec<usize>>) {}
+
+fn spawn<F>(future: F) -> JoinHandle
+where
+ F: Future + Send + 'static,
+ F::Output: Send + 'static,
+{
+ loop {}
+}
+
+struct JoinHandle;
+
+impl Future for JoinHandle {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ loop {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-78938-async-block.stderr b/tests/ui/async-await/issues/issue-78938-async-block.stderr
new file mode 100644
index 000000000..c1a4b467f
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-78938-async-block.stderr
@@ -0,0 +1,19 @@
+error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
+ --> $DIR/issue-78938-async-block.rs:8:33
+ |
+LL | let gameloop_handle = spawn(async {
+ | _________________________________^
+LL | | game_loop(Arc::clone(&room_ref))
+ | | -------- `room_ref` is borrowed here
+LL | | });
+ | |_____^ may outlive borrowed value `room_ref`
+ |
+ = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
+help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
+ |
+LL | let gameloop_handle = spawn(async move {
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/tests/ui/async-await/issues/issue-95307.rs b/tests/ui/async-await/issues/issue-95307.rs
new file mode 100644
index 000000000..f7e48070c
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-95307.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+// Regression test for #95307.
+// The ICE occurred on all the editions, specifying edition:2018 to reduce diagnostics.
+
+pub trait C {
+ async fn new() -> [u8; _];
+ //~^ ERROR: functions in traits cannot be declared `async`
+ //~| ERROR: using `_` for array lengths is unstable
+ //~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-95307.stderr b/tests/ui/async-await/issues/issue-95307.stderr
new file mode 100644
index 000000000..a497cebe3
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-95307.stderr
@@ -0,0 +1,32 @@
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/issue-95307.rs:7:5
+ |
+LL | async fn new() -> [u8; _];
+ | -----^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `async` because of this
+ |
+ = note: `async` trait functions are not currently supported
+ = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/issue-95307.rs:7:28
+ |
+LL | async fn new() -> [u8; _];
+ | ^ `_` not allowed here
+
+error[E0658]: using `_` for array lengths is unstable
+ --> $DIR/issue-95307.rs:7:28
+ |
+LL | async fn new() -> [u8; _];
+ | ^
+ |
+ = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+ = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0658, E0706.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.rs b/tests/ui/async-await/issues/non-async-enclosing-span.rs
new file mode 100644
index 000000000..d47c21377
--- /dev/null
+++ b/tests/ui/async-await/issues/non-async-enclosing-span.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+async fn do_the_thing() -> u8 {
+ 8
+}
+// #63398: point at the enclosing scope and not the previously seen closure
+fn main() { //~ NOTE this is not `async`
+ let x = move || {};
+ let y = do_the_thing().await; //~ ERROR `await` is only allowed inside `async` functions
+ //~^ NOTE only allowed inside `async` functions and blocks
+}
diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.stderr b/tests/ui/async-await/issues/non-async-enclosing-span.stderr
new file mode 100644
index 000000000..20b827479
--- /dev/null
+++ b/tests/ui/async-await/issues/non-async-enclosing-span.stderr
@@ -0,0 +1,12 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/non-async-enclosing-span.rs:9:27
+ |
+LL | fn main() {
+ | ---- this is not `async`
+LL | let x = move || {};
+LL | let y = do_the_thing().await;
+ | ^^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0728`.
diff --git a/tests/ui/async-await/large_moves.attribute.stderr b/tests/ui/async-await/large_moves.attribute.stderr
new file mode 100644
index 000000000..0c5452475
--- /dev/null
+++ b/tests/ui/async-await/large_moves.attribute.stderr
@@ -0,0 +1,45 @@
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:13:13
+ |
+LL | let x = async {
+ | _____________^
+LL | | let y = [0; 9999];
+LL | | dbg!(y);
+LL | | thing(&y).await;
+LL | | dbg!(y);
+LL | | };
+ | |_____^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+note: the lint level is defined here
+ --> $DIR/large_moves.rs:1:9
+ |
+LL | #![deny(large_assignments)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:19:14
+ |
+LL | let z = (x, 42);
+ | ^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:19:13
+ |
+LL | let z = (x, 42);
+ | ^^^^^^^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:21:13
+ |
+LL | let a = z.0;
+ | ^^^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/async-await/large_moves.option.stderr b/tests/ui/async-await/large_moves.option.stderr
new file mode 100644
index 000000000..0c5452475
--- /dev/null
+++ b/tests/ui/async-await/large_moves.option.stderr
@@ -0,0 +1,45 @@
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:13:13
+ |
+LL | let x = async {
+ | _____________^
+LL | | let y = [0; 9999];
+LL | | dbg!(y);
+LL | | thing(&y).await;
+LL | | dbg!(y);
+LL | | };
+ | |_____^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+note: the lint level is defined here
+ --> $DIR/large_moves.rs:1:9
+ |
+LL | #![deny(large_assignments)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:19:14
+ |
+LL | let z = (x, 42);
+ | ^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:19:13
+ |
+LL | let z = (x, 42);
+ | ^^^^^^^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+error: moving 10024 bytes
+ --> $DIR/large_moves.rs:21:13
+ |
+LL | let a = z.0;
+ | ^^^ value moved from here
+ |
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/async-await/large_moves.rs b/tests/ui/async-await/large_moves.rs
new file mode 100644
index 000000000..d43d0eec0
--- /dev/null
+++ b/tests/ui/async-await/large_moves.rs
@@ -0,0 +1,27 @@
+#![deny(large_assignments)]
+#![feature(large_assignments)]
+#![cfg_attr(attribute, move_size_limit = "1000")]
+// build-fail
+// only-x86_64
+// revisions: attribute option
+// [option]compile-flags: -Zmove-size-limit=1000
+
+// edition:2018
+// compile-flags: -Zmir-opt-level=0
+
+fn main() {
+ let x = async { //~ ERROR large_assignments
+ let y = [0; 9999];
+ dbg!(y);
+ thing(&y).await;
+ dbg!(y);
+ };
+ let z = (x, 42); //~ ERROR large_assignments
+ //~^ ERROR large_assignments
+ let a = z.0; //~ ERROR large_assignments
+ let b = z.1;
+}
+
+async fn thing(y: &[u8]) {
+ dbg!(y);
+}
diff --git a/tests/ui/async-await/move-part-await-return-rest-struct.rs b/tests/ui/async-await/move-part-await-return-rest-struct.rs
new file mode 100644
index 000000000..39ea2aae5
--- /dev/null
+++ b/tests/ui/async-await/move-part-await-return-rest-struct.rs
@@ -0,0 +1,18 @@
+// build-pass
+// edition:2018
+// compile-flags: --crate-type lib
+
+struct Small {
+ x: Vec<usize>,
+ y: Vec<usize>,
+}
+
+// You are allowed to move out part of a struct to an async fn, you still
+// have access to remaining parts after awaiting
+async fn move_part_await_return_rest_struct() -> Vec<usize> {
+ let s = Small { x: vec![31], y: vec![19, 1441] };
+ needs_vec(s.x).await;
+ s.y
+}
+
+async fn needs_vec(_vec: Vec<usize>) {}
diff --git a/tests/ui/async-await/move-part-await-return-rest-tuple.rs b/tests/ui/async-await/move-part-await-return-rest-tuple.rs
new file mode 100644
index 000000000..7b958b98b
--- /dev/null
+++ b/tests/ui/async-await/move-part-await-return-rest-tuple.rs
@@ -0,0 +1,12 @@
+// build-pass
+// edition:2018
+// compile-flags: --crate-type lib
+
+async fn move_part_await_return_rest_tuple() -> Vec<usize> {
+ let x = (vec![3], vec![4, 4]);
+ drop(x.1);
+ echo(x.0[0]).await;
+ x.0
+}
+
+async fn echo(x: usize) -> usize { x }
diff --git a/tests/ui/async-await/multiple-lifetimes/elided.rs b/tests/ui/async-await/multiple-lifetimes/elided.rs
new file mode 100644
index 000000000..8258e2eff
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/elided.rs
@@ -0,0 +1,10 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+
+fn main() {
+ let _ = multiple_elided_lifetimes(&22, &44);
+}
diff --git a/tests/ui/async-await/multiple-lifetimes/fn-ptr.rs b/tests/ui/async-await/multiple-lifetimes/fn-ptr.rs
new file mode 100644
index 000000000..3912b8547
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/fn-ptr.rs
@@ -0,0 +1,12 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {}
+
+fn gimme(_: &u8) { }
+
+fn main() {
+ let _ = multiple_named_lifetimes(&22, &44, gimme);
+}
diff --git a/tests/ui/async-await/multiple-lifetimes/hrtb.rs b/tests/ui/async-await/multiple-lifetimes/hrtb.rs
new file mode 100644
index 000000000..e788ca5ff
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/hrtb.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// check-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+use std::ops::Add;
+
+async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
+ _: impl for<'a> Add<&'a u8>,
+ _: impl for<'b> Add<&'b u8>,
+ _: &'c u8,
+) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/multiple-lifetimes/named.rs b/tests/ui/async-await/multiple-lifetimes/named.rs
new file mode 100644
index 000000000..e8eb98102
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/named.rs
@@ -0,0 +1,10 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+
+fn main() {
+ let _ = multiple_named_lifetimes(&22, &44);
+}
diff --git a/tests/ui/async-await/multiple-lifetimes/partial-relation.rs b/tests/ui/async-await/multiple-lifetimes/partial-relation.rs
new file mode 100644
index 000000000..02b105999
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/partial-relation.rs
@@ -0,0 +1,13 @@
+// edition:2018
+// run-pass
+
+async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32)
+ where 'b: 'a
+{
+ drop((a, c));
+ (b, b)
+}
+
+fn main() {
+ let _ = lotsa_lifetimes(&22, &44, &66);
+}
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs
new file mode 100644
index 000000000..f1002947f
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs
@@ -0,0 +1,17 @@
+// edition:2018
+// run-pass
+
+// Test member constraints that appear in the `impl Trait`
+// return type of an async function.
+// (This used to require a feature gate.)
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+ (a, b)
+}
+
+fn main() {
+ let _ = async_ret_impl_trait(&22, &44);
+}
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs
new file mode 100644
index 000000000..aebc77d26
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs
@@ -0,0 +1,31 @@
+// edition:2018
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+trait Trait<'a> { }
+impl<T> Trait<'_> for T { }
+
+// Fails to recognize that both 'a and 'b are mentioned and should thus be accepted
+async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
+ //~^ ERROR lifetime may not live long enough
+ (a, b)
+}
+
+// Only `'a` permitted in return type, not `'b`.
+async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+ //~^ ERROR captures lifetime that does not appear in bounds
+ (a, b)
+}
+
+// As above, but `'b: 'a`, so return type can be inferred to `(&'a u8,
+// &'a u8)`.
+async fn async_ret_impl_trait2<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a>
+where
+ 'b: 'a,
+{
+ (a, b)
+}
+
+fn main() {
+}
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
new file mode 100644
index 000000000..ae4d0d585
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -0,0 +1,35 @@
+error: lifetime may not live long enough
+ --> $DIR/ret-impl-trait-one.rs:10:85
+ |
+LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
+ | ________________________________--__--_______________________________________________^
+ | | | |
+ | | | lifetime `'b` defined here
+ | | lifetime `'a` defined here
+LL | |
+LL | | (a, b)
+LL | | }
+ | |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not appear in bounds
+ --> $DIR/ret-impl-trait-one.rs:16:80
+ |
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+ | ____________________________________--__________________________________________^
+ | | |
+ | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL | |
+LL | | (a, b)
+LL | | }
+ | |_^
+ |
+help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound
+ |
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-ref.rs b/tests/ui/async-await/multiple-lifetimes/ret-ref.rs
new file mode 100644
index 000000000..149c020f9
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/ret-ref.rs
@@ -0,0 +1,44 @@
+// edition:2018
+
+// Test that we get the expected borrow check errors when an async
+// function (which takes multiple lifetimes) only returns data from
+// one of them.
+
+async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 {
+ a
+}
+
+// Both are borrowed whilst the future is live.
+async fn future_live() {
+ let mut a = 22;
+ let mut b = 44;
+ let future = multiple_named_lifetimes(&a, &b);
+ a += 1; //~ ERROR cannot assign
+ b += 1; //~ ERROR cannot assign
+ let p = future.await;
+ drop(p);
+}
+
+// Just the return value is live after future is awaited.
+async fn just_return_live() {
+ let mut a = 22;
+ let mut b = 44;
+ let future = multiple_named_lifetimes(&a, &b);
+ let p = future.await;
+ a += 1; //~ ERROR cannot assign
+ b += 1;
+ drop(p);
+}
+
+// Once `p` is dead, both `a` and `b` are unborrowed.
+async fn after_both_dead() {
+ let mut a = 22;
+ let mut b = 44;
+ let future = multiple_named_lifetimes(&a, &b);
+ let p = future.await;
+ drop(p);
+ a += 1;
+ b += 1;
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr b/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr
new file mode 100644
index 000000000..d86e84033
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr
@@ -0,0 +1,37 @@
+error[E0506]: cannot assign to `a` because it is borrowed
+ --> $DIR/ret-ref.rs:16:5
+ |
+LL | let future = multiple_named_lifetimes(&a, &b);
+ | -- borrow of `a` occurs here
+LL | a += 1;
+ | ^^^^^^ assignment to borrowed `a` occurs here
+LL | b += 1;
+LL | let p = future.await;
+ | ------ borrow later used here
+
+error[E0506]: cannot assign to `b` because it is borrowed
+ --> $DIR/ret-ref.rs:17:5
+ |
+LL | let future = multiple_named_lifetimes(&a, &b);
+ | -- borrow of `b` occurs here
+LL | a += 1;
+LL | b += 1;
+ | ^^^^^^ assignment to borrowed `b` occurs here
+LL | let p = future.await;
+ | ------ borrow later used here
+
+error[E0506]: cannot assign to `a` because it is borrowed
+ --> $DIR/ret-ref.rs:28:5
+ |
+LL | let future = multiple_named_lifetimes(&a, &b);
+ | -- borrow of `a` occurs here
+LL | let p = future.await;
+LL | a += 1;
+ | ^^^^^^ assignment to borrowed `a` occurs here
+LL | b += 1;
+LL | drop(p);
+ | - borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/tests/ui/async-await/multiple-lifetimes/variance.rs b/tests/ui/async-await/multiple-lifetimes/variance.rs
new file mode 100644
index 000000000..6ed8bef95
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/variance.rs
@@ -0,0 +1,15 @@
+// edition:2018
+// run-pass
+
+// Test for async fn where the parameters have distinct lifetime
+// parameters that appear in all possible variances.
+
+async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { }
+
+fn take_any(_: &u8) { }
+fn identify(x: &u8) -> &u8 { x }
+fn give_back() -> &'static u8 { &22 }
+
+fn main() {
+ let _ = lotsa_lifetimes(take_any, identify, give_back);
+}
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
new file mode 100644
index 000000000..bb2a61f03
--- /dev/null
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
@@ -0,0 +1,13 @@
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+async fn rec_1() { //~ ERROR recursion in an `async fn`
+ rec_2().await;
+}
+
+async fn rec_2() { //~ ERROR recursion in an `async fn`
+ rec_1().await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
new file mode 100644
index 000000000..f789ad2a0
--- /dev/null
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -0,0 +1,21 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18
+ |
+LL | async fn rec_1() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+ |
+LL | async fn rec_2() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/nested-in-impl.rs b/tests/ui/async-await/nested-in-impl.rs
new file mode 100644
index 000000000..76ed827d5
--- /dev/null
+++ b/tests/ui/async-await/nested-in-impl.rs
@@ -0,0 +1,15 @@
+// Test that async fn works when nested inside of
+// impls with lifetime parameters.
+//
+// check-pass
+// edition:2018
+
+struct Foo<'a>(&'a ());
+
+impl<'a> Foo<'a> {
+ fn test() {
+ async fn test() {}
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs
new file mode 100644
index 000000000..963460c11
--- /dev/null
+++ b/tests/ui/async-await/no-async-const.rs
@@ -0,0 +1,5 @@
+// edition:2018
+// compile-flags: --crate-type lib
+
+pub async const fn x() {}
+//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
diff --git a/tests/ui/async-await/no-async-const.stderr b/tests/ui/async-await/no-async-const.stderr
new file mode 100644
index 000000000..a51dc88a4
--- /dev/null
+++ b/tests/ui/async-await/no-async-const.stderr
@@ -0,0 +1,13 @@
+error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
+ --> $DIR/no-async-const.rs:4:11
+ |
+LL | pub async const fn x() {}
+ | ------^^^^^
+ | | |
+ | | expected one of `extern`, `fn`, or `unsafe`
+ | help: `const` must come before `async`: `const async`
+ |
+ = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/no-const-async.rs b/tests/ui/async-await/no-const-async.rs
new file mode 100644
index 000000000..cfb0ef1b3
--- /dev/null
+++ b/tests/ui/async-await/no-const-async.rs
@@ -0,0 +1,6 @@
+// edition:2018
+// compile-flags: --crate-type lib
+
+pub const async fn x() {}
+//~^ ERROR functions cannot be both `const` and `async`
+//~| ERROR cycle detected
diff --git a/tests/ui/async-await/no-const-async.stderr b/tests/ui/async-await/no-const-async.stderr
new file mode 100644
index 000000000..c5bd520aa
--- /dev/null
+++ b/tests/ui/async-await/no-const-async.stderr
@@ -0,0 +1,42 @@
+error: functions cannot be both `const` and `async`
+ --> $DIR/no-const-async.rs:4:5
+ |
+LL | pub const async fn x() {}
+ | ----^^^^^-^^^^^----------
+ | | |
+ | | `async` because of this
+ | `const` because of this
+
+error[E0391]: cycle detected when computing type of `x::{opaque#0}`
+ --> $DIR/no-const-async.rs:4:24
+ |
+LL | pub const async fn x() {}
+ | ^
+ |
+note: ...which requires borrow-checking `x`...
+ --> $DIR/no-const-async.rs:4:1
+ |
+LL | pub const async fn x() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing MIR for `x`...
+ --> $DIR/no-const-async.rs:4:1
+ |
+LL | pub const async fn x() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `x`...
+ --> $DIR/no-const-async.rs:4:1
+ |
+LL | pub const async fn x() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+ = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+ --> $DIR/no-const-async.rs:4:1
+ |
+LL | pub const async fn x() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/async-await/no-move-across-await-struct.rs b/tests/ui/async-await/no-move-across-await-struct.rs
new file mode 100644
index 000000000..51c9a42b3
--- /dev/null
+++ b/tests/ui/async-await/no-move-across-await-struct.rs
@@ -0,0 +1,16 @@
+// edition:2018
+// compile-flags: --crate-type lib
+
+async fn no_move_across_await_struct() -> Vec<usize> {
+ let s = Small { x: vec![31], y: vec![19, 1441] };
+ needs_vec(s.x).await;
+ s.x
+ //~^ ERROR use of moved value: `s.x`
+}
+
+struct Small {
+ x: Vec<usize>,
+ y: Vec<usize>,
+}
+
+async fn needs_vec(_vec: Vec<usize>) {}
diff --git a/tests/ui/async-await/no-move-across-await-struct.stderr b/tests/ui/async-await/no-move-across-await-struct.stderr
new file mode 100644
index 000000000..4eaed1cf1
--- /dev/null
+++ b/tests/ui/async-await/no-move-across-await-struct.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `s.x`
+ --> $DIR/no-move-across-await-struct.rs:7:5
+ |
+LL | needs_vec(s.x).await;
+ | --- value moved here
+LL | s.x
+ | ^^^ value used here after move
+ |
+ = note: move occurs because `s.x` has type `Vec<usize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/async-await/no-move-across-await-tuple.rs b/tests/ui/async-await/no-move-across-await-tuple.rs
new file mode 100644
index 000000000..a65633269
--- /dev/null
+++ b/tests/ui/async-await/no-move-across-await-tuple.rs
@@ -0,0 +1,12 @@
+// edition:2018
+// compile-flags: --crate-type lib
+
+async fn no_move_across_await_tuple() -> Vec<usize> {
+ let x = (vec![3], vec![4, 4]);
+ drop(x.1);
+ nothing().await;
+ x.1
+ //~^ ERROR use of moved value: `x.1`
+}
+
+async fn nothing() {}
diff --git a/tests/ui/async-await/no-move-across-await-tuple.stderr b/tests/ui/async-await/no-move-across-await-tuple.stderr
new file mode 100644
index 000000000..d750df991
--- /dev/null
+++ b/tests/ui/async-await/no-move-across-await-tuple.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x.1`
+ --> $DIR/no-move-across-await-tuple.rs:8:5
+ |
+LL | drop(x.1);
+ | --- value moved here
+LL | nothing().await;
+LL | x.1
+ | ^^^ value used here after move
+ |
+ = note: move occurs because `x.1` has type `Vec<usize>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/async-await/no-non-guaranteed-initialization.rs b/tests/ui/async-await/no-non-guaranteed-initialization.rs
new file mode 100644
index 000000000..c4d81bf83
--- /dev/null
+++ b/tests/ui/async-await/no-non-guaranteed-initialization.rs
@@ -0,0 +1,12 @@
+// edition:2018
+// compile-flags: --crate-type lib
+
+async fn no_non_guaranteed_initialization(x: usize) -> usize {
+ let y;
+ if x > 5 {
+ y = echo(10).await;
+ }
+ y //~ ERROR E0381
+}
+
+async fn echo(x: usize) -> usize { x + 1 }
diff --git a/tests/ui/async-await/no-non-guaranteed-initialization.stderr b/tests/ui/async-await/no-non-guaranteed-initialization.stderr
new file mode 100644
index 000000000..12c15bf56
--- /dev/null
+++ b/tests/ui/async-await/no-non-guaranteed-initialization.stderr
@@ -0,0 +1,16 @@
+error[E0381]: used binding `y` is possibly-uninitialized
+ --> $DIR/no-non-guaranteed-initialization.rs:9:5
+ |
+LL | let y;
+ | - binding declared here but left uninitialized
+LL | if x > 5 {
+ | ----- if this `if` condition is `false`, `y` is not initialized
+LL | y = echo(10).await;
+LL | }
+ | - an `else` arm might be missing here, initializing `y`
+LL | y
+ | ^ `y` used here but it is possibly-uninitialized
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/tests/ui/async-await/no-params-non-move-async-closure.rs b/tests/ui/async-await/no-params-non-move-async-closure.rs
new file mode 100644
index 000000000..3b15f35c2
--- /dev/null
+++ b/tests/ui/async-await/no-params-non-move-async-closure.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+#![feature(async_closure)]
+
+fn main() {
+ let _ = async |x: u8| {};
+ //~^ ERROR `async` non-`move` closures with parameters are not currently supported
+}
diff --git a/tests/ui/async-await/no-params-non-move-async-closure.stderr b/tests/ui/async-await/no-params-non-move-async-closure.stderr
new file mode 100644
index 000000000..1f589c516
--- /dev/null
+++ b/tests/ui/async-await/no-params-non-move-async-closure.stderr
@@ -0,0 +1,11 @@
+error[E0708]: `async` non-`move` closures with parameters are not currently supported
+ --> $DIR/no-params-non-move-async-closure.rs:6:13
+ |
+LL | let _ = async |x: u8| {};
+ | ^^^^^^^^^^^^^
+ |
+ = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0708`.
diff --git a/tests/ui/async-await/no-std.rs b/tests/ui/async-await/no-std.rs
new file mode 100644
index 000000000..63e93cdff
--- /dev/null
+++ b/tests/ui/async-await/no-std.rs
@@ -0,0 +1,13 @@
+// edition:2018
+// check-pass
+
+#![no_std]
+#![crate_type = "rlib"]
+
+use core::future::Future;
+
+async fn a(f: impl Future) {
+ f.await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/no-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs
new file mode 100644
index 000000000..f40154e16
--- /dev/null
+++ b/tests/ui/async-await/no-unsafe-async.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+struct S;
+
+impl S {
+ #[cfg(FALSE)]
+ unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
+}
+
+#[cfg(FALSE)]
+unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
diff --git a/tests/ui/async-await/no-unsafe-async.stderr b/tests/ui/async-await/no-unsafe-async.stderr
new file mode 100644
index 000000000..f23d17d6b
--- /dev/null
+++ b/tests/ui/async-await/no-unsafe-async.stderr
@@ -0,0 +1,29 @@
+error: expected one of `extern` or `fn`, found keyword `async`
+ --> $DIR/no-unsafe-async.rs:7:12
+ |
+LL | impl S {
+ | - while parsing this item list starting here
+LL | #[cfg(FALSE)]
+LL | unsafe async fn g() {}
+ | -------^^^^^
+ | | |
+ | | expected one of `extern` or `fn`
+ | help: `async` must come before `unsafe`: `async unsafe`
+LL | }
+ | - the item list ends here
+ |
+ = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
+
+error: expected one of `extern` or `fn`, found keyword `async`
+ --> $DIR/no-unsafe-async.rs:11:8
+ |
+LL | unsafe async fn f() {}
+ | -------^^^^^
+ | | |
+ | | expected one of `extern` or `fn`
+ | help: `async` must come before `unsafe`: `async unsafe`
+ |
+ = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs
new file mode 100644
index 000000000..a3167215d
--- /dev/null
+++ b/tests/ui/async-await/non-trivial-drop.rs
@@ -0,0 +1,36 @@
+// build-pass
+// edition:2018
+// compile-flags: -Zdrop-tracking=y
+
+#![feature(generators)]
+
+fn main() {
+ let _ = foo();
+}
+
+fn foo() {
+ || {
+ yield drop(Config {
+ nickname: NonCopy,
+ b: NonCopy2,
+ }.nickname);
+ };
+}
+
+#[derive(Default)]
+struct NonCopy;
+impl Drop for NonCopy {
+ fn drop(&mut self) {}
+}
+
+#[derive(Default)]
+struct NonCopy2;
+impl Drop for NonCopy2 {
+ fn drop(&mut self) {}
+}
+
+#[derive(Default)]
+struct Config {
+ nickname: NonCopy,
+ b: NonCopy2,
+}
diff --git a/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
new file mode 100644
index 000000000..17b4ef7bd
--- /dev/null
+++ b/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
@@ -0,0 +1,35 @@
+error[E0277]: `NotSend` cannot be sent between threads safely
+ --> $DIR/partial-drop-partial-reinit.rs:9:16
+ |
+LL | gimme_send(foo());
+ | ---------- ^^^^^ `NotSend` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+...
+LL | async fn foo() {
+ | - within this `impl Future<Output = ()>`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
+ = note: required because it appears within the type `(NotSend,)`
+ = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future<Output = ()>`
+note: required because it's used within this `async fn` body
+ --> $DIR/partial-drop-partial-reinit.rs:31:16
+ |
+LL | async fn foo() {
+ | ________________^
+LL | |
+LL | |
+LL | | let mut x = (NotSend {},);
+... |
+LL | | bar().await;
+LL | | }
+ | |_^
+note: required by a bound in `gimme_send`
+ --> $DIR/partial-drop-partial-reinit.rs:17:18
+ |
+LL | fn gimme_send<T: Send>(t: T) {
+ | ^^^^ required by this bound in `gimme_send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
new file mode 100644
index 000000000..34d8a159f
--- /dev/null
+++ b/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
@@ -0,0 +1,35 @@
+error[E0277]: `NotSend` cannot be sent between threads safely
+ --> $DIR/partial-drop-partial-reinit.rs:9:16
+ |
+LL | gimme_send(foo());
+ | ---------- ^^^^^ `NotSend` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+...
+LL | async fn foo() {
+ | - within this `impl Future<Output = ()>`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
+ = note: required because it appears within the type `(NotSend,)`
+ = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
+note: required because it's used within this `async fn` body
+ --> $DIR/partial-drop-partial-reinit.rs:31:16
+ |
+LL | async fn foo() {
+ | ________________^
+LL | |
+LL | |
+LL | | let mut x = (NotSend {},);
+... |
+LL | | bar().await;
+LL | | }
+ | |_^
+note: required by a bound in `gimme_send`
+ --> $DIR/partial-drop-partial-reinit.rs:17:18
+ |
+LL | fn gimme_send<T: Send>(t: T) {
+ | ^^^^ required by this bound in `gimme_send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/partial-drop-partial-reinit.rs b/tests/ui/async-await/partial-drop-partial-reinit.rs
new file mode 100644
index 000000000..7d097e72f
--- /dev/null
+++ b/tests/ui/async-await/partial-drop-partial-reinit.rs
@@ -0,0 +1,40 @@
+// edition:2021
+// revisions: no_drop_tracking drop_tracking
+// [drop_tracking] compile-flags: -Zdrop-tracking=yes
+// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+#![feature(negative_impls)]
+#![allow(unused)]
+
+fn main() {
+ gimme_send(foo());
+ //~^ ERROR cannot be sent between threads safely
+ //~| NOTE cannot be sent
+ //~| NOTE bound introduced by
+ //~| NOTE appears within the type
+ //~| NOTE captures the following types
+}
+
+fn gimme_send<T: Send>(t: T) {
+ //~^ NOTE required by this bound
+ //~| NOTE required by a bound
+ drop(t);
+}
+
+struct NotSend {}
+
+impl Drop for NotSend {
+ fn drop(&mut self) {}
+}
+
+impl !Send for NotSend {}
+
+async fn foo() {
+ //~^ NOTE used within this `async fn` body
+ //~| NOTE within this `impl Future
+ let mut x = (NotSend {},);
+ drop(x.0);
+ x.0 = NotSend {};
+ bar().await;
+}
+
+async fn bar() {}
diff --git a/tests/ui/async-await/partial-initialization-across-await.rs b/tests/ui/async-await/partial-initialization-across-await.rs
new file mode 100644
index 000000000..7577aee3f
--- /dev/null
+++ b/tests/ui/async-await/partial-initialization-across-await.rs
@@ -0,0 +1,39 @@
+// Test that we don't allow awaiting from an async fn while a local is partially
+// initialized.
+
+// edition:2018
+
+struct S { x: i32, y: i32 }
+struct T(i32, i32);
+
+async fn noop() {}
+
+async fn test_tuple() {
+ let mut t: (i32, i32);
+ t.0 = 42; //~ ERROR E0381
+ noop().await;
+ t.1 = 88;
+ let _ = t;
+}
+
+async fn test_tuple_struct() {
+ let mut t: T;
+ t.0 = 42; //~ ERROR E0381
+ noop().await;
+ t.1 = 88;
+ let _ = t;
+}
+
+async fn test_struct() {
+ let mut t: S;
+ t.x = 42; //~ ERROR E0381
+ noop().await;
+ t.y = 88;
+ let _ = t;
+}
+
+fn main() {
+ let _ = test_tuple();
+ let _ = test_tuple_struct();
+ let _ = test_struct();
+}
diff --git a/tests/ui/async-await/partial-initialization-across-await.stderr b/tests/ui/async-await/partial-initialization-across-await.stderr
new file mode 100644
index 000000000..6a0eeffb9
--- /dev/null
+++ b/tests/ui/async-await/partial-initialization-across-await.stderr
@@ -0,0 +1,33 @@
+error[E0381]: partially assigned binding `t` isn't fully initialized
+ --> $DIR/partial-initialization-across-await.rs:13:5
+ |
+LL | let mut t: (i32, i32);
+ | ----- binding declared here but left uninitialized
+LL | t.0 = 42;
+ | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+ |
+ = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
+
+error[E0381]: partially assigned binding `t` isn't fully initialized
+ --> $DIR/partial-initialization-across-await.rs:21:5
+ |
+LL | let mut t: T;
+ | ----- binding declared here but left uninitialized
+LL | t.0 = 42;
+ | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+ |
+ = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
+
+error[E0381]: partially assigned binding `t` isn't fully initialized
+ --> $DIR/partial-initialization-across-await.rs:29:5
+ |
+LL | let mut t: S;
+ | ----- binding declared here but left uninitialized
+LL | t.x = 42;
+ | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+ |
+ = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/tests/ui/async-await/pin-needed-to-poll-2.rs b/tests/ui/async-await/pin-needed-to-poll-2.rs
new file mode 100644
index 000000000..6ce70336d
--- /dev/null
+++ b/tests/ui/async-await/pin-needed-to-poll-2.rs
@@ -0,0 +1,48 @@
+use std::{
+ future::Future,
+ pin::Pin,
+ marker::Unpin,
+ task::{Context, Poll},
+};
+
+struct Sleep(std::marker::PhantomPinned);
+
+impl Future for Sleep {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+impl Drop for Sleep {
+ fn drop(&mut self) {}
+}
+
+fn sleep() -> Sleep {
+ Sleep(std::marker::PhantomPinned)
+}
+
+
+struct MyFuture {
+ sleep: Sleep,
+}
+
+impl MyFuture {
+ fn new() -> Self {
+ Self {
+ sleep: sleep(),
+ }
+ }
+}
+
+impl Future for MyFuture {
+ type Output = ();
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Pin::new(&mut self.sleep).poll(cx)
+ //~^ ERROR `PhantomPinned` cannot be unpinned
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr
new file mode 100644
index 000000000..0a6f705e2
--- /dev/null
+++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr
@@ -0,0 +1,20 @@
+error[E0277]: `PhantomPinned` cannot be unpinned
+ --> $DIR/pin-needed-to-poll-2.rs:43:18
+ |
+LL | Pin::new(&mut self.sleep).poll(cx)
+ | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: consider using `Box::pin`
+note: required because it appears within the type `Sleep`
+ --> $DIR/pin-needed-to-poll-2.rs:8:8
+ |
+LL | struct Sleep(std::marker::PhantomPinned);
+ | ^^^^^
+note: required by a bound in `Pin::<P>::new`
+ --> $SRC_DIR/core/src/pin.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/pin-needed-to-poll.rs b/tests/ui/async-await/pin-needed-to-poll.rs
new file mode 100644
index 000000000..0d1fe684f
--- /dev/null
+++ b/tests/ui/async-await/pin-needed-to-poll.rs
@@ -0,0 +1,47 @@
+use std::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll},
+};
+
+struct Sleep;
+
+impl Future for Sleep {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+impl Drop for Sleep {
+ fn drop(&mut self) {}
+}
+
+fn sleep() -> Sleep {
+ Sleep
+}
+
+
+struct MyFuture {
+ sleep: Sleep,
+}
+
+impl MyFuture {
+ fn new() -> Self {
+ Self {
+ sleep: sleep(),
+ }
+ }
+}
+
+impl Future for MyFuture {
+ type Output = ();
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ self.sleep.poll(cx)
+ //~^ ERROR no method named `poll` found for struct `Sleep` in the current scope
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/pin-needed-to-poll.stderr b/tests/ui/async-await/pin-needed-to-poll.stderr
new file mode 100644
index 000000000..b1f4a73aa
--- /dev/null
+++ b/tests/ui/async-await/pin-needed-to-poll.stderr
@@ -0,0 +1,20 @@
+error[E0599]: no method named `poll` found for struct `Sleep` in the current scope
+ --> $DIR/pin-needed-to-poll.rs:42:20
+ |
+LL | struct Sleep;
+ | ------------ method `poll` not found for this struct
+...
+LL | self.sleep.poll(cx)
+ | ^^^^ method not found in `Sleep`
+ --> $SRC_DIR/core/src/future/future.rs:LL:COL
+ |
+ = note: the method is available for `Pin<&mut Sleep>` here
+ |
+help: consider wrapping the receiver expression with the appropriate type
+ |
+LL | Pin::new(&mut self.sleep).poll(cx)
+ | +++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/async-await/proper-span-for-type-error.fixed b/tests/ui/async-await/proper-span-for-type-error.fixed
new file mode 100644
index 000000000..7d43b575d
--- /dev/null
+++ b/tests/ui/async-await/proper-span-for-type-error.fixed
@@ -0,0 +1,12 @@
+// edition:2021
+// run-rustfix
+#![allow(dead_code)]
+
+async fn a() {}
+
+async fn foo() -> Result<(), i32> {
+ a().await;
+ Ok(()) //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/proper-span-for-type-error.rs b/tests/ui/async-await/proper-span-for-type-error.rs
new file mode 100644
index 000000000..00ccde1bf
--- /dev/null
+++ b/tests/ui/async-await/proper-span-for-type-error.rs
@@ -0,0 +1,11 @@
+// edition:2021
+// run-rustfix
+#![allow(dead_code)]
+
+async fn a() {}
+
+async fn foo() -> Result<(), i32> {
+ a().await //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/proper-span-for-type-error.stderr b/tests/ui/async-await/proper-span-for-type-error.stderr
new file mode 100644
index 000000000..25f05156c
--- /dev/null
+++ b/tests/ui/async-await/proper-span-for-type-error.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+ --> $DIR/proper-span-for-type-error.rs:8:5
+ |
+LL | a().await
+ | ^^^^^^^^^ expected enum `Result`, found `()`
+ |
+ = note: expected enum `Result<(), i32>`
+ found unit type `()`
+help: try adding an expression at the end of the block
+ |
+LL ~ a().await;
+LL ~ Ok(())
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.rs b/tests/ui/async-await/recursive-async-impl-trait-type.rs
new file mode 100644
index 000000000..edc4cb8ac
--- /dev/null
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.rs
@@ -0,0 +1,10 @@
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+async fn recursive_async_function() -> () {
+ //~^ ERROR recursion in an `async fn` requires boxing
+ recursive_async_function().await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
new file mode 100644
index 000000000..63f64f445
--- /dev/null
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/recursive-async-impl-trait-type.rs:5:40
+ |
+LL | async fn recursive_async_function() -> () {
+ | ^^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/repeat_count_const_in_async_fn.rs b/tests/ui/async-await/repeat_count_const_in_async_fn.rs
new file mode 100644
index 000000000..ebabc3fbf
--- /dev/null
+++ b/tests/ui/async-await/repeat_count_const_in_async_fn.rs
@@ -0,0 +1,10 @@
+// check-pass
+// edition:2018
+// compile-flags: --crate-type=lib
+
+pub async fn test() {
+ const C: usize = 4;
+ foo(&mut [0u8; C]).await;
+}
+
+async fn foo(_: &mut [u8]) {}
diff --git a/tests/ui/async-await/return-ty-raw-ptr-coercion.rs b/tests/ui/async-await/return-ty-raw-ptr-coercion.rs
new file mode 100644
index 000000000..9fe0869ca
--- /dev/null
+++ b/tests/ui/async-await/return-ty-raw-ptr-coercion.rs
@@ -0,0 +1,25 @@
+// Check that we apply unsizing coercions based on the return type.
+//
+// Also serves as a regression test for #60424.
+//
+// edition:2018
+// check-pass
+
+#![allow(warnings)]
+
+use std::fmt::Debug;
+
+const TMP: u32 = 22;
+
+// Coerce from `&u32` to `*const u32`
+fn raw_pointer_coercion() {
+ fn sync_example() -> *const u32 {
+ &TMP
+ }
+
+ async fn async_example() -> *const u32 {
+ &TMP
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/return-ty-unsize-coercion.rs b/tests/ui/async-await/return-ty-unsize-coercion.rs
new file mode 100644
index 000000000..93832ef7e
--- /dev/null
+++ b/tests/ui/async-await/return-ty-unsize-coercion.rs
@@ -0,0 +1,45 @@
+// Check that we apply unsizing coercions based on the return type.
+//
+// Also serves as a regression test for #60424.
+//
+// edition:2018
+// check-pass
+
+#![allow(warnings)]
+
+use std::fmt::Debug;
+
+// Unsizing coercion from `Box<&'static str>` to `Box<dyn Debug>`.
+fn unsize_trait_coercion() {
+ fn sync_example() -> Box<dyn Debug> {
+ Box::new("asdf")
+ }
+
+ async fn async_example() -> Box<dyn Debug> {
+ Box::new("asdf")
+ }
+}
+
+// Unsizing coercion from `Box<[u32; N]>` to `Box<[32]>`.
+fn unsize_slice_coercion() {
+ fn sync_example() -> Box<[u32]> {
+ Box::new([0])
+ }
+
+ async fn async_example() -> Box<[u32]> {
+ Box::new([0])
+ }
+}
+
+// Unsizing coercion from `&[&str; 1]` to `&[&str]`
+fn unsize_slice_str_coercion() {
+ fn sync_example() -> &'static [&'static str] {
+ &["hi"]
+ }
+
+ async fn async_example() -> &'static [&'static str] {
+ &["hi"]
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/suggest-missing-await-closure.fixed b/tests/ui/async-await/suggest-missing-await-closure.fixed
new file mode 100644
index 000000000..febcd0218
--- /dev/null
+++ b/tests/ui/async-await/suggest-missing-await-closure.fixed
@@ -0,0 +1,23 @@
+// edition:2018
+// run-rustfix
+
+#![feature(async_closure)]
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+ 22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_closure() {
+ async || {
+ let x = make_u32();
+ take_u32(x.await)
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider `await`ing on the `Future`
+ //~| SUGGESTION .await
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/suggest-missing-await-closure.rs b/tests/ui/async-await/suggest-missing-await-closure.rs
new file mode 100644
index 000000000..faabf6ee3
--- /dev/null
+++ b/tests/ui/async-await/suggest-missing-await-closure.rs
@@ -0,0 +1,23 @@
+// edition:2018
+// run-rustfix
+
+#![feature(async_closure)]
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+ 22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_closure() {
+ async || {
+ let x = make_u32();
+ take_u32(x)
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider `await`ing on the `Future`
+ //~| SUGGESTION .await
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/suggest-missing-await-closure.stderr b/tests/ui/async-await/suggest-missing-await-closure.stderr
new file mode 100644
index 000000000..a5958baff
--- /dev/null
+++ b/tests/ui/async-await/suggest-missing-await-closure.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await-closure.rs:16:18
+ |
+LL | take_u32(x)
+ | -------- ^ expected `u32`, found opaque type
+ | |
+ | arguments to this function are incorrect
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await-closure.rs:8:24
+ |
+LL | async fn make_u32() -> u32 {
+ | ^^^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected type `u32`
+ found opaque type `impl Future<Output = u32>`
+note: function defined here
+ --> $DIR/suggest-missing-await-closure.rs:6:4
+ |
+LL | fn take_u32(_x: u32) {}
+ | ^^^^^^^^ -------
+help: consider `await`ing on the `Future`
+ |
+LL | take_u32(x.await)
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs
new file mode 100644
index 000000000..796f82e77
--- /dev/null
+++ b/tests/ui/async-await/suggest-missing-await.rs
@@ -0,0 +1,74 @@
+// edition:2018
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+ 22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn() {
+ let x = make_u32();
+ take_u32(x)
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider `await`ing on the `Future`
+ //~| SUGGESTION .await
+}
+
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy()
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider `await`ing on the `Future`
+ //~| HELP consider using a semicolon here
+ //~| SUGGESTION .await
+}
+
+#[allow(unused)]
+async fn suggest_await_on_if() {
+ let _x = if true {
+ dummy()
+ //~^ HELP consider `await`ing on the `Future`
+ } else {
+ dummy().await
+ //~^ ERROR `if` and `else` have incompatible types [E0308]
+ };
+}
+
+#[allow(unused)]
+async fn suggest_await_on_previous_match_arms() {
+ let _x = match 0usize {
+ 0 => dummy(), //~ HELP consider `await`ing on the `Future`
+ 1 => dummy(),
+ 2 => dummy().await,
+ //~^ `match` arms have incompatible types [E0308]
+ };
+}
+
+#[allow(unused)]
+async fn suggest_await_on_match_expr() {
+ let _x = match dummy() { //~ HELP consider `await`ing on the `Future`
+ () => {} //~ ERROR mismatched types [E0308]
+ };
+}
+
+async fn dummy_result() -> Result<(), ()> {
+ Ok(())
+}
+
+#[allow(unused)]
+async fn suggest_await_in_generic_pattern() {
+ match dummy_result() {
+ //~^ HELP consider `await`ing on the `Future`
+ //~| HELP consider `await`ing on the `Future`
+ //~| SUGGESTION .await
+ Ok(_) => {}
+ //~^ ERROR mismatched types [E0308]
+ Err(_) => {}
+ //~^ ERROR mismatched types [E0308]
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr
new file mode 100644
index 000000000..1196601ac
--- /dev/null
+++ b/tests/ui/async-await/suggest-missing-await.stderr
@@ -0,0 +1,167 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:12:14
+ |
+LL | take_u32(x)
+ | -------- ^ expected `u32`, found opaque type
+ | |
+ | arguments to this function are incorrect
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:5:24
+ |
+LL | async fn make_u32() -> u32 {
+ | ^^^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected type `u32`
+ found opaque type `impl Future<Output = u32>`
+note: function defined here
+ --> $DIR/suggest-missing-await.rs:3:4
+ |
+LL | fn take_u32(_x: u32) {}
+ | ^^^^^^^^ -------
+help: consider `await`ing on the `Future`
+ |
+LL | take_u32(x.await)
+ | ++++++
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:22:5
+ |
+LL | dummy()
+ | ^^^^^^^ expected `()`, found opaque type
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:18:18
+ |
+LL | async fn dummy() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected unit type `()`
+ found opaque type `impl Future<Output = ()>`
+help: consider `await`ing on the `Future`
+ |
+LL | dummy().await
+ | ++++++
+help: consider using a semicolon here
+ |
+LL | dummy();
+ | +
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/suggest-missing-await.rs:35:9
+ |
+LL | let _x = if true {
+ | ______________-
+LL | | dummy()
+ | | ------- expected because of this
+LL | |
+LL | | } else {
+LL | | dummy().await
+ | | ^^^^^^^^^^^^^ expected opaque type, found `()`
+LL | |
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:18:18
+ |
+LL | async fn dummy() {}
+ | ^ checked the `Output` of this `async fn`, expected opaque type
+ = note: expected opaque type `impl Future<Output = ()>`
+ found unit type `()`
+help: consider `await`ing on the `Future`
+ |
+LL | dummy().await
+ | ++++++
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/suggest-missing-await.rs:45:14
+ |
+LL | let _x = match 0usize {
+ | ______________-
+LL | | 0 => dummy(),
+ | | ------- this is found to be of type `impl Future<Output = ()>`
+LL | | 1 => dummy(),
+ | | ------- this is found to be of type `impl Future<Output = ()>`
+LL | | 2 => dummy().await,
+ | | ^^^^^^^^^^^^^ expected opaque type, found `()`
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:18:18
+ |
+LL | async fn dummy() {}
+ | ^ checked the `Output` of this `async fn`, expected opaque type
+ = note: expected opaque type `impl Future<Output = ()>`
+ found unit type `()`
+help: consider `await`ing on the `Future`
+ |
+LL ~ 0 => dummy().await,
+LL ~ 1 => dummy().await,
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:53:9
+ |
+LL | let _x = match dummy() {
+ | ------- this expression has type `impl Future<Output = ()>`
+LL | () => {}
+ | ^^ expected opaque type, found `()`
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:18:18
+ |
+LL | async fn dummy() {}
+ | ^ checked the `Output` of this `async fn`, expected opaque type
+ = note: expected opaque type `impl Future<Output = ()>`
+ found unit type `()`
+help: consider `await`ing on the `Future`
+ |
+LL | let _x = match dummy().await {
+ | ++++++
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:67:9
+ |
+LL | match dummy_result() {
+ | -------------- this expression has type `impl Future<Output = Result<(), ()>>`
+...
+LL | Ok(_) => {}
+ | ^^^^^ expected opaque type, found enum `Result`
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:57:28
+ |
+LL | async fn dummy_result() -> Result<(), ()> {
+ | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
+ = note: expected opaque type `impl Future<Output = Result<(), ()>>`
+ found enum `Result<_, _>`
+help: consider `await`ing on the `Future`
+ |
+LL | match dummy_result().await {
+ | ++++++
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:69:9
+ |
+LL | match dummy_result() {
+ | -------------- this expression has type `impl Future<Output = Result<(), ()>>`
+...
+LL | Err(_) => {}
+ | ^^^^^^ expected opaque type, found enum `Result`
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/suggest-missing-await.rs:57:28
+ |
+LL | async fn dummy_result() -> Result<(), ()> {
+ | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
+ = note: expected opaque type `impl Future<Output = Result<(), ()>>`
+ found enum `Result<_, _>`
+help: consider `await`ing on the `Future`
+ |
+LL | match dummy_result().await {
+ | ++++++
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs
new file mode 100644
index 000000000..4919e0a05
--- /dev/null
+++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs
@@ -0,0 +1,47 @@
+// rustc-env:CARGO=/usr/bin/cargo
+
+use std::pin::Pin;
+use std::future::Future;
+
+fn main() {}
+
+fn await_on_struct_missing() {
+ struct S;
+ let x = S;
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| NOTE unknown field
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP set `edition = "2021"` in `Cargo.toml`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_struct_similar() {
+ struct S {
+ awai: u8,
+ }
+ let x = S { awai: 42 };
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| HELP a field with a similar name exists
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP set `edition = "2021"` in `Cargo.toml`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| NOTE unknown field
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP set `edition = "2021"` in `Cargo.toml`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_apit(x: impl Future<Output = ()>) {
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP set `edition = "2021"` in `Cargo.toml`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr
new file mode 100644
index 000000000..409eb179e
--- /dev/null
+++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr
@@ -0,0 +1,43 @@
+error[E0609]: no field `await` on type `await_on_struct_missing::S`
+ --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7
+ |
+LL | x.await;
+ | ^^^^^ unknown field
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: set `edition = "2021"` in `Cargo.toml`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `await_on_struct_similar::S`
+ --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7
+ |
+LL | x.await;
+ | ^^^^^ help: a field with a similar name exists: `awai`
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: set `edition = "2021"` in `Cargo.toml`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
+ --> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7
+ |
+LL | x.await;
+ | ^^^^^ unknown field
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: set `edition = "2021"` in `Cargo.toml`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `impl Future<Output = ()>`
+ --> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7
+ |
+LL | x.await;
+ | ^^^^^
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: set `edition = "2021"` in `Cargo.toml`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.rs b/tests/ui/async-await/suggest-switching-edition-on-await.rs
new file mode 100644
index 000000000..9852e8fc9
--- /dev/null
+++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs
@@ -0,0 +1,45 @@
+use std::pin::Pin;
+use std::future::Future;
+
+fn main() {}
+
+fn await_on_struct_missing() {
+ struct S;
+ let x = S;
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| NOTE unknown field
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP pass `--edition 2021` to `rustc`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_struct_similar() {
+ struct S {
+ awai: u8,
+ }
+ let x = S { awai: 42 };
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| HELP a field with a similar name exists
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP pass `--edition 2021` to `rustc`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| NOTE unknown field
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP pass `--edition 2021` to `rustc`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_apit(x: impl Future<Output = ()>) {
+ x.await;
+ //~^ ERROR no field `await` on type
+ //~| NOTE to `.await` a `Future`, switch to Rust 2018
+ //~| HELP pass `--edition 2021` to `rustc`
+ //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.stderr b/tests/ui/async-await/suggest-switching-edition-on-await.stderr
new file mode 100644
index 000000000..ef3334381
--- /dev/null
+++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr
@@ -0,0 +1,43 @@
+error[E0609]: no field `await` on type `await_on_struct_missing::S`
+ --> $DIR/suggest-switching-edition-on-await.rs:9:7
+ |
+LL | x.await;
+ | ^^^^^ unknown field
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `await_on_struct_similar::S`
+ --> $DIR/suggest-switching-edition-on-await.rs:22:7
+ |
+LL | x.await;
+ | ^^^^^ help: a field with a similar name exists: `awai`
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
+ --> $DIR/suggest-switching-edition-on-await.rs:31:7
+ |
+LL | x.await;
+ | ^^^^^ unknown field
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `impl Future<Output = ()>`
+ --> $DIR/suggest-switching-edition-on-await.rs:40:7
+ |
+LL | x.await;
+ | ^^^^^
+ |
+ = note: to `.await` a `Future`, switch to Rust 2018 or later
+ = help: pass `--edition 2021` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/async-await/track-caller/async-block.rs b/tests/ui/async-await/track-caller/async-block.rs
new file mode 100644
index 000000000..8e81387c3
--- /dev/null
+++ b/tests/ui/async-await/track-caller/async-block.rs
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(closure_track_caller, stmt_expr_attributes)]
+
+fn main() {
+ let _ = #[track_caller] async {
+ //~^ ERROR attribute should be applied to a function definition [E0739]
+ };
+}
diff --git a/tests/ui/async-await/track-caller/async-block.stderr b/tests/ui/async-await/track-caller/async-block.stderr
new file mode 100644
index 000000000..407439921
--- /dev/null
+++ b/tests/ui/async-await/track-caller/async-block.stderr
@@ -0,0 +1,12 @@
+error[E0739]: attribute should be applied to a function definition
+ --> $DIR/async-block.rs:6:13
+ |
+LL | let _ = #[track_caller] async {
+ | _____________^^^^^^^^^^^^^^^_-
+LL | |
+LL | | };
+ | |_____- not a function definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0739`.
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.rs b/tests/ui/async-await/track-caller/async-closure-gate.rs
new file mode 100644
index 000000000..d9d556855
--- /dev/null
+++ b/tests/ui/async-await/track-caller/async-closure-gate.rs
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(async_closure, stmt_expr_attributes)]
+
+fn main() {
+ let _ = #[track_caller] async || {
+ //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
+ };
+}
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.stderr b/tests/ui/async-await/track-caller/async-closure-gate.stderr
new file mode 100644
index 000000000..498f1b43b
--- /dev/null
+++ b/tests/ui/async-await/track-caller/async-closure-gate.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `#[track_caller]` on closures is currently unstable
+ --> $DIR/async-closure-gate.rs:6:13
+ |
+LL | let _ = #[track_caller] async || {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/track-caller/issue-105134.rs b/tests/ui/async-await/track-caller/issue-105134.rs
new file mode 100644
index 000000000..4e52b8e25
--- /dev/null
+++ b/tests/ui/async-await/track-caller/issue-105134.rs
@@ -0,0 +1,11 @@
+// check-pass
+// edition:2021
+
+#[track_caller]
+fn f() {
+ let _ = async {};
+}
+
+fn main() {
+ f();
+}
diff --git a/tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr b/tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr
new file mode 100644
index 000000000..51ea225f4
--- /dev/null
+++ b/tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr
@@ -0,0 +1,29 @@
+warning: `#[track_caller]` on async functions is a no-op
+ --> $DIR/panic-track-caller.rs:50:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+LL | / async fn bar_track_caller() {
+LL | | panic!()
+LL | | }
+ | |_- this function will not propagate the caller location
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+ = note: `#[warn(ungated_async_fn_track_caller)]` on by default
+
+warning: `#[track_caller]` on async functions is a no-op
+ --> $DIR/panic-track-caller.rs:62:5
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+LL | / async fn bar_assoc() {
+LL | | panic!();
+LL | | }
+ | |_____- this function will not propagate the caller location
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/async-await/track-caller/panic-track-caller.rs b/tests/ui/async-await/track-caller/panic-track-caller.rs
new file mode 100644
index 000000000..f45243b0e
--- /dev/null
+++ b/tests/ui/async-await/track-caller/panic-track-caller.rs
@@ -0,0 +1,113 @@
+// run-pass
+// edition:2021
+// revisions: feat nofeat
+// needs-unwind
+#![feature(async_closure, stmt_expr_attributes)]
+#![cfg_attr(feat, feature(closure_track_caller))]
+
+use std::future::Future;
+use std::panic;
+use std::sync::{Arc, Mutex};
+use std::task::{Context, Poll, Wake};
+use std::thread::{self, Thread};
+
+/// A waker that wakes up the current thread when called.
+struct ThreadWaker(Thread);
+
+impl Wake for ThreadWaker {
+ fn wake(self: Arc<Self>) {
+ self.0.unpark();
+ }
+}
+
+/// Run a future to completion on the current thread.
+fn block_on<T>(fut: impl Future<Output = T>) -> T {
+ // Pin the future so it can be polled.
+ let mut fut = Box::pin(fut);
+
+ // Create a new context to be passed to the future.
+ let t = thread::current();
+ let waker = Arc::new(ThreadWaker(t)).into();
+ let mut cx = Context::from_waker(&waker);
+
+ // Run the future to completion.
+ loop {
+ match fut.as_mut().poll(&mut cx) {
+ Poll::Ready(res) => return res,
+ Poll::Pending => thread::park(),
+ }
+ }
+}
+
+async fn bar() {
+ panic!()
+}
+
+async fn foo() {
+ bar().await
+}
+
+#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
+async fn bar_track_caller() {
+ panic!()
+}
+
+async fn foo_track_caller() {
+ bar_track_caller().await
+}
+
+struct Foo;
+
+impl Foo {
+ #[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
+ async fn bar_assoc() {
+ panic!();
+ }
+}
+
+async fn foo_assoc() {
+ Foo::bar_assoc().await
+}
+
+// Since compilation is expected to fail for this fn when using
+// `nofeat`, we test that separately in `async-closure-gate.rs`
+#[cfg(feat)]
+async fn foo_closure() {
+ let c = #[track_caller] async || {
+ panic!();
+ };
+ c().await
+}
+
+fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
+ let loc = Arc::new(Mutex::new(None));
+
+ let hook = panic::take_hook();
+ {
+ let loc = loc.clone();
+ panic::set_hook(Box::new(move |info| {
+ *loc.lock().unwrap() = info.location().map(|loc| loc.line())
+ }));
+ }
+ panic::catch_unwind(f).unwrap_err();
+ panic::set_hook(hook);
+ let x = loc.lock().unwrap().unwrap();
+ x
+}
+
+fn main() {
+ assert_eq!(panicked_at(|| block_on(foo())), 43);
+
+ #[cfg(feat)]
+ assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56);
+ #[cfg(nofeat)]
+ assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52);
+
+ #[cfg(feat)]
+ assert_eq!(panicked_at(|| block_on(foo_assoc())), 69);
+ #[cfg(nofeat)]
+ assert_eq!(panicked_at(|| block_on(foo_assoc())), 64);
+
+ #[cfg(feat)]
+ assert_eq!(panicked_at(|| block_on(foo_closure())), 79);
+}
diff --git a/tests/ui/async-await/try-on-option-in-async.rs b/tests/ui/async-await/try-on-option-in-async.rs
new file mode 100644
index 000000000..afaaed2ef
--- /dev/null
+++ b/tests/ui/async-await/try-on-option-in-async.rs
@@ -0,0 +1,28 @@
+#![feature(async_closure)]
+// edition:2018
+fn main() {}
+
+async fn an_async_block() -> u32 {
+ async {
+ let x: Option<u32> = None;
+ x?; //~ ERROR the `?` operator
+ 22
+ }
+ .await
+}
+
+async fn async_closure_containing_fn() -> u32 {
+ let async_closure = async || {
+ let x: Option<u32> = None;
+ x?; //~ ERROR the `?` operator
+ 22_u32
+ };
+
+ async_closure().await
+}
+
+async fn an_async_function() -> u32 {
+ let x: Option<u32> = None;
+ x?; //~ ERROR the `?` operator
+ 22
+}
diff --git a/tests/ui/async-await/try-on-option-in-async.stderr b/tests/ui/async-await/try-on-option-in-async.stderr
new file mode 100644
index 000000000..4c7b4fa41
--- /dev/null
+++ b/tests/ui/async-await/try-on-option-in-async.stderr
@@ -0,0 +1,44 @@
+error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/try-on-option-in-async.rs:8:10
+ |
+LL | / async {
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in an async block that returns `{integer}`
+LL | | 22
+LL | | }
+ | |_____- this function should return `Result` or `Option` to accept `?`
+ |
+ = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
+
+error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/try-on-option-in-async.rs:17:10
+ |
+LL | let async_closure = async || {
+ | __________________________________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in an async closure that returns `u32`
+LL | | 22_u32
+LL | | };
+ | |_____- this function should return `Result` or `Option` to accept `?`
+ |
+ = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/try-on-option-in-async.rs:26:6
+ |
+LL | async fn an_async_function() -> u32 {
+ | _____________________________________-
+LL | | let x: Option<u32> = None;
+LL | | x?;
+ | | ^ cannot use the `?` operator in an async function that returns `u32`
+LL | | 22
+LL | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/type-parameter-send.rs b/tests/ui/async-await/type-parameter-send.rs
new file mode 100644
index 000000000..ab2b62aa5
--- /dev/null
+++ b/tests/ui/async-await/type-parameter-send.rs
@@ -0,0 +1,18 @@
+// check-pass
+// compile-flags: --crate-type lib
+// edition:2018
+
+fn assert_send<F: Send>(_: F) {}
+
+async fn __post<T>() -> T {
+ if false {
+ todo!()
+ } else {
+ async {}.await;
+ todo!()
+ }
+}
+
+fn foo<T>() {
+ assert_send(__post::<T>());
+}
diff --git a/tests/ui/async-await/unnecessary-await.rs b/tests/ui/async-await/unnecessary-await.rs
new file mode 100644
index 000000000..24673777b
--- /dev/null
+++ b/tests/ui/async-await/unnecessary-await.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+async fn foo () { }
+fn bar() -> impl std::future::Future { async {} }
+fn boo() {}
+
+async fn baz() -> std::io::Result<()> {
+ foo().await;
+ boo().await; //~ ERROR `()` is not a future
+ bar().await;
+ std::io::Result::Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr
new file mode 100644
index 000000000..dc3089336
--- /dev/null
+++ b/tests/ui/async-await/unnecessary-await.stderr
@@ -0,0 +1,24 @@
+error[E0277]: `()` is not a future
+ --> $DIR/unnecessary-await.rs:9:10
+ |
+LL | boo().await;
+ | -----^^^^^^ `()` is not a future
+ | |
+ | this call returns `()`
+ |
+ = help: the trait `Future` is not implemented for `()`
+ = note: () must be a future or must implement `IntoFuture` to be awaited
+ = note: required for `()` to implement `IntoFuture`
+help: remove the `.await`
+ |
+LL - boo().await;
+LL + boo();
+ |
+help: alternatively, consider making `fn boo` asynchronous
+ |
+LL | async fn boo() {}
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/unreachable-lint-1.rs b/tests/ui/async-await/unreachable-lint-1.rs
new file mode 100644
index 000000000..d63d643c4
--- /dev/null
+++ b/tests/ui/async-await/unreachable-lint-1.rs
@@ -0,0 +1,12 @@
+// edition:2018
+#![deny(unreachable_code)]
+
+async fn foo() {
+ return; bar().await;
+ //~^ ERROR unreachable statement
+}
+
+async fn bar() {
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/unreachable-lint-1.stderr b/tests/ui/async-await/unreachable-lint-1.stderr
new file mode 100644
index 000000000..e93257889
--- /dev/null
+++ b/tests/ui/async-await/unreachable-lint-1.stderr
@@ -0,0 +1,16 @@
+error: unreachable statement
+ --> $DIR/unreachable-lint-1.rs:5:13
+ |
+LL | return; bar().await;
+ | ------ ^^^^^^^^^^^^ unreachable statement
+ | |
+ | any code following this expression is unreachable
+ |
+note: the lint level is defined here
+ --> $DIR/unreachable-lint-1.rs:2:9
+ |
+LL | #![deny(unreachable_code)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/unreachable-lint.rs b/tests/ui/async-await/unreachable-lint.rs
new file mode 100644
index 000000000..ca18cfde4
--- /dev/null
+++ b/tests/ui/async-await/unreachable-lint.rs
@@ -0,0 +1,13 @@
+// check-pass
+// edition:2018
+#![deny(unreachable_code)]
+
+async fn foo() {
+ endless().await;
+}
+
+async fn endless() -> ! {
+ loop {}
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/unresolved_type_param.rs b/tests/ui/async-await/unresolved_type_param.rs
new file mode 100644
index 000000000..6d6d80614
--- /dev/null
+++ b/tests/ui/async-await/unresolved_type_param.rs
@@ -0,0 +1,24 @@
+// Provoke an unresolved type error (T).
+// Error message should pinpoint the type parameter T as needing to be bound
+// (rather than give a general error message)
+// edition:2018
+// compile-flags: -Zdrop-tracking
+
+async fn bar<T>() -> () {}
+
+async fn foo() {
+ bar().await;
+ //~^ ERROR type inside `async fn` body must be known in this context
+ //~| ERROR type inside `async fn` body must be known in this context
+ //~| ERROR type inside `async fn` body must be known in this context
+ //~| NOTE cannot infer type for type parameter `T`
+ //~| NOTE cannot infer type for type parameter `T`
+ //~| NOTE cannot infer type for type parameter `T`
+ //~| NOTE the type is part of the `async fn` body because of this `await`
+ //~| NOTE the type is part of the `async fn` body because of this `await`
+ //~| NOTE the type is part of the `async fn` body because of this `await`
+ //~| NOTE in this expansion of desugaring of `await`
+ //~| NOTE in this expansion of desugaring of `await`
+ //~| NOTE in this expansion of desugaring of `await`
+}
+fn main() {}
diff --git a/tests/ui/async-await/unresolved_type_param.stderr b/tests/ui/async-await/unresolved_type_param.stderr
new file mode 100644
index 000000000..7236c681f
--- /dev/null
+++ b/tests/ui/async-await/unresolved_type_param.stderr
@@ -0,0 +1,39 @@
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:10:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:10:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:10:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:10:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:10:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:10:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0698`.
diff --git a/tests/ui/async-await/unused-lifetime.rs b/tests/ui/async-await/unused-lifetime.rs
new file mode 100644
index 000000000..6cfd36ba9
--- /dev/null
+++ b/tests/ui/async-await/unused-lifetime.rs
@@ -0,0 +1,39 @@
+// Check "unused_lifetimes" lint on both async and sync functions
+// Both cases should be diagnosed the same way.
+
+// edition:2018
+
+#![deny(unused_lifetimes)]
+
+async fn async_wrong_without_args<'a>() {} //~ ERROR lifetime parameter `'a` never used
+
+async fn async_wrong_1_lifetime<'a>(_: &i32) {} //~ ERROR lifetime parameter `'a` never used
+
+async fn async_wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} //~ ERROR lifetime parameter `'b` never used
+
+async fn async_right_1_lifetime<'a>(_: &'a i32) {}
+
+async fn async_right_2_lifetimes<'a, 'b>(_: &'a i32, _: &'b i32) {}
+
+async fn async_right_trait_bound_lifetime<'a, I>(_: I)
+where
+ I: Iterator<Item = &'a i32>
+{}
+
+fn wrong_without_args<'a>() {} //~ ERROR lifetime parameter `'a` never used
+
+fn wrong_1_lifetime<'a>(_: &i32) {} //~ ERROR lifetime parameter `'a` never used
+
+fn wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} //~ ERROR lifetime parameter `'b` never used
+
+fn right_1_lifetime<'a>(_: &'a i32) {}
+
+fn right_2_lifetimes<'a, 'b>(_: &'a i32, _: &'b i32) {}
+
+fn right_trait_bound_lifetime<'a, I>(_: I)
+where
+ I: Iterator<Item = &'a i32>
+{}
+
+
+fn main() {}
diff --git a/tests/ui/async-await/unused-lifetime.stderr b/tests/ui/async-await/unused-lifetime.stderr
new file mode 100644
index 000000000..5c00501a6
--- /dev/null
+++ b/tests/ui/async-await/unused-lifetime.stderr
@@ -0,0 +1,48 @@
+error: lifetime parameter `'a` never used
+ --> $DIR/unused-lifetime.rs:8:35
+ |
+LL | async fn async_wrong_without_args<'a>() {}
+ | -^^- help: elide the unused lifetime
+ |
+note: the lint level is defined here
+ --> $DIR/unused-lifetime.rs:6:9
+ |
+LL | #![deny(unused_lifetimes)]
+ | ^^^^^^^^^^^^^^^^
+
+error: lifetime parameter `'a` never used
+ --> $DIR/unused-lifetime.rs:10:33
+ |
+LL | async fn async_wrong_1_lifetime<'a>(_: &i32) {}
+ | -^^- help: elide the unused lifetime
+
+error: lifetime parameter `'b` never used
+ --> $DIR/unused-lifetime.rs:12:38
+ |
+LL | async fn async_wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {}
+ | --^^
+ | |
+ | help: elide the unused lifetime
+
+error: lifetime parameter `'a` never used
+ --> $DIR/unused-lifetime.rs:23:23
+ |
+LL | fn wrong_without_args<'a>() {}
+ | -^^- help: elide the unused lifetime
+
+error: lifetime parameter `'a` never used
+ --> $DIR/unused-lifetime.rs:25:21
+ |
+LL | fn wrong_1_lifetime<'a>(_: &i32) {}
+ | -^^- help: elide the unused lifetime
+
+error: lifetime parameter `'b` never used
+ --> $DIR/unused-lifetime.rs:27:26
+ |
+LL | fn wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {}
+ | --^^
+ | |
+ | help: elide the unused lifetime
+
+error: aborting due to 6 previous errors
+