summaryrefslogtreecommitdiffstats
path: root/tests/ui/suggestions
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/suggestions
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/suggestions')
-rw-r--r--tests/ui/suggestions/abi-typo.fixed6
-rw-r--r--tests/ui/suggestions/abi-typo.rs6
-rw-r--r--tests/ui/suggestions/abi-typo.stderr14
-rw-r--r--tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs28
-rw-r--r--tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr112
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.rs22
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.stderr107
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple.fixed33
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple.rs33
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple.stderr125
-rw-r--r--tests/ui/suggestions/as-ref-2.rs11
-rw-r--r--tests/ui/suggestions/as-ref-2.stderr18
-rw-r--r--tests/ui/suggestions/as-ref.rs27
-rw-r--r--tests/ui/suggestions/as-ref.stderr162
-rw-r--r--tests/ui/suggestions/assoc-const-as-field.rs13
-rw-r--r--tests/ui/suggestions/assoc-const-as-field.stderr9
-rw-r--r--tests/ui/suggestions/assoc-const-as-fn.rs18
-rw-r--r--tests/ui/suggestions/assoc-const-as-fn.stderr16
-rw-r--r--tests/ui/suggestions/assoc-ct-for-assoc-method.rs25
-rw-r--r--tests/ui/suggestions/assoc-ct-for-assoc-method.stderr47
-rw-r--r--tests/ui/suggestions/assoc-type-in-method-return.rs7
-rw-r--r--tests/ui/suggestions/assoc-type-in-method-return.stderr9
-rw-r--r--tests/ui/suggestions/assoc_fn_without_self.rs20
-rw-r--r--tests/ui/suggestions/assoc_fn_without_self.stderr42
-rw-r--r--tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs13
-rw-r--r--tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr43
-rw-r--r--tests/ui/suggestions/attribute-typos.rs11
-rw-r--r--tests/ui/suggestions/attribute-typos.stderr29
-rw-r--r--tests/ui/suggestions/auxiliary/foo.rs3
-rw-r--r--tests/ui/suggestions/auxiliary/issue-61963-1.rs40
-rw-r--r--tests/ui/suggestions/auxiliary/issue-61963.rs41
-rw-r--r--tests/ui/suggestions/auxiliary/issue-81839.rs9
-rw-r--r--tests/ui/suggestions/auxiliary/meow.rs11
-rw-r--r--tests/ui/suggestions/auxiliary/not-object-safe.rs6
-rw-r--r--tests/ui/suggestions/auxiliary/proc-macro-type-error.rs18
-rw-r--r--tests/ui/suggestions/bad-hex-float-lit.rs13
-rw-r--r--tests/ui/suggestions/bad-hex-float-lit.stderr48
-rw-r--r--tests/ui/suggestions/bool_typo_err_suggest.rs12
-rw-r--r--tests/ui/suggestions/bool_typo_err_suggest.stderr25
-rw-r--r--tests/ui/suggestions/borrow-for-loop-head.rs10
-rw-r--r--tests/ui/suggestions/borrow-for-loop-head.stderr29
-rw-r--r--tests/ui/suggestions/bound-suggestions.fixed68
-rw-r--r--tests/ui/suggestions/bound-suggestions.rs68
-rw-r--r--tests/ui/suggestions/bound-suggestions.stderr140
-rw-r--r--tests/ui/suggestions/box-future-wrong-output.rs22
-rw-r--r--tests/ui/suggestions/box-future-wrong-output.stderr14
-rw-r--r--tests/ui/suggestions/boxed-variant-field.rs15
-rw-r--r--tests/ui/suggestions/boxed-variant-field.stderr23
-rw-r--r--tests/ui/suggestions/call-boxed.rs7
-rw-r--r--tests/ui/suggestions/call-boxed.stderr20
-rw-r--r--tests/ui/suggestions/call-on-missing.rs39
-rw-r--r--tests/ui/suggestions/call-on-missing.stderr75
-rw-r--r--tests/ui/suggestions/call-on-unimplemented-ctor.rs17
-rw-r--r--tests/ui/suggestions/call-on-unimplemented-ctor.stderr21
-rw-r--r--tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs15
-rw-r--r--tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr21
-rw-r--r--tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs13
-rw-r--r--tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr21
-rw-r--r--tests/ui/suggestions/chain-method-call-mutation-in-place.rs4
-rw-r--r--tests/ui/suggestions/chain-method-call-mutation-in-place.stderr20
-rw-r--r--tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed16
-rw-r--r--tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs15
-rw-r--r--tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr43
-rw-r--r--tests/ui/suggestions/const-in-struct-pat.rs11
-rw-r--r--tests/ui/suggestions/const-in-struct-pat.stderr20
-rw-r--r--tests/ui/suggestions/const-no-type.rs51
-rw-r--r--tests/ui/suggestions/const-no-type.stderr44
-rw-r--r--tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs11
-rw-r--r--tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr18
-rw-r--r--tests/ui/suggestions/constrain-suggest-ice.rs11
-rw-r--r--tests/ui/suggestions/constrain-suggest-ice.stderr72
-rw-r--r--tests/ui/suggestions/constrain-trait.fixed47
-rw-r--r--tests/ui/suggestions/constrain-trait.rs47
-rw-r--r--tests/ui/suggestions/constrain-trait.stderr27
-rw-r--r--tests/ui/suggestions/copied-and-cloned.fixed23
-rw-r--r--tests/ui/suggestions/copied-and-cloned.rs23
-rw-r--r--tests/ui/suggestions/copied-and-cloned.stderr83
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.rs10
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.stderr16
-rw-r--r--tests/ui/suggestions/count2len.rs8
-rw-r--r--tests/ui/suggestions/count2len.stderr36
-rw-r--r--tests/ui/suggestions/crate-or-module-typo.rs17
-rw-r--r--tests/ui/suggestions/crate-or-module-typo.stderr43
-rw-r--r--tests/ui/suggestions/deref-path-method.rs6
-rw-r--r--tests/ui/suggestions/deref-path-method.stderr14
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.fixed18
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.rs18
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.stderr24
-rw-r--r--tests/ui/suggestions/derive-macro-missing-bounds.rs89
-rw-r--r--tests/ui/suggestions/derive-macro-missing-bounds.stderr113
-rw-r--r--tests/ui/suggestions/derive-trait-for-method-call.rs44
-rw-r--r--tests/ui/suggestions/derive-trait-for-method-call.stderr105
-rw-r--r--tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs5
-rw-r--r--tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr18
-rw-r--r--tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs14
-rw-r--r--tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr13
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs8
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs8
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs10
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr18
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs7
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr18
-rw-r--r--tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs15
-rw-r--r--tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr9
-rw-r--r--tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs131
-rw-r--r--tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr309
-rw-r--r--tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs138
-rw-r--r--tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr448
-rw-r--r--tests/ui/suggestions/dont-suggest-ref/simple.rs336
-rw-r--r--tests/ui/suggestions/dont-suggest-ref/simple.stderr985
-rw-r--r--tests/ui/suggestions/dont-suggest-try_into-in-macros.rs3
-rw-r--r--tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr14
-rw-r--r--tests/ui/suggestions/dont-suggest-ufcs-for-const.rs4
-rw-r--r--tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr9
-rw-r--r--tests/ui/suggestions/dont-try-removing-the-field.rs17
-rw-r--r--tests/ui/suggestions/dont-try-removing-the-field.stderr10
-rw-r--r--tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs21
-rw-r--r--tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr20
-rw-r--r--tests/ui/suggestions/enum-method-probe.fixed59
-rw-r--r--tests/ui/suggestions/enum-method-probe.rs59
-rw-r--r--tests/ui/suggestions/enum-method-probe.stderr99
-rw-r--r--tests/ui/suggestions/enum-variant-arg-mismatch.rs10
-rw-r--r--tests/ui/suggestions/enum-variant-arg-mismatch.stderr22
-rw-r--r--tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs33
-rw-r--r--tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr94
-rw-r--r--tests/ui/suggestions/field-access-considering-privacy.rs35
-rw-r--r--tests/ui/suggestions/field-access-considering-privacy.stderr14
-rw-r--r--tests/ui/suggestions/field-access.fixed35
-rw-r--r--tests/ui/suggestions/field-access.rs35
-rw-r--r--tests/ui/suggestions/field-access.stderr67
-rw-r--r--tests/ui/suggestions/field-has-method.rs23
-rw-r--r--tests/ui/suggestions/field-has-method.stderr17
-rw-r--r--tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs20
-rw-r--r--tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr39
-rw-r--r--tests/ui/suggestions/fn-missing-lifetime-in-item.rs8
-rw-r--r--tests/ui/suggestions/fn-missing-lifetime-in-item.stderr48
-rw-r--r--tests/ui/suggestions/fn-needing-specified-return-type-param.rs7
-rw-r--r--tests/ui/suggestions/fn-needing-specified-return-type-param.stderr14
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs19
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr38
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-without-args.rs47
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr283
-rw-r--r--tests/ui/suggestions/fn-to-method-deeply-nested.rs13
-rw-r--r--tests/ui/suggestions/fn-to-method-deeply-nested.stderr39
-rw-r--r--tests/ui/suggestions/fn-to-method.rs19
-rw-r--r--tests/ui/suggestions/fn-to-method.stderr38
-rw-r--r--tests/ui/suggestions/fn-trait-notation.fixed19
-rw-r--r--tests/ui/suggestions/fn-trait-notation.rs19
-rw-r--r--tests/ui/suggestions/fn-trait-notation.stderr30
-rw-r--r--tests/ui/suggestions/for-i-in-vec.fixed27
-rw-r--r--tests/ui/suggestions/for-i-in-vec.rs27
-rw-r--r--tests/ui/suggestions/for-i-in-vec.stderr49
-rw-r--r--tests/ui/suggestions/format-borrow.rs10
-rw-r--r--tests/ui/suggestions/format-borrow.stderr75
-rw-r--r--tests/ui/suggestions/if-let-typo.rs11
-rw-r--r--tests/ui/suggestions/if-let-typo.stderr73
-rw-r--r--tests/ui/suggestions/if-then-neeing-semi.rs70
-rw-r--r--tests/ui/suggestions/if-then-neeing-semi.stderr130
-rw-r--r--tests/ui/suggestions/ignore-nested-field-binding.fixed20
-rw-r--r--tests/ui/suggestions/ignore-nested-field-binding.rs20
-rw-r--r--tests/ui/suggestions/ignore-nested-field-binding.stderr20
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs18
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr22
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object-literal.rs14
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object-literal.stderr40
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object.rs8
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object.stderr13
-rw-r--r--tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs113
-rw-r--r--tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr21
-rw-r--r--tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs114
-rw-r--r--tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr105
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs68
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr172
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime.rs20
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime.stderr35
-rw-r--r--tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs21
-rw-r--r--tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr24
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-bounds.rs52
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-bounds.stderr117
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed20
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs20
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr17
-rw-r--r--tests/ui/suggestions/import-trait-for-method-call.rs16
-rw-r--r--tests/ui/suggestions/import-trait-for-method-call.stderr34
-rw-r--r--tests/ui/suggestions/inner_type.fixed40
-rw-r--r--tests/ui/suggestions/inner_type.rs40
-rw-r--r--tests/ui/suggestions/inner_type.stderr83
-rw-r--r--tests/ui/suggestions/inner_type2.rs26
-rw-r--r--tests/ui/suggestions/inner_type2.stderr29
-rw-r--r--tests/ui/suggestions/into-convert.rs26
-rw-r--r--tests/ui/suggestions/into-convert.stderr44
-rw-r--r--tests/ui/suggestions/into-str.rs6
-rw-r--r--tests/ui/suggestions/into-str.stderr26
-rw-r--r--tests/ui/suggestions/invalid-bin-op.rs7
-rw-r--r--tests/ui/suggestions/invalid-bin-op.stderr25
-rw-r--r--tests/ui/suggestions/issue-101065.fixed14
-rw-r--r--tests/ui/suggestions/issue-101065.rs14
-rw-r--r--tests/ui/suggestions/issue-101065.stderr23
-rw-r--r--tests/ui/suggestions/issue-101421.rs12
-rw-r--r--tests/ui/suggestions/issue-101421.stderr17
-rw-r--r--tests/ui/suggestions/issue-101465.rs25
-rw-r--r--tests/ui/suggestions/issue-101465.stderr25
-rw-r--r--tests/ui/suggestions/issue-101623.rs25
-rw-r--r--tests/ui/suggestions/issue-101623.stderr14
-rw-r--r--tests/ui/suggestions/issue-101984.rs27
-rw-r--r--tests/ui/suggestions/issue-101984.stderr14
-rw-r--r--tests/ui/suggestions/issue-102354.rs10
-rw-r--r--tests/ui/suggestions/issue-102354.stderr19
-rw-r--r--tests/ui/suggestions/issue-102892.rs25
-rw-r--r--tests/ui/suggestions/issue-102892.stderr57
-rw-r--r--tests/ui/suggestions/issue-103112.rs4
-rw-r--r--tests/ui/suggestions/issue-103112.stderr15
-rw-r--r--tests/ui/suggestions/issue-104086-suggest-let.rs30
-rw-r--r--tests/ui/suggestions/issue-104086-suggest-let.stderr135
-rw-r--r--tests/ui/suggestions/issue-104287.rs13
-rw-r--r--tests/ui/suggestions/issue-104287.stderr30
-rw-r--r--tests/ui/suggestions/issue-104327.rs12
-rw-r--r--tests/ui/suggestions/issue-104327.stderr17
-rw-r--r--tests/ui/suggestions/issue-104328.rs12
-rw-r--r--tests/ui/suggestions/issue-104328.stderr17
-rw-r--r--tests/ui/suggestions/issue-105226.rs22
-rw-r--r--tests/ui/suggestions/issue-105226.stderr31
-rw-r--r--tests/ui/suggestions/issue-105494.rs22
-rw-r--r--tests/ui/suggestions/issue-105494.stderr54
-rw-r--r--tests/ui/suggestions/issue-105645.rs8
-rw-r--r--tests/ui/suggestions/issue-105645.stderr18
-rw-r--r--tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed28
-rw-r--r--tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs28
-rw-r--r--tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr49
-rw-r--r--tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs23
-rw-r--r--tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr35
-rw-r--r--tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs20
-rw-r--r--tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr29
-rw-r--r--tests/ui/suggestions/issue-21673.rs13
-rw-r--r--tests/ui/suggestions/issue-21673.stderr29
-rw-r--r--tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs8
-rw-r--r--tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr16
-rw-r--r--tests/ui/suggestions/issue-52820.fixed15
-rw-r--r--tests/ui/suggestions/issue-52820.rs15
-rw-r--r--tests/ui/suggestions/issue-52820.stderr23
-rw-r--r--tests/ui/suggestions/issue-53692.fixed20
-rw-r--r--tests/ui/suggestions/issue-53692.rs20
-rw-r--r--tests/ui/suggestions/issue-53692.stderr26
-rw-r--r--tests/ui/suggestions/issue-57672.rs14
-rw-r--r--tests/ui/suggestions/issue-59819.fixed35
-rw-r--r--tests/ui/suggestions/issue-59819.rs35
-rw-r--r--tests/ui/suggestions/issue-59819.stderr38
-rw-r--r--tests/ui/suggestions/issue-61226.fixed6
-rw-r--r--tests/ui/suggestions/issue-61226.rs6
-rw-r--r--tests/ui/suggestions/issue-61226.stderr12
-rw-r--r--tests/ui/suggestions/issue-61963.rs37
-rw-r--r--tests/ui/suggestions/issue-61963.stderr98
-rw-r--r--tests/ui/suggestions/issue-62843.rs5
-rw-r--r--tests/ui/suggestions/issue-62843.stderr20
-rw-r--r--tests/ui/suggestions/issue-64252-self-type.rs14
-rw-r--r--tests/ui/suggestions/issue-64252-self-type.stderr34
-rw-r--r--tests/ui/suggestions/issue-66968-suggest-sorted-words.rs4
-rw-r--r--tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr9
-rw-r--r--tests/ui/suggestions/issue-68049-1.rs16
-rw-r--r--tests/ui/suggestions/issue-68049-1.stderr9
-rw-r--r--tests/ui/suggestions/issue-68049-2.rs21
-rw-r--r--tests/ui/suggestions/issue-68049-2.stderr25
-rw-r--r--tests/ui/suggestions/issue-71394-no-from-impl.rs5
-rw-r--r--tests/ui/suggestions/issue-71394-no-from-impl.stderr14
-rw-r--r--tests/ui/suggestions/issue-72766.rs20
-rw-r--r--tests/ui/suggestions/issue-72766.stderr15
-rw-r--r--tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs32
-rw-r--r--tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr41
-rw-r--r--tests/ui/suggestions/issue-81098.rs13
-rw-r--r--tests/ui/suggestions/issue-81098.stderr25
-rw-r--r--tests/ui/suggestions/issue-81839.rs17
-rw-r--r--tests/ui/suggestions/issue-81839.stderr27
-rw-r--r--tests/ui/suggestions/issue-82361.fixed24
-rw-r--r--tests/ui/suggestions/issue-82361.rs24
-rw-r--r--tests/ui/suggestions/issue-82361.stderr56
-rw-r--r--tests/ui/suggestions/issue-82566-1.rs21
-rw-r--r--tests/ui/suggestions/issue-82566-1.stderr35
-rw-r--r--tests/ui/suggestions/issue-82566-2.rs31
-rw-r--r--tests/ui/suggestions/issue-82566-2.stderr35
-rw-r--r--tests/ui/suggestions/issue-83892.fixed11
-rw-r--r--tests/ui/suggestions/issue-83892.rs11
-rw-r--r--tests/ui/suggestions/issue-83892.stderr14
-rw-r--r--tests/ui/suggestions/issue-83943.fixed9
-rw-r--r--tests/ui/suggestions/issue-83943.rs9
-rw-r--r--tests/ui/suggestions/issue-83943.stderr17
-rw-r--r--tests/ui/suggestions/issue-84592.rs17
-rw-r--r--tests/ui/suggestions/issue-84592.stderr17
-rw-r--r--tests/ui/suggestions/issue-84700.rs26
-rw-r--r--tests/ui/suggestions/issue-84700.stderr19
-rw-r--r--tests/ui/suggestions/issue-84973-2.rs13
-rw-r--r--tests/ui/suggestions/issue-84973-2.stderr21
-rw-r--r--tests/ui/suggestions/issue-84973-blacklist.rs28
-rw-r--r--tests/ui/suggestions/issue-84973-blacklist.stderr80
-rw-r--r--tests/ui/suggestions/issue-84973-negative.rs12
-rw-r--r--tests/ui/suggestions/issue-84973-negative.stderr36
-rw-r--r--tests/ui/suggestions/issue-84973.rs33
-rw-r--r--tests/ui/suggestions/issue-84973.stderr24
-rw-r--r--tests/ui/suggestions/issue-85347.rs9
-rw-r--r--tests/ui/suggestions/issue-85347.stderr26
-rw-r--r--tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs9
-rw-r--r--tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr23
-rw-r--r--tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs8
-rw-r--r--tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr18
-rw-r--r--tests/ui/suggestions/issue-86100-tuple-paren-comma.rs25
-rw-r--r--tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr62
-rw-r--r--tests/ui/suggestions/issue-86667.rs17
-rw-r--r--tests/ui/suggestions/issue-86667.stderr36
-rw-r--r--tests/ui/suggestions/issue-88730.rs15
-rw-r--r--tests/ui/suggestions/issue-88730.stderr17
-rw-r--r--tests/ui/suggestions/issue-89064.rs35
-rw-r--r--tests/ui/suggestions/issue-89064.stderr77
-rw-r--r--tests/ui/suggestions/issue-89333.rs11
-rw-r--r--tests/ui/suggestions/issue-89333.stderr15
-rw-r--r--tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs13
-rw-r--r--tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr24
-rw-r--r--tests/ui/suggestions/issue-90974.rs3
-rw-r--r--tests/ui/suggestions/issue-90974.stderr14
-rw-r--r--tests/ui/suggestions/issue-96223.rs52
-rw-r--r--tests/ui/suggestions/issue-96223.stderr31
-rw-r--r--tests/ui/suggestions/issue-96555.rs19
-rw-r--r--tests/ui/suggestions/issue-96555.stderr66
-rw-r--r--tests/ui/suggestions/issue-97677.fixed8
-rw-r--r--tests/ui/suggestions/issue-97677.rs8
-rw-r--r--tests/ui/suggestions/issue-97677.stderr16
-rw-r--r--tests/ui/suggestions/issue-97704.fixed19
-rw-r--r--tests/ui/suggestions/issue-97704.rs19
-rw-r--r--tests/ui/suggestions/issue-97704.stderr15
-rw-r--r--tests/ui/suggestions/issue-97760.rs9
-rw-r--r--tests/ui/suggestions/issue-97760.stderr18
-rw-r--r--tests/ui/suggestions/issue-98500.rs14
-rw-r--r--tests/ui/suggestions/issue-98500.stderr24
-rw-r--r--tests/ui/suggestions/issue-99080.rs16
-rw-r--r--tests/ui/suggestions/issue-99080.stderr20
-rw-r--r--tests/ui/suggestions/issue-99240-2.rs10
-rw-r--r--tests/ui/suggestions/issue-99240-2.stderr21
-rw-r--r--tests/ui/suggestions/issue-99240.rs6
-rw-r--r--tests/ui/suggestions/issue-99240.stderr11
-rw-r--r--tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs5
-rw-r--r--tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr8
-rw-r--r--tests/ui/suggestions/js-style-comparison-op.fixed8
-rw-r--r--tests/ui/suggestions/js-style-comparison-op.rs8
-rw-r--r--tests/ui/suggestions/js-style-comparison-op.stderr14
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.rs11
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.stderr34
-rw-r--r--tests/ui/suggestions/lifetimes/issue-105544.fixed45
-rw-r--r--tests/ui/suggestions/lifetimes/issue-105544.rs45
-rw-r--r--tests/ui/suggestions/lifetimes/issue-105544.stderr110
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed29
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs29
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr30
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed10
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs10
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr15
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs111
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr168
-rw-r--r--tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs72
-rw-r--r--tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr78
-rw-r--r--tests/ui/suggestions/many-type-ascription.rs4
-rw-r--r--tests/ui/suggestions/many-type-ascription.stderr12
-rw-r--r--tests/ui/suggestions/match-ergonomics.rs41
-rw-r--r--tests/ui/suggestions/match-ergonomics.stderr68
-rw-r--r--tests/ui/suggestions/match-needing-semi.rs21
-rw-r--r--tests/ui/suggestions/match-needing-semi.stderr37
-rw-r--r--tests/ui/suggestions/match-prev-arm-needing-semi.rs66
-rw-r--r--tests/ui/suggestions/match-prev-arm-needing-semi.stderr127
-rw-r--r--tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs30
-rw-r--r--tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr51
-rw-r--r--tests/ui/suggestions/method-access-to-range-literal-typo.fixed34
-rw-r--r--tests/ui/suggestions/method-access-to-range-literal-typo.rs34
-rw-r--r--tests/ui/suggestions/method-access-to-range-literal-typo.stderr48
-rw-r--r--tests/ui/suggestions/method-missing-parentheses.rs5
-rw-r--r--tests/ui/suggestions/method-missing-parentheses.stderr20
-rw-r--r--tests/ui/suggestions/mismatched-types-numeric-from.rs3
-rw-r--r--tests/ui/suggestions/mismatched-types-numeric-from.stderr11
-rw-r--r--tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed21
-rw-r--r--tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs18
-rw-r--r--tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr16
-rw-r--r--tests/ui/suggestions/missing-assoc-fn.rs22
-rw-r--r--tests/ui/suggestions/missing-assoc-fn.stderr36
-rw-r--r--tests/ui/suggestions/missing-assoc-type-bound-restriction.rs21
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed16
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs16
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr19
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed16
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs16
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr27
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs15
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr27
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed19
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs19
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr22
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed9
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs9
-rw-r--r--tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr17
-rw-r--r--tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs16
-rw-r--r--tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr57
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.rs57
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.stderr319
-rw-r--r--tests/ui/suggestions/missing-lt-for-hrtb.rs13
-rw-r--r--tests/ui/suggestions/missing-lt-for-hrtb.stderr36
-rw-r--r--tests/ui/suggestions/missing-trait-item.fixed20
-rw-r--r--tests/ui/suggestions/missing-trait-item.rs16
-rw-r--r--tests/ui/suggestions/missing-trait-item.stderr25
-rw-r--r--tests/ui/suggestions/missing-type-param-used-in-param.fixed8
-rw-r--r--tests/ui/suggestions/missing-type-param-used-in-param.rs8
-rw-r--r--tests/ui/suggestions/missing-type-param-used-in-param.stderr21
-rw-r--r--tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs18
-rw-r--r--tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr24
-rw-r--r--tests/ui/suggestions/multibyte-escapes.rs18
-rw-r--r--tests/ui/suggestions/multibyte-escapes.stderr33
-rw-r--r--tests/ui/suggestions/mut-borrow-needed-by-trait.rs22
-rw-r--r--tests/ui/suggestions/mut-borrow-needed-by-trait.stderr40
-rw-r--r--tests/ui/suggestions/mut-ref-reassignment.rs17
-rw-r--r--tests/ui/suggestions/mut-ref-reassignment.stderr55
-rw-r--r--tests/ui/suggestions/negative-literal-index.fixed22
-rw-r--r--tests/ui/suggestions/negative-literal-index.rs22
-rw-r--r--tests/ui/suggestions/negative-literal-index.stderr35
-rw-r--r--tests/ui/suggestions/nested-non-tuple-tuple-struct.rs18
-rw-r--r--tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr116
-rw-r--r--tests/ui/suggestions/no-extern-crate-in-type.rs7
-rw-r--r--tests/ui/suggestions/no-extern-crate-in-type.stderr14
-rw-r--r--tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs43
-rw-r--r--tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr11
-rw-r--r--tests/ui/suggestions/non-existent-field-present-in-subfield.fixed42
-rw-r--r--tests/ui/suggestions/non-existent-field-present-in-subfield.rs42
-rw-r--r--tests/ui/suggestions/non-existent-field-present-in-subfield.stderr27
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-references-self.rs12
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-references-self.stderr35
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-self.rs16
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr65
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed13
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs13
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr41
-rw-r--r--tests/ui/suggestions/opaque-type-error.rs24
-rw-r--r--tests/ui/suggestions/opaque-type-error.stderr31
-rw-r--r--tests/ui/suggestions/option-content-move-from-tuple-match.rs9
-rw-r--r--tests/ui/suggestions/option-content-move-from-tuple-match.stderr20
-rw-r--r--tests/ui/suggestions/option-content-move.rs37
-rw-r--r--tests/ui/suggestions/option-content-move.stderr35
-rw-r--r--tests/ui/suggestions/option-content-move2.rs16
-rw-r--r--tests/ui/suggestions/option-content-move2.stderr20
-rw-r--r--tests/ui/suggestions/option-to-bool.rs9
-rw-r--r--tests/ui/suggestions/option-to-bool.stderr18
-rw-r--r--tests/ui/suggestions/parenthesized-deref-suggestion.rs11
-rw-r--r--tests/ui/suggestions/parenthesized-deref-suggestion.stderr22
-rw-r--r--tests/ui/suggestions/path-by-value.rs6
-rw-r--r--tests/ui/suggestions/path-by-value.stderr17
-rw-r--r--tests/ui/suggestions/path-display.rs11
-rw-r--r--tests/ui/suggestions/path-display.stderr23
-rw-r--r--tests/ui/suggestions/pattern-slice-vec.fixed31
-rw-r--r--tests/ui/suggestions/pattern-slice-vec.rs31
-rw-r--r--tests/ui/suggestions/pattern-slice-vec.stderr44
-rw-r--r--tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs35
-rw-r--r--tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr15
-rw-r--r--tests/ui/suggestions/private-field.rs19
-rw-r--r--tests/ui/suggestions/private-field.stderr11
-rw-r--r--tests/ui/suggestions/raw-byte-string-prefix.rs10
-rw-r--r--tests/ui/suggestions/raw-byte-string-prefix.stderr20
-rw-r--r--tests/ui/suggestions/raw-name-use-suggestion.rs9
-rw-r--r--tests/ui/suggestions/raw-name-use-suggestion.stderr36
-rw-r--r--tests/ui/suggestions/recover-from-semicolon-trailing-item.rs16
-rw-r--r--tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr53
-rw-r--r--tests/ui/suggestions/recover-invalid-float.fixed10
-rw-r--r--tests/ui/suggestions/recover-invalid-float.rs10
-rw-r--r--tests/ui/suggestions/recover-invalid-float.stderr20
-rw-r--r--tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs10
-rw-r--r--tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr46
-rw-r--r--tests/ui/suggestions/ref-pattern-binding.fixed19
-rw-r--r--tests/ui/suggestions/ref-pattern-binding.rs19
-rw-r--r--tests/ui/suggestions/ref-pattern-binding.stderr107
-rw-r--r--tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs30
-rw-r--r--tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr83
-rw-r--r--tests/ui/suggestions/remove-as_str.rs21
-rw-r--r--tests/ui/suggestions/remove-as_str.stderr27
-rw-r--r--tests/ui/suggestions/restrict-type-argument.rs31
-rw-r--r--tests/ui/suggestions/restrict-type-argument.stderr111
-rw-r--r--tests/ui/suggestions/restrict-type-not-param.rs12
-rw-r--r--tests/ui/suggestions/restrict-type-not-param.stderr23
-rw-r--r--tests/ui/suggestions/return-bindings-multi.rs9
-rw-r--r--tests/ui/suggestions/return-bindings-multi.stderr34
-rw-r--r--tests/ui/suggestions/return-bindings.rs51
-rw-r--r--tests/ui/suggestions/return-bindings.stderr110
-rw-r--r--tests/ui/suggestions/return-closures.rs13
-rw-r--r--tests/ui/suggestions/return-closures.stderr27
-rw-r--r--tests/ui/suggestions/return-cycle-2.rs14
-rw-r--r--tests/ui/suggestions/return-cycle-2.stderr12
-rw-r--r--tests/ui/suggestions/return-cycle.rs14
-rw-r--r--tests/ui/suggestions/return-cycle.stderr12
-rw-r--r--tests/ui/suggestions/return-elided-lifetime.rs32
-rw-r--r--tests/ui/suggestions/return-elided-lifetime.stderr143
-rw-r--r--tests/ui/suggestions/return-without-lifetime.rs10
-rw-r--r--tests/ui/suggestions/return-without-lifetime.stderr38
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method-2.rs23
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method-2.stderr25
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method.fixed10
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method.rs10
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method.stderr26
-rw-r--r--tests/ui/suggestions/slice-issue-87994.rs16
-rw-r--r--tests/ui/suggestions/slice-issue-87994.stderr63
-rw-r--r--tests/ui/suggestions/struct-field-type-including-single-colon.rs20
-rw-r--r--tests/ui/suggestions/struct-field-type-including-single-colon.stderr40
-rw-r--r--tests/ui/suggestions/struct-initializer-comma.fixed15
-rw-r--r--tests/ui/suggestions/struct-initializer-comma.rs15
-rw-r--r--tests/ui/suggestions/struct-initializer-comma.stderr23
-rw-r--r--tests/ui/suggestions/sugg-else-for-closure.fixed8
-rw-r--r--tests/ui/suggestions/sugg-else-for-closure.rs8
-rw-r--r--tests/ui/suggestions/sugg-else-for-closure.stderr27
-rw-r--r--tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs10
-rw-r--r--tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr21
-rw-r--r--tests/ui/suggestions/suggest-add-self.rs15
-rw-r--r--tests/ui/suggestions/suggest-add-self.stderr29
-rw-r--r--tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed15
-rw-r--r--tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs15
-rw-r--r--tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr25
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed15
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-deref.rs15
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr19
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs11
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr22
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs13
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr19
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed26
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs26
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr98
-rw-r--r--tests/ui/suggestions/suggest-blanket-impl-local-trait.rs58
-rw-r--r--tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr100
-rw-r--r--tests/ui/suggestions/suggest-borrow-to-dyn-object.rs16
-rw-r--r--tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr17
-rw-r--r--tests/ui/suggestions/suggest-box.fixed8
-rw-r--r--tests/ui/suggestions/suggest-box.rs8
-rw-r--r--tests/ui/suggestions/suggest-box.stderr26
-rw-r--r--tests/ui/suggestions/suggest-change-mut.rs21
-rw-r--r--tests/ui/suggestions/suggest-change-mut.stderr41
-rw-r--r--tests/ui/suggestions/suggest-closure-return-type-1.rs7
-rw-r--r--tests/ui/suggestions/suggest-closure-return-type-1.stderr14
-rw-r--r--tests/ui/suggestions/suggest-closure-return-type-2.rs7
-rw-r--r--tests/ui/suggestions/suggest-closure-return-type-2.stderr14
-rw-r--r--tests/ui/suggestions/suggest-closure-return-type-3.rs7
-rw-r--r--tests/ui/suggestions/suggest-closure-return-type-3.stderr14
-rw-r--r--tests/ui/suggestions/suggest-dereferencing-index.fixed7
-rw-r--r--tests/ui/suggestions/suggest-dereferencing-index.rs7
-rw-r--r--tests/ui/suggestions/suggest-dereferencing-index.stderr17
-rw-r--r--tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs10
-rw-r--r--tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr18
-rw-r--r--tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs23
-rw-r--r--tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr59
-rw-r--r--tests/ui/suggestions/suggest-impl-trait-lifetime.fixed18
-rw-r--r--tests/ui/suggestions/suggest-impl-trait-lifetime.rs18
-rw-r--r--tests/ui/suggestions/suggest-impl-trait-lifetime.stderr14
-rw-r--r--tests/ui/suggestions/suggest-labels.rs16
-rw-r--r--tests/ui/suggestions/suggest-labels.stderr36
-rw-r--r--tests/ui/suggestions/suggest-let-for-assignment.fixed17
-rw-r--r--tests/ui/suggestions/suggest-let-for-assignment.rs17
-rw-r--r--tests/ui/suggestions/suggest-let-for-assignment.stderr60
-rw-r--r--tests/ui/suggestions/suggest-methods.rs30
-rw-r--r--tests/ui/suggestions/suggest-methods.stderr30
-rw-r--r--tests/ui/suggestions/suggest-move-lifetimes.rs21
-rw-r--r--tests/ui/suggestions/suggest-move-lifetimes.stderr26
-rw-r--r--tests/ui/suggestions/suggest-move-types.rs91
-rw-r--r--tests/ui/suggestions/suggest-move-types.stderr137
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed21
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs21
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr15
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop.rs17
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop.stderr15
-rw-r--r--tests/ui/suggestions/suggest-on-bare-closure-call.rs11
-rw-r--r--tests/ui/suggestions/suggest-on-bare-closure-call.stderr29
-rw-r--r--tests/ui/suggestions/suggest-ref-macro.rs29
-rw-r--r--tests/ui/suggestions/suggest-ref-macro.stderr57
-rw-r--r--tests/ui/suggestions/suggest-ref-mut.rs30
-rw-r--r--tests/ui/suggestions/suggest-ref-mut.stderr47
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-1.fixed10
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-1.rs10
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-1.stderr17
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-2.fixed10
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-2.rs10
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-2.stderr17
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-3.fixed12
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-3.rs13
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-3.stderr21
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.fixed5
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.rs5
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.stderr17
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.fixed8
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.rs8
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.stderr37
-rw-r--r--tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed9
-rw-r--r--tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs9
-rw-r--r--tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr10
-rw-r--r--tests/ui/suggestions/suggest-split-at-mut.rs8
-rw-r--r--tests/ui/suggestions/suggest-split-at-mut.stderr15
-rw-r--r--tests/ui/suggestions/suggest-std-when-using-type.fixed8
-rw-r--r--tests/ui/suggestions/suggest-std-when-using-type.rs8
-rw-r--r--tests/ui/suggestions/suggest-std-when-using-type.stderr26
-rw-r--r--tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs22
-rw-r--r--tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr48
-rw-r--r--tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs21
-rw-r--r--tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr50
-rw-r--r--tests/ui/suggestions/suggest-trait-items.rs48
-rw-r--r--tests/ui/suggestions/suggest-trait-items.stderr74
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.rs32
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.stderr69
-rw-r--r--tests/ui/suggestions/suggest-using-chars.rs7
-rw-r--r--tests/ui/suggestions/suggest-using-chars.stderr48
-rw-r--r--tests/ui/suggestions/suggest-variants.rs18
-rw-r--r--tests/ui/suggestions/suggest-variants.stderr63
-rw-r--r--tests/ui/suggestions/suggest_print_over_printf.rs8
-rw-r--r--tests/ui/suggestions/suggest_print_over_printf.stderr14
-rw-r--r--tests/ui/suggestions/too-many-field-suggestions.rs29
-rw-r--r--tests/ui/suggestions/too-many-field-suggestions.stderr44
-rw-r--r--tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed43
-rw-r--r--tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs43
-rw-r--r--tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr143
-rw-r--r--tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs44
-rw-r--r--tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr177
-rw-r--r--tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs27
-rw-r--r--tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr33
-rw-r--r--tests/ui/suggestions/try-removing-the-field.rs32
-rw-r--r--tests/ui/suggestions/try-removing-the-field.stderr26
-rw-r--r--tests/ui/suggestions/type-ascription-and-other-error.rs6
-rw-r--r--tests/ui/suggestions/type-ascription-and-other-error.stderr8
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-let.rs10
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-let.stderr18
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-method.fixed5
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-method.rs5
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-method.stderr12
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path-2.fixed6
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path-2.rs6
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path-2.stderr12
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs14
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr41
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path.rs5
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path.stderr18
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-variant.fixed5
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-variant.rs5
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-variant.stderr12
-rw-r--r--tests/ui/suggestions/type-mismatch-byte-literal.rs18
-rw-r--r--tests/ui/suggestions/type-mismatch-byte-literal.stderr42
-rw-r--r--tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs9
-rw-r--r--tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr32
-rw-r--r--tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed12
-rw-r--r--tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs12
-rw-r--r--tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr36
-rw-r--r--tests/ui/suggestions/type-not-found-in-adt-field.rs9
-rw-r--r--tests/ui/suggestions/type-not-found-in-adt-field.stderr20
-rw-r--r--tests/ui/suggestions/undeclared-module-alloc.rs5
-rw-r--r--tests/ui/suggestions/undeclared-module-alloc.stderr11
-rw-r--r--tests/ui/suggestions/unnamable-types.rs39
-rw-r--r--tests/ui/suggestions/unnamable-types.stderr66
-rw-r--r--tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs6
-rw-r--r--tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr59
-rw-r--r--tests/ui/suggestions/unsized-function-parameter.fixed23
-rw-r--r--tests/ui/suggestions/unsized-function-parameter.rs23
-rw-r--r--tests/ui/suggestions/unsized-function-parameter.stderr42
-rw-r--r--tests/ui/suggestions/unused-closure-argument.rs20
-rw-r--r--tests/ui/suggestions/unused-closure-argument.stderr20
-rw-r--r--tests/ui/suggestions/use-placement-resolve.fixed13
-rw-r--r--tests/ui/suggestions/use-placement-resolve.rs11
-rw-r--r--tests/ui/suggestions/use-placement-resolve.stderr14
-rw-r--r--tests/ui/suggestions/use-placement-typeck.fixed21
-rw-r--r--tests/ui/suggestions/use-placement-typeck.rs20
-rw-r--r--tests/ui/suggestions/use-placement-typeck.stderr21
-rw-r--r--tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs13
-rw-r--r--tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr32
-rw-r--r--tests/ui/suggestions/while-let-typo.rs9
-rw-r--r--tests/ui/suggestions/while-let-typo.stderr45
666 files changed, 21541 insertions, 0 deletions
diff --git a/tests/ui/suggestions/abi-typo.fixed b/tests/ui/suggestions/abi-typo.fixed
new file mode 100644
index 000000000..04d265865
--- /dev/null
+++ b/tests/ui/suggestions/abi-typo.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+extern "cdecl" fn cdedl() {} //~ ERROR invalid ABI
+
+fn main() {
+ cdedl();
+}
diff --git a/tests/ui/suggestions/abi-typo.rs b/tests/ui/suggestions/abi-typo.rs
new file mode 100644
index 000000000..6d80db522
--- /dev/null
+++ b/tests/ui/suggestions/abi-typo.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+extern "cdedl" fn cdedl() {} //~ ERROR invalid ABI
+
+fn main() {
+ cdedl();
+}
diff --git a/tests/ui/suggestions/abi-typo.stderr b/tests/ui/suggestions/abi-typo.stderr
new file mode 100644
index 000000000..67a84f119
--- /dev/null
+++ b/tests/ui/suggestions/abi-typo.stderr
@@ -0,0 +1,14 @@
+error[E0703]: invalid ABI: found `cdedl`
+ --> $DIR/abi-typo.rs:2:8
+ |
+LL | extern "cdedl" fn cdedl() {}
+ | ^^^^^^^
+ | |
+ | invalid ABI
+ | help: did you mean: `"cdecl"`
+ |
+ = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs
new file mode 100644
index 000000000..ef64d799b
--- /dev/null
+++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs
@@ -0,0 +1,28 @@
+trait Trait {
+ fn func1() -> Struct1<Self>; //~ ERROR E0277
+ fn func2<'a>() -> Struct2<'a, Self>; //~ ERROR E0277
+ fn func3() -> Struct3<Self>; //~ ERROR E0277
+ fn func4() -> Struct4<Self>; //~ ERROR E0277
+}
+
+struct Struct1<T>{
+ _t: std::marker::PhantomData<*const T>,
+}
+struct Struct2<'a, T>{
+ _t: &'a T,
+}
+struct Struct3<T>{
+ _t: T,
+}
+
+struct X<T>(T);
+
+struct Struct4<T>{
+ _t: X<T>,
+}
+
+struct Struct5<T: ?Sized>{
+ _t: X<T>, //~ ERROR E0277
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr
new file mode 100644
index 000000000..b77c8c7fd
--- /dev/null
+++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr
@@ -0,0 +1,112 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9
+ |
+LL | struct Struct5<T: ?Sized>{
+ | - this type parameter needs to be `std::marker::Sized`
+LL | _t: X<T>,
+ | ^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `X`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
+ |
+LL | struct X<T>(T);
+ | ^ required by this bound in `X`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10
+ |
+LL | struct X<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - struct Struct5<T: ?Sized>{
+LL + struct Struct5<T>{
+ |
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19
+ |
+LL | fn func1() -> Struct1<Self>;
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `Struct1`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:8:16
+ |
+LL | struct Struct1<T>{
+ | ^ required by this bound in `Struct1`
+help: consider further restricting `Self`
+ |
+LL | fn func1() -> Struct1<Self> where Self: Sized;
+ | +++++++++++++++++
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | struct Struct1<T: ?Sized>{
+ | ++++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:3:23
+ |
+LL | fn func2<'a>() -> Struct2<'a, Self>;
+ | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `Struct2`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:11:20
+ |
+LL | struct Struct2<'a, T>{
+ | ^ required by this bound in `Struct2`
+help: consider further restricting `Self`
+ |
+LL | fn func2<'a>() -> Struct2<'a, Self> where Self: Sized;
+ | +++++++++++++++++
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | struct Struct2<'a, T: ?Sized>{
+ | ++++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:4:19
+ |
+LL | fn func3() -> Struct3<Self>;
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `Struct3`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16
+ |
+LL | struct Struct3<T>{
+ | ^ required by this bound in `Struct3`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16
+ |
+LL | struct Struct3<T>{
+ | ^ this could be changed to `T: ?Sized`...
+LL | _t: T,
+ | - ...if indirection were used here: `Box<T>`
+help: consider further restricting `Self`
+ |
+LL | fn func3() -> Struct3<Self> where Self: Sized;
+ | +++++++++++++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:5:19
+ |
+LL | fn func4() -> Struct4<Self>;
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `Struct4`
+ --> $DIR/adt-param-with-implicit-sized-bound.rs:20:16
+ |
+LL | struct Struct4<T>{
+ | ^ required by this bound in `Struct4`
+help: consider further restricting `Self`
+ |
+LL | fn func4() -> Struct4<Self> where Self: Sized;
+ | +++++++++++++++++
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | struct Struct4<T: ?Sized>{
+ | ++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.rs b/tests/ui/suggestions/args-instead-of-tuple-errors.rs
new file mode 100644
index 000000000..f5931a1ba
--- /dev/null
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.rs
@@ -0,0 +1,22 @@
+// Ensure we don't suggest tuple-wrapping when we'd end up with a type error
+
+fn main() {
+ // we shouldn't suggest to fix these - `2` isn't a `bool`
+
+ let _: Option<(i32, bool)> = Some(1, 2);
+ //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied
+ int_bool(1, 2);
+ //~^ ERROR function takes 1 argument but 2 arguments were supplied
+
+ let _: Option<(i8,)> = Some();
+ //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
+
+ let _: Option<(i32,)> = Some(5_usize);
+ //~^ ERROR mismatched types
+
+ let _: Option<(i32,)> = Some((5_usize));
+ //~^ ERROR mismatched types
+}
+
+fn int_bool(_: (i32, bool)) {
+}
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
new file mode 100644
index 000000000..bc097bf6e
--- /dev/null
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -0,0 +1,107 @@
+error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
+ --> $DIR/args-instead-of-tuple-errors.rs:6:34
+ |
+LL | let _: Option<(i32, bool)> = Some(1, 2);
+ | ^^^^ - argument of type `{integer}` unexpected
+ |
+note: expected tuple, found integer
+ --> $DIR/args-instead-of-tuple-errors.rs:6:39
+ |
+LL | let _: Option<(i32, bool)> = Some(1, 2);
+ | ^
+ = note: expected tuple `(i32, bool)`
+ found type `{integer}`
+help: the type constructed contains `{integer}` due to the type of the argument passed
+ --> $DIR/args-instead-of-tuple-errors.rs:6:34
+ |
+LL | let _: Option<(i32, bool)> = Some(1, 2);
+ | ^^^^^-^^^^
+ | |
+ | this argument influences the type of `Some`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: remove the extra argument
+ |
+LL | let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/args-instead-of-tuple-errors.rs:8:5
+ |
+LL | int_bool(1, 2);
+ | ^^^^^^^^ - argument of type `{integer}` unexpected
+ |
+note: expected tuple, found integer
+ --> $DIR/args-instead-of-tuple-errors.rs:8:14
+ |
+LL | int_bool(1, 2);
+ | ^
+ = note: expected tuple `(i32, bool)`
+ found type `{integer}`
+note: function defined here
+ --> $DIR/args-instead-of-tuple-errors.rs:21:4
+ |
+LL | fn int_bool(_: (i32, bool)) {
+ | ^^^^^^^^ --------------
+help: remove the extra argument
+ |
+LL | int_bool(/* (i32, bool) */);
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
+ --> $DIR/args-instead-of-tuple-errors.rs:11:28
+ |
+LL | let _: Option<(i8,)> = Some();
+ | ^^^^-- an argument of type `(i8,)` is missing
+ |
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: provide the argument
+ |
+LL | let _: Option<(i8,)> = Some(/* (i8,) */);
+ | ~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/args-instead-of-tuple-errors.rs:14:34
+ |
+LL | let _: Option<(i32,)> = Some(5_usize);
+ | ---- ^^^^^^^ expected tuple, found `usize`
+ | |
+ | arguments to this enum variant are incorrect
+ |
+ = note: expected tuple `(i32,)`
+ found type `usize`
+help: the type constructed contains `usize` due to the type of the argument passed
+ --> $DIR/args-instead-of-tuple-errors.rs:14:29
+ |
+LL | let _: Option<(i32,)> = Some(5_usize);
+ | ^^^^^-------^
+ | |
+ | this argument influences the type of `Some`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+
+error[E0308]: mismatched types
+ --> $DIR/args-instead-of-tuple-errors.rs:17:34
+ |
+LL | let _: Option<(i32,)> = Some((5_usize));
+ | ---- ^^^^^^^^^ expected tuple, found `usize`
+ | |
+ | arguments to this enum variant are incorrect
+ |
+ = note: expected tuple `(i32,)`
+ found type `usize`
+help: the type constructed contains `usize` due to the type of the argument passed
+ --> $DIR/args-instead-of-tuple-errors.rs:17:29
+ |
+LL | let _: Option<(i32,)> = Some((5_usize));
+ | ^^^^^---------^
+ | |
+ | this argument influences the type of `Some`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/suggestions/args-instead-of-tuple.fixed b/tests/ui/suggestions/args-instead-of-tuple.fixed
new file mode 100644
index 000000000..f913995d7
--- /dev/null
+++ b/tests/ui/suggestions/args-instead-of-tuple.fixed
@@ -0,0 +1,33 @@
+// Test suggesting tuples where bare arguments may have been passed
+// See issue #86481 for details.
+
+// run-rustfix
+
+fn main() {
+ let _: Result<(i32, i8), ()> = Ok((1, 2));
+ //~^ ERROR enum variant takes 1 argument but 2 arguments were supplied
+ let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
+ //~^ ERROR enum variant takes 1 argument but 3 arguments were supplied
+ let _: Option<()> = Some(());
+ //~^ ERROR enum variant takes 1 argument but 0 arguments were supplied
+
+ let _: Option<(i32,)> = Some((3,));
+ //~^ ERROR mismatched types
+
+ let _: Option<(i32,)> = Some((3,));
+ //~^ ERROR mismatched types
+
+ two_ints((1, 2)); //~ ERROR function takes 1 argument
+
+ with_generic((3, 4)); //~ ERROR function takes 1 argument
+}
+
+fn two_ints(_: (i32, i32)) {
+}
+
+fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
+ if false {
+ // test generics/bound handling
+ with_generic((a, b)); //~ ERROR function takes 1 argument
+ }
+}
diff --git a/tests/ui/suggestions/args-instead-of-tuple.rs b/tests/ui/suggestions/args-instead-of-tuple.rs
new file mode 100644
index 000000000..1c65407b3
--- /dev/null
+++ b/tests/ui/suggestions/args-instead-of-tuple.rs
@@ -0,0 +1,33 @@
+// Test suggesting tuples where bare arguments may have been passed
+// See issue #86481 for details.
+
+// run-rustfix
+
+fn main() {
+ let _: Result<(i32, i8), ()> = Ok(1, 2);
+ //~^ ERROR enum variant takes 1 argument but 2 arguments were supplied
+ let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
+ //~^ ERROR enum variant takes 1 argument but 3 arguments were supplied
+ let _: Option<()> = Some();
+ //~^ ERROR enum variant takes 1 argument but 0 arguments were supplied
+
+ let _: Option<(i32,)> = Some(3);
+ //~^ ERROR mismatched types
+
+ let _: Option<(i32,)> = Some((3));
+ //~^ ERROR mismatched types
+
+ two_ints(1, 2); //~ ERROR function takes 1 argument
+
+ with_generic(3, 4); //~ ERROR function takes 1 argument
+}
+
+fn two_ints(_: (i32, i32)) {
+}
+
+fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
+ if false {
+ // test generics/bound handling
+ with_generic(a, b); //~ ERROR function takes 1 argument
+ }
+}
diff --git a/tests/ui/suggestions/args-instead-of-tuple.stderr b/tests/ui/suggestions/args-instead-of-tuple.stderr
new file mode 100644
index 000000000..3ed9dbf4a
--- /dev/null
+++ b/tests/ui/suggestions/args-instead-of-tuple.stderr
@@ -0,0 +1,125 @@
+error[E0061]: enum variant takes 1 argument but 2 arguments were supplied
+ --> $DIR/args-instead-of-tuple.rs:7:36
+ |
+LL | let _: Result<(i32, i8), ()> = Ok(1, 2);
+ | ^^
+ |
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+help: wrap these arguments in parentheses to construct a tuple
+ |
+LL | let _: Result<(i32, i8), ()> = Ok((1, 2));
+ | + +
+
+error[E0061]: enum variant takes 1 argument but 3 arguments were supplied
+ --> $DIR/args-instead-of-tuple.rs:9:46
+ |
+LL | let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
+ | ^^^^
+ |
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: wrap these arguments in parentheses to construct a tuple
+ |
+LL | let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
+ | + +
+
+error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
+ --> $DIR/args-instead-of-tuple.rs:11:25
+ |
+LL | let _: Option<()> = Some();
+ | ^^^^-- an argument of type `()` is missing
+ |
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: provide the argument
+ |
+LL | let _: Option<()> = Some(());
+ | ~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/args-instead-of-tuple.rs:14:34
+ |
+LL | let _: Option<(i32,)> = Some(3);
+ | ---- ^ expected tuple, found integer
+ | |
+ | arguments to this enum variant are incorrect
+ |
+ = note: expected tuple `(i32,)`
+ found type `{integer}`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: use a trailing comma to create a tuple with one element
+ |
+LL | let _: Option<(i32,)> = Some((3,));
+ | + ++
+
+error[E0308]: mismatched types
+ --> $DIR/args-instead-of-tuple.rs:17:34
+ |
+LL | let _: Option<(i32,)> = Some((3));
+ | ---- ^^^ expected tuple, found integer
+ | |
+ | arguments to this enum variant are incorrect
+ |
+ = note: expected tuple `(i32,)`
+ found type `{integer}`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: use a trailing comma to create a tuple with one element
+ |
+LL | let _: Option<(i32,)> = Some((3,));
+ | +
+
+error[E0061]: function takes 1 argument but 2 arguments were supplied
+ --> $DIR/args-instead-of-tuple.rs:20:5
+ |
+LL | two_ints(1, 2);
+ | ^^^^^^^^
+ |
+note: function defined here
+ --> $DIR/args-instead-of-tuple.rs:25:4
+ |
+LL | fn two_ints(_: (i32, i32)) {
+ | ^^^^^^^^ -------------
+help: wrap these arguments in parentheses to construct a tuple
+ |
+LL | two_ints((1, 2));
+ | + +
+
+error[E0061]: function takes 1 argument but 2 arguments were supplied
+ --> $DIR/args-instead-of-tuple.rs:22:5
+ |
+LL | with_generic(3, 4);
+ | ^^^^^^^^^^^^
+ |
+note: function defined here
+ --> $DIR/args-instead-of-tuple.rs:28:4
+ |
+LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
+ | ^^^^^^^^^^^^ ----------------
+help: wrap these arguments in parentheses to construct a tuple
+ |
+LL | with_generic((3, 4));
+ | + +
+
+error[E0061]: function takes 1 argument but 2 arguments were supplied
+ --> $DIR/args-instead-of-tuple.rs:31:9
+ |
+LL | with_generic(a, b);
+ | ^^^^^^^^^^^^
+ |
+note: function defined here
+ --> $DIR/args-instead-of-tuple.rs:28:4
+ |
+LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
+ | ^^^^^^^^^^^^ ----------------
+help: wrap these arguments in parentheses to construct a tuple
+ |
+LL | with_generic((a, b));
+ | + +
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/suggestions/as-ref-2.rs b/tests/ui/suggestions/as-ref-2.rs
new file mode 100644
index 000000000..b22f409b4
--- /dev/null
+++ b/tests/ui/suggestions/as-ref-2.rs
@@ -0,0 +1,11 @@
+struct Struct;
+
+fn bar(_: &Struct) -> Struct {
+ Struct
+}
+
+fn main() {
+ let foo = Some(Struct);
+ let _x: Option<Struct> = foo.map(|s| bar(&s));
+ let _y = foo; //~ERROR use of moved value: `foo`
+}
diff --git a/tests/ui/suggestions/as-ref-2.stderr b/tests/ui/suggestions/as-ref-2.stderr
new file mode 100644
index 000000000..e2129b450
--- /dev/null
+++ b/tests/ui/suggestions/as-ref-2.stderr
@@ -0,0 +1,18 @@
+error[E0382]: use of moved value: `foo`
+ --> $DIR/as-ref-2.rs:10:14
+ |
+LL | let foo = Some(Struct);
+ | --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
+LL | let _x: Option<Struct> = foo.map(|s| bar(&s));
+ | --- ---------------- `foo` moved due to this method call
+ | |
+ | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+LL | let _y = foo;
+ | ^^^ value used here after move
+ |
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `foo`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/suggestions/as-ref.rs b/tests/ui/suggestions/as-ref.rs
new file mode 100644
index 000000000..a05353441
--- /dev/null
+++ b/tests/ui/suggestions/as-ref.rs
@@ -0,0 +1,27 @@
+struct Foo;
+
+fn takes_ref(_: &Foo) {}
+
+fn main() {
+ let ref opt = Some(Foo);
+ opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308]
+ opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308]
+ let ref opt: Result<_, ()> = Ok(Foo);
+ opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308]
+ opt.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308]
+ let x: &Option<usize> = &Some(3);
+ let y: Option<&usize> = x; //~ ERROR mismatched types [E0308]
+ let x: &Result<usize, usize> = &Ok(3);
+ let y: Result<&usize, &usize> = x;
+ //~^ ERROR mismatched types [E0308]
+ // note: do not suggest because of `E: usize`
+ let x: &Result<usize, usize> = &Ok(3);
+ let y: Result<&usize, usize> = x; //~ ERROR mismatched types [E0308]
+
+ let multiple_ref_opt = &&Some(Foo);
+ multiple_ref_opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308]
+ multiple_ref_opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308]
+ let multiple_ref_result = &&Ok(Foo);
+ multiple_ref_result.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308]
+ multiple_ref_result.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/as-ref.stderr b/tests/ui/suggestions/as-ref.stderr
new file mode 100644
index 000000000..deafa9f48
--- /dev/null
+++ b/tests/ui/suggestions/as-ref.stderr
@@ -0,0 +1,162 @@
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:7:29
+ |
+LL | opt.map(|arg| takes_ref(arg));
+ | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().map`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:8:39
+ |
+LL | opt.and_then(|arg| Some(takes_ref(arg)));
+ | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().and_then`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:10:29
+ |
+LL | opt.map(|arg| takes_ref(arg));
+ | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().map`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:11:37
+ |
+LL | opt.and_then(|arg| Ok(takes_ref(arg)));
+ | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().and_then`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:13:29
+ |
+LL | let y: Option<&usize> = x;
+ | -------------- ^
+ | | |
+ | | expected enum `Option`, found `&Option<usize>`
+ | | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()`
+ | expected due to this
+ |
+ = note: expected enum `Option<&usize>`
+ found reference `&Option<usize>`
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:15:37
+ |
+LL | let y: Result<&usize, &usize> = x;
+ | ---------------------- ^ expected enum `Result`, found reference
+ | |
+ | expected due to this
+ |
+ = note: expected enum `Result<&usize, &usize>`
+ found reference `&Result<usize, usize>`
+help: you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()`
+ |
+LL | let y: Result<&usize, &usize> = x.as_ref();
+ | ~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:19:36
+ |
+LL | let y: Result<&usize, usize> = x;
+ | --------------------- ^ expected enum `Result`, found reference
+ | |
+ | expected due to this
+ |
+ = note: expected enum `Result<&usize, usize>`
+ found reference `&Result<usize, usize>`
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:22:42
+ |
+LL | multiple_ref_opt.map(|arg| takes_ref(arg));
+ | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().map`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:23:52
+ |
+LL | multiple_ref_opt.and_then(|arg| Some(takes_ref(arg)));
+ | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().and_then`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:25:45
+ |
+LL | multiple_ref_result.map(|arg| takes_ref(arg));
+ | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().map`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/as-ref.rs:26:53
+ |
+LL | multiple_ref_result.and_then(|arg| Ok(takes_ref(arg)));
+ | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
+ | help: consider using `as_ref` instead: `as_ref().and_then`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/assoc-const-as-field.rs b/tests/ui/suggestions/assoc-const-as-field.rs
new file mode 100644
index 000000000..678b58936
--- /dev/null
+++ b/tests/ui/suggestions/assoc-const-as-field.rs
@@ -0,0 +1,13 @@
+pub mod Mod {
+ pub struct Foo {}
+ impl Foo {
+ pub const BAR: usize = 42;
+ }
+}
+
+fn foo(_: usize) {}
+
+fn main() {
+ foo(Mod::Foo.Bar);
+ //~^ ERROR expected value, found
+}
diff --git a/tests/ui/suggestions/assoc-const-as-field.stderr b/tests/ui/suggestions/assoc-const-as-field.stderr
new file mode 100644
index 000000000..78e5634b2
--- /dev/null
+++ b/tests/ui/suggestions/assoc-const-as-field.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected value, found struct `Mod::Foo`
+ --> $DIR/assoc-const-as-field.rs:11:9
+ |
+LL | foo(Mod::Foo.Bar);
+ | ^^^^^^^^- help: use the path separator to refer to an item: `::`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/suggestions/assoc-const-as-fn.rs b/tests/ui/suggestions/assoc-const-as-fn.rs
new file mode 100644
index 000000000..4b4595dd5
--- /dev/null
+++ b/tests/ui/suggestions/assoc-const-as-fn.rs
@@ -0,0 +1,18 @@
+unsafe fn pointer(v: usize, w: u32) {}
+
+pub trait UniformScalar {}
+impl UniformScalar for u32 {}
+
+pub trait GlUniformScalar: UniformScalar {
+ const FACTORY: unsafe fn(usize, Self) -> ();
+}
+impl GlUniformScalar for u32 {
+ const FACTORY: unsafe fn(usize, Self) -> () = pointer;
+}
+
+pub fn foo<T: UniformScalar>(value: T) {
+ <T as GlUniformScalar>::FACTORY(1, value);
+ //~^ ERROR the trait bound `T: GlUniformScalar` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/assoc-const-as-fn.stderr b/tests/ui/suggestions/assoc-const-as-fn.stderr
new file mode 100644
index 000000000..3b6e947c5
--- /dev/null
+++ b/tests/ui/suggestions/assoc-const-as-fn.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied
+ --> $DIR/assoc-const-as-fn.rs:14:40
+ |
+LL | <T as GlUniformScalar>::FACTORY(1, value);
+ | ------------------------------- ^^^^^ the trait `GlUniformScalar` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
+ |
+help: consider further restricting this bound
+ |
+LL | pub fn foo<T: UniformScalar + GlUniformScalar>(value: T) {
+ | +++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.rs b/tests/ui/suggestions/assoc-ct-for-assoc-method.rs
new file mode 100644
index 000000000..fe2227769
--- /dev/null
+++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.rs
@@ -0,0 +1,25 @@
+struct MyS;
+
+impl MyS {
+ const FOO: i32 = 1;
+ fn foo() -> MyS {
+ MyS
+ }
+}
+
+fn main() {
+ let x: i32 = MyS::foo;
+ //~^ ERROR mismatched types
+ //~| HELP try referring to the
+
+ let z: i32 = i32::max;
+ //~^ ERROR mismatched types
+ //~| HELP try referring to the
+
+ // This example is still broken though... This is a hard suggestion to make,
+ // because we don't have access to the associated const probing code to make
+ // this suggestion where it's emitted, i.e. in trait selection.
+ let y: i32 = i32::max - 42;
+ //~^ ERROR cannot subtract
+ //~| HELP use parentheses
+}
diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr
new file mode 100644
index 000000000..afef38f12
--- /dev/null
+++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr
@@ -0,0 +1,47 @@
+error[E0308]: mismatched types
+ --> $DIR/assoc-ct-for-assoc-method.rs:11:18
+ |
+LL | let x: i32 = MyS::foo;
+ | --- ^^^^^^^^ expected `i32`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `i32`
+ found fn item `fn() -> MyS {MyS::foo}`
+help: try referring to the associated const `FOO` instead
+ |
+LL | let x: i32 = MyS::FOO;
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/assoc-ct-for-assoc-method.rs:15:18
+ |
+LL | let z: i32 = i32::max;
+ | --- ^^^^^^^^ expected `i32`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `i32`
+ found fn item `fn(i32, i32) -> i32 {<i32 as Ord>::max}`
+help: try referring to the associated const `MAX` instead
+ |
+LL | let z: i32 = i32::MAX;
+ | ~~~
+
+error[E0369]: cannot subtract `{integer}` from `fn(i32, i32) -> i32 {<i32 as Ord>::max}`
+ --> $DIR/assoc-ct-for-assoc-method.rs:22:27
+ |
+LL | let y: i32 = i32::max - 42;
+ | -------- ^ -- {integer}
+ | |
+ | fn(i32, i32) -> i32 {<i32 as Ord>::max}
+ |
+help: use parentheses to call this associated function
+ |
+LL | let y: i32 = i32::max(/* i32 */, /* i32 */) - 42;
+ | ++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/assoc-type-in-method-return.rs b/tests/ui/suggestions/assoc-type-in-method-return.rs
new file mode 100644
index 000000000..9bde65998
--- /dev/null
+++ b/tests/ui/suggestions/assoc-type-in-method-return.rs
@@ -0,0 +1,7 @@
+trait A {
+ type Bla;
+ fn to_bla(&self) -> Bla;
+ //~^ ERROR cannot find type `Bla` in this scope
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/assoc-type-in-method-return.stderr b/tests/ui/suggestions/assoc-type-in-method-return.stderr
new file mode 100644
index 000000000..202e4a16e
--- /dev/null
+++ b/tests/ui/suggestions/assoc-type-in-method-return.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Bla` in this scope
+ --> $DIR/assoc-type-in-method-return.rs:3:25
+ |
+LL | fn to_bla(&self) -> Bla;
+ | ^^^ help: you might have meant to use the associated type: `Self::Bla`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/suggestions/assoc_fn_without_self.rs b/tests/ui/suggestions/assoc_fn_without_self.rs
new file mode 100644
index 000000000..778d98477
--- /dev/null
+++ b/tests/ui/suggestions/assoc_fn_without_self.rs
@@ -0,0 +1,20 @@
+fn main() {}
+
+struct S;
+
+impl S {
+ fn foo() {}
+
+ fn bar(&self) {}
+
+ fn baz(a: u8, b: u8) {}
+
+ fn b() {
+ fn c() {
+ foo(); //~ ERROR cannot find function `foo` in this scope
+ }
+ foo(); //~ ERROR cannot find function `foo` in this scope
+ bar(); //~ ERROR cannot find function `bar` in this scope
+ baz(2, 3); //~ ERROR cannot find function `baz` in this scope
+ }
+}
diff --git a/tests/ui/suggestions/assoc_fn_without_self.stderr b/tests/ui/suggestions/assoc_fn_without_self.stderr
new file mode 100644
index 000000000..febdd6733
--- /dev/null
+++ b/tests/ui/suggestions/assoc_fn_without_self.stderr
@@ -0,0 +1,42 @@
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/assoc_fn_without_self.rs:16:9
+ |
+LL | foo();
+ | ^^^ not found in this scope
+ |
+help: consider using the associated function
+ |
+LL | Self::foo();
+ | ++++++
+
+error[E0425]: cannot find function `bar` in this scope
+ --> $DIR/assoc_fn_without_self.rs:17:9
+ |
+LL | bar();
+ | ^^^ not found in this scope
+ |
+help: consider using the associated function
+ |
+LL | self.bar();
+ | +++++
+
+error[E0425]: cannot find function `baz` in this scope
+ --> $DIR/assoc_fn_without_self.rs:18:9
+ |
+LL | baz(2, 3);
+ | ^^^ not found in this scope
+ |
+help: consider using the associated function
+ |
+LL | Self::baz(2, 3);
+ | ++++++
+
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/assoc_fn_without_self.rs:14:13
+ |
+LL | foo();
+ | ^^^ 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/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
new file mode 100644
index 000000000..156162c90
--- /dev/null
+++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
@@ -0,0 +1,13 @@
+// edition:2018
+#![feature(async_closure)]
+use std::future::Future;
+
+async fn foo() {}
+
+fn bar(f: impl Future<Output=()>) {}
+
+fn main() {
+ bar(foo); //~ERROR E0277
+ let async_closure = async || ();
+ bar(async_closure); //~ERROR E0277
+}
diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
new file mode 100644
index 000000000..8ed62f854
--- /dev/null
+++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -0,0 +1,43 @@
+error[E0277]: `fn() -> impl Future<Output = ()> {foo}` is not a future
+ --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9
+ |
+LL | bar(foo);
+ | --- ^^^ `fn() -> impl Future<Output = ()> {foo}` is not a future
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
+ = note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `bar`
+ --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
+ |
+LL | fn bar(f: impl Future<Output=()>) {}
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
+help: use parentheses to call this function
+ |
+LL | bar(foo());
+ | ++
+
+error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future
+ --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
+ |
+LL | bar(async_closure);
+ | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
+ = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `bar`
+ --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
+ |
+LL | fn bar(f: impl Future<Output=()>) {}
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
+help: use parentheses to call this closure
+ |
+LL | bar(async_closure());
+ | ++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs
new file mode 100644
index 000000000..7c8231bbb
--- /dev/null
+++ b/tests/ui/suggestions/attribute-typos.rs
@@ -0,0 +1,11 @@
+#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope
+fn foo() {}
+
+#[tests] //~ ERROR cannot find attribute `tests` in this scope
+fn bar() {}
+
+#[rustc_err]
+//~^ ERROR cannot find attribute `rustc_err` in this scope
+//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+
+fn main() {}
diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr
new file mode 100644
index 000000000..b871c9b45
--- /dev/null
+++ b/tests/ui/suggestions/attribute-typos.stderr
@@ -0,0 +1,29 @@
+error: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/attribute-typos.rs:7:3
+ |
+LL | #[rustc_err]
+ | ^^^^^^^^^
+
+error: cannot find attribute `rustc_err` in this scope
+ --> $DIR/attribute-typos.rs:7:3
+ |
+LL | #[rustc_err]
+ | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
+
+error: cannot find attribute `tests` in this scope
+ --> $DIR/attribute-typos.rs:4:3
+ |
+LL | #[tests]
+ | ^^^^^ help: an attribute macro with a similar name exists: `test`
+ --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ |
+ = note: similarly named attribute macro `test` defined here
+
+error: cannot find attribute `deprcated` in this scope
+ --> $DIR/attribute-typos.rs:1:3
+ |
+LL | #[deprcated]
+ | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/suggestions/auxiliary/foo.rs b/tests/ui/suggestions/auxiliary/foo.rs
new file mode 100644
index 000000000..e90bbef6d
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/foo.rs
@@ -0,0 +1,3 @@
+//! Contains a struct with almost the same name as itself, to trigger Levenshtein suggestions.
+
+pub struct Foo;
diff --git a/tests/ui/suggestions/auxiliary/issue-61963-1.rs b/tests/ui/suggestions/auxiliary/issue-61963-1.rs
new file mode 100644
index 000000000..6c2df7e84
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/issue-61963-1.rs
@@ -0,0 +1,40 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{Group, TokenStream, TokenTree};
+
+// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2.
+
+#[proc_macro_derive(DomObject)]
+pub fn expand_token_stream(input: TokenStream) -> TokenStream {
+ // Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because
+ // of the specially crafted generated tokens in the `attribute-crate` proc-macro.
+ let dummy_span = input.clone().into_iter().nth(0).unwrap().span();
+
+ // Define what the macro would output if constructed properly from the source using syn/quote.
+ let output: TokenStream = "impl Bar for ((), Qux<Qux<Baz> >) { }
+ impl Bar for ((), Box<Bar>) { }".parse().unwrap();
+
+ let mut tokens: Vec<_> = output.into_iter().collect();
+ // Adjust token spans to match the original crate (which would use `quote`). Some of the
+ // generated tokens point to the dummy span.
+ for token in tokens.iter_mut() {
+ if let TokenTree::Group(group) = token {
+ let mut tokens: Vec<_> = group.stream().into_iter().collect();
+ for token in tokens.iter_mut().skip(2) {
+ token.set_span(dummy_span);
+ }
+
+ let mut stream = TokenStream::new();
+ stream.extend(tokens);
+ *group = Group::new(group.delimiter(), stream);
+ }
+ }
+
+ let mut output = TokenStream::new();
+ output.extend(tokens);
+ output
+}
diff --git a/tests/ui/suggestions/auxiliary/issue-61963.rs b/tests/ui/suggestions/auxiliary/issue-61963.rs
new file mode 100644
index 000000000..e86f1610a
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/issue-61963.rs
@@ -0,0 +1,41 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream};
+
+// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2.
+
+#[proc_macro_attribute]
+pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream {
+ // Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied.
+ let attributes: TokenStream =
+ "#[derive(DomObject)]".to_string().parse().unwrap();
+ let output: TokenStream = attributes.into_iter()
+ .chain(input.into_iter()).collect();
+
+ let mut tokens: Vec<_> = output.into_iter().collect();
+ // Adjust the spacing of `>` tokens to match what `quote` would produce.
+ for token in tokens.iter_mut() {
+ if let TokenTree::Group(group) = token {
+ let mut tokens: Vec<_> = group.stream().into_iter().collect();
+ for token in tokens.iter_mut() {
+ if let TokenTree::Punct(p) = token {
+ if p.as_char() == '>' {
+ *p = Punct::new('>', Spacing::Alone);
+ }
+ }
+ }
+
+ let mut stream = TokenStream::new();
+ stream.extend(tokens);
+ *group = Group::new(group.delimiter(), stream);
+ }
+ }
+
+ let mut output = TokenStream::new();
+ output.extend(tokens);
+ output
+}
diff --git a/tests/ui/suggestions/auxiliary/issue-81839.rs b/tests/ui/suggestions/auxiliary/issue-81839.rs
new file mode 100644
index 000000000..5683c45ad
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/issue-81839.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+pub struct Test {}
+
+impl Test {
+ pub async fn answer_str(&self, _s: &str) -> Test {
+ Test {}
+ }
+}
diff --git a/tests/ui/suggestions/auxiliary/meow.rs b/tests/ui/suggestions/auxiliary/meow.rs
new file mode 100644
index 000000000..115df70a6
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/meow.rs
@@ -0,0 +1,11 @@
+pub trait Meow {
+ fn meow(&self) {}
+}
+
+pub struct GlobalMeow;
+
+impl Meow for GlobalMeow {}
+
+pub(crate) struct PrivateMeow;
+
+impl Meow for PrivateMeow {}
diff --git a/tests/ui/suggestions/auxiliary/not-object-safe.rs b/tests/ui/suggestions/auxiliary/not-object-safe.rs
new file mode 100644
index 000000000..7c9829b82
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/not-object-safe.rs
@@ -0,0 +1,6 @@
+use std::sync::Arc;
+
+pub trait A {
+ fn f();
+ fn f2(self: &Arc<Self>);
+}
diff --git a/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs
new file mode 100644
index 000000000..d71747f96
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::{quote, TokenStream};
+
+#[proc_macro_attribute]
+pub fn hello(_: TokenStream, _: TokenStream) -> TokenStream {
+ quote!(
+ fn f(_: &mut i32) {}
+ fn g() {
+ f(123);
+ }
+ )
+}
diff --git a/tests/ui/suggestions/bad-hex-float-lit.rs b/tests/ui/suggestions/bad-hex-float-lit.rs
new file mode 100644
index 000000000..cd6fdbde9
--- /dev/null
+++ b/tests/ui/suggestions/bad-hex-float-lit.rs
@@ -0,0 +1,13 @@
+fn main() {
+ let _f: f32 = 0xAAf32;
+ //~^ ERROR mismatched types
+ //~| HELP rewrite this
+
+ let _f: f32 = 0xAB_f32;
+ //~^ ERROR mismatched types
+ //~| HELP rewrite this
+
+ let _f: f64 = 0xFF_f64;
+ //~^ ERROR mismatched types
+ //~| HELP rewrite this
+}
diff --git a/tests/ui/suggestions/bad-hex-float-lit.stderr b/tests/ui/suggestions/bad-hex-float-lit.stderr
new file mode 100644
index 000000000..bc09abb1a
--- /dev/null
+++ b/tests/ui/suggestions/bad-hex-float-lit.stderr
@@ -0,0 +1,48 @@
+error[E0308]: mismatched types
+ --> $DIR/bad-hex-float-lit.rs:2:19
+ |
+LL | let _f: f32 = 0xAAf32;
+ | --- ^^^^^^^ expected `f32`, found integer
+ | |
+ | expected due to this
+ |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+ |
+LL | let _f: f32 = 0xAA as f32;
+ | ~~~~~~~~~~~
+LL | let _f: f32 = 170_f32;
+ | ~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/bad-hex-float-lit.rs:6:19
+ |
+LL | let _f: f32 = 0xAB_f32;
+ | --- ^^^^^^^^ expected `f32`, found integer
+ | |
+ | expected due to this
+ |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+ |
+LL | let _f: f32 = 0xAB as f32;
+ | ~~~~~~~~~~~
+LL | let _f: f32 = 171_f32;
+ | ~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/bad-hex-float-lit.rs:10:19
+ |
+LL | let _f: f64 = 0xFF_f64;
+ | --- ^^^^^^^^ expected `f64`, found integer
+ | |
+ | expected due to this
+ |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+ |
+LL | let _f: f64 = 0xFF as f64;
+ | ~~~~~~~~~~~
+LL | let _f: f64 = 255_f64;
+ | ~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/bool_typo_err_suggest.rs b/tests/ui/suggestions/bool_typo_err_suggest.rs
new file mode 100644
index 000000000..deab0fb05
--- /dev/null
+++ b/tests/ui/suggestions/bool_typo_err_suggest.rs
@@ -0,0 +1,12 @@
+// Suggest the boolean value instead of emit a generic error that the value
+// True is not in the scope.
+
+fn main() {
+ let x = True;
+ //~^ ERROR cannot find value `True` in this scope
+ //~| HELP you may want to use a bool value instead
+
+ let y = False;
+ //~^ ERROR cannot find value `False` in this scope
+ //~| HELP you may want to use a bool value instead
+}
diff --git a/tests/ui/suggestions/bool_typo_err_suggest.stderr b/tests/ui/suggestions/bool_typo_err_suggest.stderr
new file mode 100644
index 000000000..52bde07ca
--- /dev/null
+++ b/tests/ui/suggestions/bool_typo_err_suggest.stderr
@@ -0,0 +1,25 @@
+error[E0425]: cannot find value `True` in this scope
+ --> $DIR/bool_typo_err_suggest.rs:5:13
+ |
+LL | let x = True;
+ | ^^^^ not found in this scope
+ |
+help: you may want to use a bool value instead
+ |
+LL | let x = true;
+ | ~~~~
+
+error[E0425]: cannot find value `False` in this scope
+ --> $DIR/bool_typo_err_suggest.rs:9:13
+ |
+LL | let y = False;
+ | ^^^^^ not found in this scope
+ |
+help: you may want to use a bool value instead
+ |
+LL | let y = false;
+ | ~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/borrow-for-loop-head.rs b/tests/ui/suggestions/borrow-for-loop-head.rs
new file mode 100644
index 000000000..c2bda55e5
--- /dev/null
+++ b/tests/ui/suggestions/borrow-for-loop-head.rs
@@ -0,0 +1,10 @@
+fn main() {
+ let a = vec![1, 2, 3];
+ for i in &a {
+ for j in a {
+ //~^ ERROR cannot move out of `a` because it is borrowed
+ //~| ERROR use of moved value: `a`
+ println!("{} * {} = {}", i, j, i * j);
+ }
+ }
+}
diff --git a/tests/ui/suggestions/borrow-for-loop-head.stderr b/tests/ui/suggestions/borrow-for-loop-head.stderr
new file mode 100644
index 000000000..cbdb94877
--- /dev/null
+++ b/tests/ui/suggestions/borrow-for-loop-head.stderr
@@ -0,0 +1,29 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+ --> $DIR/borrow-for-loop-head.rs:4:18
+ |
+LL | for i in &a {
+ | -- borrow of `a` occurs here
+LL | for j in a {
+ | ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+ --> $DIR/borrow-for-loop-head.rs:4:18
+ |
+LL | let a = vec![1, 2, 3];
+ | - move occurs because `a` has type `Vec<i32>`, which does not implement the `Copy` trait
+LL | for i in &a {
+ | ----------- inside of this loop
+LL | for j in a {
+ | ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
+ |
+note: `into_iter` takes ownership of the receiver `self`, which moves `a`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop
+ |
+LL | for j in &a {
+ | +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/suggestions/bound-suggestions.fixed b/tests/ui/suggestions/bound-suggestions.fixed
new file mode 100644
index 000000000..17a019c69
--- /dev/null
+++ b/tests/ui/suggestions/bound-suggestions.fixed
@@ -0,0 +1,68 @@
+// run-rustfix
+
+#[allow(unused)]
+use std::fmt::Debug;
+// Rustfix should add this, or use `std::fmt::Debug` instead.
+
+#[allow(dead_code)]
+fn test_impl(t: impl Sized + std::fmt::Debug) {
+ println!("{:?}", t);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_no_bounds<T: std::fmt::Debug>(t: T) {
+ println!("{:?}", t);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) {
+ println!("{:?}", t);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug {
+ println!("{:?} {:?}", x, y);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug {
+ println!("{:?}", x);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized {
+ println!("{:?}", x);
+ //~^ ERROR doesn't implement
+}
+
+trait Foo<T>: Sized {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Bar: std::fmt::Display + Sized {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Baz: Sized where Self: std::fmt::Display {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Qux<T>: Sized where Self: std::fmt::Display {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Bat<T>: std::fmt::Display + Sized {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/bound-suggestions.rs b/tests/ui/suggestions/bound-suggestions.rs
new file mode 100644
index 000000000..86f708d42
--- /dev/null
+++ b/tests/ui/suggestions/bound-suggestions.rs
@@ -0,0 +1,68 @@
+// run-rustfix
+
+#[allow(unused)]
+use std::fmt::Debug;
+// Rustfix should add this, or use `std::fmt::Debug` instead.
+
+#[allow(dead_code)]
+fn test_impl(t: impl Sized) {
+ println!("{:?}", t);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_no_bounds<T>(t: T) {
+ println!("{:?}", t);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_one_bound<T: Sized>(t: T) {
+ println!("{:?}", t);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, {
+ println!("{:?} {:?}", x, y);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_one_bound_where<X>(x: X) where X: Sized {
+ println!("{:?}", x);
+ //~^ ERROR doesn't implement
+}
+
+#[allow(dead_code)]
+fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized {
+ println!("{:?}", x);
+ //~^ ERROR doesn't implement
+}
+
+trait Foo<T> {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Bar: std::fmt::Display {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Baz where Self: std::fmt::Display {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Qux<T> where Self: std::fmt::Display {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+trait Bat<T>: std::fmt::Display {
+ const SIZE: usize = core::mem::size_of::<Self>();
+ //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr
new file mode 100644
index 000000000..cd27947f0
--- /dev/null
+++ b/tests/ui/suggestions/bound-suggestions.stderr
@@ -0,0 +1,140 @@
+error[E0277]: `impl Sized` doesn't implement `Debug`
+ --> $DIR/bound-suggestions.rs:9:22
+ |
+LL | println!("{:?}", t);
+ | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+LL | fn test_impl(t: impl Sized + std::fmt::Debug) {
+ | +++++++++++++++++
+
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/bound-suggestions.rs:15:22
+ |
+LL | println!("{:?}", t);
+ | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | fn test_no_bounds<T: std::fmt::Debug>(t: T) {
+ | +++++++++++++++++
+
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/bound-suggestions.rs:21:22
+ |
+LL | println!("{:?}", t);
+ | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+LL | fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) {
+ | +++++++++++++++++
+
+error[E0277]: `Y` doesn't implement `Debug`
+ --> $DIR/bound-suggestions.rs:27:30
+ |
+LL | println!("{:?} {:?}", x, y);
+ | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting type parameter `Y`
+ |
+LL | fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug {
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error[E0277]: `X` doesn't implement `Debug`
+ --> $DIR/bound-suggestions.rs:33:22
+ |
+LL | println!("{:?}", x);
+ | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+LL | fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug {
+ | +++++++++++++++++
+
+error[E0277]: `X` doesn't implement `Debug`
+ --> $DIR/bound-suggestions.rs:39:22
+ |
+LL | println!("{:?}", x);
+ | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+LL | fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized {
+ | +++++++++++++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/bound-suggestions.rs:44:46
+ |
+LL | const SIZE: usize = core::mem::size_of::<Self>();
+ | ^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider further restricting `Self`
+ |
+LL | trait Foo<T>: Sized {
+ | +++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/bound-suggestions.rs:49:46
+ |
+LL | const SIZE: usize = core::mem::size_of::<Self>();
+ | ^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider further restricting `Self`
+ |
+LL | trait Bar: std::fmt::Display + Sized {
+ | +++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/bound-suggestions.rs:54:46
+ |
+LL | const SIZE: usize = core::mem::size_of::<Self>();
+ | ^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider further restricting `Self`
+ |
+LL | trait Baz: Sized where Self: std::fmt::Display {
+ | +++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/bound-suggestions.rs:59:46
+ |
+LL | const SIZE: usize = core::mem::size_of::<Self>();
+ | ^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider further restricting `Self`
+ |
+LL | trait Qux<T>: Sized where Self: std::fmt::Display {
+ | +++++++
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/bound-suggestions.rs:64:46
+ |
+LL | const SIZE: usize = core::mem::size_of::<Self>();
+ | ^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider further restricting `Self`
+ |
+LL | trait Bat<T>: std::fmt::Display + Sized {
+ | +++++++
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/box-future-wrong-output.rs b/tests/ui/suggestions/box-future-wrong-output.rs
new file mode 100644
index 000000000..d49819fcb
--- /dev/null
+++ b/tests/ui/suggestions/box-future-wrong-output.rs
@@ -0,0 +1,22 @@
+// Issue #72117
+// edition:2018
+
+use core::future::Future;
+use core::pin::Pin;
+
+pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
+
+impl<T: ?Sized> FutureExt for T where T: Future {}
+trait FutureExt: Future {
+ fn boxed<'a>(self) -> BoxFuture<'a, Self::Output>
+ where
+ Self: Sized + Send + 'a,
+ {
+ Box::pin(self)
+ }
+}
+
+fn main() {
+ let _: BoxFuture<'static, bool> = async {}.boxed();
+ //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/suggestions/box-future-wrong-output.stderr b/tests/ui/suggestions/box-future-wrong-output.stderr
new file mode 100644
index 000000000..e0c57af25
--- /dev/null
+++ b/tests/ui/suggestions/box-future-wrong-output.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/box-future-wrong-output.rs:20:39
+ |
+LL | let _: BoxFuture<'static, bool> = async {}.boxed();
+ | ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `Pin<Box<(dyn Future<Output = bool> + Send + 'static)>>`
+ found struct `Pin<Box<dyn Future<Output = ()> + Send>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/boxed-variant-field.rs b/tests/ui/suggestions/boxed-variant-field.rs
new file mode 100644
index 000000000..6050963c4
--- /dev/null
+++ b/tests/ui/suggestions/boxed-variant-field.rs
@@ -0,0 +1,15 @@
+enum Ty {
+ Unit,
+ List(Box<Ty>),
+}
+
+fn foo(x: Ty) -> Ty {
+ match x {
+ Ty::Unit => Ty::Unit,
+ Ty::List(elem) => foo(elem),
+ //~^ ERROR mismatched types
+ //~| HELP consider unboxing the value
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/boxed-variant-field.stderr b/tests/ui/suggestions/boxed-variant-field.stderr
new file mode 100644
index 000000000..9ae36a06a
--- /dev/null
+++ b/tests/ui/suggestions/boxed-variant-field.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+ --> $DIR/boxed-variant-field.rs:9:31
+ |
+LL | Ty::List(elem) => foo(elem),
+ | --- ^^^^ expected enum `Ty`, found struct `Box`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Ty`
+ found struct `Box<Ty>`
+note: function defined here
+ --> $DIR/boxed-variant-field.rs:6:4
+ |
+LL | fn foo(x: Ty) -> Ty {
+ | ^^^ -----
+help: consider unboxing the value
+ |
+LL | Ty::List(elem) => foo(*elem),
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/call-boxed.rs b/tests/ui/suggestions/call-boxed.rs
new file mode 100644
index 000000000..d19e4596a
--- /dev/null
+++ b/tests/ui/suggestions/call-boxed.rs
@@ -0,0 +1,7 @@
+fn main() {
+ let mut x = 1i32;
+ let y = Box::new(|| 1);
+ x = y;
+ //~^ ERROR mismatched types
+ //~| HELP use parentheses to call this closure
+}
diff --git a/tests/ui/suggestions/call-boxed.stderr b/tests/ui/suggestions/call-boxed.stderr
new file mode 100644
index 000000000..9b619ac9a
--- /dev/null
+++ b/tests/ui/suggestions/call-boxed.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/call-boxed.rs:4:9
+ |
+LL | let mut x = 1i32;
+ | ---- expected due to this value
+LL | let y = Box::new(|| 1);
+ | -- the found closure
+LL | x = y;
+ | ^ expected `i32`, found struct `Box`
+ |
+ = note: expected type `i32`
+ found struct `Box<[closure@$DIR/call-boxed.rs:3:22: 3:24]>`
+help: use parentheses to call this closure
+ |
+LL | x = y();
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/call-on-missing.rs b/tests/ui/suggestions/call-on-missing.rs
new file mode 100644
index 000000000..25ced84dd
--- /dev/null
+++ b/tests/ui/suggestions/call-on-missing.rs
@@ -0,0 +1,39 @@
+struct Foo { i: i32 }
+
+impl Foo {
+ fn bar(&self) {}
+}
+
+fn foo() -> Foo {
+ Foo { i: 1 }
+}
+
+fn main() {
+ foo.bar();
+ //~^ ERROR no method named `bar`
+ //~| HELP use parentheses to call this function
+
+ foo.i;
+ //~^ ERROR no field `i`
+ //~| HELP use parentheses to call this function
+
+ let callable = Box::new(|| Foo { i: 1 }) as Box<dyn Fn() -> Foo>;
+
+ callable.bar();
+ //~^ ERROR no method named `bar`
+ //~| HELP use parentheses to call this trait object
+
+ callable.i;
+ //~^ ERROR no field `i`
+ //~| HELP use parentheses to call this trait object
+}
+
+fn type_param<T: Fn() -> Foo>(t: T) {
+ t.bar();
+ //~^ ERROR no method named `bar`
+ //~| HELP use parentheses to call this type parameter
+
+ t.i;
+ //~^ ERROR no field `i`
+ //~| HELP use parentheses to call this type parameter
+}
diff --git a/tests/ui/suggestions/call-on-missing.stderr b/tests/ui/suggestions/call-on-missing.stderr
new file mode 100644
index 000000000..ca9abc7e9
--- /dev/null
+++ b/tests/ui/suggestions/call-on-missing.stderr
@@ -0,0 +1,75 @@
+error[E0599]: no method named `bar` found for fn item `fn() -> Foo {foo}` in the current scope
+ --> $DIR/call-on-missing.rs:12:9
+ |
+LL | foo.bar();
+ | ^^^ method not found in `fn() -> Foo {foo}`
+ |
+help: use parentheses to call this function
+ |
+LL | foo().bar();
+ | ++
+
+error[E0609]: no field `i` on type `fn() -> Foo {foo}`
+ --> $DIR/call-on-missing.rs:16:9
+ |
+LL | foo.i;
+ | ^
+ |
+help: use parentheses to call this function
+ |
+LL | foo().i;
+ | ++
+
+error[E0599]: no method named `bar` found for struct `Box<dyn Fn() -> Foo>` in the current scope
+ --> $DIR/call-on-missing.rs:22:14
+ |
+LL | callable.bar();
+ | ^^^ method not found in `Box<dyn Fn() -> Foo>`
+ |
+help: use parentheses to call this trait object
+ |
+LL | callable().bar();
+ | ++
+
+error[E0609]: no field `i` on type `Box<dyn Fn() -> Foo>`
+ --> $DIR/call-on-missing.rs:26:14
+ |
+LL | callable.i;
+ | ^ unknown field
+ |
+help: use parentheses to call this trait object
+ |
+LL | callable().i;
+ | ++
+
+error[E0599]: no method named `bar` found for type parameter `T` in the current scope
+ --> $DIR/call-on-missing.rs:32:7
+ |
+LL | fn type_param<T: Fn() -> Foo>(t: T) {
+ | - method `bar` not found for this type parameter
+LL | t.bar();
+ | ^^^ method not found in `T`
+ |
+help: use parentheses to call this type parameter
+ |
+LL | t().bar();
+ | ++
+
+error[E0609]: no field `i` on type `T`
+ --> $DIR/call-on-missing.rs:36:7
+ |
+LL | fn type_param<T: Fn() -> Foo>(t: T) {
+ | - type parameter 'T' declared here
+...
+LL | t.i;
+ | ^
+ |
+help: use parentheses to call this type parameter
+ |
+LL | t().i;
+ | ++
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0599, E0609.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/call-on-unimplemented-ctor.rs b/tests/ui/suggestions/call-on-unimplemented-ctor.rs
new file mode 100644
index 000000000..5f811044e
--- /dev/null
+++ b/tests/ui/suggestions/call-on-unimplemented-ctor.rs
@@ -0,0 +1,17 @@
+fn main() {
+ insert_resource(Marker);
+ insert_resource(Time);
+ //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
+ //~| HELP use parentheses to construct this tuple struct
+}
+
+trait Resource {}
+
+fn insert_resource<R: Resource>(resource: R) {}
+
+struct Marker;
+impl Resource for Marker {}
+
+struct Time(u32);
+
+impl Resource for Time {}
diff --git a/tests/ui/suggestions/call-on-unimplemented-ctor.stderr b/tests/ui/suggestions/call-on-unimplemented-ctor.stderr
new file mode 100644
index 000000000..58612cbfb
--- /dev/null
+++ b/tests/ui/suggestions/call-on-unimplemented-ctor.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
+ --> $DIR/call-on-unimplemented-ctor.rs:3:21
+ |
+LL | insert_resource(Time);
+ | --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `insert_resource`
+ --> $DIR/call-on-unimplemented-ctor.rs:10:23
+ |
+LL | fn insert_resource<R: Resource>(resource: R) {}
+ | ^^^^^^^^ required by this bound in `insert_resource`
+help: use parentheses to construct this tuple struct
+ |
+LL | insert_resource(Time(/* u32 */));
+ | +++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs
new file mode 100644
index 000000000..86490c724
--- /dev/null
+++ b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs
@@ -0,0 +1,15 @@
+struct Foo;
+
+trait Bar {}
+
+impl Bar for Foo {}
+
+fn needs_bar<T: Bar>(_: T) {}
+
+fn blah(f: fn() -> Foo) {
+ needs_bar(f);
+ //~^ ERROR the trait bound `fn() -> Foo: Bar` is not satisfied
+ //~| HELP use parentheses to call this function pointer
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr
new file mode 100644
index 000000000..167f7e592
--- /dev/null
+++ b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `fn() -> Foo: Bar` is not satisfied
+ --> $DIR/call-on-unimplemented-fn-ptr.rs:10:15
+ |
+LL | needs_bar(f);
+ | --------- ^ the trait `Bar` is not implemented for `fn() -> Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `needs_bar`
+ --> $DIR/call-on-unimplemented-fn-ptr.rs:7:17
+ |
+LL | fn needs_bar<T: Bar>(_: T) {}
+ | ^^^ required by this bound in `needs_bar`
+help: use parentheses to call this function pointer
+ |
+LL | needs_bar(f());
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs
new file mode 100644
index 000000000..9021dd752
--- /dev/null
+++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs
@@ -0,0 +1,13 @@
+trait Foo {}
+
+impl Foo for i32 {}
+
+fn needs_foo(_: impl Foo) {}
+
+fn test(x: &Box<dyn Fn() -> i32>) {
+ needs_foo(x);
+ //~^ ERROR the trait bound
+ //~| HELP use parentheses to call this trait object
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr
new file mode 100644
index 000000000..90f44cce0
--- /dev/null
+++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `&Box<dyn Fn() -> i32>: Foo` is not satisfied
+ --> $DIR/call-on-unimplemented-with-autoderef.rs:8:15
+ |
+LL | needs_foo(x);
+ | --------- ^ the trait `Foo` is not implemented for `&Box<dyn Fn() -> i32>`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `needs_foo`
+ --> $DIR/call-on-unimplemented-with-autoderef.rs:5:22
+ |
+LL | fn needs_foo(_: impl Foo) {}
+ | ^^^ required by this bound in `needs_foo`
+help: use parentheses to call this trait object
+ |
+LL | needs_foo(x());
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.rs b/tests/ui/suggestions/chain-method-call-mutation-in-place.rs
new file mode 100644
index 000000000..cb92ab87a
--- /dev/null
+++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.rs
@@ -0,0 +1,4 @@
+fn main() {}
+fn foo(mut s: String) -> String {
+ s.push_str("asdf") //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
new file mode 100644
index 000000000..965dbb967
--- /dev/null
+++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/chain-method-call-mutation-in-place.rs:3:5
+ |
+LL | fn foo(mut s: String) -> String {
+ | ------ expected `String` because of return type
+LL | s.push_str("asdf")
+ | ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `()`
+ |
+note: method `push_str` modifies its receiver in-place
+ --> $DIR/chain-method-call-mutation-in-place.rs:3:7
+ |
+LL | s.push_str("asdf")
+ | - ^^^^^^^^ this call modifies `s` in-place
+ | |
+ | you probably want to use this value after calling the method...
+ = note: ...instead of the `()` output of method `push_str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
new file mode 100644
index 000000000..4f9e93a47
--- /dev/null
+++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+fn wat<T: Clone>(t: &T) -> T {
+ t.clone() //~ ERROR E0308
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+ t.clone() //~ ERROR E0308
+}
+
+fn main() {
+ wat(&42);
+ wut(&Foo);
+}
diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
new file mode 100644
index 000000000..89b077d67
--- /dev/null
+++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+fn wat<T>(t: &T) -> T {
+ t.clone() //~ ERROR E0308
+}
+
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+ t.clone() //~ ERROR E0308
+}
+
+fn main() {
+ wat(&42);
+ wut(&Foo);
+}
diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
new file mode 100644
index 000000000..26ab515d9
--- /dev/null
+++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
@@ -0,0 +1,43 @@
+error[E0308]: mismatched types
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+ |
+LL | fn wat<T>(t: &T) -> T {
+ | - - expected `T` because of return type
+ | |
+ | this type parameter
+LL | t.clone()
+ | ^^^^^^^^^ expected type parameter `T`, found `&T`
+ |
+ = note: expected type parameter `T`
+ found reference `&T`
+note: `T` does not implement `Clone`, so `&T` was cloned instead
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+ |
+LL | t.clone()
+ | ^
+help: consider restricting type parameter `T`
+ |
+LL | fn wat<T: Clone>(t: &T) -> T {
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+ |
+LL | fn wut(t: &Foo) -> Foo {
+ | --- expected `Foo` because of return type
+LL | t.clone()
+ | ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+ |
+note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+ |
+LL | t.clone()
+ | ^
+help: consider annotating `Foo` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/const-in-struct-pat.rs b/tests/ui/suggestions/const-in-struct-pat.rs
new file mode 100644
index 000000000..1cbba9354
--- /dev/null
+++ b/tests/ui/suggestions/const-in-struct-pat.rs
@@ -0,0 +1,11 @@
+#[allow(non_camel_case_types)]
+struct foo;
+struct Thing {
+ foo: String,
+}
+
+fn example(t: Thing) {
+ let Thing { foo } = t; //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/const-in-struct-pat.stderr b/tests/ui/suggestions/const-in-struct-pat.stderr
new file mode 100644
index 000000000..c8b93f3dc
--- /dev/null
+++ b/tests/ui/suggestions/const-in-struct-pat.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/const-in-struct-pat.rs:8:17
+ |
+LL | struct foo;
+ | ---------- unit struct defined here
+...
+LL | let Thing { foo } = t;
+ | ^^^ - this expression has type `Thing`
+ | |
+ | expected struct `String`, found struct `foo`
+ | `foo` is interpreted as a unit struct, not a new binding
+ |
+help: bind the struct field to a different name instead
+ |
+LL | let Thing { foo: other_foo } = t;
+ | +++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/const-no-type.rs b/tests/ui/suggestions/const-no-type.rs
new file mode 100644
index 000000000..c6fdcdadb
--- /dev/null
+++ b/tests/ui/suggestions/const-no-type.rs
@@ -0,0 +1,51 @@
+// In the cases below, the type is missing from the `const` and `static` items.
+//
+// Here, we test that we:
+//
+// a) Perform parser recovery.
+//
+// b) Emit a diagnostic with the actual inferred type to RHS of `=` as the suggestion.
+
+fn main() {}
+
+// These will not reach typeck:
+
+#[cfg(FALSE)]
+const C2 = 42;
+//~^ ERROR missing type for `const` item
+//~| HELP provide a type for the item
+//~| SUGGESTION : <type>
+
+#[cfg(FALSE)]
+static S2 = "abc";
+//~^ ERROR missing type for `static` item
+//~| HELP provide a type for the item
+//~| SUGGESTION : <type>
+
+#[cfg(FALSE)]
+static mut SM2 = "abc";
+//~^ ERROR missing type for `static mut` item
+//~| HELP provide a type for the item
+//~| SUGGESTION : <type>
+
+// These will, so the diagnostics should be stolen by typeck:
+
+const C = 42;
+//~^ ERROR missing type for `const` item
+//~| HELP provide a type for the constant
+//~| SUGGESTION : i32
+
+const D = &&42;
+//~^ ERROR missing type for `const` item
+//~| HELP provide a type for the constant
+//~| SUGGESTION : &&i32
+
+static S = Vec::<String>::new();
+//~^ ERROR missing type for `static` item
+//~| HELP provide a type for the static variable
+//~| SUGGESTION : Vec<String>
+
+static mut SM = "abc";
+//~^ ERROR missing type for `static mut` item
+//~| HELP provide a type for the static variable
+//~| SUGGESTION : &str
diff --git a/tests/ui/suggestions/const-no-type.stderr b/tests/ui/suggestions/const-no-type.stderr
new file mode 100644
index 000000000..bd703992f
--- /dev/null
+++ b/tests/ui/suggestions/const-no-type.stderr
@@ -0,0 +1,44 @@
+error: missing type for `const` item
+ --> $DIR/const-no-type.rs:33:8
+ |
+LL | const C = 42;
+ | ^ help: provide a type for the constant: `: i32`
+
+error: missing type for `const` item
+ --> $DIR/const-no-type.rs:38:8
+ |
+LL | const D = &&42;
+ | ^ help: provide a type for the constant: `: &&i32`
+
+error: missing type for `static` item
+ --> $DIR/const-no-type.rs:43:9
+ |
+LL | static S = Vec::<String>::new();
+ | ^ help: provide a type for the static variable: `: Vec<String>`
+
+error: missing type for `static mut` item
+ --> $DIR/const-no-type.rs:48:14
+ |
+LL | static mut SM = "abc";
+ | ^ help: provide a type for the static variable: `: &str`
+
+error: missing type for `const` item
+ --> $DIR/const-no-type.rs:14:9
+ |
+LL | const C2 = 42;
+ | ^ help: provide a type for the item: `: <type>`
+
+error: missing type for `static` item
+ --> $DIR/const-no-type.rs:20:10
+ |
+LL | static S2 = "abc";
+ | ^ help: provide a type for the item: `: <type>`
+
+error: missing type for `static mut` item
+ --> $DIR/const-no-type.rs:26:15
+ |
+LL | static mut SM2 = "abc";
+ | ^ help: provide a type for the item: `: <type>`
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
new file mode 100644
index 000000000..15f08486f
--- /dev/null
+++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
@@ -0,0 +1,11 @@
+fn main() {
+ let A = 3;
+ //~^ ERROR refutable pattern in local binding
+ //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
+ //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
+ //~| HELP introduce a variable instead
+ //~| SUGGESTION a_var
+
+ const A: i32 = 2;
+ //~^ constant defined here
+}
diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
new file mode 100644
index 000000000..1c1cab25f
--- /dev/null
+++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
@@ -0,0 +1,18 @@
+error[E0005]: refutable pattern in local binding
+ --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
+ |
+LL | let A = 3;
+ | ^
+ | |
+ | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
+ | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
+ | help: introduce a variable instead: `a_var`
+...
+LL | const A: i32 = 2;
+ | ------------ constant defined here
+ |
+ = note: the matched value is of type `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/suggestions/constrain-suggest-ice.rs b/tests/ui/suggestions/constrain-suggest-ice.rs
new file mode 100644
index 000000000..69b874bed
--- /dev/null
+++ b/tests/ui/suggestions/constrain-suggest-ice.rs
@@ -0,0 +1,11 @@
+struct Bug<S>{ //~ ERROR parameter `S` is never used [E0392]
+ A: [(); {
+ let x: [u8; Self::W] = [0; Self::W]; //~ ERROR generic `Self` types are currently not permitted in anonymous constants
+ //~^ ERROR generic `Self` types are currently not permitted in anonymous constants
+ //~^^ ERROR the size for values of type `S` cannot be known at compilation time [E0277]
+ F //~ ERROR cannot find value `F` in this scope [E0425]
+ }
+} //~ ERROR mismatched closing delimiter: `}`
+//~^ ERROR mismatched closing delimiter: `}`
+
+fn main() {}
diff --git a/tests/ui/suggestions/constrain-suggest-ice.stderr b/tests/ui/suggestions/constrain-suggest-ice.stderr
new file mode 100644
index 000000000..2af7c2f69
--- /dev/null
+++ b/tests/ui/suggestions/constrain-suggest-ice.stderr
@@ -0,0 +1,72 @@
+error: mismatched closing delimiter: `}`
+ --> $DIR/constrain-suggest-ice.rs:2:8
+ |
+LL | struct Bug<S>{
+ | - closing delimiter possibly meant for this
+LL | A: [(); {
+ | ^ unclosed delimiter
+...
+LL | }
+ | ^ mismatched closing delimiter
+
+error: mismatched closing delimiter: `}`
+ --> $DIR/constrain-suggest-ice.rs:2:8
+ |
+LL | struct Bug<S>{
+ | - closing delimiter possibly meant for this
+LL | A: [(); {
+ | ^ unclosed delimiter
+...
+LL | }
+ | ^ mismatched closing delimiter
+
+error[E0425]: cannot find value `F` in this scope
+ --> $DIR/constrain-suggest-ice.rs:6:9
+ |
+LL | F
+ | ^ help: a local variable with a similar name exists: `x`
+
+error: generic `Self` types are currently not permitted in anonymous constants
+ --> $DIR/constrain-suggest-ice.rs:3:21
+ |
+LL | let x: [u8; Self::W] = [0; Self::W];
+ | ^^^^
+
+error: generic `Self` types are currently not permitted in anonymous constants
+ --> $DIR/constrain-suggest-ice.rs:3:36
+ |
+LL | let x: [u8; Self::W] = [0; Self::W];
+ | ^^^^
+
+error[E0277]: the size for values of type `S` cannot be known at compilation time
+ --> $DIR/constrain-suggest-ice.rs:3:36
+ |
+LL | struct Bug<S>{
+ | - this type parameter needs to be `std::marker::Sized`
+LL | A: [(); {
+LL | let x: [u8; Self::W] = [0; Self::W];
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `Bug`
+ --> $DIR/constrain-suggest-ice.rs:1:12
+ |
+LL | struct Bug<S>{
+ | ^ required by this bound in `Bug`
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | struct Bug<S: ?Sized>{
+ | ++++++++
+
+error[E0392]: parameter `S` is never used
+ --> $DIR/constrain-suggest-ice.rs:1:12
+ |
+LL | struct Bug<S>{
+ | ^ unused parameter
+ |
+ = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+ = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0277, E0392, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/constrain-trait.fixed b/tests/ui/suggestions/constrain-trait.fixed
new file mode 100644
index 000000000..f292f27f0
--- /dev/null
+++ b/tests/ui/suggestions/constrain-trait.fixed
@@ -0,0 +1,47 @@
+// run-rustfix
+// check-only
+
+#[derive(Debug)]
+struct Demo {
+ a: String
+}
+
+trait GetString {
+ fn get_a(&self) -> &String;
+}
+
+trait UseString: std::fmt::Debug + GetString {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
+ }
+}
+
+trait UseString2: GetString {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
+ }
+}
+
+impl GetString for Demo {
+ fn get_a(&self) -> &String {
+ &self.a
+ }
+}
+
+impl UseString for Demo {}
+impl UseString2 for Demo {}
+
+
+#[cfg(test)]
+mod tests {
+ use crate::{Demo, UseString};
+
+ #[test]
+ fn it_works() {
+ let d = Demo { a: "test".to_string() };
+ d.use_string();
+ }
+}
+
+
+fn main() {}
diff --git a/tests/ui/suggestions/constrain-trait.rs b/tests/ui/suggestions/constrain-trait.rs
new file mode 100644
index 000000000..99ccf7a7f
--- /dev/null
+++ b/tests/ui/suggestions/constrain-trait.rs
@@ -0,0 +1,47 @@
+// run-rustfix
+// check-only
+
+#[derive(Debug)]
+struct Demo {
+ a: String
+}
+
+trait GetString {
+ fn get_a(&self) -> &String;
+}
+
+trait UseString: std::fmt::Debug {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
+ }
+}
+
+trait UseString2 {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
+ }
+}
+
+impl GetString for Demo {
+ fn get_a(&self) -> &String {
+ &self.a
+ }
+}
+
+impl UseString for Demo {}
+impl UseString2 for Demo {}
+
+
+#[cfg(test)]
+mod tests {
+ use crate::{Demo, UseString};
+
+ #[test]
+ fn it_works() {
+ let d = Demo { a: "test".to_string() };
+ d.use_string();
+ }
+}
+
+
+fn main() {}
diff --git a/tests/ui/suggestions/constrain-trait.stderr b/tests/ui/suggestions/constrain-trait.stderr
new file mode 100644
index 000000000..a26f86917
--- /dev/null
+++ b/tests/ui/suggestions/constrain-trait.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
+ --> $DIR/constrain-trait.rs:15:31
+ |
+LL | println!("{:?}", self.get_a());
+ | ^^^^^ method not found in `&Self`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `get_a`, perhaps you need to add another supertrait for it:
+ |
+LL | trait UseString: std::fmt::Debug + GetString {
+ | +++++++++++
+
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
+ --> $DIR/constrain-trait.rs:21:31
+ |
+LL | println!("{:?}", self.get_a());
+ | ^^^^^ method not found in `&Self`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `get_a`, perhaps you need to add a supertrait for it:
+ |
+LL | trait UseString2: GetString {
+ | +++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/copied-and-cloned.fixed b/tests/ui/suggestions/copied-and-cloned.fixed
new file mode 100644
index 000000000..f801403fe
--- /dev/null
+++ b/tests/ui/suggestions/copied-and-cloned.fixed
@@ -0,0 +1,23 @@
+// run-rustfix
+
+fn expect<T>(_: T) {}
+
+fn main() {
+ let x = Some(&());
+ expect::<Option<()>>(x.copied());
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::copied` to copy the value inside the `Option`
+ let x = Ok(&());
+ expect::<Result<(), ()>>(x.copied());
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::copied` to copy the value inside the `Result`
+ let s = String::new();
+ let x = Some(&s);
+ expect::<Option<String>>(x.cloned());
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::cloned` to clone the value inside the `Option`
+ let x = Ok(&s);
+ expect::<Result<String, ()>>(x.cloned());
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::cloned` to clone the value inside the `Result`
+}
diff --git a/tests/ui/suggestions/copied-and-cloned.rs b/tests/ui/suggestions/copied-and-cloned.rs
new file mode 100644
index 000000000..640450b76
--- /dev/null
+++ b/tests/ui/suggestions/copied-and-cloned.rs
@@ -0,0 +1,23 @@
+// run-rustfix
+
+fn expect<T>(_: T) {}
+
+fn main() {
+ let x = Some(&());
+ expect::<Option<()>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::copied` to copy the value inside the `Option`
+ let x = Ok(&());
+ expect::<Result<(), ()>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::copied` to copy the value inside the `Result`
+ let s = String::new();
+ let x = Some(&s);
+ expect::<Option<String>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::cloned` to clone the value inside the `Option`
+ let x = Ok(&s);
+ expect::<Result<String, ()>>(x);
+ //~^ ERROR mismatched types
+ //~| HELP use `Result::cloned` to clone the value inside the `Result`
+}
diff --git a/tests/ui/suggestions/copied-and-cloned.stderr b/tests/ui/suggestions/copied-and-cloned.stderr
new file mode 100644
index 000000000..a6336281b
--- /dev/null
+++ b/tests/ui/suggestions/copied-and-cloned.stderr
@@ -0,0 +1,83 @@
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:7:26
+ |
+LL | expect::<Option<()>>(x);
+ | -------------------- ^ expected `()`, found `&()`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<()>`
+ found enum `Option<&()>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Option::copied` to copy the value inside the `Option`
+ |
+LL | expect::<Option<()>>(x.copied());
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:11:30
+ |
+LL | expect::<Result<(), ()>>(x);
+ | ------------------------ ^ expected `()`, found `&()`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Result<(), ()>`
+ found enum `Result<&(), _>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Result::copied` to copy the value inside the `Result`
+ |
+LL | expect::<Result<(), ()>>(x.copied());
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:16:30
+ |
+LL | expect::<Option<String>>(x);
+ | ------------------------ ^ expected struct `String`, found `&String`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<String>`
+ found enum `Option<&String>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Option::cloned` to clone the value inside the `Option`
+ |
+LL | expect::<Option<String>>(x.cloned());
+ | +++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/copied-and-cloned.rs:20:34
+ |
+LL | expect::<Result<String, ()>>(x);
+ | ---------------------------- ^ expected struct `String`, found `&String`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Result<String, ()>`
+ found enum `Result<&String, _>`
+note: function defined here
+ --> $DIR/copied-and-cloned.rs:3:4
+ |
+LL | fn expect<T>(_: T) {}
+ | ^^^^^^ ----
+help: use `Result::cloned` to clone the value inside the `Result`
+ |
+LL | expect::<Result<String, ()>>(x.cloned());
+ | +++++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.rs b/tests/ui/suggestions/core-std-import-order-issue-83564.rs
new file mode 100644
index 000000000..b7fe5af7b
--- /dev/null
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+// This is a regression test for #83564.
+// For some reason, Rust 2018 or higher is required to reproduce the bug.
+
+fn main() {
+ //~^ HELP consider importing one of these items
+ let _x = NonZeroU32::new(5).unwrap();
+ //~^ ERROR failed to resolve: use of undeclared type `NonZeroU32`
+}
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.stderr
new file mode 100644
index 000000000..e4e1fc591
--- /dev/null
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.stderr
@@ -0,0 +1,16 @@
+error[E0433]: failed to resolve: use of undeclared type `NonZeroU32`
+ --> $DIR/core-std-import-order-issue-83564.rs:8:14
+ |
+LL | let _x = NonZeroU32::new(5).unwrap();
+ | ^^^^^^^^^^ use of undeclared type `NonZeroU32`
+ |
+help: consider importing one of these items
+ |
+LL | use core::num::NonZeroU32;
+ |
+LL | use std::num::NonZeroU32;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/suggestions/count2len.rs b/tests/ui/suggestions/count2len.rs
new file mode 100644
index 000000000..f11a789ef
--- /dev/null
+++ b/tests/ui/suggestions/count2len.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let slice = [1,2,3,4];
+ let vec = vec![1,2,3,4];
+
+ slice.count(); //~ERROR: E0599
+ vec.count(); //~ERROR: E0599
+ vec.as_slice().count(); //~ERROR: E0599
+}
diff --git a/tests/ui/suggestions/count2len.stderr b/tests/ui/suggestions/count2len.stderr
new file mode 100644
index 000000000..6394a84dd
--- /dev/null
+++ b/tests/ui/suggestions/count2len.stderr
@@ -0,0 +1,36 @@
+error[E0599]: no method named `count` found for array `[{integer}; 4]` in the current scope
+ --> $DIR/count2len.rs:5:11
+ |
+LL | slice.count();
+ | ^^^^^
+ | |
+ | method cannot be called on `[{integer}; 4]` due to unsatisfied trait bounds
+ | help: consider using `len` instead
+ |
+ = note: `count` is defined on `Iterator`, which `[{integer}; 4]` does not implement
+
+error[E0599]: no method named `count` found for struct `Vec<{integer}>` in the current scope
+ --> $DIR/count2len.rs:6:9
+ |
+LL | vec.count();
+ | ^^^^^
+ | |
+ | method cannot be called on `Vec<{integer}>` due to unsatisfied trait bounds
+ | help: consider using `len` instead
+ |
+ = note: `count` is defined on `Iterator`, which `Vec<{integer}>` does not implement
+
+error[E0599]: no method named `count` found for reference `&[{integer}]` in the current scope
+ --> $DIR/count2len.rs:7:20
+ |
+LL | vec.as_slice().count();
+ | ^^^^^
+ | |
+ | method cannot be called on `&[{integer}]` due to unsatisfied trait bounds
+ | help: consider using `len` instead
+ |
+ = note: `count` is defined on `Iterator`, which `&[{integer}]` does not implement
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/crate-or-module-typo.rs b/tests/ui/suggestions/crate-or-module-typo.rs
new file mode 100644
index 000000000..2471b11c6
--- /dev/null
+++ b/tests/ui/suggestions/crate-or-module-typo.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+use st::cell::Cell; //~ ERROR failed to resolve: use of undeclared crate or module `st`
+
+mod bar {
+ pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `bar`
+
+ fn baz() {}
+}
+
+use bas::bar; //~ ERROR unresolved import `bas`
+
+struct Foo {
+ bar: st::cell::Cell<bool> //~ ERROR failed to resolve: use of undeclared crate or module `st`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr
new file mode 100644
index 000000000..98b88b4fb
--- /dev/null
+++ b/tests/ui/suggestions/crate-or-module-typo.stderr
@@ -0,0 +1,43 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `st`
+ --> $DIR/crate-or-module-typo.rs:3:5
+ |
+LL | use st::cell::Cell;
+ | ^^ use of undeclared crate or module `st`
+ |
+help: there is a crate or module with a similar name
+ |
+LL | use std::cell::Cell;
+ | ~~~
+
+error[E0432]: unresolved import `bas`
+ --> $DIR/crate-or-module-typo.rs:11:5
+ |
+LL | use bas::bar;
+ | ^^^ use of undeclared crate or module `bas`
+ |
+help: there is a crate or module with a similar name
+ |
+LL | use bar::bar;
+ | ~~~
+
+error[E0433]: failed to resolve: use of undeclared crate or module `st`
+ --> $DIR/crate-or-module-typo.rs:14:10
+ |
+LL | bar: st::cell::Cell<bool>
+ | ^^ use of undeclared crate or module `st`
+ |
+help: there is a crate or module with a similar name
+ |
+LL | bar: std::cell::Cell<bool>
+ | ~~~
+
+error[E0433]: failed to resolve: use of undeclared crate or module `bar`
+ --> $DIR/crate-or-module-typo.rs:6:20
+ |
+LL | pub fn bar() { bar::baz(); }
+ | ^^^ use of undeclared crate or module `bar`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/tests/ui/suggestions/deref-path-method.rs b/tests/ui/suggestions/deref-path-method.rs
new file mode 100644
index 000000000..0281cdb6b
--- /dev/null
+++ b/tests/ui/suggestions/deref-path-method.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let vec = Vec::new();
+ Vec::contains(&vec, &0);
+ //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+ //~| HELP the function `contains` is implemented on `[_]`
+}
diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr
new file mode 100644
index 000000000..1cc37d611
--- /dev/null
+++ b/tests/ui/suggestions/deref-path-method.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+ --> $DIR/deref-path-method.rs:3:10
+ |
+LL | Vec::contains(&vec, &0);
+ | ^^^^^^^^ function or associated item not found in `Vec<_, _>`
+ |
+help: the function `contains` is implemented on `[_]`
+ |
+LL | <[_]>::contains(&vec, &0);
+ | ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed
new file mode 100644
index 000000000..f07784d53
--- /dev/null
+++ b/tests/ui/suggestions/derive-clone-for-eq.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/79076
+
+use std::cmp::PartialEq;
+
+#[derive(Clone, Eq)] //~ ERROR [E0277]
+pub struct Struct<T: std::clone::Clone>(T);
+
+impl<T: Clone, U> PartialEq<U> for Struct<T>
+where
+ U: Into<Struct<T>> + Clone
+{
+ fn eq(&self, _other: &U) -> bool {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs
new file mode 100644
index 000000000..15c0d4659
--- /dev/null
+++ b/tests/ui/suggestions/derive-clone-for-eq.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/79076
+
+use std::cmp::PartialEq;
+
+#[derive(Clone, Eq)] //~ ERROR [E0277]
+pub struct Struct<T>(T);
+
+impl<T: Clone, U> PartialEq<U> for Struct<T>
+where
+ U: Into<Struct<T>> + Clone
+{
+ fn eq(&self, _other: &U) -> bool {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr
new file mode 100644
index 000000000..9d843c251
--- /dev/null
+++ b/tests/ui/suggestions/derive-clone-for-eq.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: Clone` is not satisfied
+ --> $DIR/derive-clone-for-eq.rs:6:17
+ |
+LL | #[derive(Clone, Eq)]
+ | ^^ the trait `Clone` is not implemented for `T`
+ |
+note: required for `Struct<T>` to implement `PartialEq`
+ --> $DIR/derive-clone-for-eq.rs:9:19
+ |
+LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
+ | ----- ^^^^^^^^^^^^ ^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `Eq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | pub struct Struct<T: std::clone::Clone>(T);
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.rs b/tests/ui/suggestions/derive-macro-missing-bounds.rs
new file mode 100644
index 000000000..56c218f97
--- /dev/null
+++ b/tests/ui/suggestions/derive-macro-missing-bounds.rs
@@ -0,0 +1,89 @@
+mod a {
+ use std::fmt::{Debug, Formatter, Result};
+ struct Inner<T>(T);
+
+ impl Debug for Inner<()> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ todo!()
+ }
+ }
+
+ #[derive(Debug)]
+ struct Outer<T>(Inner<T>); //~ ERROR `a::Inner<T>` doesn't implement `Debug`
+}
+
+mod b {
+ use std::fmt::{Debug, Formatter, Result};
+ struct Inner<T>(T);
+
+ impl<T: Debug> Debug for Inner<T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ todo!()
+ }
+ }
+
+ #[derive(Debug)]
+ struct Outer<T>(Inner<T>);
+}
+
+mod c {
+ use std::fmt::{Debug, Formatter, Result};
+ struct Inner<T>(T);
+ trait Trait {}
+
+ impl<T: Debug + Trait> Debug for Inner<T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ todo!()
+ }
+ }
+
+ #[derive(Debug)]
+ struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: c::Trait` is not satisfied
+}
+
+mod d {
+ use std::fmt::{Debug, Formatter, Result};
+ struct Inner<T>(T);
+ trait Trait {}
+
+ impl<T> Debug for Inner<T> where T: Debug, T: Trait {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ todo!()
+ }
+ }
+
+ #[derive(Debug)]
+ struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: d::Trait` is not satisfied
+}
+
+mod e {
+ use std::fmt::{Debug, Formatter, Result};
+ struct Inner<T>(T);
+ trait Trait {}
+
+ impl<T> Debug for Inner<T> where T: Debug + Trait {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ todo!()
+ }
+ }
+
+ #[derive(Debug)]
+ struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: e::Trait` is not satisfied
+}
+
+mod f {
+ use std::fmt::{Debug, Formatter, Result};
+ struct Inner<T>(T);
+ trait Trait {}
+
+ impl<T: Debug> Debug for Inner<T> where T: Trait {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ todo!()
+ }
+ }
+
+ #[derive(Debug)]
+ struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: f::Trait` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
new file mode 100644
index 000000000..79036279d
--- /dev/null
+++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -0,0 +1,113 @@
+error[E0277]: `a::Inner<T>` doesn't implement `Debug`
+ --> $DIR/derive-macro-missing-bounds.rs:12:21
+ |
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+ | ^^^^^^^^ `a::Inner<T>` cannot be formatted using `{:?}`
+ |
+ = help: the trait `Debug` is not implemented for `a::Inner<T>`
+ = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>`
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider annotating `a::Inner<T>` with `#[derive(Debug)]`
+ |
+LL | #[derive(Debug)]
+ |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | struct Outer<T>(Inner<T>) where a::Inner<T>: Debug;
+ | ++++++++++++++++++++++++
+
+error[E0277]: the trait bound `T: c::Trait` is not satisfied
+ --> $DIR/derive-macro-missing-bounds.rs:41:21
+ |
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+ | ^^^^^^^^ the trait `c::Trait` is not implemented for `T`
+ |
+note: required for `c::Inner<T>` to implement `Debug`
+ --> $DIR/derive-macro-missing-bounds.rs:34:28
+ |
+LL | impl<T: Debug + Trait> Debug for Inner<T> {
+ | ----- ^^^^^ ^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&c::Inner<T>` to implement `Debug`
+ = note: required for the cast from `&c::Inner<T>` to the object type `dyn Debug`
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | struct Outer<T: c::Trait>(Inner<T>);
+ | ++++++++++
+
+error[E0277]: the trait bound `T: d::Trait` is not satisfied
+ --> $DIR/derive-macro-missing-bounds.rs:56:21
+ |
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+ | ^^^^^^^^ the trait `d::Trait` is not implemented for `T`
+ |
+note: required for `d::Inner<T>` to implement `Debug`
+ --> $DIR/derive-macro-missing-bounds.rs:49:13
+ |
+LL | impl<T> Debug for Inner<T> where T: Debug, T: Trait {
+ | ^^^^^ ^^^^^^^^ ----- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&d::Inner<T>` to implement `Debug`
+ = note: required for the cast from `&d::Inner<T>` to the object type `dyn Debug`
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | struct Outer<T: d::Trait>(Inner<T>);
+ | ++++++++++
+
+error[E0277]: the trait bound `T: e::Trait` is not satisfied
+ --> $DIR/derive-macro-missing-bounds.rs:71:21
+ |
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+ | ^^^^^^^^ the trait `e::Trait` is not implemented for `T`
+ |
+note: required for `e::Inner<T>` to implement `Debug`
+ --> $DIR/derive-macro-missing-bounds.rs:64:13
+ |
+LL | impl<T> Debug for Inner<T> where T: Debug + Trait {
+ | ^^^^^ ^^^^^^^^ ----- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&e::Inner<T>` to implement `Debug`
+ = note: required for the cast from `&e::Inner<T>` to the object type `dyn Debug`
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | struct Outer<T: e::Trait>(Inner<T>);
+ | ++++++++++
+
+error[E0277]: the trait bound `T: f::Trait` is not satisfied
+ --> $DIR/derive-macro-missing-bounds.rs:86:21
+ |
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+ | ^^^^^^^^ the trait `f::Trait` is not implemented for `T`
+ |
+note: required for `f::Inner<T>` to implement `Debug`
+ --> $DIR/derive-macro-missing-bounds.rs:79:20
+ |
+LL | impl<T: Debug> Debug for Inner<T> where T: Trait {
+ | ^^^^^ ^^^^^^^^ ----- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&f::Inner<T>` to implement `Debug`
+ = note: required for the cast from `&f::Inner<T>` to the object type `dyn Debug`
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | struct Outer<T: f::Trait>(Inner<T>);
+ | ++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/derive-trait-for-method-call.rs b/tests/ui/suggestions/derive-trait-for-method-call.rs
new file mode 100644
index 000000000..25043da52
--- /dev/null
+++ b/tests/ui/suggestions/derive-trait-for-method-call.rs
@@ -0,0 +1,44 @@
+use std::time::Instant;
+
+enum Enum {
+ First
+}
+
+#[derive(Clone)]
+enum CloneEnum {
+ First
+}
+
+struct Struct {
+}
+
+#[derive(Clone)]
+struct CloneStruct {
+}
+
+struct Foo<X, Y> (X, Y);
+impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+ fn test(&self) -> (X, Y) {
+ (self.0, self.1)
+ }
+}
+
+fn test1() {
+ let x = Foo(Enum::First, CloneEnum::First);
+ let y = x.test();
+ //~^the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn test2() {
+ let x = Foo(Struct{}, CloneStruct{});
+ let y = x.test();
+ //~^the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn test3() {
+ let x = Foo(Vec::<Enum>::new(), Instant::now());
+ let y = x.test();
+ //~^the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr
new file mode 100644
index 000000000..924b26a8c
--- /dev/null
+++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr
@@ -0,0 +1,105 @@
+error[E0599]: the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied
+ --> $DIR/derive-trait-for-method-call.rs:28:15
+ |
+LL | enum Enum {
+ | ---------
+ | |
+ | doesn't satisfy `Enum: Clone`
+ | doesn't satisfy `Enum: Default`
+...
+LL | enum CloneEnum {
+ | -------------- doesn't satisfy `CloneEnum: Default`
+...
+LL | struct Foo<X, Y> (X, Y);
+ | ---------------- method `test` not found for this struct
+...
+LL | let y = x.test();
+ | ^^^^ method cannot be called on `Foo<Enum, CloneEnum>` due to unsatisfied trait bounds
+ |
+note: the following trait bounds were not satisfied:
+ `CloneEnum: Default`
+ `Enum: Clone`
+ `Enum: Default`
+ --> $DIR/derive-trait-for-method-call.rs:20:9
+ |
+LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+ | ^^^^^ ^^^^^^^ ^^^^^^^ ---------
+ | | | |
+ | | | unsatisfied trait bound introduced here
+ | | unsatisfied trait bound introduced here
+ | unsatisfied trait bound introduced here
+note: the trait `Default` must be implemented
+ --> $SRC_DIR/core/src/default.rs:LL:COL
+help: consider annotating `Enum` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
+
+error[E0599]: the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied
+ --> $DIR/derive-trait-for-method-call.rs:34:15
+ |
+LL | struct Struct {
+ | -------------
+ | |
+ | doesn't satisfy `Struct: Clone`
+ | doesn't satisfy `Struct: Default`
+...
+LL | struct CloneStruct {
+ | ------------------ doesn't satisfy `CloneStruct: Default`
+...
+LL | struct Foo<X, Y> (X, Y);
+ | ---------------- method `test` not found for this struct
+...
+LL | let y = x.test();
+ | ^^^^ method cannot be called on `Foo<Struct, CloneStruct>` due to unsatisfied trait bounds
+ |
+note: the following trait bounds were not satisfied:
+ `CloneStruct: Default`
+ `Struct: Clone`
+ `Struct: Default`
+ --> $DIR/derive-trait-for-method-call.rs:20:9
+ |
+LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+ | ^^^^^ ^^^^^^^ ^^^^^^^ ---------
+ | | | |
+ | | | unsatisfied trait bound introduced here
+ | | unsatisfied trait bound introduced here
+ | unsatisfied trait bound introduced here
+help: consider annotating `CloneStruct` with `#[derive(Default)]`
+ |
+LL | #[derive(Default)]
+ |
+help: consider annotating `Struct` with `#[derive(Clone, Default)]`
+ |
+LL | #[derive(Clone, Default)]
+ |
+
+error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
+ --> $DIR/derive-trait-for-method-call.rs:40:15
+ |
+LL | struct Foo<X, Y> (X, Y);
+ | ---------------- method `test` not found for this struct
+...
+LL | let y = x.test();
+ | ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+ --> $SRC_DIR/std/src/time.rs:LL:COL
+ |
+ = note: doesn't satisfy `Instant: Default`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ |
+ = note: doesn't satisfy `Vec<Enum>: Clone`
+ |
+note: the following trait bounds were not satisfied:
+ `Instant: Default`
+ `Vec<Enum>: Clone`
+ --> $DIR/derive-trait-for-method-call.rs:20:9
+ |
+LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+ | ^^^^^ ^^^^^^^ ---------
+ | | |
+ | | unsatisfied trait bound introduced here
+ | unsatisfied trait bound introduced here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs
new file mode 100644
index 000000000..a25be862a
--- /dev/null
+++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs
@@ -0,0 +1,5 @@
+use std::result;
+impl result { //~ ERROR expected type, found module `result`
+ fn into_future() -> Err {} //~ ERROR expected type, found variant `Err`
+}
+fn main() {}
diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
new file mode 100644
index 000000000..0cd6267b3
--- /dev/null
+++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
@@ -0,0 +1,18 @@
+error[E0573]: expected type, found module `result`
+ --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:2:6
+ |
+LL | impl result {
+ | ^^^^^^ help: an enum with a similar name exists: `Result`
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+ |
+ = note: similarly named enum `Result` defined here
+
+error[E0573]: expected type, found variant `Err`
+ --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25
+ |
+LL | fn into_future() -> Err {}
+ | ^^^ not a type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs
new file mode 100644
index 000000000..ef1c09d21
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs
@@ -0,0 +1,14 @@
+fn warn(_: &str) {}
+
+macro_rules! intrinsic_match {
+ ($intrinsic:expr) => {
+ warn(format!("unsupported intrinsic {}", $intrinsic));
+ //~^ ERROR mismatched types
+ };
+}
+
+fn main() {
+ intrinsic_match! {
+ "abc"
+ };
+}
diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr
new file mode 100644
index 000000000..5dc4e6444
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+ --> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:11:5
+ |
+LL | / intrinsic_match! {
+LL | | "abc"
+LL | | };
+ | |_____^ expected `&str`, found struct `String`
+ |
+ = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (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 E0308`.
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs
new file mode 100644
index 000000000..15e0af1de
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs
@@ -0,0 +1,8 @@
+#![crate_type = "lib"]
+
+extern crate core;
+
+pub mod __private {
+ #[doc(hidden)]
+ pub use core::option::Option::{self, None, Some};
+}
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs
new file mode 100644
index 000000000..5a5079d82
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs
@@ -0,0 +1,8 @@
+#![crate_type = "lib"]
+
+extern crate core;
+
+#[doc(hidden)]
+pub mod __private {
+ pub use core::option::Option::{self, None, Some};
+}
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs
new file mode 100644
index 000000000..38dabc9d7
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs
@@ -0,0 +1,10 @@
+// aux-build:hidden-child.rs
+
+// FIXME(compiler-errors): This currently suggests the wrong thing.
+// UI test exists to track the problem.
+
+extern crate hidden_child;
+
+fn main() {
+ let x: Option<i32> = 1i32; //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr
new file mode 100644
index 000000000..67f4ac08d
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/hidden-child.rs:9:26
+ |
+LL | let x: Option<i32> = 1i32;
+ | ----------- ^^^^ expected enum `Option`, found `i32`
+ | |
+ | expected due to this
+ |
+ = note: expected enum `Option<i32>`
+ found type `i32`
+help: try wrapping the expression in `hidden_child::__private::Some`
+ |
+LL | let x: Option<i32> = hidden_child::__private::Some(1i32);
+ | ++++++++++++++++++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs
new file mode 100644
index 000000000..4d96d6c16
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs
@@ -0,0 +1,7 @@
+// aux-build:hidden-parent.rs
+
+extern crate hidden_parent;
+
+fn main() {
+ let x: Option<i32> = 1i32; //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr
new file mode 100644
index 000000000..d92b81279
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/hidden-parent.rs:6:26
+ |
+LL | let x: Option<i32> = 1i32;
+ | ----------- ^^^^ expected enum `Option`, found `i32`
+ | |
+ | expected due to this
+ |
+ = note: expected enum `Option<i32>`
+ found type `i32`
+help: try wrapping the expression in `Some`
+ |
+LL | let x: Option<i32> = Some(1i32);
+ | +++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs
new file mode 100644
index 000000000..acb897571
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs
@@ -0,0 +1,15 @@
+// https://github.com/rust-lang/rust/issues/96834
+//
+// This test case verifies that rustc does not make an unhelpful suggestion:
+//
+// help: consider wrapping the receiver expression with the appropriate type
+// |
+// 14 | Pin::new(&mut a).set(0, 3);
+// | +++++++++++++ +
+//
+// We can tell that it isn't helpful, because `Pin::set` takes two parameters (including
+// the receiver), but the function call on line 14 supplies three.
+fn main() {
+ let mut a = [0u8; 1];
+ a.set(0, 3); //~ERROR
+}
diff --git a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr
new file mode 100644
index 000000000..c66da3ea6
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `set` found for array `[u8; 1]` in the current scope
+ --> $DIR/dont-suggest-pin-array-dot-set.rs:14:7
+ |
+LL | a.set(0, 3);
+ | ^^^ help: there is a method with a similar name: `get`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
new file mode 100644
index 000000000..e19d497f2
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
@@ -0,0 +1,131 @@
+#[derive(Clone)]
+enum Either {
+ One(X),
+ Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+
+pub fn main() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let r = &e;
+ let rm = &mut Either::One(X(Y));
+
+ let x = X(Y);
+ let mut xm = X(Y);
+
+ let s = &x;
+ let sm = &mut X(Y);
+
+ let ve = vec![Either::One(X(Y))];
+
+ let vr = &ve;
+ let vrm = &mut vec![Either::One(X(Y))];
+
+ let vx = vec![X(Y)];
+
+ let vs = &vx;
+ let vsm = &mut vec![X(Y)];
+
+ // test for duplicate suggestions
+
+ let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+ //~^ ERROR cannot move
+ //~| HELP consider removing the borrow
+ if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the borrow
+ while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the borrow
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the borrow
+ &(Either::Two(_t), Either::One(_u)) => (),
+ //~^ HELP consider removing the borrow
+ _ => (),
+ }
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the borrow
+ | &(Either::Two(_t), Either::One(_u)) => (),
+ // FIXME: would really like a suggestion here too
+ _ => (),
+ }
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the borrow
+ &(Either::Two(ref _t), Either::One(ref _u)) => (),
+ _ => (),
+ }
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the borrow
+ (Either::Two(_t), Either::One(_u)) => (),
+ _ => (),
+ }
+ fn f5(&(X(_t), X(_u)): &(X, X)) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the borrow
+
+ let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ //~^ ERROR cannot move
+ //~| HELP consider removing the mutable borrow
+ if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the mutable borrow
+ while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the mutable borrow
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the mutable borrow
+ &mut (Either::Two(_t), Either::One(_u)) => (),
+ //~^ HELP consider removing the mutable borrow
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the mutable borrow
+ | &mut (Either::Two(_t), Either::One(_u)) => (),
+ // FIXME: would really like a suggestion here too
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the mutable borrow
+ &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the mutable borrow
+ &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the mutable borrow
+ (Either::Two(_t), Either::One(_u)) => (),
+ _ => (),
+ }
+ fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the mutable borrow
+}
diff --git a/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
new file mode 100644
index 000000000..b96b3713f
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
@@ -0,0 +1,309 @@
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:39:27
+ |
+LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+LL + let (X(_t), X(_u)) = &(x.clone(), x.clone());
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:42:50
+ |
+LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL + if let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:45:53
+ |
+LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL + while let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:48:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+LL |
+LL | &(Either::Two(_t), Either::One(_u)) => (),
+ | -- ...and here -- ...and here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - &(Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+help: consider removing the borrow
+ |
+LL - &(Either::Two(_t), Either::One(_u)) => (),
+LL + (Either::Two(_t), Either::One(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:56:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &(Either::One(_t), Either::Two(_u))
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - &(Either::One(_t), Either::Two(_u))
+LL + (Either::One(_t), Either::Two(_u))
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:64:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - &(Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:71:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - &(Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:82:31
+ |
+LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+LL + let (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:85:54
+ |
+LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL + if let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:88:57
+ |
+LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL + while let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:91:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+LL |
+LL | &mut (Either::Two(_t), Either::One(_u)) => (),
+ | -- ...and here -- ...and here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::Two(_t), Either::One(_u)) => (),
+LL + (Either::Two(_t), Either::One(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:99:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &mut (Either::One(_t), Either::Two(_u))
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u))
+LL + (Either::One(_t), Either::Two(_u))
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:107:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:114:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:121:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/duplicate-suggestions.rs:78:11
+ |
+LL | fn f5(&(X(_t), X(_u)): &(X, X)) { }
+ | ^^^^--^^^^^--^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - fn f5(&(X(_t), X(_u)): &(X, X)) { }
+LL + fn f5((X(_t), X(_u)): &(X, X)) { }
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/duplicate-suggestions.rs:128:11
+ |
+LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+ | ^^^^^^^^--^^^^^--^^
+ | | |
+ | | ...and here
+ | data moved here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+LL + fn f6((X(_t), X(_u)): &mut (X, X)) { }
+ |
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs
new file mode 100644
index 000000000..44eac3691
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs
@@ -0,0 +1,138 @@
+#[derive(Clone)]
+enum Either {
+ One(X),
+ Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+fn consume_fn<F: Fn()>(_f: F) { }
+
+fn consume_fnmut<F: FnMut()>(_f: F) { }
+
+pub fn main() { }
+
+fn move_into_fn() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let x = X(Y);
+
+ // move into Fn
+
+ consume_fn(|| {
+ let X(_t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ if let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ while let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(mut _t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ if let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ while let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(mut _t)
+ | Either::Two(mut _t) => (),
+ }
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(mut _t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ });
+}
+
+fn move_into_fnmut() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let x = X(Y);
+
+ // move into FnMut
+
+ consume_fnmut(|| {
+ let X(_t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ if let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ while let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(mut _t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ if let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ while let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(mut _t)
+ | Either::Two(mut _t) => (),
+ }
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(mut _t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(mut _t) => (),
+ Either::Two(ref mut _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ });
+}
diff --git a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
new file mode 100644
index 000000000..edda2cbc7
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
@@ -0,0 +1,448 @@
+error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:28:21
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+LL | let X(_t) = x;
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &x;
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:31:34
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | if let Either::One(_t) = e { }
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &e { }
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:34:37
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | while let Either::One(_t) = e { }
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &e { }
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:37:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | match e {
+ | ^
+...
+LL | Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:43:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | match e {
+ | ^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
+
+error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:51:25
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | let X(mut _t) = x;
+ | ------ ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(mut _t) = &x;
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:54:38
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | if let Either::One(mut _t) = em { }
+ | ------ ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(mut _t) = &em { }
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:57:41
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | while let Either::One(mut _t) = em { }
+ | ------ ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(mut _t) = &em { }
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:60:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | match em {
+ | ^^
+...
+LL | Either::One(mut _t)
+ | ------
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:66:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fn(|| {
+ | -- captured by this `Fn` closure
+...
+LL | match em {
+ | ^^
+...
+LL | Either::One(mut _t) => (),
+ | ------
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
+
+error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:85:21
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+LL | let X(_t) = x;
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &x;
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:88:34
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | if let Either::One(_t) = e { }
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &e { }
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:91:37
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | while let Either::One(_t) = e { }
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &e { }
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:94:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | match e {
+ | ^
+...
+LL | Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
+
+error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:100:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | match e {
+ | ^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
+
+error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:108:25
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | let X(mut _t) = x;
+ | ------ ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(mut _t) = &x;
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:111:38
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | if let Either::One(mut _t) = em { }
+ | ------ ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(mut _t) = &em { }
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:114:41
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | while let Either::One(mut _t) = em { }
+ | ------ ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(mut _t) = &em { }
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:117:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | match em {
+ | ^^
+...
+LL | Either::One(mut _t)
+ | ------
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:123:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | match em {
+ | ^^
+...
+LL | Either::One(mut _t) => (),
+ | ------
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
+
+error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:130:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | consume_fnmut(|| {
+ | -- captured by this `FnMut` closure
+...
+LL | match em {
+ | ^^
+...
+LL | Either::One(mut _t) => (),
+ | ------
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.rs b/tests/ui/suggestions/dont-suggest-ref/simple.rs
new file mode 100644
index 000000000..1e40e60a1
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ref/simple.rs
@@ -0,0 +1,336 @@
+#[derive(Clone)]
+enum Either {
+ One(X),
+ Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+pub fn main() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let r = &e;
+ let rm = &mut Either::One(X(Y));
+
+ let x = X(Y);
+ let mut xm = X(Y);
+
+ let s = &x;
+ let sm = &mut X(Y);
+
+ let ve = vec![Either::One(X(Y))];
+
+ let vr = &ve;
+ let vrm = &mut vec![Either::One(X(Y))];
+
+ let vx = vec![X(Y)];
+
+ let vs = &vx;
+ let vsm = &mut vec![X(Y)];
+
+ // move from Either/X place
+
+ let X(_t) = *s;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ if let Either::One(_t) = *r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ while let Either::One(_t) = *r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ match *r {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match *r {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(_t) = *sm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ if let Either::One(_t) = *rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ while let Either::One(_t) = *rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the dereference here
+ Either::One(_t) => (),
+ Either::Two(ref mut _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(_t) = vs[0];
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ if let Either::One(_t) = vr[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ while let Either::One(_t) = vr[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ match vr[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match vr[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(_t) = vsm[0];
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ if let Either::One(_t) = vrm[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ while let Either::One(_t) = vrm[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ match vrm[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match vrm[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ match vrm[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ Either::One(_t) => (),
+ Either::Two(ref mut _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ // move from &Either/&X place
+
+ let &X(_t) = s;
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ if let &Either::One(_t) = r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ while let &Either::One(_t) = r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t)
+ //~^ HELP consider removing
+ | &Either::Two(_t) => (),
+ // FIXME: would really like a suggestion here too
+ }
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing
+ &Either::Two(ref _t) => (),
+ }
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing
+ Either::Two(_t) => (),
+ }
+ fn f1(&X(_t): &X) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+
+ let &mut X(_t) = sm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ if let &mut Either::One(_t) = rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ while let &mut Either::One(_t) = rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ &mut Either::Two(_t) => (),
+ //~^ HELP consider removing
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ &mut Either::Two(ref _t) => (),
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ &mut Either::Two(ref mut _t) => (),
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ Either::Two(_t) => (),
+ }
+ fn f2(&mut X(_t): &mut X) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+
+ // move from tuple of &Either/&X
+
+ // FIXME: These should have suggestions.
+
+ let (&X(_t),) = (&x.clone(),);
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ if let (&Either::One(_t),) = (&e.clone(),) { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ while let (&Either::One(_t),) = (&e.clone(),) { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ match (&e.clone(),) {
+ //~^ ERROR cannot move
+ (&Either::One(_t),)
+ //~^ HELP consider borrowing the pattern binding
+ | (&Either::Two(_t),) => (),
+ }
+ fn f3((&X(_t),): (&X,)) { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+
+ let (&mut X(_t),) = (&mut xm.clone(),);
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ match (&mut em.clone(),) {
+ //~^ ERROR cannot move
+ (&mut Either::One(_t),) => (),
+ //~^ HELP consider borrowing the pattern binding
+ (&mut Either::Two(_t),) => (),
+ //~^ HELP consider borrowing the pattern binding
+ }
+ fn f4((&mut X(_t),): (&mut X,)) { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+
+ // move from &Either/&X value
+
+ let &X(_t) = &x;
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ if let &Either::One(_t) = &e { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ while let &Either::One(_t) = &e { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t)
+ //~^ HELP consider removing
+ | &Either::Two(_t) => (),
+ // FIXME: would really like a suggestion here too
+ }
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing
+ &Either::Two(ref _t) => (),
+ }
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing
+ Either::Two(_t) => (),
+ }
+
+ let &mut X(_t) = &mut xm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ if let &mut Either::One(_t) = &mut em { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ while let &mut Either::One(_t) = &mut em { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t)
+ //~^ HELP consider removing
+ | &mut Either::Two(_t) => (),
+ // FIXME: would really like a suggestion here too
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ &mut Either::Two(ref _t) => (),
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ &mut Either::Two(ref mut _t) => (),
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing
+ Either::Two(_t) => (),
+ }
+}
+
+struct Testing {
+ a: Option<String>
+}
+
+fn testing(a: &Testing) {
+ let Some(_s) = a.a else {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ return;
+ };
+}
diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.stderr b/tests/ui/suggestions/dont-suggest-ref/simple.stderr
new file mode 100644
index 000000000..526326524
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ref/simple.stderr
@@ -0,0 +1,985 @@
+error[E0507]: cannot move out of `s` which is behind a shared reference
+ --> $DIR/simple.rs:38:17
+ |
+LL | let X(_t) = *s;
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let X(_t) = *s;
+LL + let X(_t) = s;
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:41:30
+ |
+LL | if let Either::One(_t) = *r { }
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - if let Either::One(_t) = *r { }
+LL + if let Either::One(_t) = r { }
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:44:33
+ |
+LL | while let Either::One(_t) = *r { }
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - while let Either::One(_t) = *r { }
+LL + while let Either::One(_t) = r { }
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
+ --> $DIR/simple.rs:47:11
+ |
+LL | match *r {
+ | ^^
+...
+LL | Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *r {
+LL + match r {
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:53:11
+ |
+LL | match *r {
+ | ^^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *r {
+LL + match r {
+ |
+
+error[E0507]: cannot move out of `sm` which is behind a mutable reference
+ --> $DIR/simple.rs:61:17
+ |
+LL | let X(_t) = *sm;
+ | -- ^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let X(_t) = *sm;
+LL + let X(_t) = sm;
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:64:30
+ |
+LL | if let Either::One(_t) = *rm { }
+ | -- ^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - if let Either::One(_t) = *rm { }
+LL + if let Either::One(_t) = rm { }
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:67:33
+ |
+LL | while let Either::One(_t) = *rm { }
+ | -- ^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - while let Either::One(_t) = *rm { }
+LL + while let Either::One(_t) = rm { }
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
+ --> $DIR/simple.rs:70:11
+ |
+LL | match *rm {
+ | ^^^
+...
+LL | Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *rm {
+LL + match rm {
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:76:11
+ |
+LL | match *rm {
+ | ^^^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *rm {
+LL + match rm {
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:83:11
+ |
+LL | match *rm {
+ | ^^^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *rm {
+LL + match rm {
+ |
+
+error[E0507]: cannot move out of index of `Vec<X>`
+ --> $DIR/simple.rs:91:17
+ |
+LL | let X(_t) = vs[0];
+ | -- ^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &vs[0];
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:94:30
+ |
+LL | if let Either::One(_t) = vr[0] { }
+ | -- ^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &vr[0] { }
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:97:33
+ |
+LL | while let Either::One(_t) = vr[0] { }
+ | -- ^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &vr[0] { }
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:100:11
+ |
+LL | match vr[0] {
+ | ^^^^^
+...
+LL | Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vr[0] {
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:106:11
+ |
+LL | match vr[0] {
+ | ^^^^^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vr[0] {
+ | +
+
+error[E0507]: cannot move out of index of `Vec<X>`
+ --> $DIR/simple.rs:114:17
+ |
+LL | let X(_t) = vsm[0];
+ | -- ^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &vsm[0];
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:117:30
+ |
+LL | if let Either::One(_t) = vrm[0] { }
+ | -- ^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &vrm[0] { }
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:120:33
+ |
+LL | while let Either::One(_t) = vrm[0] { }
+ | -- ^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &vrm[0] { }
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:123:11
+ |
+LL | match vrm[0] {
+ | ^^^^^^
+...
+LL | Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vrm[0] {
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:129:11
+ |
+LL | match vrm[0] {
+ | ^^^^^^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vrm[0] {
+ | +
+
+error[E0507]: cannot move out of index of `Vec<Either>`
+ --> $DIR/simple.rs:136:11
+ |
+LL | match vrm[0] {
+ | ^^^^^^
+...
+LL | Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vrm[0] {
+ | +
+
+error[E0507]: cannot move out of `s` which is behind a shared reference
+ --> $DIR/simple.rs:146:18
+ |
+LL | let &X(_t) = s;
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - let &X(_t) = s;
+LL + let X(_t) = s;
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:149:31
+ |
+LL | if let &Either::One(_t) = r { }
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - if let &Either::One(_t) = r { }
+LL + if let Either::One(_t) = r { }
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:152:34
+ |
+LL | while let &Either::One(_t) = r { }
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - while let &Either::One(_t) = r { }
+LL + while let Either::One(_t) = r { }
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
+ --> $DIR/simple.rs:155:11
+ |
+LL | match r {
+ | ^
+LL |
+LL | &Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t)
+LL + Either::One(_t)
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:162:11
+ |
+LL | match r {
+ | ^
+LL |
+LL | &Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
+ --> $DIR/simple.rs:168:11
+ |
+LL | match r {
+ | ^
+LL |
+LL | &Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of `sm` which is behind a mutable reference
+ --> $DIR/simple.rs:178:22
+ |
+LL | let &mut X(_t) = sm;
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - let &mut X(_t) = sm;
+LL + let X(_t) = sm;
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:181:35
+ |
+LL | if let &mut Either::One(_t) = rm { }
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - if let &mut Either::One(_t) = rm { }
+LL + if let Either::One(_t) = rm { }
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:184:38
+ |
+LL | while let &mut Either::One(_t) = rm { }
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - while let &mut Either::One(_t) = rm { }
+LL + while let Either::One(_t) = rm { }
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
+ --> $DIR/simple.rs:187:11
+ |
+LL | match rm {
+ | ^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | -- data moved here
+LL |
+LL | &mut Either::Two(_t) => (),
+ | -- ...and here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::Two(_t) => (),
+LL + Either::Two(_t) => (),
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:194:11
+ |
+LL | match rm {
+ | ^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:200:11
+ |
+LL | match rm {
+ | ^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
+ --> $DIR/simple.rs:206:11
+ |
+LL | match rm {
+ | ^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:220:21
+ |
+LL | let (&X(_t),) = (&x.clone(),);
+ | -- ^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let (&X(ref _t),) = (&x.clone(),);
+ | +++
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:223:34
+ |
+LL | if let (&Either::One(_t),) = (&e.clone(),) { }
+ | -- ^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | if let (&Either::One(ref _t),) = (&e.clone(),) { }
+ | +++
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:226:37
+ |
+LL | while let (&Either::One(_t),) = (&e.clone(),) { }
+ | -- ^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | while let (&Either::One(ref _t),) = (&e.clone(),) { }
+ | +++
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:229:11
+ |
+LL | match (&e.clone(),) {
+ | ^^^^^^^^^^^^^
+LL |
+LL | (&Either::One(_t),)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | (&Either::One(ref _t),)
+ | +++
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:239:25
+ |
+LL | let (&mut X(_t),) = (&mut xm.clone(),);
+ | -- ^^^^^^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let (&mut X(ref _t),) = (&mut xm.clone(),);
+ | +++
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:242:38
+ |
+LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ | -- ^^^^^^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+ | +++
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:245:41
+ |
+LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ | -- ^^^^^^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+ | +++
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:248:11
+ |
+LL | match (&mut em.clone(),) {
+ | ^^^^^^^^^^^^^^^^^^
+LL |
+LL | (&mut Either::One(_t),) => (),
+ | -- data moved here
+LL |
+LL | (&mut Either::Two(_t),) => (),
+ | -- ...and here
+ |
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | (&mut Either::One(ref _t),) => (),
+ | +++
+help: consider borrowing the pattern binding
+ |
+LL | (&mut Either::Two(ref _t),) => (),
+ | +++
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:261:18
+ |
+LL | let &X(_t) = &x;
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - let &X(_t) = &x;
+LL + let X(_t) = &x;
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:264:31
+ |
+LL | if let &Either::One(_t) = &e { }
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - if let &Either::One(_t) = &e { }
+LL + if let Either::One(_t) = &e { }
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:267:34
+ |
+LL | while let &Either::One(_t) = &e { }
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - while let &Either::One(_t) = &e { }
+LL + while let Either::One(_t) = &e { }
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:270:11
+ |
+LL | match &e {
+ | ^^
+LL |
+LL | &Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t)
+LL + Either::One(_t)
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:277:11
+ |
+LL | match &e {
+ | ^^
+LL |
+LL | &Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:283:11
+ |
+LL | match &e {
+ | ^^
+LL |
+LL | &Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:290:22
+ |
+LL | let &mut X(_t) = &mut xm;
+ | -- ^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - let &mut X(_t) = &mut xm;
+LL + let X(_t) = &mut xm;
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:293:35
+ |
+LL | if let &mut Either::One(_t) = &mut em { }
+ | -- ^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - if let &mut Either::One(_t) = &mut em { }
+LL + if let Either::One(_t) = &mut em { }
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:296:38
+ |
+LL | while let &mut Either::One(_t) = &mut em { }
+ | -- ^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - while let &mut Either::One(_t) = &mut em { }
+LL + while let Either::One(_t) = &mut em { }
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:299:11
+ |
+LL | match &mut em {
+ | ^^^^^^^
+LL |
+LL | &mut Either::One(_t)
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t)
+LL + Either::One(_t)
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:306:11
+ |
+LL | match &mut em {
+ | ^^^^^^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:312:11
+ |
+LL | match &mut em {
+ | ^^^^^^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:318:11
+ |
+LL | match &mut em {
+ | ^^^^^^^
+LL |
+LL | &mut Either::One(_t) => (),
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:174:11
+ |
+LL | fn f1(&X(_t): &X) { }
+ | ^^^--^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - fn f1(&X(_t): &X) { }
+LL + fn f1(X(_t): &X) { }
+ |
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:212:11
+ |
+LL | fn f2(&mut X(_t): &mut X) { }
+ | ^^^^^^^--^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - fn f2(&mut X(_t): &mut X) { }
+LL + fn f2(X(_t): &mut X) { }
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/simple.rs:235:11
+ |
+LL | fn f3((&X(_t),): (&X,)) { }
+ | ^^^^--^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | fn f3((&X(ref _t),): (&X,)) { }
+ | +++
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/simple.rs:255:11
+ |
+LL | fn f4((&mut X(_t),): (&mut X,)) { }
+ | ^^^^^^^^--^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | fn f4((&mut X(ref _t),): (&mut X,)) { }
+ | +++
+
+error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference
+ --> $DIR/simple.rs:331:20
+ |
+LL | let Some(_s) = a.a else {
+ | -- ^^^
+ | |
+ | data moved here
+ | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let Some(ref _s) = a.a else {
+ | +++
+
+error: aborting due to 61 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/dont-suggest-try_into-in-macros.rs b/tests/ui/suggestions/dont-suggest-try_into-in-macros.rs
new file mode 100644
index 000000000..d625199c9
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-try_into-in-macros.rs
@@ -0,0 +1,3 @@
+fn main() {
+ assert_eq!(10u64, 10usize); //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr
new file mode 100644
index 000000000..bc6342004
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/dont-suggest-try_into-in-macros.rs:2:5
+ |
+LL | assert_eq!(10u64, 10usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected `u64`, found `usize`
+ | expected because this is `u64`
+ |
+ = note: this error originates in the macro `assert_eq` (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 E0308`.
diff --git a/tests/ui/suggestions/dont-suggest-ufcs-for-const.rs b/tests/ui/suggestions/dont-suggest-ufcs-for-const.rs
new file mode 100644
index 000000000..06cf243f1
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ufcs-for-const.rs
@@ -0,0 +1,4 @@
+fn main() {
+ 1_u32.MAX();
+ //~^ ERROR no method named `MAX` found for type `u32` in the current scope
+}
diff --git a/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr b/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr
new file mode 100644
index 000000000..0d9543e0b
--- /dev/null
+++ b/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `MAX` found for type `u32` in the current scope
+ --> $DIR/dont-suggest-ufcs-for-const.rs:2:11
+ |
+LL | 1_u32.MAX();
+ | ^^^ method not found in `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/dont-try-removing-the-field.rs b/tests/ui/suggestions/dont-try-removing-the-field.rs
new file mode 100644
index 000000000..948aa2b94
--- /dev/null
+++ b/tests/ui/suggestions/dont-try-removing-the-field.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![allow(dead_code)]
+
+struct Foo {
+ foo: i32,
+ bar: i32,
+ baz: (),
+}
+
+fn use_foo(x: Foo) -> (i32, i32) {
+ let Foo { foo, bar, baz } = x; //~ WARNING unused variable: `baz`
+ //~| help: try ignoring the field
+ return (foo, bar);
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/dont-try-removing-the-field.stderr b/tests/ui/suggestions/dont-try-removing-the-field.stderr
new file mode 100644
index 000000000..263171a4a
--- /dev/null
+++ b/tests/ui/suggestions/dont-try-removing-the-field.stderr
@@ -0,0 +1,10 @@
+warning: unused variable: `baz`
+ --> $DIR/dont-try-removing-the-field.rs:12:25
+ |
+LL | let Foo { foo, bar, baz } = x;
+ | ^^^ help: try ignoring the field: `baz: _`
+ |
+ = note: `#[warn(unused_variables)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs
new file mode 100644
index 000000000..baa2128eb
--- /dev/null
+++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs
@@ -0,0 +1,21 @@
+mod banana {
+ //~^ HELP the following traits are implemented but not in scope
+ pub struct Chaenomeles;
+
+ pub trait Apple {
+ fn pick(&self) {}
+ }
+ impl Apple for Chaenomeles {}
+
+ pub trait Peach {
+ fn pick(&self, a: &mut ()) {}
+ }
+ impl<Mango: Peach> Peach for Box<Mango> {}
+ impl Peach for Chaenomeles {}
+}
+
+fn main() {
+ banana::Chaenomeles.pick()
+ //~^ ERROR no method named
+ //~| HELP items from traits can only be used if the trait is in scope
+}
diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr
new file mode 100644
index 000000000..4658ecb3a
--- /dev/null
+++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr
@@ -0,0 +1,20 @@
+error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope
+ --> $DIR/dont-wrap-ambiguous-receivers.rs:18:25
+ |
+LL | pub struct Chaenomeles;
+ | ---------------------- method `pick` not found for this struct
+...
+LL | banana::Chaenomeles.pick()
+ | ^^^^ method not found in `Chaenomeles`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+ |
+LL | use banana::Apple;
+ |
+LL | use banana::Peach;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed
new file mode 100644
index 000000000..6499c92bc
--- /dev/null
+++ b/tests/ui/suggestions/enum-method-probe.fixed
@@ -0,0 +1,59 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+ fn get(&self) -> u8 {
+ 42
+ }
+}
+
+fn test_result_in_result() -> Result<(), ()> {
+ let res: Result<_, ()> = Ok(Foo);
+ res?.get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP use the `?` operator
+ Ok(())
+}
+
+async fn async_test_result_in_result() -> Result<(), ()> {
+ let res: Result<_, ()> = Ok(Foo);
+ res?.get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP use the `?` operator
+ Ok(())
+}
+
+fn test_result_in_unit_return() {
+ let res: Result<_, ()> = Ok(Foo);
+ res.expect("REASON").get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+async fn async_test_result_in_unit_return() {
+ let res: Result<_, ()> = Ok(Foo);
+ res.expect("REASON").get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+fn test_option_in_option() -> Option<()> {
+ let res: Option<_> = Some(Foo);
+ res?.get();
+ //~^ ERROR no method named `get` found for enum `Option` in the current scope
+ //~| HELP use the `?` operator
+ Some(())
+}
+
+fn test_option_in_unit_return() {
+ let res: Option<_> = Some(Foo);
+ res.expect("REASON").get();
+ //~^ ERROR no method named `get` found for enum `Option` in the current scope
+ //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs
new file mode 100644
index 000000000..18ea8ed8a
--- /dev/null
+++ b/tests/ui/suggestions/enum-method-probe.rs
@@ -0,0 +1,59 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+ fn get(&self) -> u8 {
+ 42
+ }
+}
+
+fn test_result_in_result() -> Result<(), ()> {
+ let res: Result<_, ()> = Ok(Foo);
+ res.get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP use the `?` operator
+ Ok(())
+}
+
+async fn async_test_result_in_result() -> Result<(), ()> {
+ let res: Result<_, ()> = Ok(Foo);
+ res.get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP use the `?` operator
+ Ok(())
+}
+
+fn test_result_in_unit_return() {
+ let res: Result<_, ()> = Ok(Foo);
+ res.get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+async fn async_test_result_in_unit_return() {
+ let res: Result<_, ()> = Ok(Foo);
+ res.get();
+ //~^ ERROR no method named `get` found for enum `Result` in the current scope
+ //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+fn test_option_in_option() -> Option<()> {
+ let res: Option<_> = Some(Foo);
+ res.get();
+ //~^ ERROR no method named `get` found for enum `Option` in the current scope
+ //~| HELP use the `?` operator
+ Some(())
+}
+
+fn test_option_in_unit_return() {
+ let res: Option<_> = Some(Foo);
+ res.get();
+ //~^ ERROR no method named `get` found for enum `Option` in the current scope
+ //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr
new file mode 100644
index 000000000..6ed14984f
--- /dev/null
+++ b/tests/ui/suggestions/enum-method-probe.stderr
@@ -0,0 +1,99 @@
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+ --> $DIR/enum-method-probe.rs:24:9
+ |
+LL | res.get();
+ | ^^^ method not found in `Result<Foo, ()>`
+ |
+note: the method `get` exists on the type `Foo`
+ --> $DIR/enum-method-probe.rs:9:5
+ |
+LL | fn get(&self) -> u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller
+ |
+LL | res?.get();
+ | +
+
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+ --> $DIR/enum-method-probe.rs:39:9
+ |
+LL | res.get();
+ | ^^^ method not found in `Result<Foo, ()>`
+ |
+note: the method `get` exists on the type `Foo`
+ --> $DIR/enum-method-probe.rs:9:5
+ |
+LL | fn get(&self) -> u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+ |
+LL | res.expect("REASON").get();
+ | +++++++++++++++++
+
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+ --> $DIR/enum-method-probe.rs:16:9
+ |
+LL | res.get();
+ | ^^^ method not found in `Result<Foo, ()>`
+ |
+note: the method `get` exists on the type `Foo`
+ --> $DIR/enum-method-probe.rs:9:5
+ |
+LL | fn get(&self) -> u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller
+ |
+LL | res?.get();
+ | +
+
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+ --> $DIR/enum-method-probe.rs:32:9
+ |
+LL | res.get();
+ | ^^^ method not found in `Result<Foo, ()>`
+ |
+note: the method `get` exists on the type `Foo`
+ --> $DIR/enum-method-probe.rs:9:5
+ |
+LL | fn get(&self) -> u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+ |
+LL | res.expect("REASON").get();
+ | +++++++++++++++++
+
+error[E0599]: no method named `get` found for enum `Option` in the current scope
+ --> $DIR/enum-method-probe.rs:46:9
+ |
+LL | res.get();
+ | ^^^ method not found in `Option<Foo>`
+ |
+note: the method `get` exists on the type `Foo`
+ --> $DIR/enum-method-probe.rs:9:5
+ |
+LL | fn get(&self) -> u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+help: use the `?` operator to extract the `Foo` value, propagating an `Option::None` value to the caller
+ |
+LL | res?.get();
+ | +
+
+error[E0599]: no method named `get` found for enum `Option` in the current scope
+ --> $DIR/enum-method-probe.rs:54:9
+ |
+LL | res.get();
+ | ^^^ method not found in `Option<Foo>`
+ |
+note: the method `get` exists on the type `Foo`
+ --> $DIR/enum-method-probe.rs:9:5
+ |
+LL | fn get(&self) -> u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
+ |
+LL | res.expect("REASON").get();
+ | +++++++++++++++++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/enum-variant-arg-mismatch.rs b/tests/ui/suggestions/enum-variant-arg-mismatch.rs
new file mode 100644
index 000000000..8de5bae92
--- /dev/null
+++ b/tests/ui/suggestions/enum-variant-arg-mismatch.rs
@@ -0,0 +1,10 @@
+pub enum Sexpr<'a> {
+ Ident(&'a str),
+}
+
+fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {}
+
+fn main() {
+ map(Sexpr::Ident);
+ //~^ ERROR type mismatch in function arguments
+}
diff --git a/tests/ui/suggestions/enum-variant-arg-mismatch.stderr b/tests/ui/suggestions/enum-variant-arg-mismatch.stderr
new file mode 100644
index 000000000..f76019b70
--- /dev/null
+++ b/tests/ui/suggestions/enum-variant-arg-mismatch.stderr
@@ -0,0 +1,22 @@
+error[E0631]: type mismatch in function arguments
+ --> $DIR/enum-variant-arg-mismatch.rs:8:9
+ |
+LL | Ident(&'a str),
+ | ----- found signature defined here
+...
+LL | map(Sexpr::Ident);
+ | --- ^^^^^^^^^^^^ expected due to this
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: expected function signature `fn(String) -> _`
+ found function signature `fn(&str) -> _`
+note: required by a bound in `map`
+ --> $DIR/enum-variant-arg-mismatch.rs:5:15
+ |
+LL | fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs
new file mode 100644
index 000000000..7e9c5492d
--- /dev/null
+++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs
@@ -0,0 +1,33 @@
+// edition:2018
+#![allow(dead_code)]
+use std::future::Future;
+use std::pin::Pin;
+
+type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
+// ^^^^^^^^^ This would come from the `futures` crate in real code.
+
+fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ // We could instead use an `async` block, but this way we have no std spans.
+ x //~ ERROR mismatched types
+}
+
+fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ Box::new(x) //~ ERROR mismatched types
+}
+
+fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ Pin::new(x) //~ ERROR mismatched types
+ //~^ ERROR E0277
+}
+
+fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ Pin::new(Box::new(x)) //~ ERROR E0277
+}
+
+fn zap() -> BoxFuture<'static, i32> {
+ async { //~ ERROR mismatched types
+ 42
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
new file mode 100644
index 000000000..b1e04dab8
--- /dev/null
+++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -0,0 +1,94 @@
+error[E0308]: mismatched types
+ --> $DIR/expected-boxed-future-isnt-pinned.rs:11:5
+ |
+LL | fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ | - this type parameter ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
+LL | // We could instead use an `async` block, but this way we have no std spans.
+LL | x
+ | ^ expected struct `Pin`, found type parameter `F`
+ |
+ = note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
+ found type parameter `F`
+help: you need to pin and box this expression
+ |
+LL | Box::pin(x)
+ | +++++++++ +
+
+error[E0308]: mismatched types
+ --> $DIR/expected-boxed-future-isnt-pinned.rs:15:5
+ |
+LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ | ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
+LL | Box::new(x)
+ | ^^^^^^^^^^^ expected struct `Pin`, found struct `Box`
+ |
+ = note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
+ found struct `Box<F>`
+ = help: use `Box::pin`
+
+error[E0308]: mismatched types
+ --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
+ |
+LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
+ | - this type parameter
+LL | Pin::new(x)
+ | -------- ^ expected struct `Box`, found type parameter `F`
+ | |
+ | arguments to this function are incorrect
+ | help: use `Box::pin` to pin and box this expression: `Box::pin`
+ |
+ = note: expected struct `Box<dyn Future<Output = i32> + Send>`
+ found type parameter `F`
+note: associated function defined here
+ --> $SRC_DIR/core/src/pin.rs:LL:COL
+
+error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
+ --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
+ |
+LL | Pin::new(x)
+ | -------- ^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: consider using `Box::pin`
+note: required by a bound in `Pin::<P>::new`
+ --> $SRC_DIR/core/src/pin.rs:LL:COL
+
+error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
+ --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
+ |
+LL | Pin::new(Box::new(x))
+ | -------- ^^^^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: consider using `Box::pin`
+note: required by a bound in `Pin::<P>::new`
+ --> $SRC_DIR/core/src/pin.rs:LL:COL
+
+error[E0308]: mismatched types
+ --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
+ |
+LL | / async {
+LL | | 42
+LL | | }
+ | | ^
+ | | |
+ | |_____expected struct `Pin`, found `async` block
+ | arguments to this function are incorrect
+ |
+ = note: expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
+ found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
+note: function defined here
+ --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+help: you need to pin and box this expression
+ |
+LL ~ Box::pin(async {
+LL | 42
+LL ~ })
+ |
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/field-access-considering-privacy.rs b/tests/ui/suggestions/field-access-considering-privacy.rs
new file mode 100644
index 000000000..3de06b214
--- /dev/null
+++ b/tests/ui/suggestions/field-access-considering-privacy.rs
@@ -0,0 +1,35 @@
+use a::TyCtxt;
+
+mod a {
+ use std::ops::Deref;
+ pub struct TyCtxt<'tcx> {
+ gcx: &'tcx GlobalCtxt<'tcx>,
+ }
+
+ impl<'tcx> Deref for TyCtxt<'tcx> {
+ type Target = &'tcx GlobalCtxt<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.gcx
+ }
+ }
+
+ pub struct GlobalCtxt<'tcx> {
+ pub sess: &'tcx Session,
+ _t: &'tcx (),
+ }
+
+ pub struct Session {
+ pub opts: (),
+ }
+}
+
+mod b {
+ fn foo<'tcx>(tcx: crate::TyCtxt<'tcx>) {
+ tcx.opts;
+ //~^ ERROR no field `opts` on type `TyCtxt<'tcx>`
+ //~| HELP one of the expressions' fields has a field of the same name
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/field-access-considering-privacy.stderr b/tests/ui/suggestions/field-access-considering-privacy.stderr
new file mode 100644
index 000000000..cbf6f3d10
--- /dev/null
+++ b/tests/ui/suggestions/field-access-considering-privacy.stderr
@@ -0,0 +1,14 @@
+error[E0609]: no field `opts` on type `TyCtxt<'tcx>`
+ --> $DIR/field-access-considering-privacy.rs:29:13
+ |
+LL | tcx.opts;
+ | ^^^^ unknown field
+ |
+help: one of the expressions' fields has a field of the same name
+ |
+LL | tcx.sess.opts;
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/suggestions/field-access.fixed b/tests/ui/suggestions/field-access.fixed
new file mode 100644
index 000000000..ed9aef6e3
--- /dev/null
+++ b/tests/ui/suggestions/field-access.fixed
@@ -0,0 +1,35 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct A {
+ b: B,
+}
+
+enum B {
+ Fst,
+ Snd,
+}
+
+union Foo {
+ bar: u32,
+ qux: f32,
+}
+
+fn main() {
+ let a = A { b: B::Fst };
+ if let B::Fst = a.b {}; //~ ERROR mismatched types [E0308]
+ //~^ HELP you might have meant to use field `b` whose type is `B`
+ match a.b {
+ //~^ HELP you might have meant to use field `b` whose type is `B`
+ //~| HELP you might have meant to use field `b` whose type is `B`
+ B::Fst => (), //~ ERROR mismatched types [E0308]
+ B::Snd => (), //~ ERROR mismatched types [E0308]
+ }
+
+ let foo = Foo { bar: 42 };
+ match unsafe { foo.bar } {
+ //~^ HELP you might have meant to use field `bar` whose type is `u32`
+ 1u32 => (), //~ ERROR mismatched types [E0308]
+ _ => (),
+ }
+}
diff --git a/tests/ui/suggestions/field-access.rs b/tests/ui/suggestions/field-access.rs
new file mode 100644
index 000000000..d80488e8a
--- /dev/null
+++ b/tests/ui/suggestions/field-access.rs
@@ -0,0 +1,35 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct A {
+ b: B,
+}
+
+enum B {
+ Fst,
+ Snd,
+}
+
+union Foo {
+ bar: u32,
+ qux: f32,
+}
+
+fn main() {
+ let a = A { b: B::Fst };
+ if let B::Fst = a {}; //~ ERROR mismatched types [E0308]
+ //~^ HELP you might have meant to use field `b` whose type is `B`
+ match a {
+ //~^ HELP you might have meant to use field `b` whose type is `B`
+ //~| HELP you might have meant to use field `b` whose type is `B`
+ B::Fst => (), //~ ERROR mismatched types [E0308]
+ B::Snd => (), //~ ERROR mismatched types [E0308]
+ }
+
+ let foo = Foo { bar: 42 };
+ match foo {
+ //~^ HELP you might have meant to use field `bar` whose type is `u32`
+ 1u32 => (), //~ ERROR mismatched types [E0308]
+ _ => (),
+ }
+}
diff --git a/tests/ui/suggestions/field-access.stderr b/tests/ui/suggestions/field-access.stderr
new file mode 100644
index 000000000..b9f0f788b
--- /dev/null
+++ b/tests/ui/suggestions/field-access.stderr
@@ -0,0 +1,67 @@
+error[E0308]: mismatched types
+ --> $DIR/field-access.rs:20:12
+ |
+LL | Fst,
+ | --- unit variant defined here
+...
+LL | if let B::Fst = a {};
+ | ^^^^^^ - this expression has type `A`
+ | |
+ | expected struct `A`, found enum `B`
+ |
+help: you might have meant to use field `b` whose type is `B`
+ |
+LL | if let B::Fst = a.b {};
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/field-access.rs:25:9
+ |
+LL | Fst,
+ | --- unit variant defined here
+...
+LL | match a {
+ | - this expression has type `A`
+...
+LL | B::Fst => (),
+ | ^^^^^^ expected struct `A`, found enum `B`
+ |
+help: you might have meant to use field `b` whose type is `B`
+ |
+LL | match a.b {
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/field-access.rs:26:9
+ |
+LL | Snd,
+ | --- unit variant defined here
+...
+LL | match a {
+ | - this expression has type `A`
+...
+LL | B::Snd => (),
+ | ^^^^^^ expected struct `A`, found enum `B`
+ |
+help: you might have meant to use field `b` whose type is `B`
+ |
+LL | match a.b {
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/field-access.rs:32:9
+ |
+LL | match foo {
+ | --- this expression has type `Foo`
+LL |
+LL | 1u32 => (),
+ | ^^^^ expected union `Foo`, found `u32`
+ |
+help: you might have meant to use field `bar` whose type is `u32`
+ |
+LL | match unsafe { foo.bar } {
+ | ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/field-has-method.rs b/tests/ui/suggestions/field-has-method.rs
new file mode 100644
index 000000000..980000151
--- /dev/null
+++ b/tests/ui/suggestions/field-has-method.rs
@@ -0,0 +1,23 @@
+struct Kind;
+
+struct Ty {
+ kind: Kind,
+}
+
+impl Ty {
+ fn kind(&self) -> Kind {
+ todo!()
+ }
+}
+
+struct InferOk<T> {
+ value: T,
+ predicates: Vec<()>,
+}
+
+fn foo(i: InferOk<Ty>) {
+ let k = i.kind();
+ //~^ no method named `kind` found for struct `InferOk` in the current scope
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/field-has-method.stderr b/tests/ui/suggestions/field-has-method.stderr
new file mode 100644
index 000000000..def164017
--- /dev/null
+++ b/tests/ui/suggestions/field-has-method.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `kind` found for struct `InferOk` in the current scope
+ --> $DIR/field-has-method.rs:19:15
+ |
+LL | struct InferOk<T> {
+ | ----------------- method `kind` not found for this struct
+...
+LL | let k = i.kind();
+ | ^^^^ method not found in `InferOk<Ty>`
+ |
+help: one of the expressions' fields has a method of the same name
+ |
+LL | let k = i.value.kind();
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
new file mode 100644
index 000000000..4303e5c54
--- /dev/null
+++ b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
@@ -0,0 +1,20 @@
+// edition:2018
+trait T {
+ type O;
+}
+
+struct S;
+
+impl T for S {
+ type O = ();
+}
+
+fn foo() -> impl T<O=()> { S }
+
+fn bar(f: impl T<O=()>) {}
+
+fn main() {
+ bar(foo); //~ERROR E0277
+ let closure = || S;
+ bar(closure); //~ERROR E0277
+}
diff --git a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
new file mode 100644
index 000000000..955148315
--- /dev/null
+++ b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -0,0 +1,39 @@
+error[E0277]: the trait bound `fn() -> impl T<O = ()> {foo}: T` is not satisfied
+ --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9
+ |
+LL | bar(foo);
+ | --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `bar`
+ --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
+ |
+LL | fn bar(f: impl T<O=()>) {}
+ | ^^^^^^^ required by this bound in `bar`
+help: use parentheses to call this function
+ |
+LL | bar(foo());
+ | ++
+
+error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied
+ --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9
+ |
+LL | bar(closure);
+ | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `bar`
+ --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
+ |
+LL | fn bar(f: impl T<O=()>) {}
+ | ^^^^^^^ required by this bound in `bar`
+help: use parentheses to call this closure
+ |
+LL | bar(closure());
+ | ++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/fn-missing-lifetime-in-item.rs b/tests/ui/suggestions/fn-missing-lifetime-in-item.rs
new file mode 100644
index 000000000..dac6610b3
--- /dev/null
+++ b/tests/ui/suggestions/fn-missing-lifetime-in-item.rs
@@ -0,0 +1,8 @@
+struct S1<F: Fn(&i32, &i32) -> &'a i32>(F); //~ ERROR use of undeclared lifetime name `'a`
+struct S2<F: Fn(&i32, &i32) -> &i32>(F); //~ ERROR missing lifetime specifier
+struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear
+struct S4<F: for<'x> Fn(&'x i32, &'x i32) -> &'x i32>(F);
+const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None;
+//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear
+fn main() {}
diff --git a/tests/ui/suggestions/fn-missing-lifetime-in-item.stderr b/tests/ui/suggestions/fn-missing-lifetime-in-item.stderr
new file mode 100644
index 000000000..6d7c3d730
--- /dev/null
+++ b/tests/ui/suggestions/fn-missing-lifetime-in-item.stderr
@@ -0,0 +1,48 @@
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/fn-missing-lifetime-in-item.rs:1:33
+ |
+LL | struct S1<F: Fn(&i32, &i32) -> &'a i32>(F);
+ | ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+ | +++++++
+help: consider introducing lifetime `'a` here
+ |
+LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
+ | +++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/fn-missing-lifetime-in-item.rs:2:32
+ |
+LL | struct S2<F: Fn(&i32, &i32) -> &i32>(F);
+ | ---- ---- ^ 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 argument 1 or argument 2
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | struct S2<F: for<'a> Fn(&'a i32, &'a i32) -> &'a i32>(F);
+ | +++++++ ++ ++ ++
+help: consider introducing a named lifetime parameter
+ |
+LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F);
+ | +++ ++ ++ ++
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+ --> $DIR/fn-missing-lifetime-in-item.rs:3:40
+ |
+LL | struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+ | ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+ --> $DIR/fn-missing-lifetime-in-item.rs:6:55
+ |
+LL | const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None;
+ | ^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0106, E0261, E0582.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/fn-needing-specified-return-type-param.rs b/tests/ui/suggestions/fn-needing-specified-return-type-param.rs
new file mode 100644
index 000000000..bcc91b5cb
--- /dev/null
+++ b/tests/ui/suggestions/fn-needing-specified-return-type-param.rs
@@ -0,0 +1,7 @@
+fn f<A>() -> A { unimplemented!() }
+fn foo() {
+ let _ = f;
+ //~^ ERROR type annotations needed
+ //~| HELP consider specifying the generic argument
+}
+fn main() {}
diff --git a/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr b/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr
new file mode 100644
index 000000000..9dea667fb
--- /dev/null
+++ b/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+ --> $DIR/fn-needing-specified-return-type-param.rs:3:13
+ |
+LL | let _ = f;
+ | ^ cannot infer type of the type parameter `A` declared on the function `f`
+ |
+help: consider specifying the generic argument
+ |
+LL | let _ = f::<A>;
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs
new file mode 100644
index 000000000..ae1dbfeea
--- /dev/null
+++ b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs
@@ -0,0 +1,19 @@
+fn foo(a: usize, b: usize) -> usize { a }
+
+struct S(usize, usize);
+
+trait T {
+ fn baz(x: usize, y: usize) -> usize { x }
+}
+
+fn main() {
+ let _: usize = foo(_, _);
+ //~^ ERROR `_` can only be used on the left-hand side of an assignment
+ //~| ERROR `_` can only be used on the left-hand side of an assignment
+ let _: S = S(_, _);
+ //~^ ERROR `_` can only be used on the left-hand side of an assignment
+ //~| ERROR `_` can only be used on the left-hand side of an assignment
+ let _: usize = T::baz(_, _);
+ //~^ ERROR `_` can only be used on the left-hand side of an assignment
+ //~| ERROR `_` can only be used on the left-hand side of an assignment
+}
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr
new file mode 100644
index 000000000..aa5620306
--- /dev/null
+++ b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr
@@ -0,0 +1,38 @@
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24
+ |
+LL | let _: usize = foo(_, _);
+ | ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27
+ |
+LL | let _: usize = foo(_, _);
+ | ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18
+ |
+LL | let _: S = S(_, _);
+ | ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21
+ |
+LL | let _: S = S(_, _);
+ | ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27
+ |
+LL | let _: usize = T::baz(_, _);
+ | ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+ --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30
+ |
+LL | let _: usize = T::baz(_, _);
+ | ^ `_` not allowed here
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.rs b/tests/ui/suggestions/fn-or-tuple-struct-without-args.rs
new file mode 100644
index 000000000..dd5af3e34
--- /dev/null
+++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.rs
@@ -0,0 +1,47 @@
+fn foo(a: usize, b: usize) -> usize { a }
+
+fn bar() -> usize { 42 }
+
+struct S(usize, usize);
+enum E {
+ A(usize),
+ B { a: usize },
+}
+struct V();
+
+trait T {
+ fn baz(x: usize, y: usize) -> usize { x }
+ fn bat(x: usize) -> usize { 42 }
+ fn bax(x: usize) -> usize { 42 }
+ fn bach(x: usize) -> usize;
+ fn ban(&self) -> usize { 42 }
+ fn bal(&self) -> usize;
+}
+
+struct X;
+
+impl T for X {
+ fn bach(x: usize) -> usize { 42 }
+ fn bal(&self) -> usize { 42 }
+}
+
+fn main() {
+ let _: usize = foo; //~ ERROR mismatched types
+ let _: S = S; //~ ERROR mismatched types
+ let _: usize = bar; //~ ERROR mismatched types
+ let _: V = V; //~ ERROR mismatched types
+ let _: usize = T::baz; //~ ERROR mismatched types
+ let _: usize = T::bat; //~ ERROR mismatched types
+ let _: E = E::A; //~ ERROR mismatched types
+ let _: E = E::B; //~ ERROR expected value, found struct variant `E::B`
+ let _: usize = X::baz; //~ ERROR mismatched types
+ let _: usize = X::bat; //~ ERROR mismatched types
+ let _: usize = X::bax; //~ ERROR mismatched types
+ let _: usize = X::bach; //~ ERROR mismatched types
+ let _: usize = X::ban; //~ ERROR mismatched types
+ let _: usize = X::bal; //~ ERROR mismatched types
+ let _: usize = X.ban; //~ ERROR attempted to take value of method
+ let _: usize = X.bal; //~ ERROR attempted to take value of method
+ let closure = || 42;
+ let _: usize = closure; //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
new file mode 100644
index 000000000..4cbcd31fa
--- /dev/null
+++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -0,0 +1,283 @@
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:29:20
+ |
+LL | fn foo(a: usize, b: usize) -> usize { a }
+ | ----------------------------------- function `foo` defined here
+...
+LL | let _: usize = foo;
+ | ----- ^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize, usize) -> usize {foo}`
+help: use parentheses to call this function
+ |
+LL | let _: usize = foo(/* usize */, /* usize */);
+ | ++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:30:16
+ |
+LL | struct S(usize, usize);
+ | -------- `S` defines a struct constructor here, which should be called
+...
+LL | let _: S = S;
+ | - ^ expected struct `S`, found struct constructor
+ | |
+ | expected due to this
+ |
+ = note: expected struct `S`
+ found struct constructor `fn(usize, usize) -> S {S}`
+help: use parentheses to construct this tuple struct
+ |
+LL | let _: S = S(/* usize */, /* usize */);
+ | ++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:31:20
+ |
+LL | fn bar() -> usize { 42 }
+ | ----------------- function `bar` defined here
+...
+LL | let _: usize = bar;
+ | ----- ^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn() -> usize {bar}`
+help: use parentheses to call this function
+ |
+LL | let _: usize = bar();
+ | ++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:32:16
+ |
+LL | struct V();
+ | -------- `V` defines a struct constructor here, which should be called
+...
+LL | let _: V = V;
+ | - ^ expected struct `V`, found struct constructor
+ | |
+ | expected due to this
+ |
+ = note: expected struct `V`
+ found struct constructor `fn() -> V {V}`
+help: use parentheses to construct this tuple struct
+ |
+LL | let _: V = V();
+ | ++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:33:20
+ |
+LL | fn baz(x: usize, y: usize) -> usize { x }
+ | ----------------------------------- associated function `baz` defined here
+...
+LL | let _: usize = T::baz;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize, usize) -> usize {<_ as T>::baz}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = T::baz(/* usize */, /* usize */);
+ | ++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:34:20
+ |
+LL | fn bat(x: usize) -> usize { 42 }
+ | ------------------------- associated function `bat` defined here
+...
+LL | let _: usize = T::bat;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize) -> usize {<_ as T>::bat}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = T::bat(/* usize */);
+ | +++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:35:16
+ |
+LL | A(usize),
+ | - `A` defines an enum variant constructor here, which should be called
+...
+LL | let _: E = E::A;
+ | - ^^^^ expected enum `E`, found enum constructor
+ | |
+ | expected due to this
+ |
+ = note: expected enum `E`
+ found enum constructor `fn(usize) -> E {E::A}`
+help: use parentheses to construct this tuple variant
+ |
+LL | let _: E = E::A(/* usize */);
+ | +++++++++++++
+
+error[E0533]: expected value, found struct variant `E::B`
+ --> $DIR/fn-or-tuple-struct-without-args.rs:36:16
+ |
+LL | let _: E = E::B;
+ | ^^^^ not a value
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:37:20
+ |
+LL | fn baz(x: usize, y: usize) -> usize { x }
+ | ----------------------------------- associated function `baz` defined here
+...
+LL | let _: usize = X::baz;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize, usize) -> usize {<X as T>::baz}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = X::baz(/* usize */, /* usize */);
+ | ++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:38:20
+ |
+LL | fn bat(x: usize) -> usize { 42 }
+ | ------------------------- associated function `bat` defined here
+...
+LL | let _: usize = X::bat;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize) -> usize {<X as T>::bat}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = X::bat(/* usize */);
+ | +++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:39:20
+ |
+LL | fn bax(x: usize) -> usize { 42 }
+ | ------------------------- associated function `bax` defined here
+...
+LL | let _: usize = X::bax;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize) -> usize {<X as T>::bax}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = X::bax(/* usize */);
+ | +++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:40:20
+ |
+LL | fn bach(x: usize) -> usize;
+ | --------------------------- associated function `bach` defined here
+...
+LL | let _: usize = X::bach;
+ | ----- ^^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `fn(usize) -> usize {<X as T>::bach}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = X::bach(/* usize */);
+ | +++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:41:20
+ |
+LL | fn ban(&self) -> usize { 42 }
+ | ---------------------- associated function `ban` defined here
+...
+LL | let _: usize = X::ban;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `for<'a> fn(&'a X) -> usize {<X as T>::ban}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = X::ban(/* &X */);
+ | ++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:42:20
+ |
+LL | fn bal(&self) -> usize;
+ | ----------------------- associated function `bal` defined here
+...
+LL | let _: usize = X::bal;
+ | ----- ^^^^^^ expected `usize`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found fn item `for<'a> fn(&'a X) -> usize {<X as T>::bal}`
+help: use parentheses to call this associated function
+ |
+LL | let _: usize = X::bal(/* &X */);
+ | ++++++++++
+
+error[E0615]: attempted to take value of method `ban` on type `X`
+ --> $DIR/fn-or-tuple-struct-without-args.rs:43:22
+ |
+LL | let _: usize = X.ban;
+ | ^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | let _: usize = X.ban();
+ | ++
+
+error[E0615]: attempted to take value of method `bal` on type `X`
+ --> $DIR/fn-or-tuple-struct-without-args.rs:44:22
+ |
+LL | let _: usize = X.bal;
+ | ^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | let _: usize = X.bal();
+ | ++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-or-tuple-struct-without-args.rs:46:20
+ |
+LL | let closure = || 42;
+ | -- the found closure
+LL | let _: usize = closure;
+ | ----- ^^^^^^^ expected `usize`, found closure
+ | |
+ | expected due to this
+ |
+ = note: expected type `usize`
+ found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:21]`
+help: use parentheses to call this closure
+ |
+LL | let _: usize = closure();
+ | ++
+
+error: aborting due to 17 previous errors
+
+Some errors have detailed explanations: E0308, E0533, E0615.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/fn-to-method-deeply-nested.rs b/tests/ui/suggestions/fn-to-method-deeply-nested.rs
new file mode 100644
index 000000000..58ee3d640
--- /dev/null
+++ b/tests/ui/suggestions/fn-to-method-deeply-nested.rs
@@ -0,0 +1,13 @@
+fn main() -> Result<(), ()> {
+ a(b(c(d(e(
+ //~^ ERROR cannot find function `a` in this scope
+ //~| ERROR cannot find function `b` in this scope
+ //~| ERROR cannot find function `c` in this scope
+ //~| ERROR cannot find function `d` in this scope
+ //~| ERROR cannot find function `e` in this scope
+ z????????????????????????????????????????????????????????????????????????????????????????
+ ?????????????????????????????????????????????????????????????????????????????????????????
+ ??????????????????????????????????????????????????????????????????
+ //~^^^ ERROR cannot find value `z` in this scope
+ )))))
+}
diff --git a/tests/ui/suggestions/fn-to-method-deeply-nested.stderr b/tests/ui/suggestions/fn-to-method-deeply-nested.stderr
new file mode 100644
index 000000000..ce813ea7a
--- /dev/null
+++ b/tests/ui/suggestions/fn-to-method-deeply-nested.stderr
@@ -0,0 +1,39 @@
+error[E0425]: cannot find value `z` in this scope
+ --> $DIR/fn-to-method-deeply-nested.rs:8:9
+ |
+LL | z????????????????????????????????????????????????????????????????????????????????????????
+ | ^ not found in this scope
+
+error[E0425]: cannot find function `e` in this scope
+ --> $DIR/fn-to-method-deeply-nested.rs:2:13
+ |
+LL | a(b(c(d(e(
+ | ^ not found in this scope
+
+error[E0425]: cannot find function `d` in this scope
+ --> $DIR/fn-to-method-deeply-nested.rs:2:11
+ |
+LL | a(b(c(d(e(
+ | ^ not found in this scope
+
+error[E0425]: cannot find function `c` in this scope
+ --> $DIR/fn-to-method-deeply-nested.rs:2:9
+ |
+LL | a(b(c(d(e(
+ | ^ not found in this scope
+
+error[E0425]: cannot find function `b` in this scope
+ --> $DIR/fn-to-method-deeply-nested.rs:2:7
+ |
+LL | a(b(c(d(e(
+ | ^ not found in this scope
+
+error[E0425]: cannot find function `a` in this scope
+ --> $DIR/fn-to-method-deeply-nested.rs:2:5
+ |
+LL | a(b(c(d(e(
+ | ^ not found in this scope
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/fn-to-method.rs b/tests/ui/suggestions/fn-to-method.rs
new file mode 100644
index 000000000..9a35c3efc
--- /dev/null
+++ b/tests/ui/suggestions/fn-to-method.rs
@@ -0,0 +1,19 @@
+struct Foo;
+
+impl Foo {
+ fn bar(self) {}
+}
+
+fn main() {
+ let x = cmp(&1, &2);
+ //~^ ERROR cannot find function `cmp` in this scope
+ //~| HELP use the `.` operator to call the method `Ord::cmp` on `&{integer}`
+
+ let y = len([1, 2, 3]);
+ //~^ ERROR cannot find function `len` in this scope
+ //~| HELP use the `.` operator to call the method `len` on `&[{integer}]`
+
+ let z = bar(Foo);
+ //~^ ERROR cannot find function `bar` in this scope
+ //~| HELP use the `.` operator to call the method `bar` on `Foo`
+}
diff --git a/tests/ui/suggestions/fn-to-method.stderr b/tests/ui/suggestions/fn-to-method.stderr
new file mode 100644
index 000000000..36c17e60d
--- /dev/null
+++ b/tests/ui/suggestions/fn-to-method.stderr
@@ -0,0 +1,38 @@
+error[E0425]: cannot find function `cmp` in this scope
+ --> $DIR/fn-to-method.rs:8:13
+ |
+LL | let x = cmp(&1, &2);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `Ord::cmp` on `&{integer}`
+ |
+LL | let x = (&1).cmp(&2);
+ | ~ ~~~~~~~~~
+
+error[E0425]: cannot find function `len` in this scope
+ --> $DIR/fn-to-method.rs:12:13
+ |
+LL | let y = len([1, 2, 3]);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `len` on `&[{integer}]`
+ |
+LL - let y = len([1, 2, 3]);
+LL + let y = [1, 2, 3].len();
+ |
+
+error[E0425]: cannot find function `bar` in this scope
+ --> $DIR/fn-to-method.rs:16:13
+ |
+LL | let z = bar(Foo);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `bar` on `Foo`
+ |
+LL - let z = bar(Foo);
+LL + let z = Foo.bar();
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/fn-trait-notation.fixed b/tests/ui/suggestions/fn-trait-notation.fixed
new file mode 100644
index 000000000..cf940f4e9
--- /dev/null
+++ b/tests/ui/suggestions/fn-trait-notation.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+fn e0658<F, G, H>(f: F, g: G, h: H) -> i32
+where
+ F: Fn(i32) -> i32, //~ ERROR E0658
+ G: Fn(i32, i32) -> (i32, i32), //~ ERROR E0658
+ H: Fn(i32) -> i32, //~ ERROR E0658
+{
+ f(3);
+ g(3, 4);
+ h(3)
+}
+
+fn main() {
+ e0658(
+ |a| a,
+ |a, b| (b, a),
+ |a| a,
+ );
+}
diff --git a/tests/ui/suggestions/fn-trait-notation.rs b/tests/ui/suggestions/fn-trait-notation.rs
new file mode 100644
index 000000000..f0bb03315
--- /dev/null
+++ b/tests/ui/suggestions/fn-trait-notation.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+fn e0658<F, G, H>(f: F, g: G, h: H) -> i32
+where
+ F: Fn<i32, Output = i32>, //~ ERROR E0658
+ G: Fn<(i32, i32, ), Output = (i32, i32)>, //~ ERROR E0658
+ H: Fn<(i32,), Output = i32>, //~ ERROR E0658
+{
+ f(3);
+ g(3, 4);
+ h(3)
+}
+
+fn main() {
+ e0658(
+ |a| a,
+ |a, b| (b, a),
+ |a| a,
+ );
+}
diff --git a/tests/ui/suggestions/fn-trait-notation.stderr b/tests/ui/suggestions/fn-trait-notation.stderr
new file mode 100644
index 000000000..3e3b54174
--- /dev/null
+++ b/tests/ui/suggestions/fn-trait-notation.stderr
@@ -0,0 +1,30 @@
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+ --> $DIR/fn-trait-notation.rs:4:8
+ |
+LL | F: Fn<i32, Output = i32>,
+ | ^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32`
+ |
+ = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+ = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+ --> $DIR/fn-trait-notation.rs:5:8
+ |
+LL | G: Fn<(i32, i32, ), Output = (i32, i32)>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32, i32) -> (i32, i32)`
+ |
+ = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+ = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+ --> $DIR/fn-trait-notation.rs:6:8
+ |
+LL | H: Fn<(i32,), Output = i32>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32`
+ |
+ = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+ = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/suggestions/for-i-in-vec.fixed b/tests/ui/suggestions/for-i-in-vec.fixed
new file mode 100644
index 000000000..4f2007bef
--- /dev/null
+++ b/tests/ui/suggestions/for-i-in-vec.fixed
@@ -0,0 +1,27 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Foo {
+ v: Vec<u32>,
+ h: std::collections::HashMap<i32, i32>,
+}
+
+impl Foo {
+ fn bar(&self) {
+ for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+ }
+ for _ in &self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference
+ }
+ }
+}
+
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+ for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference
+ return Some(loader);
+ }
+ None
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/for-i-in-vec.rs b/tests/ui/suggestions/for-i-in-vec.rs
new file mode 100644
index 000000000..55fc7ad4e
--- /dev/null
+++ b/tests/ui/suggestions/for-i-in-vec.rs
@@ -0,0 +1,27 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Foo {
+ v: Vec<u32>,
+ h: std::collections::HashMap<i32, i32>,
+}
+
+impl Foo {
+ fn bar(&self) {
+ for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+ }
+ for _ in self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference
+ }
+ }
+}
+
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+ for loader in *LOADERS { //~ ERROR cannot move out of a shared reference
+ return Some(loader);
+ }
+ None
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/for-i-in-vec.stderr b/tests/ui/suggestions/for-i-in-vec.stderr
new file mode 100644
index 000000000..c5b81e6b8
--- /dev/null
+++ b/tests/ui/suggestions/for-i-in-vec.stderr
@@ -0,0 +1,49 @@
+error[E0507]: cannot move out of `self.v` which is behind a shared reference
+ --> $DIR/for-i-in-vec.rs:11:18
+ |
+LL | for _ in self.v {
+ | ^^^^^^
+ | |
+ | `self.v` moved due to this implicit call to `.into_iter()`
+ | move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
+ |
+note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
+ |
+LL | for _ in &self.v {
+ | +
+
+error[E0507]: cannot move out of `self.h` which is behind a shared reference
+ --> $DIR/for-i-in-vec.rs:13:18
+ |
+LL | for _ in self.h {
+ | ^^^^^^
+ | |
+ | `self.h` moved due to this implicit call to `.into_iter()`
+ | move occurs because `self.h` has type `HashMap<i32, i32>`, which does not implement the `Copy` trait
+ |
+help: consider iterating over a slice of the `HashMap<i32, i32>`'s content to avoid moving into the `for` loop
+ |
+LL | for _ in &self.h {
+ | +
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/for-i-in-vec.rs:21:19
+ |
+LL | for loader in *LOADERS {
+ | ^^^^^^^^
+ | |
+ | value moved due to this implicit call to `.into_iter()`
+ | move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
+ |
+note: `into_iter` takes ownership of the receiver `self`, which moves value
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop
+ |
+LL | for loader in &*LOADERS {
+ | +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/format-borrow.rs b/tests/ui/suggestions/format-borrow.rs
new file mode 100644
index 000000000..599a79fc0
--- /dev/null
+++ b/tests/ui/suggestions/format-borrow.rs
@@ -0,0 +1,10 @@
+fn main() {
+ let a: String = &String::from("a");
+ //~^ ERROR mismatched types
+ let b: String = &format!("b");
+ //~^ ERROR mismatched types
+ let c: String = &mut format!("c");
+ //~^ ERROR mismatched types
+ let d: String = &mut (format!("d"));
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/format-borrow.stderr b/tests/ui/suggestions/format-borrow.stderr
new file mode 100644
index 000000000..8ed2b9c9a
--- /dev/null
+++ b/tests/ui/suggestions/format-borrow.stderr
@@ -0,0 +1,75 @@
+error[E0308]: mismatched types
+ --> $DIR/format-borrow.rs:2:21
+ |
+LL | let a: String = &String::from("a");
+ | ------ ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | |
+ | expected due to this
+ |
+help: consider removing the borrow
+ |
+LL - let a: String = &String::from("a");
+LL + let a: String = String::from("a");
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let a: &String = &String::from("a");
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/format-borrow.rs:4:21
+ |
+LL | let b: String = &format!("b");
+ | ------ ^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | |
+ | expected due to this
+ |
+help: consider removing the borrow
+ |
+LL - let b: String = &format!("b");
+LL + let b: String = format!("b");
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let b: &String = &format!("b");
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/format-borrow.rs:6:21
+ |
+LL | let c: String = &mut format!("c");
+ | ------ ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | |
+ | expected due to this
+ |
+help: consider removing the borrow
+ |
+LL - let c: String = &mut format!("c");
+LL + let c: String = format!("c");
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let c: &mut String = &mut format!("c");
+ | ++++
+
+error[E0308]: mismatched types
+ --> $DIR/format-borrow.rs:8:21
+ |
+LL | let d: String = &mut (format!("d"));
+ | ------ ^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | |
+ | expected due to this
+ |
+help: consider removing the borrow
+ |
+LL - let d: String = &mut (format!("d"));
+LL + let d: String = format!("d"));
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let d: &mut String = &mut (format!("d"));
+ | ++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/if-let-typo.rs b/tests/ui/suggestions/if-let-typo.rs
new file mode 100644
index 000000000..375bd3f03
--- /dev/null
+++ b/tests/ui/suggestions/if-let-typo.rs
@@ -0,0 +1,11 @@
+fn main() {
+ let foo = Some(0);
+ let bar = None;
+ if Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
+ //~^ ERROR mismatched types
+ if Some(foo) = bar {} //~ ERROR mismatched types
+ if 3 = foo {} //~ ERROR mismatched types
+ if Some(3) = foo {} //~ ERROR mismatched types
+ //~^ ERROR invalid left-hand side of assignment
+ if x = 5 {} //~ ERROR cannot find value `x` in this scope
+}
diff --git a/tests/ui/suggestions/if-let-typo.stderr b/tests/ui/suggestions/if-let-typo.stderr
new file mode 100644
index 000000000..02148b7f7
--- /dev/null
+++ b/tests/ui/suggestions/if-let-typo.stderr
@@ -0,0 +1,73 @@
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/if-let-typo.rs:4:13
+ |
+LL | if Some(x) = foo {}
+ | ^ not found in this scope
+ |
+help: you might have meant to use pattern matching
+ |
+LL | if let Some(x) = foo {}
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/if-let-typo.rs:10:8
+ |
+LL | if x = 5 {}
+ | ^ not found in this scope
+ |
+help: you might have meant to use pattern matching
+ |
+LL | if let x = 5 {}
+ | +++
+
+error[E0308]: mismatched types
+ --> $DIR/if-let-typo.rs:4:8
+ |
+LL | if Some(x) = foo {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: consider adding `let`
+ |
+LL | if let Some(x) = foo {}
+ | +++
+
+error[E0308]: mismatched types
+ --> $DIR/if-let-typo.rs:6:8
+ |
+LL | if Some(foo) = bar {}
+ | ^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: consider adding `let`
+ |
+LL | if let Some(foo) = bar {}
+ | +++
+
+error[E0308]: mismatched types
+ --> $DIR/if-let-typo.rs:7:8
+ |
+LL | if 3 = foo {}
+ | ^^^^^^^ expected `bool`, found `()`
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/if-let-typo.rs:8:16
+ |
+LL | if Some(3) = foo {}
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0308]: mismatched types
+ --> $DIR/if-let-typo.rs:8:8
+ |
+LL | if Some(3) = foo {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: consider adding `let`
+ |
+LL | if let Some(3) = foo {}
+ | +++
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0070, E0308, E0425.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/tests/ui/suggestions/if-then-neeing-semi.rs b/tests/ui/suggestions/if-then-neeing-semi.rs
new file mode 100644
index 000000000..b487f013d
--- /dev/null
+++ b/tests/ui/suggestions/if-then-neeing-semi.rs
@@ -0,0 +1,70 @@
+// edition:2018
+
+fn dummy() -> i32 {
+ 42
+}
+
+fn extra_semicolon() {
+ let _ = if true {
+ //~^ NOTE `if` and `else` have incompatible types
+ dummy(); //~ NOTE expected because of this
+ //~^ HELP consider removing this semicolon
+ } else {
+ dummy() //~ ERROR `if` and `else` have incompatible types
+ //~^ NOTE expected `()`, found `i32`
+ };
+}
+
+async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE 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
+async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+
+async fn async_extra_semicolon_same() {
+ let _ = if true {
+ //~^ NOTE `if` and `else` have incompatible types
+ async_dummy(); //~ NOTE expected because of this
+ //~^ HELP consider removing this semicolon
+ } else {
+ async_dummy() //~ ERROR `if` and `else` have incompatible types
+ //~^ NOTE expected `()`, found opaque type
+ //~| NOTE expected unit type `()`
+ //~| HELP consider `await`ing on the `Future`
+ };
+}
+
+async fn async_extra_semicolon_different() {
+ let _ = if true {
+ //~^ NOTE `if` and `else` have incompatible types
+ async_dummy(); //~ NOTE expected because of this
+ //~^ HELP consider removing this semicolon
+ } else {
+ async_dummy2() //~ ERROR `if` and `else` have incompatible types
+ //~^ NOTE expected `()`, found opaque type
+ //~| NOTE expected unit type `()`
+ //~| HELP consider `await`ing on the `Future`
+ };
+}
+
+async fn async_different_futures() {
+ let _ = if true {
+ //~^ NOTE `if` and `else` have incompatible types
+ async_dummy() //~ NOTE expected because of this
+ //~| HELP consider `await`ing on both `Future`s
+ } else {
+ async_dummy2() //~ ERROR `if` and `else` have incompatible types
+ //~^ NOTE expected opaque type, found a different opaque type
+ //~| NOTE expected opaque type `impl Future<Output = ()>`
+ //~| NOTE distinct uses of `impl Trait` result in different opaque types
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr
new file mode 100644
index 000000000..d7c5818ab
--- /dev/null
+++ b/tests/ui/suggestions/if-then-neeing-semi.stderr
@@ -0,0 +1,130 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/if-then-neeing-semi.rs:37:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | |
+LL | | async_dummy();
+ | | -------------- expected because of this
+LL | |
+LL | | } else {
+LL | | async_dummy()
+ | | ^^^^^^^^^^^^^ expected `()`, found opaque type
+... |
+LL | |
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/if-then-neeing-semi.rs:18:24
+ |
+LL | async fn async_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 | async_dummy().await
+ | ++++++
+help: consider removing this semicolon
+ |
+LL - async_dummy();
+LL + async_dummy()
+ |
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/if-then-neeing-semi.rs:50:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | |
+LL | | async_dummy();
+ | | -------------- expected because of this
+LL | |
+LL | | } else {
+LL | | async_dummy2()
+ | | ^^^^^^^^^^^^^^ expected `()`, found opaque type
+... |
+LL | |
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/if-then-neeing-semi.rs:24:25
+ |
+LL | async fn async_dummy2() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected unit type `()`
+ found opaque type `impl Future<Output = ()>`
+help: consider `await`ing on the `Future`
+ |
+LL | async_dummy2().await
+ | ++++++
+help: consider removing this semicolon and boxing the expressions
+ |
+LL ~ Box::new(async_dummy())
+LL |
+LL | } else {
+LL ~ Box::new(async_dummy2())
+ |
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/if-then-neeing-semi.rs:63:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | |
+LL | | async_dummy()
+ | | ------------- expected because of this
+LL | |
+LL | | } else {
+LL | | async_dummy2()
+ | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
+... |
+LL | |
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/if-then-neeing-semi.rs:18:24
+ |
+LL | async fn async_dummy() {}
+ | ^ checked the `Output` of this `async fn`, expected opaque type
+note: while checking the return type of the `async fn`
+ --> $DIR/if-then-neeing-semi.rs:24:25
+ |
+LL | async fn async_dummy2() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>)
+ found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>)
+ = note: distinct uses of `impl Trait` result in different opaque types
+help: consider `await`ing on both `Future`s
+ |
+LL ~ async_dummy().await
+LL |
+LL | } else {
+LL ~ async_dummy2().await
+ |
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/if-then-neeing-semi.rs:13:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | |
+LL | | dummy();
+ | | --------
+ | | | |
+ | | | help: consider removing this semicolon
+ | | expected because of this
+LL | |
+LL | | } else {
+LL | | dummy()
+ | | ^^^^^^^ expected `()`, found `i32`
+LL | |
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/ignore-nested-field-binding.fixed b/tests/ui/suggestions/ignore-nested-field-binding.fixed
new file mode 100644
index 000000000..1dc44838e
--- /dev/null
+++ b/tests/ui/suggestions/ignore-nested-field-binding.fixed
@@ -0,0 +1,20 @@
+// Regression test for #88403, where prefixing with an underscore was
+// erroneously suggested for a nested shorthand struct field binding.
+
+// run-rustfix
+#![allow(unused)]
+#![forbid(unused_variables)]
+
+struct Inner { i: i32 }
+struct Outer { o: Inner }
+
+fn foo(Outer { o: Inner { i: _ } }: Outer) {}
+//~^ ERROR: unused variable: `i`
+//~| HELP: try ignoring the field
+
+fn main() {
+ let s = Outer { o: Inner { i: 42 } };
+ let Outer { o: Inner { i: _ } } = s;
+ //~^ ERROR: unused variable: `i`
+ //~| HELP: try ignoring the field
+}
diff --git a/tests/ui/suggestions/ignore-nested-field-binding.rs b/tests/ui/suggestions/ignore-nested-field-binding.rs
new file mode 100644
index 000000000..6dc0263ec
--- /dev/null
+++ b/tests/ui/suggestions/ignore-nested-field-binding.rs
@@ -0,0 +1,20 @@
+// Regression test for #88403, where prefixing with an underscore was
+// erroneously suggested for a nested shorthand struct field binding.
+
+// run-rustfix
+#![allow(unused)]
+#![forbid(unused_variables)]
+
+struct Inner { i: i32 }
+struct Outer { o: Inner }
+
+fn foo(Outer { o: Inner { i } }: Outer) {}
+//~^ ERROR: unused variable: `i`
+//~| HELP: try ignoring the field
+
+fn main() {
+ let s = Outer { o: Inner { i: 42 } };
+ let Outer { o: Inner { i } } = s;
+ //~^ ERROR: unused variable: `i`
+ //~| HELP: try ignoring the field
+}
diff --git a/tests/ui/suggestions/ignore-nested-field-binding.stderr b/tests/ui/suggestions/ignore-nested-field-binding.stderr
new file mode 100644
index 000000000..b2936a22a
--- /dev/null
+++ b/tests/ui/suggestions/ignore-nested-field-binding.stderr
@@ -0,0 +1,20 @@
+error: unused variable: `i`
+ --> $DIR/ignore-nested-field-binding.rs:11:27
+ |
+LL | fn foo(Outer { o: Inner { i } }: Outer) {}
+ | ^ help: try ignoring the field: `i: _`
+ |
+note: the lint level is defined here
+ --> $DIR/ignore-nested-field-binding.rs:6:11
+ |
+LL | #![forbid(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+
+error: unused variable: `i`
+ --> $DIR/ignore-nested-field-binding.rs:17:28
+ |
+LL | let Outer { o: Inner { i } } = s;
+ | ^ help: try ignoring the field: `i: _`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs
new file mode 100644
index 000000000..319789c4e
--- /dev/null
+++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs
@@ -0,0 +1,18 @@
+// Regression test for #70813 (this used to trigger a debug assertion)
+
+trait Trait {}
+
+struct S;
+
+impl<'a> Trait for &'a mut S {}
+
+fn foo<X>(_: X)
+where
+ for<'b> &'b X: Trait,
+{
+}
+
+fn main() {
+ let s = S;
+ foo::<S>(s); //~ ERROR the trait bound `for<'b> &'b S: Trait` is not satisfied
+}
diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
new file mode 100644
index 000000000..864ab0535
--- /dev/null
+++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied
+ --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:14
+ |
+LL | foo::<S>(s);
+ | -------- ^ the trait `for<'b> Trait` is not implemented for `&'b S`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for `&'a mut S`
+ = note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S`
+note: required by a bound in `foo`
+ --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20
+ |
+LL | fn foo<X>(_: X)
+ | --- required by a bound in this
+LL | where
+LL | for<'b> &'b X: Trait,
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal.rs b/tests/ui/suggestions/imm-ref-trait-object-literal.rs
new file mode 100644
index 000000000..22ca6dde4
--- /dev/null
+++ b/tests/ui/suggestions/imm-ref-trait-object-literal.rs
@@ -0,0 +1,14 @@
+trait Trait {}
+
+struct S;
+
+impl<'a> Trait for &'a mut S {}
+
+fn foo<X: Trait>(_: X) {}
+
+
+fn main() {
+ let s = S;
+ foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied
+ foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied
+}
diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr
new file mode 100644
index 000000000..e01102e38
--- /dev/null
+++ b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr
@@ -0,0 +1,40 @@
+error[E0277]: the trait bound `&S: Trait` is not satisfied
+ --> $DIR/imm-ref-trait-object-literal.rs:12:7
+ |
+LL | foo(&s);
+ | --- ^^ the trait `Trait` is not implemented for `&S`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for `&'a mut S`
+note: required by a bound in `foo`
+ --> $DIR/imm-ref-trait-object-literal.rs:7:11
+ |
+LL | fn foo<X: Trait>(_: X) {}
+ | ^^^^^ required by this bound in `foo`
+help: consider changing this borrow's mutability
+ |
+LL | foo(&mut s);
+ | ~~~~
+
+error[E0277]: the trait bound `S: Trait` is not satisfied
+ --> $DIR/imm-ref-trait-object-literal.rs:13:7
+ |
+LL | foo(s);
+ | --- ^ the trait `Trait` is not implemented for `S`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/imm-ref-trait-object-literal.rs:7:11
+ |
+LL | fn foo<X: Trait>(_: X) {}
+ | ^^^^^ required by this bound in `foo`
+help: consider mutably borrowing here
+ |
+LL | foo(&mut s);
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/imm-ref-trait-object.rs b/tests/ui/suggestions/imm-ref-trait-object.rs
new file mode 100644
index 000000000..c1c969b90
--- /dev/null
+++ b/tests/ui/suggestions/imm-ref-trait-object.rs
@@ -0,0 +1,8 @@
+fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
+ t.min().unwrap() //~ ERROR the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
+}
+
+fn main() {
+ let array = [0u64];
+ test(&mut array.iter());
+}
diff --git a/tests/ui/suggestions/imm-ref-trait-object.stderr b/tests/ui/suggestions/imm-ref-trait-object.stderr
new file mode 100644
index 000000000..f7f7902c1
--- /dev/null
+++ b/tests/ui/suggestions/imm-ref-trait-object.stderr
@@ -0,0 +1,13 @@
+error: the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
+ --> $DIR/imm-ref-trait-object.rs:2:8
+ |
+LL | t.min().unwrap()
+ | ^^^
+ |
+help: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
+ |
+LL | fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
+ | +++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
new file mode 100644
index 000000000..711cbbd38
--- /dev/null
+++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
@@ -0,0 +1,113 @@
+// FIXME: the following cases need to suggest more things to make users reach a working end state.
+
+mod bav {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {
+ type Assoc: Bar;
+ }
+ trait MyTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ trait Bar {}
+
+ impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ impl Bar for i32 {}
+
+ fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+ val.use_self() //~ ERROR cannot return reference to function parameter
+ }
+}
+
+mod bap {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {
+ type Assoc: Bar;
+ }
+ trait MyTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ trait Bar {}
+
+ impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ impl Bar for i32 {}
+
+ fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+ val.use_self() //~ ERROR E0515
+ }
+}
+
+// This case in particular requires the user to write all of the bounds we have in `mod bax`.
+mod bay {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {
+ type Assoc: Bar;
+ }
+ trait MyTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ trait Bar {}
+
+ impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ impl Bar for i32 {}
+
+ fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+ val.use_self()
+ }
+}
+
+mod bax {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {
+ type Assoc: Bar;
+ }
+ trait MyTrait<'a> {
+ fn use_self(&'a self) -> &'a () { panic!() }
+ }
+ trait Bar {}
+
+ impl<'a> MyTrait<'a> for Box<dyn ObjectTrait<Assoc = i32> + 'a> {
+ fn use_self(&'a self) -> &'a () { panic!() }
+ }
+ impl Bar for i32 {}
+
+ fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+ val.use_self()
+ }
+}
+
+mod baw {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {
+ type Assoc: Bar;
+ }
+ trait MyTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ trait Bar {}
+
+ impl<'a> MyTrait for Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>> {
+ fn use_self(&self) -> &() { panic!() }
+ }
+
+ fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>>) -> impl OtherTrait<'a> + 'a{
+ val.use_self() //~ ERROR E0515
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
new file mode 100644
index 000000000..2dc300ac7
--- /dev/null
+++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
@@ -0,0 +1,21 @@
+error[E0515]: cannot return reference to function parameter `val`
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
+ |
+LL | val.use_self()
+ | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to function parameter `val`
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
+ |
+LL | val.use_self()
+ | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to function parameter `val`
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9
+ |
+LL | val.use_self()
+ | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
new file mode 100644
index 000000000..ae3cd315c
--- /dev/null
+++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -0,0 +1,114 @@
+// FIXME(#96332): We should be able to suggest a fix and automatically fix.
+
+#![allow(dead_code)]
+
+mod foo {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait<T> {}
+ trait MyTrait<T> {
+ fn use_self<K>(&self) -> &();
+ }
+ trait Irrelevant {}
+
+ impl<T> MyTrait<T> for dyn ObjectTrait<T> {
+ fn use_self<K>(&self) -> &() { panic!() }
+ }
+ impl<T> Irrelevant for dyn ObjectTrait<T> {}
+
+ fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+ val.use_self::<T>() //~ ERROR borrowed data escapes
+ }
+}
+
+mod bar {
+ trait ObjectTrait {}
+ trait MyTrait {
+ fn use_self(&self) -> &();
+ }
+ trait Irrelevant {}
+
+ impl MyTrait for dyn ObjectTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ impl Irrelevant for dyn ObjectTrait {}
+
+ fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
+ val.use_self()
+ }
+}
+
+mod baz {
+ trait ObjectTrait {}
+ trait MyTrait {
+ fn use_self(&self) -> &();
+ }
+ trait Irrelevant {}
+
+ impl MyTrait for Box<dyn ObjectTrait> {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ impl Irrelevant for Box<dyn ObjectTrait> {}
+
+ fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
+ val.use_self()
+ }
+}
+
+mod bat {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {}
+
+ impl dyn ObjectTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+
+ fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+ val.use_self()
+ //~^ ERROR borrowed data escapes
+ }
+}
+
+mod ban {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {}
+ trait MyTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ trait Irrelevant {
+ fn use_self(&self) -> &() { panic!() }
+ }
+
+ impl MyTrait for dyn ObjectTrait {}
+
+ fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+ val.use_self() //~ ERROR borrowed data escapes
+ }
+}
+
+mod bal {
+ trait OtherTrait<'a> {}
+ impl<'a> OtherTrait<'a> for &'a () {}
+
+ trait ObjectTrait {}
+ trait MyTrait {
+ fn use_self(&self) -> &() { panic!() }
+ }
+ trait Irrelevant {
+ fn use_self(&self) -> &() { panic!() }
+ }
+
+ impl MyTrait for dyn ObjectTrait {}
+ impl Irrelevant for dyn ObjectTrait {}
+
+ fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+ MyTrait::use_self(val) //~ ERROR borrowed data escapes
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
new file mode 100644
index 000000000..679ebd61e
--- /dev/null
+++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
@@ -0,0 +1,105 @@
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:21:9
+ |
+LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+ | -- --- `val` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | val.use_self::<T>()
+ | ^^^^^^^^^^^^^^^^^^^
+ | |
+ | `val` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+ |
+note: the used `impl` has a `'static` requirement
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:32
+ |
+LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> {
+ | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL | fn use_self<K>(&self) -> &() { panic!() }
+ | -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+ |
+LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
+ | ++++
+
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:70:9
+ |
+LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+ | -- --- `val` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | val.use_self()
+ | ^^^^^^^^^^^^^^
+ | |
+ | `val` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+ |
+note: the used `impl` has a `'static` requirement
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:65:14
+ |
+LL | impl dyn ObjectTrait {
+ | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL | fn use_self(&self) -> &() { panic!() }
+ | -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+ |
+LL | impl dyn ObjectTrait + '_ {
+ | ++++
+
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:90:9
+ |
+LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+ | -- --- `val` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | val.use_self()
+ | ^^^^^^^^^^^^^^
+ | |
+ | `val` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+ |
+note: the used `impl` has a `'static` requirement
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26
+ |
+LL | fn use_self(&self) -> &() { panic!() }
+ | -------- calling this method introduces the `impl`'s 'static` requirement
+...
+LL | impl MyTrait for dyn ObjectTrait {}
+ | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+help: consider relaxing the implicit `'static` requirement
+ |
+LL | impl MyTrait for dyn ObjectTrait + '_ {}
+ | ++++
+
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:110:9
+ |
+LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+ | -- --- `val` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | MyTrait::use_self(val)
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `val` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+ |
+note: the used `impl` has a `'static` requirement
+ --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26
+ |
+LL | fn use_self(&self) -> &() { panic!() }
+ | -------- calling this method introduces the `impl`'s 'static` requirement
+...
+LL | impl MyTrait for dyn ObjectTrait {}
+ | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+help: consider relaxing the implicit `'static` requirement
+ |
+LL | impl MyTrait for dyn ObjectTrait + '_ {}
+ | ++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs
new file mode 100644
index 000000000..a1a51c481
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs
@@ -0,0 +1,68 @@
+// edition:2021
+// gate-test-anonymous_lifetime_in_impl_trait
+// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.
+
+mod elided {
+ fn f(_: impl Iterator<Item = &()>) {}
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+ fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+ //~| ERROR missing lifetime specifier
+
+ // Anonymous lifetimes in async fn are already allowed.
+ // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
+ async fn h(_: impl Iterator<Item = &()>) {}
+
+ // Anonymous lifetimes in async fn are already allowed.
+ // But that lifetime does not participate in resolution.
+ async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+ //~^ ERROR missing lifetime specifier
+}
+
+mod underscore {
+ fn f(_: impl Iterator<Item = &'_ ()>) {}
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+ fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+ //~| ERROR missing lifetime specifier
+
+ // Anonymous lifetimes in async fn are already allowed.
+ // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
+ async fn h(_: impl Iterator<Item = &'_ ()>) {}
+
+ // Anonymous lifetimes in async fn are already allowed.
+ // But that lifetime does not participate in resolution.
+ async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ //~^ ERROR missing lifetime specifier
+}
+
+mod alone_in_path {
+ trait Foo<'a> { fn next(&mut self) -> Option<&'a ()>; }
+
+ fn f(_: impl Foo) {}
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+ fn g(mut x: impl Foo) -> Option<&()> { x.next() }
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+ //~| ERROR missing lifetime specifier
+}
+
+mod in_path {
+ trait Foo<'a, T> { fn next(&mut self) -> Option<&'a T>; }
+
+ fn f(_: impl Foo<()>) {}
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+ fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
+ //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+ //~| ERROR missing lifetime specifier
+}
+
+// This must not err, as the `&` actually resolves to `'a`.
+fn resolved_anonymous<'a, T>(f: impl Fn(&'a str) -> &T) {
+ f("f")
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
new file mode 100644
index 000000000..50806a672
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
@@ -0,0 +1,172 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:9:54
+ |
+LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
+ | +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:19:60
+ |
+LL | async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | async fn i(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
+ | +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:27:58
+ |
+LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ | ^^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
+ | ~~~~~~~
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64
+ |
+LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ | ^^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
+ | ~~~~~~~
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37
+ |
+LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn g(mut x: impl Foo) -> Option<&'static ()> { x.next() }
+ | +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:58:41
+ |
+LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn g(mut x: impl Foo<()>) -> Option<&'static ()> { x.next() }
+ | +++++++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35
+ |
+LL | fn f(_: impl Iterator<Item = &()>) {}
+ | ^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
+ | ++++ ++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:9:39
+ |
+LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+ | ^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&()> { x.next() }
+ | ++++ ++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:24:35
+ |
+LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
+ | ^^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
+ | ++++ ~~
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:27:39
+ |
+LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ | ^^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'_ ()> { x.next() }
+ | ++++ ~~
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:44:18
+ |
+LL | fn f(_: impl Foo) {}
+ | ^^^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f<'a>(_: impl Foo<'a>) {}
+ | ++++ ++++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:47:22
+ |
+LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() }
+ | ^^^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
+ | ++++ ++++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:55:22
+ |
+LL | fn f(_: impl Foo<()>) {}
+ | ^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f<'a>(_: impl Foo<'a, ()>) {}
+ | ++++ +++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+ --> $DIR/impl-trait-missing-lifetime-gated.rs:58:26
+ |
+LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
+ | ^ expected named lifetime parameter
+ |
+ = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() }
+ | ++++ +++
+
+error: aborting due to 14 previous errors
+
+Some errors have detailed explanations: E0106, E0658.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.rs b/tests/ui/suggestions/impl-trait-missing-lifetime.rs
new file mode 100644
index 000000000..6f7c912d7
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime.rs
@@ -0,0 +1,20 @@
+// edition:2021
+
+#![feature(anonymous_lifetime_in_impl_trait)]
+
+// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
+fn f(_: impl Iterator<Item = &'_ ()>) {}
+
+// But that lifetime does not participate in resolution.
+fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+//~^ ERROR missing lifetime specifier
+
+// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
+async fn h(_: impl Iterator<Item = &'_ ()>) {}
+
+// But that lifetime does not participate in resolution.
+async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+//~^ ERROR missing lifetime specifier
+//~| ERROR lifetime may not live long enough
+
+fn main() {}
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
new file mode 100644
index 000000000..b476d6101
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
@@ -0,0 +1,35 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime.rs:9:54
+ |
+LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ | ^^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
+ | ~~~~~~~
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/impl-trait-missing-lifetime.rs:16:60
+ |
+LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ | ^^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
+ | ~~~~~~~
+
+error: lifetime may not live long enough
+ --> $DIR/impl-trait-missing-lifetime.rs:16:69
+ |
+LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+ | -------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+ | |
+ | return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs
new file mode 100644
index 000000000..cd3741356
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs
@@ -0,0 +1,21 @@
+trait Bar {}
+
+impl Bar for i32 {}
+
+struct Qux;
+
+impl Bar for Qux {}
+
+fn foo() -> impl Bar {
+ //~^ ERROR the trait bound `(): Bar` is not satisfied
+ 5;
+ //~^ HELP remove this semicolon
+}
+
+fn bar() -> impl Bar {
+ //~^ ERROR the trait bound `(): Bar` is not satisfied
+ //~| HELP the following other types implement trait `Bar`:
+ "";
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
new file mode 100644
index 000000000..e74c2c421
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `(): Bar` is not satisfied
+ --> $DIR/impl-trait-return-trailing-semicolon.rs:9:13
+ |
+LL | fn foo() -> impl Bar {
+ | ^^^^^^^^ the trait `Bar` is not implemented for `()`
+LL |
+LL | 5;
+ | -- help: remove this semicolon
+ | |
+ | this expression has type `{integer}`, which implements `Bar`
+
+error[E0277]: the trait bound `(): Bar` is not satisfied
+ --> $DIR/impl-trait-return-trailing-semicolon.rs:15:13
+ |
+LL | fn bar() -> impl Bar {
+ | ^^^^^^^^ the trait `Bar` is not implemented for `()`
+ |
+ = help: the following other types implement trait `Bar`:
+ Qux
+ i32
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/impl-trait-with-missing-bounds.rs b/tests/ui/suggestions/impl-trait-with-missing-bounds.rs
new file mode 100644
index 000000000..949b23600
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-with-missing-bounds.rs
@@ -0,0 +1,52 @@
+// The double space in `impl Iterator` is load bearing! We want to make sure we don't regress by
+// accident if the internal string representation changes.
+#[rustfmt::skip]
+fn foo(constraints: impl Iterator) {
+ for constraint in constraints {
+ qux(constraint);
+//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ }
+}
+
+fn bar<T>(t: T, constraints: impl Iterator) where T: std::fmt::Debug {
+ for constraint in constraints {
+ qux(t);
+ qux(constraint);
+//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ }
+}
+
+fn baz(t: impl std::fmt::Debug, constraints: impl Iterator) {
+ for constraint in constraints {
+ qux(t);
+ qux(constraint);
+//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ }
+}
+
+fn bat<I, T: std::fmt::Debug>(t: T, constraints: impl Iterator, _: I) {
+ for constraint in constraints {
+ qux(t);
+ qux(constraint);
+//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ }
+}
+
+fn bak(constraints: impl Iterator + std::fmt::Debug) {
+ for constraint in constraints {
+ qux(constraint);
+//~^ ERROR `<impl Iterator + std::fmt::Debug as Iterator>::Item` doesn't implement
+ }
+}
+
+#[rustfmt::skip]
+fn baw<>(constraints: impl Iterator) {
+ for constraint in constraints {
+ qux(constraint);
+//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ }
+}
+
+fn qux(_: impl std::fmt::Debug) {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr b/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr
new file mode 100644
index 000000000..a763eb6f2
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr
@@ -0,0 +1,117 @@
+error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:6:13
+ |
+LL | qux(constraint);
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
+note: required by a bound in `qux`
+ --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+ |
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn foo<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug {
+ | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++
+
+error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:14:13
+ |
+LL | qux(constraint);
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
+note: required by a bound in `qux`
+ --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+ |
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn bar<T, I: Iterator>(t: T, constraints: I) where T: std::fmt::Debug, <I as Iterator>::Item: Debug {
+ | +++++++++++++ ~ ++++++++++++++++++++++++++++++
+
+error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:22:13
+ |
+LL | qux(constraint);
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
+note: required by a bound in `qux`
+ --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+ |
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn baz<I: Iterator>(t: impl std::fmt::Debug, constraints: I) where <I as Iterator>::Item: Debug {
+ | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++
+
+error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:30:13
+ |
+LL | qux(constraint);
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
+note: required by a bound in `qux`
+ --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+ |
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn bat<I, T: std::fmt::Debug, U: Iterator>(t: T, constraints: U, _: I) where <U as Iterator>::Item: Debug {
+ | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++
+
+error[E0277]: `<impl Iterator + std::fmt::Debug as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:37:13
+ |
+LL | qux(constraint);
+ | --- ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Debug` is not implemented for `<impl Iterator + std::fmt::Debug as Iterator>::Item`
+note: required by a bound in `qux`
+ --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+ |
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn bak<I: Iterator + std::fmt::Debug>(constraints: I) where <I as Iterator>::Item: Debug {
+ | +++++++++++++++++++++++++++++++ ~ ++++++++++++++++++++++++++++++++++
+
+error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:45:13
+ |
+LL | qux(constraint);
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
+note: required by a bound in `qux`
+ --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+ |
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn baw<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug {
+ | ~~~~~~~~~~~~~ ~ ++++++++++++++++++++++++++++++++++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed
new file mode 100644
index 000000000..5109511f9
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+
+trait Foo {}
+
+trait Bar {
+ fn hello(&self) {}
+}
+
+struct S;
+
+impl Foo for S {}
+impl Bar for S {}
+
+fn test(foo: impl Foo + Bar) {
+ foo.hello(); //~ ERROR E0599
+}
+
+fn main() {
+ test(S);
+}
diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs
new file mode 100644
index 000000000..cd05b7738
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs
@@ -0,0 +1,20 @@
+// run-rustfix
+
+trait Foo {}
+
+trait Bar {
+ fn hello(&self) {}
+}
+
+struct S;
+
+impl Foo for S {}
+impl Bar for S {}
+
+fn test(foo: impl Foo) {
+ foo.hello(); //~ ERROR E0599
+}
+
+fn main() {
+ test(S);
+}
diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
new file mode 100644
index 000000000..20f8e65f7
--- /dev/null
+++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope
+ --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9
+ |
+LL | fn test(foo: impl Foo) {
+ | -------- method `hello` not found for this type parameter
+LL | foo.hello();
+ | ^^^^^ method not found in `impl Foo`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it:
+ |
+LL | fn test(foo: impl Foo + Bar) {
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/import-trait-for-method-call.rs b/tests/ui/suggestions/import-trait-for-method-call.rs
new file mode 100644
index 000000000..4dbadbdf9
--- /dev/null
+++ b/tests/ui/suggestions/import-trait-for-method-call.rs
@@ -0,0 +1,16 @@
+use std::hash::BuildHasher;
+
+fn next_u64() -> u64 {
+ let bh = std::collections::hash_map::RandomState::new();
+ let h = bh.build_hasher();
+ h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher`
+}
+
+trait Bar {}
+impl Bar for String {}
+
+fn main() {
+ let s = String::from("hey");
+ let x: &dyn Bar = &s;
+ x.as_ref(); //~ ERROR the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds
+}
diff --git a/tests/ui/suggestions/import-trait-for-method-call.stderr b/tests/ui/suggestions/import-trait-for-method-call.stderr
new file mode 100644
index 000000000..f159b51a2
--- /dev/null
+++ b/tests/ui/suggestions/import-trait-for-method-call.stderr
@@ -0,0 +1,34 @@
+error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope
+ --> $DIR/import-trait-for-method-call.rs:6:7
+ |
+LL | h.finish()
+ | ^^^^^^ method not found in `DefaultHasher`
+ --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
+ |
+ = note: the method is available for `DefaultHasher` here
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use std::hash::Hasher;
+ |
+
+error[E0599]: the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds were not satisfied
+ --> $DIR/import-trait-for-method-call.rs:15:7
+ |
+LL | trait Bar {}
+ | --------- doesn't satisfy `dyn Bar: AsRef<_>`
+...
+LL | x.as_ref();
+ | ^^^^^^ method cannot be called on `&dyn Bar` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `dyn Bar: AsRef<_>`
+ which is required by `&dyn Bar: AsRef<_>`
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `as_ref`, perhaps you need to implement it:
+ candidate #1: `AsRef`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed
new file mode 100644
index 000000000..7af7391ca
--- /dev/null
+++ b/tests/ui/suggestions/inner_type.fixed
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+pub struct Struct<T> {
+ pub p: T,
+}
+
+impl<T> Struct<T> {
+ pub fn method(&self) {}
+
+ pub fn some_mutable_method(&mut self) {}
+}
+
+fn main() {
+ let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
+
+ other_item.borrow().method();
+ //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
+
+ other_item.borrow_mut().some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
+
+ let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
+
+ another_item.lock().unwrap().method();
+ //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599]
+ //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
+
+ another_item.read().unwrap().method();
+ //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ another_item.write().unwrap().some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+}
diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs
new file mode 100644
index 000000000..4aca50716
--- /dev/null
+++ b/tests/ui/suggestions/inner_type.rs
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+pub struct Struct<T> {
+ pub p: T,
+}
+
+impl<T> Struct<T> {
+ pub fn method(&self) {}
+
+ pub fn some_mutable_method(&mut self) {}
+}
+
+fn main() {
+ let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
+
+ other_item.method();
+ //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
+
+ other_item.some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
+
+ let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
+
+ another_item.method();
+ //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599]
+ //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
+
+ another_item.method();
+ //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ another_item.some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+}
diff --git a/tests/ui/suggestions/inner_type.stderr b/tests/ui/suggestions/inner_type.stderr
new file mode 100644
index 000000000..5ac3d04f1
--- /dev/null
+++ b/tests/ui/suggestions/inner_type.stderr
@@ -0,0 +1,83 @@
+error[E0599]: no method named `method` found for struct `RefCell` in the current scope
+ --> $DIR/inner_type.rs:17:16
+ |
+LL | other_item.method();
+ | ^^^^^^ method not found in `RefCell<Struct<u32>>`
+ |
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:9:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+help: use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
+ |
+LL | other_item.borrow().method();
+ | +++++++++
+
+error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope
+ --> $DIR/inner_type.rs:21:16
+ |
+LL | other_item.some_mutable_method();
+ | ^^^^^^^^^^^^^^^^^^^ method not found in `RefCell<Struct<u32>>`
+ |
+note: the method `some_mutable_method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:11:5
+ |
+LL | pub fn some_mutable_method(&mut self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use `.borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
+ |
+LL | other_item.borrow_mut().some_mutable_method();
+ | +++++++++++++
+
+error[E0599]: no method named `method` found for struct `Mutex` in the current scope
+ --> $DIR/inner_type.rs:27:18
+ |
+LL | another_item.method();
+ | ^^^^^^ method not found in `Mutex<Struct<u32>>`
+ |
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:9:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+help: use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+ |
+LL | another_item.lock().unwrap().method();
+ | ++++++++++++++++
+
+error[E0599]: no method named `method` found for struct `RwLock` in the current scope
+ --> $DIR/inner_type.rs:33:18
+ |
+LL | another_item.method();
+ | ^^^^^^ method not found in `RwLock<Struct<u32>>`
+ |
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:9:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+help: use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+ |
+LL | another_item.read().unwrap().method();
+ | ++++++++++++++++
+
+error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope
+ --> $DIR/inner_type.rs:37:18
+ |
+LL | another_item.some_mutable_method();
+ | ^^^^^^^^^^^^^^^^^^^ method not found in `RwLock<Struct<u32>>`
+ |
+note: the method `some_mutable_method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:11:5
+ |
+LL | pub fn some_mutable_method(&mut self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+ |
+LL | another_item.write().unwrap().some_mutable_method();
+ | +++++++++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/inner_type2.rs b/tests/ui/suggestions/inner_type2.rs
new file mode 100644
index 000000000..fac68c053
--- /dev/null
+++ b/tests/ui/suggestions/inner_type2.rs
@@ -0,0 +1,26 @@
+pub struct Struct<T> {
+ pub p: T,
+}
+
+impl<T> Struct<T> {
+ pub fn method(&self) {}
+
+ pub fn some_mutable_method(&mut self) {}
+}
+
+thread_local! {
+ static STRUCT: Struct<u32> = Struct {
+ p: 42_u32
+ };
+}
+
+fn main() {
+ STRUCT.method();
+ //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599]
+ //~| HELP use `with` or `try_with` to access thread local storage
+
+ let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 });
+ item.method();
+ //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599]
+ //~| HELP if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
+}
diff --git a/tests/ui/suggestions/inner_type2.stderr b/tests/ui/suggestions/inner_type2.stderr
new file mode 100644
index 000000000..984366123
--- /dev/null
+++ b/tests/ui/suggestions/inner_type2.stderr
@@ -0,0 +1,29 @@
+error[E0599]: no method named `method` found for struct `LocalKey` in the current scope
+ --> $DIR/inner_type2.rs:18:12
+ |
+LL | STRUCT.method();
+ | ^^^^^^ method not found in `LocalKey<Struct<u32>>`
+ |
+ = help: use `with` or `try_with` to access thread local storage
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type2.rs:6:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope
+ --> $DIR/inner_type2.rs:23:10
+ |
+LL | item.method();
+ | ^^^^^^ method not found in `MaybeUninit<Struct<u32>>`
+ |
+ = help: if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type2.rs:6:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/into-convert.rs b/tests/ui/suggestions/into-convert.rs
new file mode 100644
index 000000000..1c9a9e0aa
--- /dev/null
+++ b/tests/ui/suggestions/into-convert.rs
@@ -0,0 +1,26 @@
+use std::path::{Path, PathBuf};
+use std::sync::atomic::AtomicU32;
+use std::sync::Arc;
+
+fn main() {
+ let x: A = B;
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression to convert `B` into `A`
+
+ let y: Arc<Path> = PathBuf::new();
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression to convert `PathBuf` into `Arc<Path>`
+
+ let z: AtomicU32 = 1;
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression to convert `{integer}` into `AtomicU32`
+}
+
+struct A;
+struct B;
+
+impl From<B> for A {
+ fn from(_: B) -> Self {
+ A
+ }
+}
diff --git a/tests/ui/suggestions/into-convert.stderr b/tests/ui/suggestions/into-convert.stderr
new file mode 100644
index 000000000..d43104a21
--- /dev/null
+++ b/tests/ui/suggestions/into-convert.stderr
@@ -0,0 +1,44 @@
+error[E0308]: mismatched types
+ --> $DIR/into-convert.rs:6:16
+ |
+LL | let x: A = B;
+ | - ^ expected struct `A`, found struct `B`
+ | |
+ | expected due to this
+ |
+help: call `Into::into` on this expression to convert `B` into `A`
+ |
+LL | let x: A = B.into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/into-convert.rs:10:24
+ |
+LL | let y: Arc<Path> = PathBuf::new();
+ | --------- ^^^^^^^^^^^^^^ expected struct `Arc`, found struct `PathBuf`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `Arc<Path>`
+ found struct `PathBuf`
+help: call `Into::into` on this expression to convert `PathBuf` into `Arc<Path>`
+ |
+LL | let y: Arc<Path> = PathBuf::new().into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/into-convert.rs:14:24
+ |
+LL | let z: AtomicU32 = 1;
+ | --------- ^ expected struct `AtomicU32`, found integer
+ | |
+ | expected due to this
+ |
+help: call `Into::into` on this expression to convert `{integer}` into `AtomicU32`
+ |
+LL | let z: AtomicU32 = 1.into();
+ | +++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/into-str.rs b/tests/ui/suggestions/into-str.rs
new file mode 100644
index 000000000..606e44b2e
--- /dev/null
+++ b/tests/ui/suggestions/into-str.rs
@@ -0,0 +1,6 @@
+fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
+
+fn main() {
+ foo(String::new());
+ //~^ ERROR the trait bound `&str: From<String>` is not satisfied
+}
diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr
new file mode 100644
index 000000000..a56a2a188
--- /dev/null
+++ b/tests/ui/suggestions/into-str.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the trait bound `&str: From<String>` is not satisfied
+ --> $DIR/into-str.rs:4:9
+ |
+LL | foo(String::new());
+ | --- ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `&str`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: to coerce a `String` into a `&str`, use `&*` as a prefix
+ = help: the following other types implement trait `From<T>`:
+ <String as From<&String>>
+ <String as From<&mut str>>
+ <String as From<&str>>
+ <String as From<Box<str>>>
+ <String as From<Cow<'a, str>>>
+ <String as From<char>>
+ = note: required for `String` to implement `Into<&str>`
+note: required by a bound in `foo`
+ --> $DIR/into-str.rs:1:31
+ |
+LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
+ | ^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/invalid-bin-op.rs b/tests/ui/suggestions/invalid-bin-op.rs
new file mode 100644
index 000000000..bea1b9155
--- /dev/null
+++ b/tests/ui/suggestions/invalid-bin-op.rs
@@ -0,0 +1,7 @@
+pub fn foo<T>(s: S<T>, t: S<T>) {
+ let _ = s == t; //~ ERROR binary operation `==` cannot be applied to type `S<T>`
+}
+
+struct S<T>(T);
+
+fn main() {}
diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr
new file mode 100644
index 000000000..08502dfeb
--- /dev/null
+++ b/tests/ui/suggestions/invalid-bin-op.stderr
@@ -0,0 +1,25 @@
+error[E0369]: binary operation `==` cannot be applied to type `S<T>`
+ --> $DIR/invalid-bin-op.rs:2:15
+ |
+LL | let _ = s == t;
+ | - ^^ - S<T>
+ | |
+ | S<T>
+ |
+note: an implementation of `PartialEq<_>` might be missing for `S<T>`
+ --> $DIR/invalid-bin-op.rs:5:1
+ |
+LL | struct S<T>(T);
+ | ^^^^^^^^^^^ must implement `PartialEq<_>`
+help: consider annotating `S<T>` with `#[derive(PartialEq)]`
+ |
+LL | #[derive(PartialEq)]
+ |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | pub fn foo<T>(s: S<T>, t: S<T>) where S<T>: PartialEq {
+ | +++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/suggestions/issue-101065.fixed b/tests/ui/suggestions/issue-101065.fixed
new file mode 100644
index 000000000..88c716cc8
--- /dev/null
+++ b/tests/ui/suggestions/issue-101065.fixed
@@ -0,0 +1,14 @@
+// check-fail
+// run-rustfix
+
+enum FakeResult<T> {
+ Ok(T)
+}
+
+fn main() {
+ let _x = if true {
+ FakeResult::Ok(FakeResult::Ok(()))
+ } else {
+ FakeResult::Ok(FakeResult::Ok(())) //~ERROR E0308
+ };
+}
diff --git a/tests/ui/suggestions/issue-101065.rs b/tests/ui/suggestions/issue-101065.rs
new file mode 100644
index 000000000..2715f1027
--- /dev/null
+++ b/tests/ui/suggestions/issue-101065.rs
@@ -0,0 +1,14 @@
+// check-fail
+// run-rustfix
+
+enum FakeResult<T> {
+ Ok(T)
+}
+
+fn main() {
+ let _x = if true {
+ FakeResult::Ok(FakeResult::Ok(()))
+ } else {
+ FakeResult::Ok(()) //~ERROR E0308
+ };
+}
diff --git a/tests/ui/suggestions/issue-101065.stderr b/tests/ui/suggestions/issue-101065.stderr
new file mode 100644
index 000000000..6f7ecd24c
--- /dev/null
+++ b/tests/ui/suggestions/issue-101065.stderr
@@ -0,0 +1,23 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/issue-101065.rs:12:9
+ |
+LL | let _x = if true {
+ | ______________-
+LL | | FakeResult::Ok(FakeResult::Ok(()))
+ | | ---------------------------------- expected because of this
+LL | | } else {
+LL | | FakeResult::Ok(())
+ | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()`
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+ = note: expected enum `FakeResult<FakeResult<()>>`
+ found enum `FakeResult<()>`
+help: try wrapping the expression in `FakeResult::Ok`
+ |
+LL | FakeResult::Ok(FakeResult::Ok(()))
+ | +++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-101421.rs b/tests/ui/suggestions/issue-101421.rs
new file mode 100644
index 000000000..b615997d1
--- /dev/null
+++ b/tests/ui/suggestions/issue-101421.rs
@@ -0,0 +1,12 @@
+pub trait Ice {
+ fn f(&self, _: ());
+}
+
+impl Ice for () {
+ fn f(&self, _: ()) {}
+}
+
+fn main() {
+ ().f::<()>(());
+ //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
+}
diff --git a/tests/ui/suggestions/issue-101421.stderr b/tests/ui/suggestions/issue-101421.stderr
new file mode 100644
index 000000000..f8e1efb88
--- /dev/null
+++ b/tests/ui/suggestions/issue-101421.stderr
@@ -0,0 +1,17 @@
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-101421.rs:10:8
+ |
+LL | ().f::<()>(());
+ | ^------ help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/issue-101421.rs:2:8
+ |
+LL | fn f(&self, _: ());
+ | ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/issue-101465.rs b/tests/ui/suggestions/issue-101465.rs
new file mode 100644
index 000000000..8e42e2c22
--- /dev/null
+++ b/tests/ui/suggestions/issue-101465.rs
@@ -0,0 +1,25 @@
+#![feature(trait_alias)]
+
+struct B;
+struct C;
+
+trait Tr {}
+
+impl Tr for B {}
+impl Tr for C {}
+
+trait Tr2<S> = Into<S>;
+
+fn foo2<T: Tr2<()>>() {}
+
+fn foo() -> impl Tr {
+ let x = foo2::<_>();
+
+ match true {
+ true => B,
+ false => C,
+ //~^ `match` arms have incompatible types
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-101465.stderr b/tests/ui/suggestions/issue-101465.stderr
new file mode 100644
index 000000000..e2ca77712
--- /dev/null
+++ b/tests/ui/suggestions/issue-101465.stderr
@@ -0,0 +1,25 @@
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/issue-101465.rs:20:18
+ |
+LL | / match true {
+LL | | true => B,
+ | | - this is found to be of type `B`
+LL | | false => C,
+ | | ^ expected struct `B`, found struct `C`
+LL | |
+LL | | }
+ | |_____- `match` arms have incompatible types
+ |
+help: you could change the return type to be a boxed trait object
+ |
+LL | fn foo() -> Box<dyn Tr> {
+ | ~~~~~~~ +
+help: if you change the return type to expect trait objects, box the returned expressions
+ |
+LL ~ true => Box::new(B),
+LL ~ false => Box::new(C),
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-101623.rs b/tests/ui/suggestions/issue-101623.rs
new file mode 100644
index 000000000..d18a4a21f
--- /dev/null
+++ b/tests/ui/suggestions/issue-101623.rs
@@ -0,0 +1,25 @@
+pub struct Stuff {
+ inner: *mut (),
+}
+
+pub struct Wrap<T>(T);
+
+fn fun<T>(t: T) -> Wrap<T> {
+ todo!()
+}
+
+pub trait Trait<'de> {
+ fn do_stuff(_: Wrap<&'de mut Self>);
+}
+
+impl<'a> Trait<'a> for () {
+ fn do_stuff(_: Wrap<&'a mut Self>) {}
+}
+
+fn fun2(t: &mut Stuff) -> () {
+ let Stuff { inner, .. } = t;
+ Trait::do_stuff({ fun(&mut *inner) });
+ //~^ ERROR the trait bound `*mut (): Trait<'_>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr
new file mode 100644
index 000000000..361483cc0
--- /dev/null
+++ b/tests/ui/suggestions/issue-101623.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `*mut (): Trait<'_>` is not satisfied
+ --> $DIR/issue-101623.rs:21:21
+ |
+LL | Trait::do_stuff({ fun(&mut *inner) });
+ | --------------- ^^----------------^^
+ | | |
+ | | the trait `Trait<'_>` is not implemented for `*mut ()`
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait<'a>` is implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-101984.rs b/tests/ui/suggestions/issue-101984.rs
new file mode 100644
index 000000000..5f7ecb77e
--- /dev/null
+++ b/tests/ui/suggestions/issue-101984.rs
@@ -0,0 +1,27 @@
+use std::marker::PhantomData;
+
+type Component = fn(&());
+
+struct Wrapper {
+ router: Router<(Component, Box<Self>)>,
+}
+
+struct Match<C>(PhantomData<C>);
+
+struct Router<T>(PhantomData<T>);
+
+impl<T> Router<T> {
+ pub fn at(&self) -> Result<Match<&T>, ()> {
+ todo!()
+ }
+}
+
+impl Wrapper {
+ fn at(&self, path: &str) -> Result<(Component, Box<Self>), ()> {
+ let (cmp, router) = self.router.at()?;
+ //~^ ERROR mismatched types
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-101984.stderr b/tests/ui/suggestions/issue-101984.stderr
new file mode 100644
index 000000000..81758a700
--- /dev/null
+++ b/tests/ui/suggestions/issue-101984.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-101984.rs:21:13
+ |
+LL | let (cmp, router) = self.router.at()?;
+ | ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
+ | |
+ | expected struct `Match`, found tuple
+ |
+ = note: expected struct `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
+ found tuple `(_, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-102354.rs b/tests/ui/suggestions/issue-102354.rs
new file mode 100644
index 000000000..f881feb00
--- /dev/null
+++ b/tests/ui/suggestions/issue-102354.rs
@@ -0,0 +1,10 @@
+trait Trait {
+ fn func() {}
+}
+
+impl Trait for i32 {}
+
+fn main() {
+ let x: i32 = 123;
+ x.func(); //~ERROR no method
+}
diff --git a/tests/ui/suggestions/issue-102354.stderr b/tests/ui/suggestions/issue-102354.stderr
new file mode 100644
index 000000000..08d4b9955
--- /dev/null
+++ b/tests/ui/suggestions/issue-102354.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `func` found for type `i32` in the current scope
+ --> $DIR/issue-102354.rs:9:7
+ |
+LL | x.func();
+ | --^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `i32::func()`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `Trait`
+ --> $DIR/issue-102354.rs:2:5
+ |
+LL | fn func() {}
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/issue-102892.rs b/tests/ui/suggestions/issue-102892.rs
new file mode 100644
index 000000000..c1a791d8d
--- /dev/null
+++ b/tests/ui/suggestions/issue-102892.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code, unused_variables)]
+
+use std::sync::Arc;
+
+#[derive(Debug)]
+struct A;
+#[derive(Debug)]
+struct B;
+
+fn process_without_annot(arc: &Arc<(A, B)>) {
+ let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
+}
+
+fn process_with_annot(arc: &Arc<(A, B)>) {
+ let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
+ //~^ ERROR mismatched types
+}
+
+fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) {
+ let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr
new file mode 100644
index 000000000..a3dbc7cb8
--- /dev/null
+++ b/tests/ui/suggestions/issue-102892.stderr
@@ -0,0 +1,57 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102892.rs:15:26
+ |
+LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
+ | ------ ^^^^^^ expected tuple, found `&(A, B)`
+ | |
+ | expected due to this
+ |
+ = note: expected tuple `(A, B)`
+ found reference `&(A, B)`
+help: consider removing the borrow
+ |
+LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
+LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-102892.rs:20:32
+ |
+LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ | ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)`
+ |
+ = note: expected tuple `(A, B)`
+ found mutable reference `&mut (A, B)`
+help: consider removing the borrow
+ |
+LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ | ++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-102892.rs:20:48
+ |
+LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ | ^^^^^^^^^^ expected struct `A`, found `&A`
+ |
+help: consider removing the borrow
+ |
+LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ | +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-103112.rs b/tests/ui/suggestions/issue-103112.rs
new file mode 100644
index 000000000..111ae7c73
--- /dev/null
+++ b/tests/ui/suggestions/issue-103112.rs
@@ -0,0 +1,4 @@
+fn main() {
+ std::process::abort!();
+ //~^ ERROR: failed to resolve
+}
diff --git a/tests/ui/suggestions/issue-103112.stderr b/tests/ui/suggestions/issue-103112.stderr
new file mode 100644
index 000000000..4ca7fdf9b
--- /dev/null
+++ b/tests/ui/suggestions/issue-103112.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: could not find `abort` in `process`
+ --> $DIR/issue-103112.rs:2:19
+ |
+LL | std::process::abort!();
+ | ^^^^^ could not find `abort` in `process`
+ |
+help: std::process::abort is not a macro, but a function, try to remove `!`
+ |
+LL - std::process::abort!();
+LL + std::process::abort();
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/suggestions/issue-104086-suggest-let.rs b/tests/ui/suggestions/issue-104086-suggest-let.rs
new file mode 100644
index 000000000..d22ad27d0
--- /dev/null
+++ b/tests/ui/suggestions/issue-104086-suggest-let.rs
@@ -0,0 +1,30 @@
+fn main() {
+ x = x = x;
+ //~^ ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `x` in this scope
+
+ x = y = y = y;
+ //~^ ERROR cannot find value `y` in this scope
+ //~| ERROR cannot find value `y` in this scope
+ //~| ERROR cannot find value `y` in this scope
+ //~| ERROR cannot find value `x` in this scope
+
+ x = y = y;
+ //~^ ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `y` in this scope
+ //~| ERROR cannot find value `y` in this scope
+
+ x = x = y;
+ //~^ ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `y` in this scope
+
+ x = x; // will suggest add `let`
+ //~^ ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `x` in this scope
+
+ x = y // will suggest add `let`
+ //~^ ERROR cannot find value `x` in this scope
+ //~| ERROR cannot find value `y` in this scope
+}
diff --git a/tests/ui/suggestions/issue-104086-suggest-let.stderr b/tests/ui/suggestions/issue-104086-suggest-let.stderr
new file mode 100644
index 000000000..fb4ea3121
--- /dev/null
+++ b/tests/ui/suggestions/issue-104086-suggest-let.stderr
@@ -0,0 +1,135 @@
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:2:5
+ |
+LL | x = x = x;
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = x = x;
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:2:9
+ |
+LL | x = x = x;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:2:13
+ |
+LL | x = x = x;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:7:5
+ |
+LL | x = y = y = y;
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = y = y = y;
+ | +++
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:7:9
+ |
+LL | x = y = y = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:7:13
+ |
+LL | x = y = y = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:7:17
+ |
+LL | x = y = y = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:13:5
+ |
+LL | x = y = y;
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = y = y;
+ | +++
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:13:9
+ |
+LL | x = y = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:13:13
+ |
+LL | x = y = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:18:5
+ |
+LL | x = x = y;
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = x = y;
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:18:9
+ |
+LL | x = x = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:18:13
+ |
+LL | x = x = y;
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:23:5
+ |
+LL | x = x; // will suggest add `let`
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = x; // will suggest add `let`
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:23:9
+ |
+LL | x = x; // will suggest add `let`
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:27:5
+ |
+LL | x = y // will suggest add `let`
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = y // will suggest add `let`
+ | +++
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/issue-104086-suggest-let.rs:27:9
+ |
+LL | x = y // will suggest add `let`
+ | ^ not found in this scope
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/issue-104287.rs b/tests/ui/suggestions/issue-104287.rs
new file mode 100644
index 000000000..e3fa22a8f
--- /dev/null
+++ b/tests/ui/suggestions/issue-104287.rs
@@ -0,0 +1,13 @@
+// The purpose of this test is not to validate the output of the compiler.
+// Instead, it ensures the suggestion is generated without performing an arithmetic overflow.
+
+struct S;
+impl S {
+ fn foo(&self) {}
+}
+fn main() {
+ let x = S;
+ foo::<()>(x);
+ //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
+ //~| ERROR cannot find function `foo` in this scope
+}
diff --git a/tests/ui/suggestions/issue-104287.stderr b/tests/ui/suggestions/issue-104287.stderr
new file mode 100644
index 000000000..602a01828
--- /dev/null
+++ b/tests/ui/suggestions/issue-104287.stderr
@@ -0,0 +1,30 @@
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-104287.rs:10:5
+ |
+LL | foo::<()>(x);
+ | ^^^------ help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/issue-104287.rs:6:8
+ |
+LL | fn foo(&self) {}
+ | ^^^
+
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/issue-104287.rs:10:5
+ |
+LL | foo::<()>(x);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `foo` on `&S`
+ |
+LL - foo::<()>(x);
+LL + x.foo();
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0425.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/issue-104327.rs b/tests/ui/suggestions/issue-104327.rs
new file mode 100644
index 000000000..dd621ae71
--- /dev/null
+++ b/tests/ui/suggestions/issue-104327.rs
@@ -0,0 +1,12 @@
+trait Bar {}
+
+trait Foo {
+ fn f() {}
+}
+
+impl Foo for dyn Bar {}
+
+fn main() {
+ Foo::f();
+ //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
diff --git a/tests/ui/suggestions/issue-104327.stderr b/tests/ui/suggestions/issue-104327.stderr
new file mode 100644
index 000000000..acec3a55d
--- /dev/null
+++ b/tests/ui/suggestions/issue-104327.stderr
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+ --> $DIR/issue-104327.rs:10:5
+ |
+LL | fn f() {}
+ | --------- `Foo::f` defined here
+...
+LL | Foo::f();
+ | ^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL | <(dyn Bar + 'static) as Foo>::f();
+ | +++++++++++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/tests/ui/suggestions/issue-104328.rs b/tests/ui/suggestions/issue-104328.rs
new file mode 100644
index 000000000..c3707baf7
--- /dev/null
+++ b/tests/ui/suggestions/issue-104328.rs
@@ -0,0 +1,12 @@
+#![feature(object_safe_for_dispatch)]
+
+trait Foo {
+ fn f() {}
+}
+
+impl Foo for dyn Sized {}
+
+fn main() {
+ Foo::f();
+ //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
diff --git a/tests/ui/suggestions/issue-104328.stderr b/tests/ui/suggestions/issue-104328.stderr
new file mode 100644
index 000000000..b31b84781
--- /dev/null
+++ b/tests/ui/suggestions/issue-104328.stderr
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+ --> $DIR/issue-104328.rs:10:5
+ |
+LL | fn f() {}
+ | --------- `Foo::f` defined here
+...
+LL | Foo::f();
+ | ^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL | <(dyn Sized + 'static) as Foo>::f();
+ | +++++++++++++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/tests/ui/suggestions/issue-105226.rs b/tests/ui/suggestions/issue-105226.rs
new file mode 100644
index 000000000..f123dbf4c
--- /dev/null
+++ b/tests/ui/suggestions/issue-105226.rs
@@ -0,0 +1,22 @@
+use std::fmt;
+
+struct S {
+}
+
+impl S {
+ fn hello<P>(&self, val: &P) where P: fmt::Display; {
+ //~^ ERROR non-item in item list
+ //~| ERROR associated function in `impl` without body
+ println!("val: {}", val);
+ }
+}
+
+impl S {
+ fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+ //~^ ERROR associated function in `impl` without body
+}
+
+fn main() {
+ let s = S{};
+ s.hello(&32);
+}
diff --git a/tests/ui/suggestions/issue-105226.stderr b/tests/ui/suggestions/issue-105226.stderr
new file mode 100644
index 000000000..f16a80901
--- /dev/null
+++ b/tests/ui/suggestions/issue-105226.stderr
@@ -0,0 +1,31 @@
+error: non-item in item list
+ --> $DIR/issue-105226.rs:7:56
+ |
+LL | impl S {
+ | - item list starts here
+LL | fn hello<P>(&self, val: &P) where P: fmt::Display; {
+ | - ^ non-item starts here
+ | |
+ | help: consider removing this semicolon
+...
+LL | }
+ | - item list ends here
+
+error: associated function in `impl` without body
+ --> $DIR/issue-105226.rs:7:5
+ |
+LL | fn hello<P>(&self, val: &P) where P: fmt::Display; {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+ | |
+ | help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+ --> $DIR/issue-105226.rs:15:5
+ |
+LL | fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+ | |
+ | help: provide a definition for the function: `{ <body> }`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/issue-105494.rs b/tests/ui/suggestions/issue-105494.rs
new file mode 100644
index 000000000..8b409232c
--- /dev/null
+++ b/tests/ui/suggestions/issue-105494.rs
@@ -0,0 +1,22 @@
+fn test1() {
+ let _v: i32 = (1 as i32).to_string(); //~ ERROR mismatched types
+
+ // won't suggestion
+ let _v: i32 = (1 as i128).to_string(); //~ ERROR mismatched types
+
+ let _v: &str = "foo".to_string(); //~ ERROR mismatched types
+}
+
+fn test2() {
+ let mut path: String = "/usr".to_string();
+ let folder: String = "lib".to_string();
+
+ path = format!("{}/{}", path, folder).as_str(); //~ ERROR mismatched types
+
+ println!("{}", &path);
+}
+
+fn main() {
+ test1();
+ test2();
+}
diff --git a/tests/ui/suggestions/issue-105494.stderr b/tests/ui/suggestions/issue-105494.stderr
new file mode 100644
index 000000000..5aa3f2af7
--- /dev/null
+++ b/tests/ui/suggestions/issue-105494.stderr
@@ -0,0 +1,54 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-105494.rs:2:19
+ |
+LL | let _v: i32 = (1 as i32).to_string();
+ | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | |
+ | expected due to this
+ |
+help: try removing the method call
+ |
+LL - let _v: i32 = (1 as i32).to_string();
+LL + let _v: i32 = (1 as i32);
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/issue-105494.rs:5:19
+ |
+LL | let _v: i32 = (1 as i128).to_string();
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/issue-105494.rs:7:20
+ |
+LL | let _v: &str = "foo".to_string();
+ | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String`
+ | |
+ | expected due to this
+ |
+help: try removing the method call
+ |
+LL - let _v: &str = "foo".to_string();
+LL + let _v: &str = "foo";
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/issue-105494.rs:14:12
+ |
+LL | let mut path: String = "/usr".to_string();
+ | ------ expected due to this type
+...
+LL | path = format!("{}/{}", path, folder).as_str();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str`
+ |
+help: try removing the method call
+ |
+LL - path = format!("{}/{}", path, folder).as_str();
+LL + path = format!("{}/{}", path, folder);
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-105645.rs b/tests/ui/suggestions/issue-105645.rs
new file mode 100644
index 000000000..681ce1c6e
--- /dev/null
+++ b/tests/ui/suggestions/issue-105645.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let mut buf = [0u8; 50];
+ let mut bref = buf.as_slice();
+ foo(&mut bref);
+ //~^ ERROR 4:9: 4:18: the trait bound `&[u8]: std::io::Write` is not satisfied [E0277]
+}
+
+fn foo(_: &mut impl std::io::Write) {}
diff --git a/tests/ui/suggestions/issue-105645.stderr b/tests/ui/suggestions/issue-105645.stderr
new file mode 100644
index 000000000..895f5ffd1
--- /dev/null
+++ b/tests/ui/suggestions/issue-105645.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `&[u8]: std::io::Write` is not satisfied
+ --> $DIR/issue-105645.rs:4:9
+ |
+LL | foo(&mut bref);
+ | --- ^^^^^^^^^ the trait `std::io::Write` is not implemented for `&[u8]`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `std::io::Write` is implemented for `&mut [u8]`
+note: required by a bound in `foo`
+ --> $DIR/issue-105645.rs:8:21
+ |
+LL | fn foo(_: &mut impl std::io::Write) {}
+ | ^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed
new file mode 100644
index 000000000..78e48364b
--- /dev/null
+++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed
@@ -0,0 +1,28 @@
+//run-rustfix
+#![allow(unused)]
+
+struct S;
+impl S {
+ fn foo(&mut self) {
+ let x = |this: &Self, v: i32| {
+ this.bar();
+ this.hel();
+ };
+ self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+ x(self, 1);
+ x(self, 3);
+ }
+ fn bar(&self) {}
+ fn hel(&self) {}
+ fn qux(&mut self) {}
+
+ fn hello(&mut self) {
+ let y = |this: &Self| {
+ this.bar();
+ };
+ self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+ y(self);
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs
new file mode 100644
index 000000000..6d8a9ffc1
--- /dev/null
+++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs
@@ -0,0 +1,28 @@
+//run-rustfix
+#![allow(unused)]
+
+struct S;
+impl S {
+ fn foo(&mut self) {
+ let x = |v: i32| {
+ self.bar();
+ self.hel();
+ };
+ self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+ x(1);
+ x(3);
+ }
+ fn bar(&self) {}
+ fn hel(&self) {}
+ fn qux(&mut self) {}
+
+ fn hello(&mut self) {
+ let y = || {
+ self.bar();
+ };
+ self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+ y();
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr
new file mode 100644
index 000000000..bc97d32eb
--- /dev/null
+++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr
@@ -0,0 +1,49 @@
+error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
+ --> $DIR/issue-105761-suggest-self-for-closure.rs:11:9
+ |
+LL | let x = |v: i32| {
+ | -------- immutable borrow occurs here
+LL | self.bar();
+ | ---- first borrow occurs due to use of `self` in closure
+...
+LL | self.qux();
+ | ^^^^^^^^^^ mutable borrow occurs here
+LL | x(1);
+ | - immutable borrow later used here
+ |
+help: try explicitly pass `&Self` into the Closure as an argument
+ |
+LL ~ let x = |this: &Self, v: i32| {
+LL ~ this.bar();
+LL ~ this.hel();
+LL | };
+LL | self.qux();
+LL ~ x(self, 1);
+LL ~ x(self, 3);
+ |
+
+error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
+ --> $DIR/issue-105761-suggest-self-for-closure.rs:23:9
+ |
+LL | let y = || {
+ | -- immutable borrow occurs here
+LL | self.bar();
+ | ---- first borrow occurs due to use of `self` in closure
+LL | };
+LL | self.qux();
+ | ^^^^^^^^^^ mutable borrow occurs here
+LL | y();
+ | - immutable borrow later used here
+ |
+help: try explicitly pass `&Self` into the Closure as an argument
+ |
+LL ~ let y = |this: &Self| {
+LL ~ this.bar();
+LL | };
+LL | self.qux();
+LL ~ y(self);
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs
new file mode 100644
index 000000000..48efdb82c
--- /dev/null
+++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs
@@ -0,0 +1,23 @@
+#[derive(Clone)]
+struct S;
+
+// without Clone
+struct T;
+
+fn foo(_: S) {}
+
+fn test1() {
+ let s = &S;
+ foo(s); //~ ERROR mismatched types
+}
+
+fn bar(_: T) {}
+fn test2() {
+ let t = &T;
+ bar(t); //~ ERROR mismatched types
+}
+
+fn main() {
+ test1();
+ test2();
+}
diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
new file mode 100644
index 000000000..1e66fe3af
--- /dev/null
+++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-106443-sugg-clone-for-arg.rs:11:9
+ |
+LL | foo(s);
+ | --- ^ expected struct `S`, found `&S`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-106443-sugg-clone-for-arg.rs:7:4
+ |
+LL | fn foo(_: S) {}
+ | ^^^ ----
+help: consider using clone here
+ |
+LL | foo(s.clone());
+ | ++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-106443-sugg-clone-for-arg.rs:17:9
+ |
+LL | bar(t);
+ | --- ^ expected struct `T`, found `&T`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-106443-sugg-clone-for-arg.rs:14:4
+ |
+LL | fn bar(_: T) {}
+ | ^^^ ----
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs
new file mode 100644
index 000000000..3b2e316b2
--- /dev/null
+++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs
@@ -0,0 +1,20 @@
+#[derive(Clone)]
+struct S;
+
+trait X {}
+
+impl X for S {}
+
+fn foo<T: X>(_: T) {}
+fn bar<T: X>(s: &T) {
+ foo(s); //~ ERROR the trait bound `&T: X` is not satisfied
+}
+
+fn bar_with_clone<T: X + Clone>(s: &T) {
+ foo(s); //~ ERROR the trait bound `&T: X` is not satisfied
+}
+
+fn main() {
+ let s = &S;
+ bar(s);
+}
diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
new file mode 100644
index 000000000..8607917ed
--- /dev/null
+++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `&T: X` is not satisfied
+ --> $DIR/issue-106443-sugg-clone-for-bound.rs:10:9
+ |
+LL | foo(s);
+ | ^ the trait `X` is not implemented for `&T`
+ |
+help: consider further restricting this bound
+ |
+LL | fn bar<T: X + Clone>(s: &T) {
+ | +++++++
+help: consider using clone here
+ |
+LL | foo(s.clone());
+ | ++++++++
+
+error[E0277]: the trait bound `&T: X` is not satisfied
+ --> $DIR/issue-106443-sugg-clone-for-bound.rs:14:9
+ |
+LL | foo(s);
+ | ^ the trait `X` is not implemented for `&T`
+ |
+help: consider using clone here
+ |
+LL | foo(s.clone());
+ | ++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-21673.rs b/tests/ui/suggestions/issue-21673.rs
new file mode 100644
index 000000000..9d66cae05
--- /dev/null
+++ b/tests/ui/suggestions/issue-21673.rs
@@ -0,0 +1,13 @@
+trait Foo {
+ fn method(&self) {}
+}
+
+fn call_method<T: std::fmt::Debug>(x: &T) {
+ x.method() //~ ERROR E0599
+}
+
+fn call_method_2<T>(x: T) {
+ x.method() //~ ERROR E0599
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-21673.stderr b/tests/ui/suggestions/issue-21673.stderr
new file mode 100644
index 000000000..523d7a7cc
--- /dev/null
+++ b/tests/ui/suggestions/issue-21673.stderr
@@ -0,0 +1,29 @@
+error[E0599]: no method named `method` found for reference `&T` in the current scope
+ --> $DIR/issue-21673.rs:6:7
+ |
+LL | x.method()
+ | ^^^^^^ method not found in `&T`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
+ |
+LL | fn call_method<T: std::fmt::Debug + Foo>(x: &T) {
+ | +++++
+
+error[E0599]: no method named `method` found for type parameter `T` in the current scope
+ --> $DIR/issue-21673.rs:10:7
+ |
+LL | fn call_method_2<T>(x: T) {
+ | - method `method` not found for this type parameter
+LL | x.method()
+ | ^^^^^^ method not found in `T`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
+ |
+LL | fn call_method_2<T: Foo>(x: T) {
+ | +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs
new file mode 100644
index 000000000..37f078285
--- /dev/null
+++ b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs
@@ -0,0 +1,8 @@
+fn vindictive() -> bool { true }
+
+fn perfidy() -> (i32, i32) {
+ vindictive() //~ ERROR expected function, found `bool`
+ (1, 2)
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
new file mode 100644
index 000000000..438075083
--- /dev/null
+++ b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
@@ -0,0 +1,16 @@
+error[E0618]: expected function, found `bool`
+ --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5
+ |
+LL | fn vindictive() -> bool { true }
+ | ----------------------- `vindictive` defined here returns `bool`
+...
+LL | vindictive()
+ | -^^^^^^^^^^^- help: consider using a semicolon here: `;`
+ | _____|
+ | |
+LL | | (1, 2)
+ | |__________- call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/tests/ui/suggestions/issue-52820.fixed b/tests/ui/suggestions/issue-52820.fixed
new file mode 100644
index 000000000..514690de4
--- /dev/null
+++ b/tests/ui/suggestions/issue-52820.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Bravery {
+ guts: String,
+ brains: String,
+}
+
+fn main() {
+ let guts = "mettle";
+ let _ = Bravery {
+ guts: guts.to_string(), //~ ERROR mismatched types
+ brains: guts.to_string(), //~ ERROR mismatched types
+ };
+}
diff --git a/tests/ui/suggestions/issue-52820.rs b/tests/ui/suggestions/issue-52820.rs
new file mode 100644
index 000000000..17cd9224c
--- /dev/null
+++ b/tests/ui/suggestions/issue-52820.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Bravery {
+ guts: String,
+ brains: String,
+}
+
+fn main() {
+ let guts = "mettle";
+ let _ = Bravery {
+ guts, //~ ERROR mismatched types
+ brains: guts.clone(), //~ ERROR mismatched types
+ };
+}
diff --git a/tests/ui/suggestions/issue-52820.stderr b/tests/ui/suggestions/issue-52820.stderr
new file mode 100644
index 000000000..09269ed4e
--- /dev/null
+++ b/tests/ui/suggestions/issue-52820.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-52820.rs:12:9
+ |
+LL | guts,
+ | ^^^^ expected struct `String`, found `&str`
+ |
+help: try using a conversion method
+ |
+LL | guts: guts.to_string(),
+ | +++++ ++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-52820.rs:13:17
+ |
+LL | brains: guts.clone(),
+ | ^^^^^-----^^
+ | | |
+ | | help: try using a conversion method: `to_string`
+ | expected struct `String`, found `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-53692.fixed b/tests/ui/suggestions/issue-53692.fixed
new file mode 100644
index 000000000..35a677b47
--- /dev/null
+++ b/tests/ui/suggestions/issue-53692.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn main() {
+ let items = vec![1, 2, 3];
+ let ref_items: &[i32] = &items;
+ let items_clone: Vec<i32> = ref_items.to_vec();
+ //~^ ERROR mismatched types
+
+ // in that case no suggestion will be triggered
+ let items_clone_2: Vec<i32> = items.clone();
+
+ let s = "hi";
+ let string: String = s.to_string();
+ //~^ ERROR mismatched types
+
+ // in that case no suggestion will be triggered
+ let s2 = "hi";
+ let string_2: String = s2.to_string();
+}
diff --git a/tests/ui/suggestions/issue-53692.rs b/tests/ui/suggestions/issue-53692.rs
new file mode 100644
index 000000000..6f6707be5
--- /dev/null
+++ b/tests/ui/suggestions/issue-53692.rs
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn main() {
+ let items = vec![1, 2, 3];
+ let ref_items: &[i32] = &items;
+ let items_clone: Vec<i32> = ref_items.clone();
+ //~^ ERROR mismatched types
+
+ // in that case no suggestion will be triggered
+ let items_clone_2: Vec<i32> = items.clone();
+
+ let s = "hi";
+ let string: String = s.clone();
+ //~^ ERROR mismatched types
+
+ // in that case no suggestion will be triggered
+ let s2 = "hi";
+ let string_2: String = s2.to_string();
+}
diff --git a/tests/ui/suggestions/issue-53692.stderr b/tests/ui/suggestions/issue-53692.stderr
new file mode 100644
index 000000000..3a1b624f4
--- /dev/null
+++ b/tests/ui/suggestions/issue-53692.stderr
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-53692.rs:7:33
+ |
+LL | let items_clone: Vec<i32> = ref_items.clone();
+ | -------- ^^^^^^^^^^-----^^
+ | | | |
+ | | | help: try using a conversion method: `to_vec`
+ | | expected struct `Vec`, found `&[i32]`
+ | expected due to this
+ |
+ = note: expected struct `Vec<i32>`
+ found reference `&[i32]`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-53692.rs:14:26
+ |
+LL | let string: String = s.clone();
+ | ------ ^^-----^^
+ | | | |
+ | | | help: try using a conversion method: `to_string`
+ | | expected struct `String`, found `&str`
+ | expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-57672.rs b/tests/ui/suggestions/issue-57672.rs
new file mode 100644
index 000000000..ee999d83e
--- /dev/null
+++ b/tests/ui/suggestions/issue-57672.rs
@@ -0,0 +1,14 @@
+// aux-build:foo.rs
+// compile-flags:--extern foo
+// check-pass
+// edition:2018
+
+#![deny(unused_extern_crates)]
+
+extern crate foo as foo_renamed;
+
+pub mod m {
+ pub use foo_renamed::Foo;
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-59819.fixed b/tests/ui/suggestions/issue-59819.fixed
new file mode 100644
index 000000000..644d2a4e4
--- /dev/null
+++ b/tests/ui/suggestions/issue-59819.fixed
@@ -0,0 +1,35 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as
+// references.
+
+struct Foo(i32);
+
+struct Bar(String);
+
+impl std::ops::Deref for Foo {
+ type Target = i32;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl std::ops::Deref for Bar {
+ type Target = String;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+fn main() {
+ let x = Foo(42);
+ let y: i32 = *x; //~ ERROR mismatched types
+ let a = &42;
+ let b: i32 = *a; //~ ERROR mismatched types
+
+ // Do not make a suggestion when adding a `*` wouldn't actually fix the issue:
+ let f = Bar("bar".to_string());
+ let g: String = f.to_string(); //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/issue-59819.rs b/tests/ui/suggestions/issue-59819.rs
new file mode 100644
index 000000000..8e8ff8372
--- /dev/null
+++ b/tests/ui/suggestions/issue-59819.rs
@@ -0,0 +1,35 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as
+// references.
+
+struct Foo(i32);
+
+struct Bar(String);
+
+impl std::ops::Deref for Foo {
+ type Target = i32;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl std::ops::Deref for Bar {
+ type Target = String;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+fn main() {
+ let x = Foo(42);
+ let y: i32 = x; //~ ERROR mismatched types
+ let a = &42;
+ let b: i32 = a; //~ ERROR mismatched types
+
+ // Do not make a suggestion when adding a `*` wouldn't actually fix the issue:
+ let f = Bar("bar".to_string());
+ let g: String = f; //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/issue-59819.stderr b/tests/ui/suggestions/issue-59819.stderr
new file mode 100644
index 000000000..40e4c7b78
--- /dev/null
+++ b/tests/ui/suggestions/issue-59819.stderr
@@ -0,0 +1,38 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-59819.rs:28:18
+ |
+LL | let y: i32 = x;
+ | --- ^ expected `i32`, found struct `Foo`
+ | |
+ | expected due to this
+ |
+help: consider dereferencing the type
+ |
+LL | let y: i32 = *x;
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-59819.rs:30:18
+ |
+LL | let b: i32 = a;
+ | --- ^ expected `i32`, found `&{integer}`
+ | |
+ | expected due to this
+ |
+help: consider dereferencing the borrow
+ |
+LL | let b: i32 = *a;
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-59819.rs:34:21
+ |
+LL | let g: String = f;
+ | ------ ^- help: try using a conversion method: `.to_string()`
+ | | |
+ | | expected struct `String`, found struct `Bar`
+ | expected due to this
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-61226.fixed b/tests/ui/suggestions/issue-61226.fixed
new file mode 100644
index 000000000..6e9d74344
--- /dev/null
+++ b/tests/ui/suggestions/issue-61226.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+struct X {}
+fn main() {
+ let _ = vec![X {}]; //…
+ //~^ ERROR expected value, found struct `X`
+}
diff --git a/tests/ui/suggestions/issue-61226.rs b/tests/ui/suggestions/issue-61226.rs
new file mode 100644
index 000000000..695fe7341
--- /dev/null
+++ b/tests/ui/suggestions/issue-61226.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+struct X {}
+fn main() {
+ let _ = vec![X]; //…
+ //~^ ERROR expected value, found struct `X`
+}
diff --git a/tests/ui/suggestions/issue-61226.stderr b/tests/ui/suggestions/issue-61226.stderr
new file mode 100644
index 000000000..cda962a90
--- /dev/null
+++ b/tests/ui/suggestions/issue-61226.stderr
@@ -0,0 +1,12 @@
+error[E0423]: expected value, found struct `X`
+ --> $DIR/issue-61226.rs:4:18
+ |
+LL | struct X {}
+ | ----------- `X` defined here
+LL | fn main() {
+LL | let _ = vec![X]; //…
+ | ^ help: use struct literal syntax instead: `X {}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs
new file mode 100644
index 000000000..a27c38452
--- /dev/null
+++ b/tests/ui/suggestions/issue-61963.rs
@@ -0,0 +1,37 @@
+// aux-build:issue-61963.rs
+// aux-build:issue-61963-1.rs
+#![deny(bare_trait_objects)]
+
+#[macro_use]
+extern crate issue_61963;
+#[macro_use]
+extern crate issue_61963_1;
+
+// This test checks that the bare trait object lint does not trigger on macro attributes that
+// generate code which would trigger the lint.
+
+pub struct Baz;
+pub trait Bar {}
+pub struct Qux<T>(T);
+
+#[dom_struct]
+pub struct Foo {
+ //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+ //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+ //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+ //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+ qux: Qux<Qux<Baz>>,
+ bar: Box<Bar>,
+ //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+ //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+ //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+ //~| WARN this is accepted in the current edition
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr
new file mode 100644
index 000000000..b99b1b0b9
--- /dev/null
+++ b/tests/ui/suggestions/issue-61963.stderr
@@ -0,0 +1,98 @@
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:28:14
+ |
+LL | bar: Box<Bar>,
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+note: the lint level is defined here
+ --> $DIR/issue-61963.rs:3:9
+ |
+LL | #![deny(bare_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^
+help: use `dyn`
+ |
+LL | bar: Box<dyn Bar>,
+ | +++
+
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:18:1
+ |
+LL | pub struct Foo {
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | dyn pub struct Foo {
+ | +++
+
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:28:14
+ |
+LL | bar: Box<Bar>,
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | bar: Box<dyn Bar>,
+ | +++
+
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:28:14
+ |
+LL | bar: Box<Bar>,
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | bar: Box<dyn Bar>,
+ | +++
+
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:18:1
+ |
+LL | pub struct Foo {
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | dyn pub struct Foo {
+ | +++
+
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:18:1
+ |
+LL | pub struct Foo {
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | dyn pub struct Foo {
+ | +++
+
+error: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/issue-61963.rs:18:1
+ |
+LL | pub struct Foo {
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | dyn pub struct Foo {
+ | +++
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/suggestions/issue-62843.rs b/tests/ui/suggestions/issue-62843.rs
new file mode 100644
index 000000000..d96b12fd1
--- /dev/null
+++ b/tests/ui/suggestions/issue-62843.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let line = String::from("abc");
+ let pattern = String::from("bc");
+ println!("{:?}", line.find(pattern)); //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr
new file mode 100644
index 000000000..b6e271de8
--- /dev/null
+++ b/tests/ui/suggestions/issue-62843.stderr
@@ -0,0 +1,20 @@
+error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
+ --> $DIR/issue-62843.rs:4:32
+ |
+LL | println!("{:?}", line.find(pattern));
+ | ---- ^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `String: Pattern<'_>` is not satisfied
+ = note: required for `String` to implement `Pattern<'_>`
+note: required by a bound in `core::str::<impl str>::find`
+ --> $SRC_DIR/core/src/str/mod.rs:LL:COL
+help: consider borrowing here
+ |
+LL | println!("{:?}", line.find(&pattern));
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-64252-self-type.rs b/tests/ui/suggestions/issue-64252-self-type.rs
new file mode 100644
index 000000000..128d5e85c
--- /dev/null
+++ b/tests/ui/suggestions/issue-64252-self-type.rs
@@ -0,0 +1,14 @@
+// This test checks that a suggestion to add a `self: ` parameter name is provided
+// to functions where this is applicable.
+
+pub fn foo(Box<Self>) { }
+//~^ ERROR expected one of `:`, `@`, or `|`, found `<`
+
+struct Bar;
+
+impl Bar {
+ fn bar(Box<Self>) { }
+ //~^ ERROR expected one of `:`, `@`, or `|`, found `<`
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr
new file mode 100644
index 000000000..c3418dab0
--- /dev/null
+++ b/tests/ui/suggestions/issue-64252-self-type.stderr
@@ -0,0 +1,34 @@
+error: expected one of `:`, `@`, or `|`, found `<`
+ --> $DIR/issue-64252-self-type.rs:4:15
+ |
+LL | pub fn foo(Box<Self>) { }
+ | ^ expected one of `:`, `@`, or `|`
+ |
+ = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this is a `self` type, give it a parameter name
+ |
+LL | pub fn foo(self: Box<Self>) { }
+ | +++++
+help: if this is a type, explicitly ignore the parameter name
+ |
+LL | pub fn foo(_: Box<Self>) { }
+ | ++
+
+error: expected one of `:`, `@`, or `|`, found `<`
+ --> $DIR/issue-64252-self-type.rs:10:15
+ |
+LL | fn bar(Box<Self>) { }
+ | ^ expected one of `:`, `@`, or `|`
+ |
+ = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this is a `self` type, give it a parameter name
+ |
+LL | fn bar(self: Box<Self>) { }
+ | +++++
+help: if this is a type, explicitly ignore the parameter name
+ |
+LL | fn bar(_: Box<Self>) { }
+ | ++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/suggestions/issue-66968-suggest-sorted-words.rs b/tests/ui/suggestions/issue-66968-suggest-sorted-words.rs
new file mode 100644
index 000000000..440bb653a
--- /dev/null
+++ b/tests/ui/suggestions/issue-66968-suggest-sorted-words.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let a_longer_variable_name = 1;
+ println!("{}", a_variable_longer_name); //~ ERROR E0425
+}
diff --git a/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr b/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr
new file mode 100644
index 000000000..d7b33ea41
--- /dev/null
+++ b/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `a_variable_longer_name` in this scope
+ --> $DIR/issue-66968-suggest-sorted-words.rs:3:20
+ |
+LL | println!("{}", a_variable_longer_name);
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `a_longer_variable_name`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/issue-68049-1.rs b/tests/ui/suggestions/issue-68049-1.rs
new file mode 100644
index 000000000..0acb7b1bf
--- /dev/null
+++ b/tests/ui/suggestions/issue-68049-1.rs
@@ -0,0 +1,16 @@
+use std::alloc::{GlobalAlloc, Layout};
+
+struct Test(u32);
+
+unsafe impl GlobalAlloc for Test {
+ unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
+ self.0 += 1; //~ ERROR cannot assign
+ 0 as *mut u8
+ }
+
+ unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
+ unimplemented!();
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-68049-1.stderr b/tests/ui/suggestions/issue-68049-1.stderr
new file mode 100644
index 000000000..7f931f0cd
--- /dev/null
+++ b/tests/ui/suggestions/issue-68049-1.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
+ --> $DIR/issue-68049-1.rs:7:9
+ |
+LL | self.0 += 1;
+ | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/suggestions/issue-68049-2.rs b/tests/ui/suggestions/issue-68049-2.rs
new file mode 100644
index 000000000..1c3430c14
--- /dev/null
+++ b/tests/ui/suggestions/issue-68049-2.rs
@@ -0,0 +1,21 @@
+trait Hello {
+ fn example(&self, input: &i32); // should suggest here
+}
+
+struct Test1(i32);
+
+impl Hello for Test1 {
+ fn example(&self, input: &i32) { // should not suggest here
+ *input = self.0; //~ ERROR cannot assign
+ }
+}
+
+struct Test2(i32);
+
+impl Hello for Test2 {
+ fn example(&self, input: &i32) { // should not suggest here
+ self.0 += *input; //~ ERROR cannot assign
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-68049-2.stderr b/tests/ui/suggestions/issue-68049-2.stderr
new file mode 100644
index 000000000..de35aa5b1
--- /dev/null
+++ b/tests/ui/suggestions/issue-68049-2.stderr
@@ -0,0 +1,25 @@
+error[E0594]: cannot assign to `*input`, which is behind a `&` reference
+ --> $DIR/issue-68049-2.rs:9:7
+ |
+LL | *input = self.0;
+ | ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing that to be a mutable reference
+ |
+LL | fn example(&self, input: &mut i32); // should suggest here
+ | ~~~~~~~~
+
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
+ --> $DIR/issue-68049-2.rs:17:5
+ |
+LL | self.0 += *input;
+ | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing that to be a mutable reference
+ |
+LL | fn example(&mut self, input: &i32); // should suggest here
+ | ~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.rs b/tests/ui/suggestions/issue-71394-no-from-impl.rs
new file mode 100644
index 000000000..0c35deb51
--- /dev/null
+++ b/tests/ui/suggestions/issue-71394-no-from-impl.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let data: &[u8] = &[0; 10];
+ let _: &[i8] = data.into();
+ //~^ ERROR the trait bound `&[i8]: From<&[u8]>` is not satisfied
+}
diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr
new file mode 100644
index 000000000..a5e6f5b5f
--- /dev/null
+++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
+ --> $DIR/issue-71394-no-from-impl.rs:3:25
+ |
+LL | let _: &[i8] = data.into();
+ | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
+ |
+ = help: the following other types implement trait `From<T>`:
+ <[T; LANES] as From<Simd<T, LANES>>>
+ <[bool; LANES] as From<Mask<T, LANES>>>
+ = note: required for `&[u8]` to implement `Into<&[i8]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-72766.rs b/tests/ui/suggestions/issue-72766.rs
new file mode 100644
index 000000000..c54be7f5d
--- /dev/null
+++ b/tests/ui/suggestions/issue-72766.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// incremental
+
+pub struct SadGirl;
+
+impl SadGirl {
+ pub async fn call(&self) -> Result<(), ()> {
+ Ok(())
+ }
+}
+
+async fn async_main() -> Result<(), ()> {
+ // should be `.call().await?`
+ SadGirl {}.call()?; //~ ERROR: the `?` operator can only be applied to values
+ Ok(())
+}
+
+fn main() {
+ let _ = async_main();
+}
diff --git a/tests/ui/suggestions/issue-72766.stderr b/tests/ui/suggestions/issue-72766.stderr
new file mode 100644
index 000000000..f257bb9b0
--- /dev/null
+++ b/tests/ui/suggestions/issue-72766.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/issue-72766.rs:14:5
+ |
+LL | SadGirl {}.call()?;
+ | ^^^^^^^^^^^^^^^^^^ 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 | SadGirl {}.call().await?;
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs
new file mode 100644
index 000000000..3cd6d336e
--- /dev/null
+++ b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs
@@ -0,0 +1,32 @@
+// Regression test: if we suggest replacing an `impl Trait` argument to an async
+// fn with a named type parameter in order to add bounds, the suggested function
+// signature should be well-formed.
+//
+// edition:2018
+
+trait Foo {
+ type Bar;
+ fn bar(&self) -> Self::Bar;
+}
+
+async fn run(_: &(), foo: impl Foo) -> std::io::Result<()> {
+ let bar = foo.bar();
+ assert_is_send(&bar);
+//~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+
+ Ok(())
+}
+
+// Test our handling of cases where there is a generic parameter list in the
+// source, but only synthetic generic parameters
+async fn run2< >(_: &(), foo: impl Foo) -> std::io::Result<()> {
+ let bar = foo.bar();
+ assert_is_send(&bar);
+//~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+
+ Ok(())
+}
+
+fn assert_is_send<T: Send>(_: &T) {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr
new file mode 100644
index 000000000..a3ab0b8ef
--- /dev/null
+++ b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr
@@ -0,0 +1,41 @@
+error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20
+ |
+LL | assert_is_send(&bar);
+ | -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
+note: required by a bound in `assert_is_send`
+ --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:30:22
+ |
+LL | fn assert_is_send<T: Send>(_: &T) {}
+ | ^^^^ required by this bound in `assert_is_send`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | async fn run<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send {
+ | ++++++++ ~ +++++++++++++++++++++++++++
+
+error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20
+ |
+LL | assert_is_send(&bar);
+ | -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
+note: required by a bound in `assert_is_send`
+ --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:30:22
+ |
+LL | fn assert_is_send<T: Send>(_: &T) {}
+ | ^^^^ required by this bound in `assert_is_send`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | async fn run2<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send {
+ | ~~~~~~~~ ~ +++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-81098.rs b/tests/ui/suggestions/issue-81098.rs
new file mode 100644
index 000000000..a601b5866
--- /dev/null
+++ b/tests/ui/suggestions/issue-81098.rs
@@ -0,0 +1,13 @@
+// Don't suggest removing a semicolon if the last statement isn't an expression with semicolon
+// (#81098)
+fn wat() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display`
+ fn why() {}
+}
+
+// Do it if the last statement is an expression with semicolon
+// (#54771)
+fn ok() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display`
+ 1;
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-81098.stderr b/tests/ui/suggestions/issue-81098.stderr
new file mode 100644
index 000000000..4dc47a202
--- /dev/null
+++ b/tests/ui/suggestions/issue-81098.stderr
@@ -0,0 +1,25 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/issue-81098.rs:3:13
+ |
+LL | fn wat() -> impl core::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/issue-81098.rs:9:12
+ |
+LL | fn ok() -> impl core::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
+LL | 1;
+ | -- help: remove this semicolon
+ | |
+ | this expression has type `{integer}`, which implements `std::fmt::Display`
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-81839.rs b/tests/ui/suggestions/issue-81839.rs
new file mode 100644
index 000000000..0b9b7aefe
--- /dev/null
+++ b/tests/ui/suggestions/issue-81839.rs
@@ -0,0 +1,17 @@
+// aux-build:issue-81839.rs
+// edition:2018
+
+extern crate issue_81839;
+
+async fn test(ans: &str, num: i32, cx: &issue_81839::Test) -> u32 {
+ match num {
+ 1 => {
+ cx.answer_str("hi");
+ }
+ _ => cx.answer_str("hi"), //~ `match` arms have incompatible types
+ }
+
+ 1
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-81839.stderr b/tests/ui/suggestions/issue-81839.stderr
new file mode 100644
index 000000000..fae474ced
--- /dev/null
+++ b/tests/ui/suggestions/issue-81839.stderr
@@ -0,0 +1,27 @@
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/issue-81839.rs:11:14
+ |
+LL | / match num {
+LL | | 1 => {
+LL | | cx.answer_str("hi");
+ | | --------------------
+ | | | |
+ | | | help: consider removing this semicolon
+ | | this is found to be of type `()`
+LL | | }
+LL | | _ => cx.answer_str("hi"),
+ | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type
+LL | | }
+ | |_____- `match` arms have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/auxiliary/issue-81839.rs:6:49
+ |
+LL | pub async fn answer_str(&self, _s: &str) -> Test {
+ | ^^^^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected unit type `()`
+ found opaque type `impl Future<Output = Test>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-82361.fixed b/tests/ui/suggestions/issue-82361.fixed
new file mode 100644
index 000000000..d72de982b
--- /dev/null
+++ b/tests/ui/suggestions/issue-82361.fixed
@@ -0,0 +1,24 @@
+// run-rustfix
+
+fn main() {
+ let a: usize = 123;
+ let b: &usize = &a;
+
+ if true {
+ a
+ } else {
+ *b //~ ERROR `if` and `else` have incompatible types [E0308]
+ };
+
+ if true {
+ 1
+ } else {
+ 1 //~ ERROR `if` and `else` have incompatible types [E0308]
+ };
+
+ if true {
+ 1
+ } else {
+ 1 //~ ERROR `if` and `else` have incompatible types [E0308]
+ };
+}
diff --git a/tests/ui/suggestions/issue-82361.rs b/tests/ui/suggestions/issue-82361.rs
new file mode 100644
index 000000000..c068f6d22
--- /dev/null
+++ b/tests/ui/suggestions/issue-82361.rs
@@ -0,0 +1,24 @@
+// run-rustfix
+
+fn main() {
+ let a: usize = 123;
+ let b: &usize = &a;
+
+ if true {
+ a
+ } else {
+ b //~ ERROR `if` and `else` have incompatible types [E0308]
+ };
+
+ if true {
+ 1
+ } else {
+ &1 //~ ERROR `if` and `else` have incompatible types [E0308]
+ };
+
+ if true {
+ 1
+ } else {
+ &mut 1 //~ ERROR `if` and `else` have incompatible types [E0308]
+ };
+}
diff --git a/tests/ui/suggestions/issue-82361.stderr b/tests/ui/suggestions/issue-82361.stderr
new file mode 100644
index 000000000..e4e8ad15d
--- /dev/null
+++ b/tests/ui/suggestions/issue-82361.stderr
@@ -0,0 +1,56 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/issue-82361.rs:10:9
+ |
+LL | / if true {
+LL | | a
+ | | - expected because of this
+LL | | } else {
+LL | | b
+ | | ^ expected `usize`, found `&usize`
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+help: consider dereferencing the borrow
+ |
+LL | *b
+ | +
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/issue-82361.rs:16:9
+ |
+LL | / if true {
+LL | | 1
+ | | - expected because of this
+LL | | } else {
+LL | | &1
+ | | ^^ expected integer, found `&{integer}`
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+help: consider removing the borrow
+ |
+LL - &1
+LL + 1
+ |
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/issue-82361.rs:22:9
+ |
+LL | / if true {
+LL | | 1
+ | | - expected because of this
+LL | | } else {
+LL | | &mut 1
+ | | ^^^^^^ expected integer, found `&mut {integer}`
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+help: consider removing the borrow
+ |
+LL - &mut 1
+LL + 1
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-82566-1.rs b/tests/ui/suggestions/issue-82566-1.rs
new file mode 100644
index 000000000..95c31fbaa
--- /dev/null
+++ b/tests/ui/suggestions/issue-82566-1.rs
@@ -0,0 +1,21 @@
+struct T1<const X1: usize>;
+struct T2<const X1: usize, const X2: usize>;
+struct T3<const X1: usize, const X2: usize, const X3: usize>;
+
+impl T1<1> {
+ const C: () = ();
+}
+
+impl T2<1, 2> {
+ const C: () = ();
+}
+
+impl T3<1, 2, 3> {
+ const C: () = ();
+}
+
+fn main() {
+ T1<1>::C; //~ ERROR: comparison operators cannot be chained
+ T2<1, 2>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+ T3<1, 2, 3>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+}
diff --git a/tests/ui/suggestions/issue-82566-1.stderr b/tests/ui/suggestions/issue-82566-1.stderr
new file mode 100644
index 000000000..72f0f45fb
--- /dev/null
+++ b/tests/ui/suggestions/issue-82566-1.stderr
@@ -0,0 +1,35 @@
+error: comparison operators cannot be chained
+ --> $DIR/issue-82566-1.rs:18:7
+ |
+LL | T1<1>::C;
+ | ^ ^
+ |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ |
+LL | T1::<1>::C;
+ | ++
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+ --> $DIR/issue-82566-1.rs:19:9
+ |
+LL | T2<1, 2>::C;
+ | ^ expected one of `.`, `;`, `?`, `}`, or an operator
+ |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ |
+LL | T2::<1, 2>::C;
+ | ++
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+ --> $DIR/issue-82566-1.rs:20:9
+ |
+LL | T3<1, 2, 3>::C;
+ | ^ expected one of `.`, `;`, `?`, `}`, or an operator
+ |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ |
+LL | T3::<1, 2, 3>::C;
+ | ++
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/issue-82566-2.rs b/tests/ui/suggestions/issue-82566-2.rs
new file mode 100644
index 000000000..80c8034bd
--- /dev/null
+++ b/tests/ui/suggestions/issue-82566-2.rs
@@ -0,0 +1,31 @@
+struct Foo1<const N1: usize>;
+struct Foo2<const N1: usize, const N2: usize>;
+struct Foo3<const N1: usize, const N2: usize, const N3: usize>;
+
+impl<const N1: usize> Foo1<N1> {
+ const SUM: usize = N1;
+}
+
+impl<const N1: usize, const N2: usize> Foo2<N1, N2> {
+ const SUM: usize = N1 + N2;
+}
+
+impl<const N1: usize, const N2: usize, const N3: usize> Foo3<N1, N2, N3> {
+ const SUM: usize = N1 + N2 + N3;
+}
+
+fn foo1() -> [(); Foo1<10>::SUM] { //~ ERROR: comparison operators cannot be chained
+ todo!()
+}
+
+fn foo2() -> [(); Foo2<10, 20>::SUM] {
+ //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
+ todo!()
+}
+
+fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
+ //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
+ todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-82566-2.stderr b/tests/ui/suggestions/issue-82566-2.stderr
new file mode 100644
index 000000000..ef9a41430
--- /dev/null
+++ b/tests/ui/suggestions/issue-82566-2.stderr
@@ -0,0 +1,35 @@
+error: comparison operators cannot be chained
+ --> $DIR/issue-82566-2.rs:17:23
+ |
+LL | fn foo1() -> [(); Foo1<10>::SUM] {
+ | ^ ^
+ |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ |
+LL | fn foo1() -> [(); Foo1::<10>::SUM] {
+ | ++
+
+error: expected one of `.`, `?`, `]`, or an operator, found `,`
+ --> $DIR/issue-82566-2.rs:21:26
+ |
+LL | fn foo2() -> [(); Foo2<10, 20>::SUM] {
+ | ^ expected one of `.`, `?`, `]`, or an operator
+ |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ |
+LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] {
+ | ++
+
+error: expected one of `.`, `?`, `]`, or an operator, found `,`
+ --> $DIR/issue-82566-2.rs:26:26
+ |
+LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
+ | ^ expected one of `.`, `?`, `]`, or an operator
+ |
+help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+ |
+LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] {
+ | ++
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/issue-83892.fixed b/tests/ui/suggestions/issue-83892.fixed
new file mode 100644
index 000000000..dd093a7a0
--- /dev/null
+++ b/tests/ui/suggestions/issue-83892.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+fn func() -> u8 {
+ 0
+}
+
+fn main() {
+ match () {
+ () => func() //~ ERROR mismatched types
+ };
+}
diff --git a/tests/ui/suggestions/issue-83892.rs b/tests/ui/suggestions/issue-83892.rs
new file mode 100644
index 000000000..1d56ecee8
--- /dev/null
+++ b/tests/ui/suggestions/issue-83892.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+fn func() -> u8 {
+ 0
+}
+
+fn main() {
+ match () {
+ () => func() //~ ERROR mismatched types
+ }
+}
diff --git a/tests/ui/suggestions/issue-83892.stderr b/tests/ui/suggestions/issue-83892.stderr
new file mode 100644
index 000000000..baf6b1447
--- /dev/null
+++ b/tests/ui/suggestions/issue-83892.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-83892.rs:9:15
+ |
+LL | fn main() {
+ | - expected `()` because of default return type
+LL | match () {
+LL | () => func()
+ | ^^^^^^ expected `()`, found `u8`
+LL | }
+ | - help: consider using a semicolon here: `;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-83943.fixed b/tests/ui/suggestions/issue-83943.fixed
new file mode 100644
index 000000000..e0d4ee29e
--- /dev/null
+++ b/tests/ui/suggestions/issue-83943.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+ if true {
+ "A".to_string()
+ } else {
+ "B".to_string() //~ ERROR `if` and `else` have incompatible types
+ };
+}
diff --git a/tests/ui/suggestions/issue-83943.rs b/tests/ui/suggestions/issue-83943.rs
new file mode 100644
index 000000000..68d50c177
--- /dev/null
+++ b/tests/ui/suggestions/issue-83943.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+ if true {
+ "A".to_string()
+ } else {
+ "B" //~ ERROR `if` and `else` have incompatible types
+ };
+}
diff --git a/tests/ui/suggestions/issue-83943.stderr b/tests/ui/suggestions/issue-83943.stderr
new file mode 100644
index 000000000..885106e84
--- /dev/null
+++ b/tests/ui/suggestions/issue-83943.stderr
@@ -0,0 +1,17 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/issue-83943.rs:7:9
+ |
+LL | / if true {
+LL | | "A".to_string()
+ | | --------------- expected because of this
+LL | | } else {
+LL | | "B"
+ | | ^^^- help: try using a conversion method: `.to_string()`
+ | | |
+ | | expected struct `String`, found `&str`
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-84592.rs b/tests/ui/suggestions/issue-84592.rs
new file mode 100644
index 000000000..aa246aaa3
--- /dev/null
+++ b/tests/ui/suggestions/issue-84592.rs
@@ -0,0 +1,17 @@
+/* Checks whether issue #84592 has been resolved. The issue was
+ * that in this example, there are two expected/missing lifetime
+ * parameters with *different spans*, leading to incorrect
+ * suggestions from rustc.
+ */
+
+struct TwoLifetimes<'x, 'y> {
+ x: &'x (),
+ y: &'y (),
+}
+
+fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> {
+//~^ ERROR missing lifetime specifiers [E0106]
+ TwoLifetimes { x: &(), y: &() }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-84592.stderr b/tests/ui/suggestions/issue-84592.stderr
new file mode 100644
index 000000000..70c96feb1
--- /dev/null
+++ b/tests/ui/suggestions/issue-84592.stderr
@@ -0,0 +1,17 @@
+error[E0106]: missing lifetime specifiers
+ --> $DIR/issue-84592.rs:12:57
+ |
+LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> {
+ | --- --- ^^ ^^ expected named lifetime parameter
+ | |
+ | 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 `a` or `b`
+help: consider introducing a named lifetime parameter
+ |
+LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> {
+ | ++++ ++ ++ ~~ ~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/issue-84700.rs b/tests/ui/suggestions/issue-84700.rs
new file mode 100644
index 000000000..a27169fdb
--- /dev/null
+++ b/tests/ui/suggestions/issue-84700.rs
@@ -0,0 +1,26 @@
+// test for suggestion on fieldless enum variant
+
+#[derive(PartialEq, Debug)]
+enum FarmAnimal {
+ Worm,
+ Cow,
+ Bull,
+ Chicken { num_eggs: usize },
+ Dog (String),
+}
+
+fn what_does_the_animal_say(animal: &FarmAnimal) {
+
+ let noise = match animal {
+ FarmAnimal::Cow(_) => "moo".to_string(),
+ //~^ ERROR expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow`
+ FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
+ //~^ ERROR expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
+ FarmAnimal::Dog{..} => "woof!".to_string(),
+ _ => todo!()
+ };
+
+ println!("{:?} says: {:?}", animal, noise);
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-84700.stderr b/tests/ui/suggestions/issue-84700.stderr
new file mode 100644
index 000000000..ac9f5ab0b
--- /dev/null
+++ b/tests/ui/suggestions/issue-84700.stderr
@@ -0,0 +1,19 @@
+error[E0532]: expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow`
+ --> $DIR/issue-84700.rs:15:9
+ |
+LL | Cow,
+ | --- `FarmAnimal::Cow` defined here
+...
+LL | FarmAnimal::Cow(_) => "moo".to_string(),
+ | ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow`
+
+error[E0164]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
+ --> $DIR/issue-84700.rs:17:9
+ |
+LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
+ | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0164, E0532.
+For more information about an error, try `rustc --explain E0164`.
diff --git a/tests/ui/suggestions/issue-84973-2.rs b/tests/ui/suggestions/issue-84973-2.rs
new file mode 100644
index 000000000..050cf8c64
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973-2.rs
@@ -0,0 +1,13 @@
+// A slight variation of issue-84973.rs. Here, a mutable borrow is
+// required (and the obligation kind is different).
+
+trait Tr {}
+impl Tr for &mut i32 {}
+
+fn foo<T: Tr>(i: T) {}
+
+fn main() {
+ let a: i32 = 32;
+ foo(a);
+ //~^ ERROR: the trait bound `i32: Tr` is not satisfied [E0277]
+}
diff --git a/tests/ui/suggestions/issue-84973-2.stderr b/tests/ui/suggestions/issue-84973-2.stderr
new file mode 100644
index 000000000..513bf28fb
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973-2.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `i32: Tr` is not satisfied
+ --> $DIR/issue-84973-2.rs:11:9
+ |
+LL | foo(a);
+ | --- ^ the trait `Tr` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/issue-84973-2.rs:7:11
+ |
+LL | fn foo<T: Tr>(i: T) {}
+ | ^^ required by this bound in `foo`
+help: consider mutably borrowing here
+ |
+LL | foo(&mut a);
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-84973-blacklist.rs b/tests/ui/suggestions/issue-84973-blacklist.rs
new file mode 100644
index 000000000..6813b07a2
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973-blacklist.rs
@@ -0,0 +1,28 @@
+// Checks that certain traits for which we don't want to suggest borrowing
+// are blacklisted and don't cause the suggestion to be issued.
+
+#![feature(generators)]
+
+fn f_copy<T: Copy>(t: T) {}
+fn f_clone<T: Clone>(t: T) {}
+fn f_unpin<T: Unpin>(t: T) {}
+fn f_sized<T: Sized>(t: T) {}
+fn f_send<T: Send>(t: T) {}
+
+struct S;
+
+fn main() {
+ f_copy("".to_string()); //~ ERROR: the trait bound `String: Copy` is not satisfied [E0277]
+ f_clone(S); //~ ERROR: the trait bound `S: Clone` is not satisfied [E0277]
+ f_unpin(static || { yield; });
+ //~^ ERROR: cannot be unpinned [E0277]
+
+ let cl = || ();
+ let ref_cl: &dyn Fn() -> () = &cl;
+ f_sized(*ref_cl);
+ //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
+
+ use std::rc::Rc;
+ let rc = Rc::new(0);
+ f_send(rc); //~ ERROR: `Rc<{integer}>` cannot be sent between threads safely [E0277]
+}
diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr
new file mode 100644
index 000000000..c20cc8164
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973-blacklist.stderr
@@ -0,0 +1,80 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+ --> $DIR/issue-84973-blacklist.rs:15:12
+ |
+LL | f_copy("".to_string());
+ | ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f_copy`
+ --> $DIR/issue-84973-blacklist.rs:6:14
+ |
+LL | fn f_copy<T: Copy>(t: T) {}
+ | ^^^^ required by this bound in `f_copy`
+
+error[E0277]: the trait bound `S: Clone` is not satisfied
+ --> $DIR/issue-84973-blacklist.rs:16:13
+ |
+LL | f_clone(S);
+ | ------- ^ the trait `Clone` is not implemented for `S`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f_clone`
+ --> $DIR/issue-84973-blacklist.rs:7:15
+ |
+LL | fn f_clone<T: Clone>(t: T) {}
+ | ^^^^^ required by this bound in `f_clone`
+help: consider annotating `S` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
+
+error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned
+ --> $DIR/issue-84973-blacklist.rs:17:13
+ |
+LL | f_unpin(static || { yield; });
+ | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: consider using `Box::pin`
+note: required by a bound in `f_unpin`
+ --> $DIR/issue-84973-blacklist.rs:8:15
+ |
+LL | fn f_unpin<T: Unpin>(t: T) {}
+ | ^^^^^ required by this bound in `f_unpin`
+
+error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time
+ --> $DIR/issue-84973-blacklist.rs:22:13
+ |
+LL | f_sized(*ref_cl);
+ | ------- ^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `dyn Fn()`
+note: required by a bound in `f_sized`
+ --> $DIR/issue-84973-blacklist.rs:9:12
+ |
+LL | fn f_sized<T: Sized>(t: T) {}
+ | ^ required by this bound in `f_sized`
+
+error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
+ --> $DIR/issue-84973-blacklist.rs:27:12
+ |
+LL | f_send(rc);
+ | ------ ^^ `Rc<{integer}>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `Rc<{integer}>`
+note: required by a bound in `f_send`
+ --> $DIR/issue-84973-blacklist.rs:10:14
+ |
+LL | fn f_send<T: Send>(t: T) {}
+ | ^^^^ required by this bound in `f_send`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-84973-negative.rs b/tests/ui/suggestions/issue-84973-negative.rs
new file mode 100644
index 000000000..f339251e5
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973-negative.rs
@@ -0,0 +1,12 @@
+// Checks that we only suggest borrowing if &T actually implements the trait.
+
+trait Tr {}
+impl Tr for &f32 {}
+fn bar<T: Tr>(t: T) {}
+
+fn main() {
+ let a = 0i32;
+ let b = 0.0f32;
+ bar(a); //~ ERROR: the trait bound `i32: Tr` is not satisfied [E0277]
+ bar(b); //~ ERROR: the trait bound `f32: Tr` is not satisfied [E0277]
+}
diff --git a/tests/ui/suggestions/issue-84973-negative.stderr b/tests/ui/suggestions/issue-84973-negative.stderr
new file mode 100644
index 000000000..ce838bce0
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973-negative.stderr
@@ -0,0 +1,36 @@
+error[E0277]: the trait bound `i32: Tr` is not satisfied
+ --> $DIR/issue-84973-negative.rs:10:9
+ |
+LL | bar(a);
+ | --- ^ the trait `Tr` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Tr` is implemented for `&f32`
+note: required by a bound in `bar`
+ --> $DIR/issue-84973-negative.rs:5:11
+ |
+LL | fn bar<T: Tr>(t: T) {}
+ | ^^ required by this bound in `bar`
+
+error[E0277]: the trait bound `f32: Tr` is not satisfied
+ --> $DIR/issue-84973-negative.rs:11:9
+ |
+LL | bar(b);
+ | --- ^ the trait `Tr` is not implemented for `f32`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `bar`
+ --> $DIR/issue-84973-negative.rs:5:11
+ |
+LL | fn bar<T: Tr>(t: T) {}
+ | ^^ required by this bound in `bar`
+help: consider borrowing here
+ |
+LL | bar(&b);
+ | +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-84973.rs b/tests/ui/suggestions/issue-84973.rs
new file mode 100644
index 000000000..42468478e
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973.rs
@@ -0,0 +1,33 @@
+// Checks whether borrowing is suggested when a trait bound is not satisfied
+// for found type `T`, but is for `&/&mut T`.
+
+fn main() {
+ let f = Fancy{};
+ let o = Other::new(f);
+ //~^ ERROR: the trait bound `Fancy: SomeTrait` is not satisfied [E0277]
+}
+
+struct Fancy {}
+
+impl <'a> SomeTrait for &'a Fancy {
+}
+
+trait SomeTrait {}
+
+struct Other<'a, G> {
+ a: &'a str,
+ g: G,
+}
+
+// Broadly copied from https://docs.rs/petgraph/0.5.1/src/petgraph/dot.rs.html#70
+impl<'a, G> Other<'a, G>
+where
+ G: SomeTrait,
+{
+ pub fn new(g: G) -> Self {
+ Other {
+ a: "hi",
+ g: g,
+ }
+ }
+}
diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr
new file mode 100644
index 000000000..ae2bf5aac
--- /dev/null
+++ b/tests/ui/suggestions/issue-84973.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied
+ --> $DIR/issue-84973.rs:6:24
+ |
+LL | let o = Other::new(f);
+ | ---------- ^ the trait `SomeTrait` is not implemented for `Fancy`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `Other::<'a, G>::new`
+ --> $DIR/issue-84973.rs:25:8
+ |
+LL | G: SomeTrait,
+ | ^^^^^^^^^ required by this bound in `Other::<'a, G>::new`
+LL | {
+LL | pub fn new(g: G) -> Self {
+ | --- required by a bound in this
+help: consider borrowing here
+ |
+LL | let o = Other::new(&f);
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-85347.rs b/tests/ui/suggestions/issue-85347.rs
new file mode 100644
index 000000000..02b5fb618
--- /dev/null
+++ b/tests/ui/suggestions/issue-85347.rs
@@ -0,0 +1,9 @@
+use std::ops::Deref;
+trait Foo {
+ type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+ //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+ //~| ERROR associated type bindings are not allowed here
+ //~| HELP add missing
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr
new file mode 100644
index 000000000..17c1b7dc4
--- /dev/null
+++ b/tests/ui/suggestions/issue-85347.stderr
@@ -0,0 +1,26 @@
+error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+ --> $DIR/issue-85347.rs:3:42
+ |
+LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+ | ^^^ expected 1 lifetime argument
+ |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+ --> $DIR/issue-85347.rs:3:10
+ |
+LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+ | ^^^ --
+help: add missing lifetime argument
+ |
+LL | type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>;
+ | +++
+
+error[E0229]: associated type bindings are not allowed here
+ --> $DIR/issue-85347.rs:3:46
+ |
+LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+ | ^^^^^^^^^^^^^ associated type not allowed here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0229.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
new file mode 100644
index 000000000..390d8bbdd
--- /dev/null
+++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
@@ -0,0 +1,9 @@
+// Regression test for #85943: should not emit suggestions for adding
+// indirection to type parameters in where-clauses when suggesting
+// adding `?Sized`.
+struct A<T>(T) where T: Send;
+struct B(A<[u8]>);
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
new file mode 100644
index 000000000..752533cdc
--- /dev/null
+++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:5:10
+ |
+LL | struct B(A<[u8]>);
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `A`
+ --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10
+ |
+LL | struct A<T>(T) where T: Send;
+ | ^ required by this bound in `A`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10
+ |
+LL | struct A<T>(T) where T: Send;
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs
new file mode 100644
index 000000000..1a36f6e8e
--- /dev/null
+++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs
@@ -0,0 +1,8 @@
+// Regression test for #85945: Don't suggest `?Sized` bound if an explicit
+// `Sized` bound is already in a `where` clause.
+fn foo<T>(_: &T) where T: Sized {}
+fn bar() { foo(""); }
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr
new file mode 100644
index 000000000..92be9f764
--- /dev/null
+++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16
+ |
+LL | fn bar() { foo(""); }
+ | --- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `str`
+note: required by a bound in `foo`
+ --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8
+ |
+LL | fn foo<T>(_: &T) where T: Sized {}
+ | ^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-86100-tuple-paren-comma.rs b/tests/ui/suggestions/issue-86100-tuple-paren-comma.rs
new file mode 100644
index 000000000..fa9d1a889
--- /dev/null
+++ b/tests/ui/suggestions/issue-86100-tuple-paren-comma.rs
@@ -0,0 +1,25 @@
+// Tests that a suggestion is issued for type mismatch errors when a
+// 1-tuple is expected and a parenthesized expression of non-tuple
+// type is supplied.
+
+fn foo<T>(_t: (T,)) {}
+struct S { _s: (String,) }
+
+fn main() {
+ let _x: (i32,) = (5);
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: use a trailing comma to create a tuple with one element
+
+ foo((Some(3)));
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: use a trailing comma to create a tuple with one element
+
+ let _s = S { _s: ("abc".to_string()) };
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: use a trailing comma to create a tuple with one element
+
+ // Do not issue the suggestion if the found type is already a tuple.
+ let t = (1, 2);
+ let _x: (i32,) = (t);
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr
new file mode 100644
index 000000000..8c9a41a20
--- /dev/null
+++ b/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr
@@ -0,0 +1,62 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:9:22
+ |
+LL | let _x: (i32,) = (5);
+ | ------ ^^^ expected tuple, found integer
+ | |
+ | expected due to this
+ |
+ = note: expected tuple `(i32,)`
+ found type `{integer}`
+help: use a trailing comma to create a tuple with one element
+ |
+LL | let _x: (i32,) = (5,);
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:13:9
+ |
+LL | foo((Some(3)));
+ | --- ^^^^^^^^^ expected tuple, found enum `Option`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected tuple `(_,)`
+ found enum `Option<{integer}>`
+note: function defined here
+ --> $DIR/issue-86100-tuple-paren-comma.rs:5:4
+ |
+LL | fn foo<T>(_t: (T,)) {}
+ | ^^^ --------
+help: use a trailing comma to create a tuple with one element
+ |
+LL | foo((Some(3),));
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:17:22
+ |
+LL | let _s = S { _s: ("abc".to_string()) };
+ | ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String`
+ |
+ = note: expected tuple `(String,)`
+ found struct `String`
+help: use a trailing comma to create a tuple with one element
+ |
+LL | let _s = S { _s: ("abc".to_string(),) };
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-86100-tuple-paren-comma.rs:23:22
+ |
+LL | let _x: (i32,) = (t);
+ | ------ ^^^ expected a tuple with 1 element, found one with 2 elements
+ | |
+ | expected due to this
+ |
+ = note: expected tuple `(i32,)`
+ found tuple `({integer}, {integer})`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs
new file mode 100644
index 000000000..366787df1
--- /dev/null
+++ b/tests/ui/suggestions/issue-86667.rs
@@ -0,0 +1,17 @@
+// Regression test for #86667, where a garbled suggestion was issued for
+// a missing named lifetime parameter.
+
+// compile-flags: --edition 2018
+
+async fn a(s1: &str, s2: &str) -> &str {
+//~^ ERROR: missing lifetime specifier [E0106]
+ s1
+//~^ ERROR: lifetime may not live long enough
+}
+
+fn b(s1: &str, s2: &str) -> &str {
+//~^ ERROR: missing lifetime specifier [E0106]
+ s1
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-86667.stderr b/tests/ui/suggestions/issue-86667.stderr
new file mode 100644
index 000000000..8d6116416
--- /dev/null
+++ b/tests/ui/suggestions/issue-86667.stderr
@@ -0,0 +1,36 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-86667.rs:6:35
+ |
+LL | async fn a(s1: &str, s2: &str) -> &str {
+ | ---- ---- ^ 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 `s1` or `s2`
+help: consider introducing a named lifetime parameter
+ |
+LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str {
+ | ++++ ++ ++ ++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-86667.rs:12:29
+ |
+LL | fn b(s1: &str, s2: &str) -> &str {
+ | ---- ---- ^ 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 `s1` or `s2`
+help: consider introducing a named lifetime parameter
+ |
+LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str {
+ | ++++ ++ ++ ++
+
+error: lifetime may not live long enough
+ --> $DIR/issue-86667.rs:8:5
+ |
+LL | async fn a(s1: &str, s2: &str) -> &str {
+ | - let's call the lifetime of this reference `'1`
+LL |
+LL | s1
+ | ^^ returning this value requires that `'1` must outlive `'static`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/issue-88730.rs b/tests/ui/suggestions/issue-88730.rs
new file mode 100644
index 000000000..d161ed284
--- /dev/null
+++ b/tests/ui/suggestions/issue-88730.rs
@@ -0,0 +1,15 @@
+#![allow(unused, nonstandard_style)]
+
+// If an enum has two different variants,
+// then it cannot be matched upon in a function argument.
+// It still gets an error, but no suggestions.
+enum Foo {
+ C,
+ D,
+}
+
+fn foo(C: Foo) {} //~ERROR
+
+fn main() {
+ let C = Foo::D; //~ERROR
+}
diff --git a/tests/ui/suggestions/issue-88730.stderr b/tests/ui/suggestions/issue-88730.stderr
new file mode 100644
index 000000000..0bd1b7ba4
--- /dev/null
+++ b/tests/ui/suggestions/issue-88730.stderr
@@ -0,0 +1,17 @@
+error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo`
+ --> $DIR/issue-88730.rs:11:8
+ |
+LL | fn foo(C: Foo) {}
+ | ^
+ |
+ = note: `#[deny(bindings_with_variant_name)]` on by default
+
+error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo`
+ --> $DIR/issue-88730.rs:14:9
+ |
+LL | let C = Foo::D;
+ | ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0170`.
diff --git a/tests/ui/suggestions/issue-89064.rs b/tests/ui/suggestions/issue-89064.rs
new file mode 100644
index 000000000..fa5fc899d
--- /dev/null
+++ b/tests/ui/suggestions/issue-89064.rs
@@ -0,0 +1,35 @@
+use std::convert::TryInto;
+
+trait A<T> {
+ fn foo() {}
+}
+
+trait B<T, U> {
+ fn bar() {}
+}
+
+struct S;
+
+impl<T> A<T> for S {}
+impl<T, U> B<T, U> for S {}
+
+fn main() {
+ let _ = A::foo::<S>();
+ //~^ ERROR
+ //~| HELP remove these generics
+ //~| HELP consider moving this generic argument
+
+ let _ = B::bar::<S, S>();
+ //~^ ERROR
+ //~| HELP remove these generics
+ //~| HELP consider moving these generic arguments
+
+ let _ = A::<S>::foo::<S>();
+ //~^ ERROR
+ //~| HELP remove these generics
+
+ let _ = 42.into::<Option<_>>();
+ //~^ ERROR
+ //~| HELP remove these generics
+ //~| HELP consider moving this generic argument
+}
diff --git a/tests/ui/suggestions/issue-89064.stderr b/tests/ui/suggestions/issue-89064.stderr
new file mode 100644
index 000000000..93d8da226
--- /dev/null
+++ b/tests/ui/suggestions/issue-89064.stderr
@@ -0,0 +1,77 @@
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-89064.rs:17:16
+ |
+LL | let _ = A::foo::<S>();
+ | ^^^ expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/issue-89064.rs:4:8
+ |
+LL | fn foo() {}
+ | ^^^
+help: consider moving this generic argument to the `A` trait, which takes up to 1 argument
+ |
+LL - let _ = A::foo::<S>();
+LL + let _ = A::<S>::foo();
+ |
+help: remove these generics
+ |
+LL - let _ = A::foo::<S>();
+LL + let _ = A::foo();
+ |
+
+error[E0107]: this associated function takes 0 generic arguments but 2 generic arguments were supplied
+ --> $DIR/issue-89064.rs:22:16
+ |
+LL | let _ = B::bar::<S, S>();
+ | ^^^ expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/issue-89064.rs:8:8
+ |
+LL | fn bar() {}
+ | ^^^
+help: consider moving these generic arguments to the `B` trait, which takes up to 2 arguments
+ |
+LL - let _ = B::bar::<S, S>();
+LL + let _ = B::<S, S>::bar();
+ |
+help: remove these generics
+ |
+LL - let _ = B::bar::<S, S>();
+LL + let _ = B::bar();
+ |
+
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-89064.rs:27:21
+ |
+LL | let _ = A::<S>::foo::<S>();
+ | ^^^----- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/issue-89064.rs:4:8
+ |
+LL | fn foo() {}
+ | ^^^
+
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-89064.rs:31:16
+ |
+LL | let _ = 42.into::<Option<_>>();
+ | ^^^^ expected 0 generic arguments
+ |
+help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument
+ |
+LL | let _ = Into::<Option<_>>::into(42);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: remove these generics
+ |
+LL - let _ = 42.into::<Option<_>>();
+LL + let _ = 42.into();
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/issue-89333.rs b/tests/ui/suggestions/issue-89333.rs
new file mode 100644
index 000000000..03ed28ede
--- /dev/null
+++ b/tests/ui/suggestions/issue-89333.rs
@@ -0,0 +1,11 @@
+// check-fail
+// Ensure we don't error when emitting trait bound not satisfied when self type
+// has late bound var
+
+fn main() {
+ test(&|| 0); //~ ERROR the trait bound
+}
+
+trait Trait {}
+
+fn test<T>(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {}
diff --git a/tests/ui/suggestions/issue-89333.stderr b/tests/ui/suggestions/issue-89333.stderr
new file mode 100644
index 000000000..f73f1147d
--- /dev/null
+++ b/tests/ui/suggestions/issue-89333.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied
+ --> $DIR/issue-89333.rs:6:5
+ |
+LL | test(&|| 0);
+ | ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _`
+ |
+note: required by a bound in `test`
+ --> $DIR/issue-89333.rs:11:55
+ |
+LL | fn test<T>(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {}
+ | ^^^^^ required by this bound in `test`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs
new file mode 100644
index 000000000..1e36b2fab
--- /dev/null
+++ b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs
@@ -0,0 +1,13 @@
+// Checks that we do not ICE when comparing `Self` to `Pin`
+// edition:2021
+
+struct S;
+
+impl S {
+ fn foo(_: Box<Option<S>>) {}
+ fn bar() {
+ Self::foo(None) //~ ERROR mismatched types
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr
new file mode 100644
index 000000000..611f7d5dd
--- /dev/null
+++ b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19
+ |
+LL | Self::foo(None)
+ | --------- ^^^^ expected struct `Box`, found enum `Option`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected struct `Box<Option<S>>`
+ found enum `Option<_>`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+note: associated function defined here
+ --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:7:8
+ |
+LL | fn foo(_: Box<Option<S>>) {}
+ | ^^^ -----------------
+help: store this in the heap by calling `Box::new`
+ |
+LL | Self::foo(Box::new(None))
+ | +++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-90974.rs b/tests/ui/suggestions/issue-90974.rs
new file mode 100644
index 000000000..83590dbf7
--- /dev/null
+++ b/tests/ui/suggestions/issue-90974.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("{}", (3.).recip()); //~ERROR
+}
diff --git a/tests/ui/suggestions/issue-90974.stderr b/tests/ui/suggestions/issue-90974.stderr
new file mode 100644
index 000000000..e1fb479a3
--- /dev/null
+++ b/tests/ui/suggestions/issue-90974.stderr
@@ -0,0 +1,14 @@
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
+ --> $DIR/issue-90974.rs:2:25
+ |
+LL | println!("{}", (3.).recip());
+ | ^^^^^
+ |
+help: you must specify a concrete type for this numeric value, like `f32`
+ |
+LL | println!("{}", (3_f32).recip());
+ | ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/tests/ui/suggestions/issue-96223.rs b/tests/ui/suggestions/issue-96223.rs
new file mode 100644
index 000000000..85667bb84
--- /dev/null
+++ b/tests/ui/suggestions/issue-96223.rs
@@ -0,0 +1,52 @@
+// Previously ICEd because we didn't properly track binders in suggestions
+// check-fail
+
+pub trait Foo<'de>: Sized {}
+
+pub trait Bar<'a>: 'static {
+ type Inner: 'a;
+}
+
+pub trait Fubar {
+ type Bar: for<'a> Bar<'a>;
+}
+
+pub struct Baz<T>(pub T);
+
+impl<'de, T> Foo<'de> for Baz<T> where T: Foo<'de> {}
+
+struct Empty;
+
+impl<M> Dummy<M> for Empty
+where
+ M: Fubar,
+ for<'de> Baz<<M::Bar as Bar<'de>>::Inner>: Foo<'de>,
+{
+}
+
+pub trait Dummy<M>
+where
+ M: Fubar,
+{
+}
+
+pub struct EmptyBis<'a>(&'a [u8]);
+
+impl<'a> Bar<'a> for EmptyBis<'static> {
+ type Inner = EmptyBis<'a>;
+}
+
+pub struct EmptyMarker;
+
+impl Fubar for EmptyMarker {
+ type Bar = EmptyBis<'static>;
+}
+
+fn icey_bounds<D: Dummy<EmptyMarker>>(p: &D) {}
+
+fn trigger_ice() {
+ let p = Empty;
+ icey_bounds(&p); //~ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-96223.stderr b/tests/ui/suggestions/issue-96223.stderr
new file mode 100644
index 000000000..d4e9433df
--- /dev/null
+++ b/tests/ui/suggestions/issue-96223.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied
+ --> $DIR/issue-96223.rs:49:17
+ |
+LL | icey_bounds(&p);
+ | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Foo<'de>` is implemented for `Baz<T>`
+note: required for `Baz<EmptyBis<'de>>` to implement `for<'de> Foo<'de>`
+ --> $DIR/issue-96223.rs:16:14
+ |
+LL | impl<'de, T> Foo<'de> for Baz<T> where T: Foo<'de> {}
+ | ^^^^^^^^ ^^^^^^ -------- unsatisfied trait bound introduced here
+note: required for `Empty` to implement `Dummy<EmptyMarker>`
+ --> $DIR/issue-96223.rs:20:9
+ |
+LL | impl<M> Dummy<M> for Empty
+ | ^^^^^^^^ ^^^^^
+...
+LL | for<'de> Baz<<M::Bar as Bar<'de>>::Inner>: Foo<'de>,
+ | -------- unsatisfied trait bound introduced here
+note: required by a bound in `icey_bounds`
+ --> $DIR/issue-96223.rs:45:19
+ |
+LL | fn icey_bounds<D: Dummy<EmptyMarker>>(p: &D) {}
+ | ^^^^^^^^^^^^^^^^^^ required by this bound in `icey_bounds`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-96555.rs b/tests/ui/suggestions/issue-96555.rs
new file mode 100644
index 000000000..9f0a047c6
--- /dev/null
+++ b/tests/ui/suggestions/issue-96555.rs
@@ -0,0 +1,19 @@
+// edition:2018
+
+async fn f() {
+ m::f1().await; //~ ERROR `()` is not a future
+ m::f2().await; //~ ERROR `()` is not a future
+ m::f3().await; //~ ERROR `()` is not a future
+}
+
+mod m {
+ pub fn f1() {}
+
+ pub(crate) fn f2() {}
+
+ pub
+ fn
+ f3() {}
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-96555.stderr b/tests/ui/suggestions/issue-96555.stderr
new file mode 100644
index 000000000..9a8a183dc
--- /dev/null
+++ b/tests/ui/suggestions/issue-96555.stderr
@@ -0,0 +1,66 @@
+error[E0277]: `()` is not a future
+ --> $DIR/issue-96555.rs:4:12
+ |
+LL | m::f1().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 - m::f1().await;
+LL + m::f1();
+ |
+help: alternatively, consider making `fn f1` asynchronous
+ |
+LL | pub async fn f1() {}
+ | +++++
+
+error[E0277]: `()` is not a future
+ --> $DIR/issue-96555.rs:5:12
+ |
+LL | m::f2().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 - m::f2().await;
+LL + m::f2();
+ |
+help: alternatively, consider making `fn f2` asynchronous
+ |
+LL | pub(crate) async fn f2() {}
+ | +++++
+
+error[E0277]: `()` is not a future
+ --> $DIR/issue-96555.rs:6:12
+ |
+LL | m::f3().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 - m::f3().await;
+LL + m::f3();
+ |
+help: alternatively, consider making `fn f3` asynchronous
+ |
+LL | pub async
+ | +++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-97677.fixed b/tests/ui/suggestions/issue-97677.fixed
new file mode 100644
index 000000000..1e7569fa4
--- /dev/null
+++ b/tests/ui/suggestions/issue-97677.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn add_ten<N: std::ops::Add<i32, Output = N>>(n: N) -> N {
+ n + 10
+ //~^ ERROR cannot add `{integer}` to `N`
+}
+
+fn main() { add_ten(0); }
diff --git a/tests/ui/suggestions/issue-97677.rs b/tests/ui/suggestions/issue-97677.rs
new file mode 100644
index 000000000..2abf2af33
--- /dev/null
+++ b/tests/ui/suggestions/issue-97677.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn add_ten<N>(n: N) -> N {
+ n + 10
+ //~^ ERROR cannot add `{integer}` to `N`
+}
+
+fn main() { add_ten(0); }
diff --git a/tests/ui/suggestions/issue-97677.stderr b/tests/ui/suggestions/issue-97677.stderr
new file mode 100644
index 000000000..575d79267
--- /dev/null
+++ b/tests/ui/suggestions/issue-97677.stderr
@@ -0,0 +1,16 @@
+error[E0369]: cannot add `{integer}` to `N`
+ --> $DIR/issue-97677.rs:4:7
+ |
+LL | n + 10
+ | - ^ -- {integer}
+ | |
+ | N
+ |
+help: consider restricting type parameter `N`
+ |
+LL | fn add_ten<N: std::ops::Add<i32, Output = N>>(n: N) -> N {
+ | ++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/suggestions/issue-97704.fixed b/tests/ui/suggestions/issue-97704.fixed
new file mode 100644
index 000000000..c42bdfff5
--- /dev/null
+++ b/tests/ui/suggestions/issue-97704.fixed
@@ -0,0 +1,19 @@
+// edition:2021
+// run-rustfix
+
+#![allow(unused)]
+
+use std::future::Future;
+
+async fn foo() -> Result<(), i32> {
+ func(async { Ok::<_, i32>(()) }).await?;
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+
+ Ok(())
+}
+
+async fn func<T>(fut: impl Future<Output = T>) -> T {
+ fut.await
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-97704.rs b/tests/ui/suggestions/issue-97704.rs
new file mode 100644
index 000000000..5dfee6cac
--- /dev/null
+++ b/tests/ui/suggestions/issue-97704.rs
@@ -0,0 +1,19 @@
+// edition:2021
+// run-rustfix
+
+#![allow(unused)]
+
+use std::future::Future;
+
+async fn foo() -> Result<(), i32> {
+ func(async { Ok::<_, i32>(()) })?;
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+
+ Ok(())
+}
+
+async fn func<T>(fut: impl Future<Output = T>) -> T {
+ fut.await
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-97704.stderr b/tests/ui/suggestions/issue-97704.stderr
new file mode 100644
index 000000000..ca017be45
--- /dev/null
+++ b/tests/ui/suggestions/issue-97704.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/issue-97704.rs:9:5
+ |
+LL | func(async { Ok::<_, i32>(()) })?;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), i32>>`
+ |
+ = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), i32>>`
+help: consider `await`ing on the `Future`
+ |
+LL | func(async { Ok::<_, i32>(()) }).await?;
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-97760.rs b/tests/ui/suggestions/issue-97760.rs
new file mode 100644
index 000000000..cf9c3c58d
--- /dev/null
+++ b/tests/ui/suggestions/issue-97760.rs
@@ -0,0 +1,9 @@
+pub fn print_values(values: &impl IntoIterator)
+where {
+ for x in values.into_iter() {
+ println!("{x}");
+ //~^ ERROR <impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-97760.stderr b/tests/ui/suggestions/issue-97760.stderr
new file mode 100644
index 000000000..bbcc3693f
--- /dev/null
+++ b/tests/ui/suggestions/issue-97760.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `<impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display`
+ --> $DIR/issue-97760.rs:4:20
+ |
+LL | println!("{x}");
+ | ^ `<impl IntoIterator as IntoIterator>::Item` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `<impl IntoIterator as IntoIterator>::Item`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL ~ pub fn print_values<I: IntoIterator>(values: &I)
+LL ~ where <I as IntoIterator>::Item: std::fmt::Display {
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-98500.rs b/tests/ui/suggestions/issue-98500.rs
new file mode 100644
index 000000000..a2717fd92
--- /dev/null
+++ b/tests/ui/suggestions/issue-98500.rs
@@ -0,0 +1,14 @@
+// aux-build:not-object-safe.rs
+
+extern crate not_object_safe;
+
+pub trait B where
+ Self: not_object_safe::A,
+{
+ fn f2(&self);
+}
+
+struct S(Box<dyn B>);
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr
new file mode 100644
index 000000000..e7251d735
--- /dev/null
+++ b/tests/ui/suggestions/issue-98500.stderr
@@ -0,0 +1,24 @@
+error[E0038]: the trait `B` cannot be made into an object
+ --> $DIR/issue-98500.rs:11:14
+ |
+LL | struct S(Box<dyn B>);
+ | ^^^^^ `B` 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/auxiliary/not-object-safe.rs:4:8
+ |
+LL | fn f();
+ | ^ ...because associated function `f` has no `self` parameter
+LL | fn f2(self: &Arc<Self>);
+ | ^^ ...because method `f2`'s `self` parameter cannot be dispatched on
+ |
+ ::: $DIR/issue-98500.rs:5:11
+ |
+LL | pub trait B where
+ | - this trait cannot be made into an object...
+ = help: consider moving `f` to another trait
+ = help: consider moving `f2` to another trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/suggestions/issue-99080.rs b/tests/ui/suggestions/issue-99080.rs
new file mode 100644
index 000000000..91f574f35
--- /dev/null
+++ b/tests/ui/suggestions/issue-99080.rs
@@ -0,0 +1,16 @@
+// aux-build:meow.rs
+
+extern crate meow;
+
+use meow::Meow;
+
+fn needs_meow<T: Meow>(t: T) {}
+
+fn main() {
+ needs_meow(1usize);
+ //~^ ERROR the trait bound `usize: Meow` is not satisfied
+}
+
+struct LocalMeow;
+
+impl Meow for LocalMeow {}
diff --git a/tests/ui/suggestions/issue-99080.stderr b/tests/ui/suggestions/issue-99080.stderr
new file mode 100644
index 000000000..d1908dd9d
--- /dev/null
+++ b/tests/ui/suggestions/issue-99080.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `usize: Meow` is not satisfied
+ --> $DIR/issue-99080.rs:10:16
+ |
+LL | needs_meow(1usize);
+ | ---------- ^^^^^^ the trait `Meow` is not implemented for `usize`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `Meow`:
+ GlobalMeow
+ LocalMeow
+note: required by a bound in `needs_meow`
+ --> $DIR/issue-99080.rs:7:18
+ |
+LL | fn needs_meow<T: Meow>(t: T) {}
+ | ^^^^ required by this bound in `needs_meow`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-99240-2.rs b/tests/ui/suggestions/issue-99240-2.rs
new file mode 100644
index 000000000..0a418b5ae
--- /dev/null
+++ b/tests/ui/suggestions/issue-99240-2.rs
@@ -0,0 +1,10 @@
+enum Enum {
+ Unit,
+}
+type Alias = Enum;
+
+fn main() {
+ Alias::
+ Unit();
+ //~^^ ERROR expected function, found enum variant `Alias::Unit`
+}
diff --git a/tests/ui/suggestions/issue-99240-2.stderr b/tests/ui/suggestions/issue-99240-2.stderr
new file mode 100644
index 000000000..a2b559784
--- /dev/null
+++ b/tests/ui/suggestions/issue-99240-2.stderr
@@ -0,0 +1,21 @@
+error[E0618]: expected function, found enum variant `Alias::Unit`
+ --> $DIR/issue-99240-2.rs:7:5
+ |
+LL | Unit,
+ | ---- enum variant `Alias::Unit` defined here
+...
+LL | // Alias::
+LL | || Unit();
+ | ||________^_- call expression requires function
+ | |________|
+ |
+ |
+help: `Alias::Unit` is a unit enum variant, and does not take parentheses to be constructed
+ |
+LL - Unit();
+LL + Unit;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/tests/ui/suggestions/issue-99240.rs b/tests/ui/suggestions/issue-99240.rs
new file mode 100644
index 000000000..2115a4266
--- /dev/null
+++ b/tests/ui/suggestions/issue-99240.rs
@@ -0,0 +1,6 @@
+fn fmt(it: &(std::cell::Cell<Option<impl FnOnce()>>,)) {
+ (it.0.take())()
+ //~^ ERROR expected function
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-99240.stderr b/tests/ui/suggestions/issue-99240.stderr
new file mode 100644
index 000000000..f1bea688b
--- /dev/null
+++ b/tests/ui/suggestions/issue-99240.stderr
@@ -0,0 +1,11 @@
+error[E0618]: expected function, found `Option<impl FnOnce()>`
+ --> $DIR/issue-99240.rs:2:5
+ |
+LL | (it.0.take())()
+ | ^^^^^^^^^^^^^--
+ | |
+ | call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs
new file mode 100644
index 000000000..b24d25648
--- /dev/null
+++ b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs
@@ -0,0 +1,5 @@
+fn main() {
+ if 1 == = 1 { //~ ERROR expected expression
+ println!("yup!");
+ }
+}
diff --git a/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr
new file mode 100644
index 000000000..6adefe3de
--- /dev/null
+++ b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found `=`
+ --> $DIR/js-style-comparison-op-separate-eq-token.rs:2:13
+ |
+LL | if 1 == = 1 {
+ | ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/js-style-comparison-op.fixed b/tests/ui/suggestions/js-style-comparison-op.fixed
new file mode 100644
index 000000000..f7e977b91
--- /dev/null
+++ b/tests/ui/suggestions/js-style-comparison-op.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+ if 1 == 1 { //~ ERROR invalid comparison operator `===`
+ println!("yup!");
+ } else if 1 != 1 { //~ ERROR invalid comparison operator `!==`
+ println!("nope!");
+ }
+}
diff --git a/tests/ui/suggestions/js-style-comparison-op.rs b/tests/ui/suggestions/js-style-comparison-op.rs
new file mode 100644
index 000000000..c89c1052e
--- /dev/null
+++ b/tests/ui/suggestions/js-style-comparison-op.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+ if 1 === 1 { //~ ERROR invalid comparison operator `===`
+ println!("yup!");
+ } else if 1 !== 1 { //~ ERROR invalid comparison operator `!==`
+ println!("nope!");
+ }
+}
diff --git a/tests/ui/suggestions/js-style-comparison-op.stderr b/tests/ui/suggestions/js-style-comparison-op.stderr
new file mode 100644
index 000000000..33f7a0844
--- /dev/null
+++ b/tests/ui/suggestions/js-style-comparison-op.stderr
@@ -0,0 +1,14 @@
+error: invalid comparison operator `===`
+ --> $DIR/js-style-comparison-op.rs:3:10
+ |
+LL | if 1 === 1 {
+ | ^^^ help: `===` is not a valid comparison operator, use `==`
+
+error: invalid comparison operator `!==`
+ --> $DIR/js-style-comparison-op.rs:5:17
+ |
+LL | } else if 1 !== 1 {
+ | ^^^ help: `!==` is not a valid comparison operator, use `!=`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
new file mode 100644
index 000000000..06ee421fc
--- /dev/null
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
@@ -0,0 +1,11 @@
+pub fn foo(num: i32) -> i32 {
+ let foo: i32::from_be(num);
+ //~^ ERROR expected type, found local variable `num`
+ //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
+ //~| ERROR ambiguous associated type
+ foo
+}
+
+fn main() {
+ let _ = foo(42);
+}
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
new file mode 100644
index 000000000..b90ae051f
--- /dev/null
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
@@ -0,0 +1,34 @@
+error[E0573]: expected type, found local variable `num`
+ --> $DIR/let-binding-init-expr-as-ty.rs:2:27
+ |
+LL | let foo: i32::from_be(num);
+ | -- ^^^ not a type
+ | |
+ | help: use `=` if you meant to assign
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/let-binding-init-expr-as-ty.rs:2:19
+ |
+LL | let foo: i32::from_be(num);
+ | ^^^^^^^^^^^^ only `Fn` traits may use parentheses
+ |
+help: use angle brackets instead
+ |
+LL | let foo: i32::from_be<num>;
+ | ~ ~
+
+error[E0223]: ambiguous associated type
+ --> $DIR/let-binding-init-expr-as-ty.rs:2:14
+ |
+LL | let foo: i32::from_be(num);
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path
+ |
+LL | let foo: <i32 as Example>::from_be;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0214, E0223, E0573.
+For more information about an error, try `rustc --explain E0214`.
diff --git a/tests/ui/suggestions/lifetimes/issue-105544.fixed b/tests/ui/suggestions/lifetimes/issue-105544.fixed
new file mode 100644
index 000000000..47087eb47
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/issue-105544.fixed
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `impl Sized` may not live long enough
+ //~| NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+}
+
+fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+ (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+ //~^ ERROR the parameter type `impl Sized` may not live long enough
+}
+
+fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough
+ //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
+}
+
+fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+ (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds
+ //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/issue-105544.rs b/tests/ui/suggestions/lifetimes/issue-105544.rs
new file mode 100644
index 000000000..bd3bc1ef9
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/issue-105544.rs
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `impl Sized` may not live long enough
+ //~| NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+}
+
+fn foo1<'b>(d: impl Sized, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+ (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+ //~^ ERROR the parameter type `impl Sized` may not live long enough
+}
+
+fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough
+ //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
+}
+
+fn bar<T : Sized>(d: T, p: & mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn bar1<'b, T : Sized>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+ (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds
+ //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+ (d, p)
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/issue-105544.stderr b/tests/ui/suggestions/lifetimes/issue-105544.stderr
new file mode 100644
index 000000000..08fe21b11
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/issue-105544.stderr
@@ -0,0 +1,110 @@
+error[E0311]: the parameter type `impl Sized` may not live long enough
+ --> $DIR/issue-105544.rs:7:5
+ |
+LL | (d, p)
+ | ^^^^^^
+ |
+note: the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
+ --> $DIR/issue-105544.rs:5:26
+ |
+LL | fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ {
+ | ^^^^^^^
+note: ...so that the type `impl Sized` will meet its required lifetime bounds
+ --> $DIR/issue-105544.rs:7:5
+ |
+LL | (d, p)
+ | ^^^^^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ {
+ | ++++ ++++ ++
+
+error[E0309]: the parameter type `impl Sized` may not live long enough
+ --> $DIR/issue-105544.rs:14:5
+ |
+LL | (d, p)
+ | ^^^^^^ ...so that the type `impl Sized` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ {
+ | ++++
+
+error[E0311]: the parameter type `impl Sized + 'a` may not live long enough
+ --> $DIR/issue-105544.rs:20:5
+ |
+LL | (d, p)
+ | ^^^^^^
+ |
+note: the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
+ --> $DIR/issue-105544.rs:18:36
+ |
+LL | fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ {
+ | ^^^^^^^
+note: ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
+ --> $DIR/issue-105544.rs:20:5
+ |
+LL | (d, p)
+ | ^^^^^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ {
+ | +++ ++++ ++
+
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/issue-105544.rs:27:5
+ |
+LL | (d, p)
+ | ^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/issue-105544.rs:25:28
+ |
+LL | fn bar<T : Sized>(d: T, p: & mut ()) -> impl Sized + '_ {
+ | ^^^^^^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+ --> $DIR/issue-105544.rs:27:5
+ |
+LL | (d, p)
+ | ^^^^^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ {
+ | +++ ++++ ++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/issue-105544.rs:34:5
+ |
+LL | (d, p)
+ | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+ | ++++
+
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/issue-105544.rs:40:5
+ |
+LL | (d, p)
+ | ^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/issue-105544.rs:38:38
+ |
+LL | fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ {
+ | ^^^^^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+ --> $DIR/issue-105544.rs:40:5
+ |
+LL | (d, p)
+ | ^^^^^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+ | +++ ++++ ++
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0309, E0311.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed
new file mode 100644
index 000000000..4013d98c3
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed
@@ -0,0 +1,29 @@
+// Regression test for #81650
+// run-rustfix
+
+#![allow(warnings)]
+
+struct Foo<'a> {
+ x: &'a mut &'a i32,
+}
+
+impl<'a> Foo<'a> {
+ fn bar<F, T>(&self, f: F)
+ where
+ F: FnOnce(&Foo<'a>) -> T,
+ F: 'a,
+ {}
+}
+
+trait Test {
+ fn test(&self);
+}
+
+fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) {
+ foo.bar(move |_| {
+ //~^ ERROR the parameter type `T` may not live long enough
+ t.test();
+ });
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs
new file mode 100644
index 000000000..4096d95e5
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs
@@ -0,0 +1,29 @@
+// Regression test for #81650
+// run-rustfix
+
+#![allow(warnings)]
+
+struct Foo<'a> {
+ x: &'a mut &'a i32,
+}
+
+impl<'a> Foo<'a> {
+ fn bar<F, T>(&self, f: F)
+ where
+ F: FnOnce(&Foo<'a>) -> T,
+ F: 'a,
+ {}
+}
+
+trait Test {
+ fn test(&self);
+}
+
+fn func<T: Test>(foo: &Foo, t: T) {
+ foo.bar(move |_| {
+ //~^ ERROR the parameter type `T` may not live long enough
+ t.test();
+ });
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
new file mode 100644
index 000000000..936d87f79
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
@@ -0,0 +1,30 @@
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature-2.rs:23:5
+ |
+LL | / foo.bar(move |_| {
+LL | |
+LL | | t.test();
+LL | | });
+ | |______^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature-2.rs:22:24
+ |
+LL | fn func<T: Test>(foo: &Foo, t: T) {
+ | ^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature-2.rs:23:5
+ |
+LL | / foo.bar(move |_| {
+LL | |
+LL | | t.test();
+LL | | });
+ | |______^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) {
+ | +++ ++++ ++ ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed
new file mode 100644
index 000000000..3c06f4f88
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/95616
+
+fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { //~ERROR [E0106]
+ return "";
+}
+
+fn main() {
+ buggy_const(&Some([69,69,69,69,0]), "test");
+}
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs
new file mode 100644
index 000000000..110468cbb
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/95616
+
+fn buggy_const<const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &str { //~ERROR [E0106]
+ return "";
+}
+
+fn main() {
+ buggy_const(&Some([69,69,69,69,0]), "test");
+}
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr
new file mode 100644
index 000000000..7b126c90e
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetimes-in-signature-before-const.rs:4:67
+ |
+LL | fn buggy_const<const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &str {
+ | ---------------- ---- ^ 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 `_a` or `_f`
+help: consider introducing a named lifetime parameter
+ |
+LL | fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str {
+ | +++ ++ ++ ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
new file mode 100644
index 000000000..b641f5941
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
@@ -0,0 +1,111 @@
+pub trait Get<T> {
+ fn get(self) -> T;
+}
+
+struct Foo {
+ x: usize,
+}
+
+impl Get<usize> for Foo {
+ fn get(self) -> usize {
+ self.x
+ }
+}
+
+fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+where
+ G: Get<T>,
+{
+ move || {
+ //~^ ERROR hidden type for `impl FnOnce()` captures lifetime
+ *dest = g.get();
+ }
+}
+
+// After applying suggestion for `foo`:
+fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+where
+ G: Get<T>,
+{
+ move || {
+ //~^ ERROR the parameter type `G` may not live long enough
+ *dest = g.get();
+ }
+}
+
+// After applying suggestion for `bar`:
+fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR undeclared lifetime name `'a`
+where
+ G: Get<T>,
+{
+ move || {
+ *dest = g.get();
+ }
+}
+
+// After applying suggestion for `baz`:
+fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+where
+ G: Get<T>,
+{
+ move || {
+ //~^ ERROR the parameter type `G` may not live long enough
+ *dest = g.get();
+ }
+}
+
+// Same as above, but show that we pay attention to lifetime names from parent item
+impl<'a> Foo {
+ fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ move || {
+ //~^ ERROR the parameter type `G` may not live long enough
+ *dest = g.get();
+ }
+ }
+}
+
+// After applying suggestion for `qux`:
+fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+where
+ G: Get<T>,
+{
+ move || {
+ //~^ ERROR the parameter type `G` may not live long enough
+ //~| ERROR explicit lifetime required
+ *dest = g.get();
+ }
+}
+
+// Potential incorrect attempt:
+fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+where
+ G: Get<T>,
+{
+ move || {
+ //~^ ERROR the parameter type `G` may not live long enough
+ *dest = g.get();
+ }
+}
+
+// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure:
+fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+where
+ G: Get<T>,
+{
+ move || {
+ *dest = g.get();
+ }
+}
+
+// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
+fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
+where
+ G: Get<T>,
+{
+ move || {
+ *dest = g.get();
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
new file mode 100644
index 000000000..c5c3f7b46
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -0,0 +1,168 @@
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/missing-lifetimes-in-signature.rs:37:11
+ |
+LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `'a,`
+
+error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:19:5
+ |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+ | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
+...
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:30:5
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:26:26
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:30:5
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+help: consider adding an explicit lifetime bound...
+ |
+LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_
+LL | where
+LL ~ G: Get<T> + 'a,
+ |
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:52:5
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:48:34
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:52:5
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_
+ | +++ ++++ ++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:61:9
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_________^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:60:47
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:61:9
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_________^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + '_ {
+ | +++ ++++ ++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:73:5
+ |
+LL | / move || {
+LL | |
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:69:34
+ |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:73:5
+ |
+LL | / move || {
+LL | |
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ + 'a
+ | +++ ++++ ++
+
+error[E0621]: explicit lifetime required in the type of `dest`
+ --> $DIR/missing-lifetimes-in-signature.rs:73:5
+ |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+...
+LL | / move || {
+LL | |
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^ lifetime `'a` required
+
+error[E0309]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:85:5
+ |
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^ ...so that the type `G` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | G: Get<T> + 'a,
+ | ++++
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs
new file mode 100644
index 000000000..ff27011f8
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs
@@ -0,0 +1,72 @@
+trait Foo {}
+impl<'a, T: Foo> Foo for &'a T {}
+impl<T: Foo + ?Sized> Foo for Box<T> {}
+
+struct Iter<'a, T> {
+ current: Option<Box<dyn Foo + 'a>>,
+ remaining: T,
+}
+
+impl<'a, T> Iterator for Iter<'a, T>
+where
+ T: Iterator,
+ T::Item: Foo + 'a,
+{
+ type Item = Box<dyn Foo + 'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let result = self.current.take();
+ self.current = Box::new(self.remaining.next()).map(|f| Box::new(f) as _);
+ result
+ }
+}
+
+struct Bar(Vec<Box<dyn Foo>>);
+
+impl Bar {
+ fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
+ Iter {
+ //~^ ERROR lifetime may not live long enough
+ current: None,
+ remaining: self.0.iter(),
+ }
+ }
+}
+
+struct Baz(Vec<Box<dyn Foo>>);
+
+impl Baz {
+ fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
+ Iter {
+ //~^ ERROR lifetime may not live long enough
+ current: None,
+ remaining: self.0.iter(),
+ }
+ }
+}
+
+struct Bat(Vec<Box<dyn Foo>>);
+
+impl Bat {
+ fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
+ Iter {
+ //~^ ERROR lifetime may not live long enough
+ current: None,
+ remaining: self.0.iter(),
+ }
+ }
+}
+
+struct Ban(Vec<Box<dyn Foo>>);
+
+impl Ban {
+ fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
+ Iter {
+ //~^ ERROR lifetime may not live long enough
+ current: None,
+ remaining: self.0.iter(),
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
new file mode 100644
index 000000000..c77ef79e7
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
@@ -0,0 +1,78 @@
+error: lifetime may not live long enough
+ --> $DIR/trait-object-nested-in-impl-trait.rs:28:9
+ |
+LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
+ | - let's call the lifetime of this reference `'1`
+LL | / Iter {
+LL | |
+LL | | current: None,
+LL | | remaining: self.0.iter(),
+LL | | }
+ | |_________^ returning this value requires that `'1` must outlive `'static`
+ |
+help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
+ | ++++
+help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> {
+ | ++++
+
+error: lifetime may not live long enough
+ --> $DIR/trait-object-nested-in-impl-trait.rs:40:9
+ |
+LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
+ | - let's call the lifetime of this reference `'1`
+LL | / Iter {
+LL | |
+LL | | current: None,
+LL | | remaining: self.0.iter(),
+LL | | }
+ | |_________^ returning this value requires that `'1` must outlive `'static`
+ |
+help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> + '_ {
+ | ++++
+
+error: lifetime may not live long enough
+ --> $DIR/trait-object-nested-in-impl-trait.rs:52:9
+ |
+LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
+ | -- lifetime `'a` defined here
+LL | / Iter {
+LL | |
+LL | | current: None,
+LL | | remaining: self.0.iter(),
+LL | | }
+ | |_________^ returning this value requires that `'a` must outlive `'static`
+ |
+help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound
+ |
+LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> + 'a {
+ | ++++
+
+error: lifetime may not live long enough
+ --> $DIR/trait-object-nested-in-impl-trait.rs:64:9
+ |
+LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
+ | -- lifetime `'a` defined here
+LL | / Iter {
+LL | |
+LL | | current: None,
+LL | | remaining: self.0.iter(),
+LL | | }
+ | |_________^ returning this value requires that `'a` must outlive `'static`
+ |
+help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'a` lifetime bound
+ |
+LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
+ | ++++
+help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound
+ |
+LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> {
+ | ++++
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/suggestions/many-type-ascription.rs b/tests/ui/suggestions/many-type-ascription.rs
new file mode 100644
index 000000000..31ac556b9
--- /dev/null
+++ b/tests/ui/suggestions/many-type-ascription.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let _ = 0: i32; //~ ERROR: type ascription is experimental
+ let _ = 0: i32; // (error only emitted once)
+}
diff --git a/tests/ui/suggestions/many-type-ascription.stderr b/tests/ui/suggestions/many-type-ascription.stderr
new file mode 100644
index 000000000..3706bbae9
--- /dev/null
+++ b/tests/ui/suggestions/many-type-ascription.stderr
@@ -0,0 +1,12 @@
+error[E0658]: type ascription is experimental
+ --> $DIR/many-type-ascription.rs:2:13
+ |
+LL | let _ = 0: i32;
+ | ^^^^^^
+ |
+ = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+ = help: add `#![feature(type_ascription)]` 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/suggestions/match-ergonomics.rs b/tests/ui/suggestions/match-ergonomics.rs
new file mode 100644
index 000000000..c4fc01469
--- /dev/null
+++ b/tests/ui/suggestions/match-ergonomics.rs
@@ -0,0 +1,41 @@
+fn main() {
+ let x = vec![1i32];
+ match &x[..] {
+ [&v] => {}, //~ ERROR mismatched types
+ _ => {},
+ }
+ match x {
+ [&v] => {}, //~ ERROR expected an array or slice
+ _ => {},
+ }
+ match &x[..] {
+ [v] => {},
+ _ => {},
+ }
+ match &x[..] {
+ &[v] => {},
+ _ => {},
+ }
+ match x {
+ [v] => {}, //~ ERROR expected an array or slice
+ _ => {},
+ }
+ let y = 1i32;
+ match &y {
+ &v => {},
+ _ => {},
+ }
+ match y {
+ &v => {}, //~ ERROR mismatched types
+ _ => {},
+ }
+ match &y {
+ v => {},
+ _ => {},
+ }
+ match y {
+ v => {},
+ _ => {},
+ }
+ if let [&v] = &x[..] {} //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/match-ergonomics.stderr b/tests/ui/suggestions/match-ergonomics.stderr
new file mode 100644
index 000000000..aa2b407bf
--- /dev/null
+++ b/tests/ui/suggestions/match-ergonomics.stderr
@@ -0,0 +1,68 @@
+error[E0308]: mismatched types
+ --> $DIR/match-ergonomics.rs:4:10
+ |
+LL | match &x[..] {
+ | ------ this expression has type `&[i32]`
+LL | [&v] => {},
+ | ^^ expected `i32`, found reference
+ |
+ = note: expected type `i32`
+ found reference `&_`
+help: consider removing `&` from the pattern
+ |
+LL - [&v] => {},
+LL + [v] => {},
+ |
+
+error[E0529]: expected an array or slice, found `Vec<i32>`
+ --> $DIR/match-ergonomics.rs:8:9
+ |
+LL | match x {
+ | - help: consider slicing here: `x[..]`
+LL | [&v] => {},
+ | ^^^^ pattern cannot match with input type `Vec<i32>`
+
+error[E0529]: expected an array or slice, found `Vec<i32>`
+ --> $DIR/match-ergonomics.rs:20:9
+ |
+LL | match x {
+ | - help: consider slicing here: `x[..]`
+LL | [v] => {},
+ | ^^^ pattern cannot match with input type `Vec<i32>`
+
+error[E0308]: mismatched types
+ --> $DIR/match-ergonomics.rs:29:9
+ |
+LL | match y {
+ | - this expression has type `i32`
+LL | &v => {},
+ | ^^ expected `i32`, found reference
+ |
+ = note: expected type `i32`
+ found reference `&_`
+help: consider removing `&` from the pattern
+ |
+LL - &v => {},
+LL + v => {},
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/match-ergonomics.rs:40:13
+ |
+LL | if let [&v] = &x[..] {}
+ | ^^ ------ this expression has type `&[i32]`
+ | |
+ | expected `i32`, found reference
+ |
+ = note: expected type `i32`
+ found reference `&_`
+help: consider removing `&` from the pattern
+ |
+LL - if let [&v] = &x[..] {}
+LL + if let [v] = &x[..] {}
+ |
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0529.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/match-needing-semi.rs b/tests/ui/suggestions/match-needing-semi.rs
new file mode 100644
index 000000000..833555d0e
--- /dev/null
+++ b/tests/ui/suggestions/match-needing-semi.rs
@@ -0,0 +1,21 @@
+// check-only
+
+fn main() {
+ match 3 {
+ 4 => 1,
+ 3 => {
+ foo() //~ ERROR mismatched types
+ }
+ _ => 2
+ }
+ match 3 { //~ ERROR mismatched types
+ 4 => 1,
+ 3 => 2,
+ _ => 2
+ }
+ let _ = ();
+}
+
+fn foo() -> i32 {
+ 42
+}
diff --git a/tests/ui/suggestions/match-needing-semi.stderr b/tests/ui/suggestions/match-needing-semi.stderr
new file mode 100644
index 000000000..b5f01d703
--- /dev/null
+++ b/tests/ui/suggestions/match-needing-semi.stderr
@@ -0,0 +1,37 @@
+error[E0308]: mismatched types
+ --> $DIR/match-needing-semi.rs:7:13
+ |
+LL | / match 3 {
+LL | | 4 => 1,
+LL | | 3 => {
+LL | | foo()
+ | | ^^^^^ expected `()`, found `i32`
+LL | | }
+LL | | _ => 2
+LL | | }
+ | |_____- expected this to be `()`
+ |
+help: consider using a semicolon here
+ |
+LL | foo();
+ | +
+help: consider using a semicolon here
+ |
+LL | };
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/match-needing-semi.rs:11:5
+ |
+LL | / match 3 {
+LL | | 4 => 1,
+LL | | 3 => 2,
+LL | | _ => 2
+LL | | }
+ | | ^- help: consider using a semicolon here
+ | |_____|
+ | expected `()`, found integer
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.rs b/tests/ui/suggestions/match-prev-arm-needing-semi.rs
new file mode 100644
index 000000000..8c8abe047
--- /dev/null
+++ b/tests/ui/suggestions/match-prev-arm-needing-semi.rs
@@ -0,0 +1,66 @@
+// edition:2018
+
+fn dummy() -> i32 { 42 }
+
+fn extra_semicolon() {
+ let _ = match true { //~ NOTE `match` arms have incompatible types
+ true => {
+ dummy(); //~ NOTE this is found to be
+ //~^ HELP consider removing this semicolon
+ }
+ false => dummy(), //~ ERROR `match` arms have incompatible types
+ //~^ NOTE expected `()`, found `i32`
+ };
+}
+
+async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE 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
+async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+//~| NOTE while checking the return type of the `async fn`
+//~| NOTE in this expansion of desugaring of `async` block or function
+
+async fn async_extra_semicolon_same() {
+ let _ = match true { //~ NOTE `match` arms have incompatible types
+ true => {
+ async_dummy(); //~ NOTE this is found to be
+ //~^ HELP consider removing this semicolon
+ }
+ false => async_dummy(), //~ ERROR `match` arms have incompatible types
+ //~^ NOTE expected `()`, found opaque type
+ //~| NOTE expected unit type `()`
+ //~| HELP consider `await`ing on the `Future`
+ };
+}
+
+async fn async_extra_semicolon_different() {
+ let _ = match true { //~ NOTE `match` arms have incompatible types
+ true => {
+ async_dummy(); //~ NOTE this is found to be
+ //~^ HELP consider removing this semicolon
+ }
+ false => async_dummy2(), //~ ERROR `match` arms have incompatible types
+ //~^ NOTE expected `()`, found opaque type
+ //~| NOTE expected unit type `()`
+ //~| HELP consider `await`ing on the `Future`
+ };
+}
+
+async fn async_different_futures() {
+ let _ = match true { //~ NOTE `match` arms have incompatible types
+ true => async_dummy(), //~ NOTE this is found to be
+ //~| HELP consider `await`ing on both `Future`s
+ false => async_dummy2(), //~ ERROR `match` arms have incompatible types
+ //~^ NOTE expected opaque type, found a different opaque type
+ //~| NOTE expected opaque type `impl Future<Output = ()>`
+ //~| NOTE distinct uses of `impl Trait` result in different opaque types
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
new file mode 100644
index 000000000..8d735b71f
--- /dev/null
+++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
@@ -0,0 +1,127 @@
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/match-prev-arm-needing-semi.rs:35:18
+ |
+LL | let _ = match true {
+ | _____________-
+LL | | true => {
+LL | | async_dummy();
+ | | -------------- this is found to be of type `()`
+LL | |
+LL | | }
+LL | | false => async_dummy(),
+ | | ^^^^^^^^^^^^^ expected `()`, found opaque type
+... |
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/match-prev-arm-needing-semi.rs:16:24
+ |
+LL | async fn async_dummy() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected unit type `()`
+ found opaque type `impl Future<Output = ()>`
+help: consider `await`ing on the `Future`
+ |
+LL | false => async_dummy().await,
+ | ++++++
+help: consider removing this semicolon
+ |
+LL - async_dummy();
+LL + async_dummy()
+ |
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/match-prev-arm-needing-semi.rs:48:18
+ |
+LL | let _ = match true {
+ | _____________-
+LL | | true => {
+LL | | async_dummy();
+ | | -------------- this is found to be of type `()`
+LL | |
+LL | | }
+LL | | false => async_dummy2(),
+ | | ^^^^^^^^^^^^^^ expected `()`, found opaque type
+... |
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/match-prev-arm-needing-semi.rs:22:25
+ |
+LL | async fn async_dummy2() {}
+ | ^ 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 | false => async_dummy2().await,
+ | ++++++
+help: consider removing this semicolon and boxing the expressions
+ |
+LL ~ Box::new(async_dummy())
+LL |
+LL | }
+LL ~ false => Box::new(async_dummy2()),
+ |
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/match-prev-arm-needing-semi.rs:59:18
+ |
+LL | let _ = match true {
+ | _____________-
+LL | | true => async_dummy(),
+ | | ------------- this is found to be of type `impl Future<Output = ()>`
+LL | |
+LL | | false => async_dummy2(),
+ | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
+... |
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/match-prev-arm-needing-semi.rs:16:24
+ |
+LL | async fn async_dummy() {}
+ | ^ checked the `Output` of this `async fn`, expected opaque type
+note: while checking the return type of the `async fn`
+ --> $DIR/match-prev-arm-needing-semi.rs:22:25
+ |
+LL | async fn async_dummy2() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
+ found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>)
+ = note: distinct uses of `impl Trait` result in different opaque types
+help: consider `await`ing on both `Future`s
+ |
+LL ~ true => async_dummy().await,
+LL |
+LL ~ false => async_dummy2().await,
+ |
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/match-prev-arm-needing-semi.rs:11:18
+ |
+LL | let _ = match true {
+ | _____________-
+LL | | true => {
+LL | | dummy();
+ | | --------
+ | | | |
+ | | | help: consider removing this semicolon
+ | | this is found to be of type `()`
+LL | |
+LL | | }
+LL | | false => dummy(),
+ | | ^^^^^^^ expected `()`, found `i32`
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs
new file mode 100644
index 000000000..0360ce6e6
--- /dev/null
+++ b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs
@@ -0,0 +1,30 @@
+pub trait Foo {}
+
+struct Bar;
+struct Baz;
+
+impl Foo for Bar { }
+impl Foo for Baz { }
+
+fn not_all_paths(a: &str) -> u32 { //~ ERROR mismatched types
+ match a {
+ "baz" => 0,
+ _ => 1,
+ };
+}
+
+fn right(b: &str) -> Box<dyn Foo> {
+ match b {
+ "baz" => Box::new(Baz),
+ _ => Box::new(Bar),
+ }
+}
+
+fn wrong(c: &str) -> Box<dyn Foo> { //~ ERROR mismatched types
+ match c {
+ "baz" => Box::new(Baz),
+ _ => Box::new(Bar), //~ ERROR `match` arms have incompatible types
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
new file mode 100644
index 000000000..00aa7d18a
--- /dev/null
+++ b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
@@ -0,0 +1,51 @@
+error[E0308]: mismatched types
+ --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:9:30
+ |
+LL | fn not_all_paths(a: &str) -> u32 {
+ | ------------- ^^^ expected `u32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+...
+LL | };
+ | - help: remove this semicolon to return this value
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:26:14
+ |
+LL | / match c {
+LL | | "baz" => Box::new(Baz),
+ | | ------------- this is found to be of type `Box<Baz>`
+LL | | _ => Box::new(Bar),
+ | | ^^^^^^^^^^^^^ expected struct `Baz`, found struct `Bar`
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected struct `Box<Baz>`
+ found struct `Box<Bar>`
+note: you might have meant to return the `match` expression
+ --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:27:6
+ |
+LL | fn wrong(c: &str) -> Box<dyn Foo> {
+ | ------------ the `match` arms can conform to this return type
+LL | / match c {
+LL | | "baz" => Box::new(Baz),
+LL | | _ => Box::new(Bar),
+LL | | };
+ | | -^ the `match` is a statement because of this semicolon, consider removing it
+ | |_____|
+ | this could be implicitly returned but it is a statement, not a tail expression
+
+error[E0308]: mismatched types
+ --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:23:22
+ |
+LL | fn wrong(c: &str) -> Box<dyn Foo> {
+ | ----- ^^^^^^^^^^^^ expected struct `Box`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected struct `Box<(dyn Foo + 'static)>`
+ found unit type `()`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.fixed b/tests/ui/suggestions/method-access-to-range-literal-typo.fixed
new file mode 100644
index 000000000..13601eef6
--- /dev/null
+++ b/tests/ui/suggestions/method-access-to-range-literal-typo.fixed
@@ -0,0 +1,34 @@
+// run-rustfix
+
+#![allow(unused)]
+
+fn as_ref() -> Option<Vec<u8>> {
+ None
+}
+struct Type {
+ option: Option<Vec<u8>>
+}
+trait Trait {
+ fn foo(&self) -> &Vec<u8>;
+}
+impl Trait for Option<Vec<u8>> {
+ fn foo(&self) -> &Vec<u8> {
+ self.as_ref().unwrap()
+ }
+}
+
+impl Type {
+ fn method(&self) -> Option<&Vec<u8>> {
+ self.option.as_ref().map(|x| x)
+ //~^ ERROR E0308
+ }
+ fn method2(&self) -> Option<&u8> {
+ self.option.foo().get(0)
+ //~^ ERROR E0425
+ //~| ERROR E0308
+ }
+}
+
+fn main() {
+ let _ = Type { option: None }.method();
+}
diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.rs b/tests/ui/suggestions/method-access-to-range-literal-typo.rs
new file mode 100644
index 000000000..fdcd6425d
--- /dev/null
+++ b/tests/ui/suggestions/method-access-to-range-literal-typo.rs
@@ -0,0 +1,34 @@
+// run-rustfix
+
+#![allow(unused)]
+
+fn as_ref() -> Option<Vec<u8>> {
+ None
+}
+struct Type {
+ option: Option<Vec<u8>>
+}
+trait Trait {
+ fn foo(&self) -> &Vec<u8>;
+}
+impl Trait for Option<Vec<u8>> {
+ fn foo(&self) -> &Vec<u8> {
+ self.as_ref().unwrap()
+ }
+}
+
+impl Type {
+ fn method(&self) -> Option<&Vec<u8>> {
+ self.option..as_ref().map(|x| x)
+ //~^ ERROR E0308
+ }
+ fn method2(&self) -> Option<&u8> {
+ self.option..foo().get(0)
+ //~^ ERROR E0425
+ //~| ERROR E0308
+ }
+}
+
+fn main() {
+ let _ = Type { option: None }.method();
+}
diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
new file mode 100644
index 000000000..f42140894
--- /dev/null
+++ b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
@@ -0,0 +1,48 @@
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/method-access-to-range-literal-typo.rs:26:22
+ |
+LL | self.option..foo().get(0)
+ | ^^^ not found in this scope
+ |
+help: you might have meant to write `.` instead of `..`
+ |
+LL - self.option..foo().get(0)
+LL + self.option.foo().get(0)
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/method-access-to-range-literal-typo.rs:22:9
+ |
+LL | fn method(&self) -> Option<&Vec<u8>> {
+ | ---------------- expected `Option<&Vec<u8>>` because of return type
+LL | self.option..as_ref().map(|x| x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+ |
+ = note: expected enum `Option<&Vec<u8>>`
+ found struct `std::ops::Range<Option<Vec<u8>>>`
+help: you likely meant to write a method call instead of a range
+ |
+LL - self.option..as_ref().map(|x| x)
+LL + self.option.as_ref().map(|x| x)
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/method-access-to-range-literal-typo.rs:26:9
+ |
+LL | fn method2(&self) -> Option<&u8> {
+ | ----------- expected `Option<&u8>` because of return type
+LL | self.option..foo().get(0)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+ |
+ = note: expected enum `Option<&u8>`
+ found struct `std::ops::Range<Option<Vec<u8>>>`
+help: you likely meant to write a method call instead of a range
+ |
+LL - self.option..foo().get(0)
+LL + self.option.foo().get(0)
+ |
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/method-missing-parentheses.rs b/tests/ui/suggestions/method-missing-parentheses.rs
new file mode 100644
index 000000000..f10bfb56d
--- /dev/null
+++ b/tests/ui/suggestions/method-missing-parentheses.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let _ = vec![].into_iter().collect::<usize>;
+ //~^ ERROR attempted to take value of method `collect` on type `std::vec::IntoIter<_>`
+ //~| ERROR field expressions cannot have generic arguments
+}
diff --git a/tests/ui/suggestions/method-missing-parentheses.stderr b/tests/ui/suggestions/method-missing-parentheses.stderr
new file mode 100644
index 000000000..1bfff56a6
--- /dev/null
+++ b/tests/ui/suggestions/method-missing-parentheses.stderr
@@ -0,0 +1,20 @@
+error: field expressions cannot have generic arguments
+ --> $DIR/method-missing-parentheses.rs:2:41
+ |
+LL | let _ = vec![].into_iter().collect::<usize>;
+ | ^^^^^^^
+
+error[E0615]: attempted to take value of method `collect` on type `std::vec::IntoIter<_>`
+ --> $DIR/method-missing-parentheses.rs:2:32
+ |
+LL | let _ = vec![].into_iter().collect::<usize>;
+ | ^^^^^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | let _ = vec![].into_iter().collect::<usize>();
+ | ++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/tests/ui/suggestions/mismatched-types-numeric-from.rs b/tests/ui/suggestions/mismatched-types-numeric-from.rs
new file mode 100644
index 000000000..56549da9c
--- /dev/null
+++ b/tests/ui/suggestions/mismatched-types-numeric-from.rs
@@ -0,0 +1,3 @@
+fn main() {
+ let _: u32 = i32::from(0_u8); //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/mismatched-types-numeric-from.stderr b/tests/ui/suggestions/mismatched-types-numeric-from.stderr
new file mode 100644
index 000000000..4d44d893a
--- /dev/null
+++ b/tests/ui/suggestions/mismatched-types-numeric-from.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/mismatched-types-numeric-from.rs:2:18
+ |
+LL | let _: u32 = i32::from(0_u8);
+ | --- ^^^^^^^^^^^^^^^ expected `u32`, found `i32`
+ | |
+ | expected due to this
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed
new file mode 100644
index 000000000..a0cb39a3f
--- /dev/null
+++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed
@@ -0,0 +1,21 @@
+// run-rustfix
+trait TraitB {
+ type Item;
+}
+
+trait TraitA<A> {
+ type Type;
+ fn bar<T>(_: T) -> Self;
+ fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
+}
+
+struct S;
+struct Type;
+
+impl TraitA<()> for S { //~ ERROR not all trait items implemented
+fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() }
+fn bar<T>(_: T) -> Self { todo!() }
+type Type = Type;
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs
new file mode 100644
index 000000000..c80ede1b2
--- /dev/null
+++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+trait TraitB {
+ type Item;
+}
+
+trait TraitA<A> {
+ type Type;
+ fn bar<T>(_: T) -> Self;
+ fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
+}
+
+struct S;
+struct Type;
+
+impl TraitA<()> for S { //~ ERROR not all trait items implemented
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr
new file mode 100644
index 000000000..4c75fbe4c
--- /dev/null
+++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr
@@ -0,0 +1,16 @@
+error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz`
+ --> $DIR/missing-assoc-fn-applicable-suggestions.rs:15:1
+ |
+LL | type Type;
+ | --------- `Type` from trait
+LL | fn bar<T>(_: T) -> Self;
+ | ------------------------ `bar` from trait
+LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
+ | ------------------------------------------------------------------- `baz` from trait
+...
+LL | impl TraitA<()> for S {
+ | ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/missing-assoc-fn.rs b/tests/ui/suggestions/missing-assoc-fn.rs
new file mode 100644
index 000000000..9af8e5a93
--- /dev/null
+++ b/tests/ui/suggestions/missing-assoc-fn.rs
@@ -0,0 +1,22 @@
+trait TraitB {
+ type Item;
+}
+
+trait TraitA<A> {
+ fn foo<T: TraitB<Item = A>>(_: T) -> Self;
+ fn bar<T>(_: T) -> Self;
+ fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
+ fn bat<T: TraitB<Item: Copy>>(_: T) -> Self; //~ ERROR associated type bounds are unstable
+}
+
+struct S;
+
+impl TraitA<()> for S { //~ ERROR not all trait items implemented
+}
+
+use std::iter::FromIterator;
+struct X;
+impl FromIterator<()> for X { //~ ERROR not all trait items implemented
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-assoc-fn.stderr b/tests/ui/suggestions/missing-assoc-fn.stderr
new file mode 100644
index 000000000..136ec2152
--- /dev/null
+++ b/tests/ui/suggestions/missing-assoc-fn.stderr
@@ -0,0 +1,36 @@
+error[E0658]: associated type bounds are unstable
+ --> $DIR/missing-assoc-fn.rs:9:22
+ |
+LL | fn bat<T: TraitB<Item: Copy>>(_: T) -> Self;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+ = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `bat`
+ --> $DIR/missing-assoc-fn.rs:14:1
+ |
+LL | fn foo<T: TraitB<Item = A>>(_: T) -> Self;
+ | ------------------------------------------ `foo` from trait
+LL | fn bar<T>(_: T) -> Self;
+ | ------------------------ `bar` from trait
+LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy;
+ | ------------------------------------------------------------------- `baz` from trait
+LL | fn bat<T: TraitB<Item: Copy>>(_: T) -> Self;
+ | -------------------------------------------- `bat` from trait
+...
+LL | impl TraitA<()> for S {
+ | ^^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `bat` in implementation
+
+error[E0046]: not all trait items implemented, missing: `from_iter`
+ --> $DIR/missing-assoc-fn.rs:19:1
+ |
+LL | impl FromIterator<()> for X {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation
+ |
+ = help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = A { todo!() }`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0046, E0658.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/missing-assoc-type-bound-restriction.rs b/tests/ui/suggestions/missing-assoc-type-bound-restriction.rs
new file mode 100644
index 000000000..4954a8a69
--- /dev/null
+++ b/tests/ui/suggestions/missing-assoc-type-bound-restriction.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Parent {
+ type Ty;
+ type Assoc: Child<Self::Ty>;
+}
+
+trait Child<T> {}
+
+struct ChildWrapper<T>(T);
+
+impl<A, T> Child<A> for ChildWrapper<T> where T: Child<A> {}
+
+struct ParentWrapper<T>(T);
+
+impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
+ type Ty = A;
+ type Assoc = ChildWrapper<T::Assoc>;
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
new file mode 100644
index 000000000..ac0b14fba
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+ pub x: T,
+ pub y: T
+}
+
+#[derive(Debug, Copy, Clone)]
+pub struct AABB<K: Debug + std::marker::Copy>{
+ pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
+ pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs
new file mode 100644
index 000000000..31f8cd6fc
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+ pub x: T,
+ pub y: T
+}
+
+#[derive(Debug, Copy, Clone)]
+pub struct AABB<K: Debug>{
+ pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
+ pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
new file mode 100644
index 000000000..03082be69
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `K: Copy` is not satisfied
+ --> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14
+ |
+LL | pub loc: Vector2<K>,
+ | ^^^^^^^^^^ the trait `Copy` is not implemented for `K`
+ |
+note: required by a bound in `Vector2`
+ --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31
+ |
+LL | pub struct Vector2<T: Debug + Copy + Clone>{
+ | ^^^^ required by this bound in `Vector2`
+help: consider further restricting this bound
+ |
+LL | pub struct AABB<K: Debug + std::marker::Copy>{
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
new file mode 100644
index 000000000..304360d48
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
@@ -0,0 +1,16 @@
+//run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+ pub x: T,
+ pub y: T
+}
+
+#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
+pub struct AABB<K: Copy + Debug>{
+ pub loc: Vector2<K>,
+ pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs
new file mode 100644
index 000000000..14e1fbb33
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs
@@ -0,0 +1,16 @@
+//run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+ pub x: T,
+ pub y: T
+}
+
+#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
+pub struct AABB<K: Copy>{
+ pub loc: Vector2<K>,
+ pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
new file mode 100644
index 000000000..faf730a5c
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
@@ -0,0 +1,27 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17
+ |
+LL | #[derive(Debug, Copy, Clone)]
+ | ^^^^
+LL | pub struct AABB<K: Copy>{
+LL | pub loc: Vector2<K>,
+ | ------------------- this field does not implement `Copy`
+LL | pub size: Vector2<K>
+ | -------------------- this field does not implement `Copy`
+ |
+note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
+ --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14
+ |
+LL | pub loc: Vector2<K>,
+ | ^^^^^^^^^^
+LL | pub size: Vector2<K>
+ | ^^^^^^^^^^
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+ |
+LL | pub struct AABB<K: Copy + Debug>{
+ | +++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs
new file mode 100644
index 000000000..52163bddd
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs
@@ -0,0 +1,15 @@
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+ pub x: T,
+ pub y: T
+}
+
+#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
+pub struct AABB<K>{
+ pub loc: Vector2<K>,
+ pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
new file mode 100644
index 000000000..11bc54099
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
@@ -0,0 +1,27 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17
+ |
+LL | #[derive(Debug, Copy, Clone)]
+ | ^^^^
+LL | pub struct AABB<K>{
+LL | pub loc: Vector2<K>,
+ | ------------------- this field does not implement `Copy`
+LL | pub size: Vector2<K>
+ | -------------------- this field does not implement `Copy`
+ |
+note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
+ --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14
+ |
+LL | pub loc: Vector2<K>,
+ | ^^^^^^^^^^
+LL | pub size: Vector2<K>
+ | ^^^^^^^^^^
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `K`
+ |
+LL | pub struct AABB<K: Debug>{
+ | +++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed
new file mode 100644
index 000000000..691e7553a
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
+
+impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
+ fn clone(&self) -> Self {
+ OnlyCopyIfDisplay(std::marker::PhantomData)
+ }
+}
+
+impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
+
+impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs
new file mode 100644
index 000000000..e3185e7ef
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
+
+impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
+ fn clone(&self) -> Self {
+ OnlyCopyIfDisplay(std::marker::PhantomData)
+ }
+}
+
+impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
+
+impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
new file mode 100644
index 000000000..9e6f0d9eb
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
@@ -0,0 +1,22 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18
+ |
+LL | struct Wrapper<T>(T);
+ | - this field does not implement `Copy`
+...
+LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display`
+ --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19
+ |
+LL | struct Wrapper<T>(T);
+ | ^
+help: consider restricting type parameter `S`
+ |
+LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed
new file mode 100644
index 000000000..32a7215c5
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+impl<S: Copy> Copy for Wrapper<S> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs
new file mode 100644
index 000000000..c688f4d41
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Wrapper<T>(T);
+
+impl<S> Copy for Wrapper<S> {}
+//~^ ERROR the trait `Copy` may not be implemented for this type
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
new file mode 100644
index 000000000..fe2d133c8
--- /dev/null
+++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
@@ -0,0 +1,17 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18
+ |
+LL | struct Wrapper<T>(T);
+ | - this field does not implement `Copy`
+LL |
+LL | impl<S> Copy for Wrapper<S> {}
+ | ^^^^^^^^^^
+ |
+help: consider restricting type parameter `S`
+ |
+LL | impl<S: Copy> Copy for Wrapper<S> {}
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
new file mode 100644
index 000000000..38332627f
--- /dev/null
+++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
@@ -0,0 +1,16 @@
+trait ZstAssert: Sized {
+ const A: &str = ""; //~ ERROR missing lifetime specifier
+ const B: S = S { s: &() }; //~ ERROR missing lifetime specifier
+ const C: &'_ str = ""; //~ ERROR missing lifetime specifier
+ const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier
+}
+
+struct S<'a> {
+ s: &'a (),
+}
+struct T<'a, 'b> {
+ a: &'a (),
+ b: &'b (),
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr
new file mode 100644
index 000000000..233f1bc5a
--- /dev/null
+++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr
@@ -0,0 +1,57 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetime-in-assoc-const-type.rs:2:14
+ |
+LL | const A: &str = "";
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ trait ZstAssert<'a>: Sized {
+LL ~ const A: &'a str = "";
+ |
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetime-in-assoc-const-type.rs:3:14
+ |
+LL | const B: S = S { s: &() };
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ trait ZstAssert<'a>: Sized {
+LL | const A: &str = "";
+LL ~ const B: S<'a> = S { s: &() };
+ |
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetime-in-assoc-const-type.rs:4:15
+ |
+LL | const C: &'_ str = "";
+ | ^^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ trait ZstAssert<'a>: Sized {
+LL | const A: &str = "";
+LL | const B: S = S { s: &() };
+LL ~ const C: &'a str = "";
+ |
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-in-assoc-const-type.rs:5:14
+ |
+LL | const D: T = T { a: &(), b: &() };
+ | ^ expected 2 lifetime parameters
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ trait ZstAssert<'a>: Sized {
+LL | const A: &str = "";
+LL | const B: S = S { s: &() };
+LL | const C: &'_ str = "";
+LL ~ const D: T<'a, 'a> = T { a: &(), b: &() };
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs
new file mode 100644
index 000000000..24f5f782f
--- /dev/null
+++ b/tests/ui/suggestions/missing-lifetime-specifier.rs
@@ -0,0 +1,57 @@
+#![allow(bare_trait_objects)]
+use std::collections::HashMap;
+use std::cell::RefCell;
+
+pub union Foo<'t, 'k> {
+ i: &'t i64,
+ f: &'k f64,
+}
+trait Bar<'t, 'k> {}
+
+pub union Qux<'t, 'k, I> {
+ i: &'t I,
+ f: &'k I,
+}
+trait Tar<'t, 'k, I> {}
+
+thread_local! {
+ static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
+ //~^ ERROR missing lifetime specifiers
+ //~| ERROR missing lifetime specifiers
+}
+thread_local! {
+ static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
+ //~^ ERROR missing lifetime specifiers
+ //~| ERROR missing lifetime specifiers
+}
+thread_local! {
+ static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
+ //~^ ERROR missing lifetime specifiers
+ //~| ERROR missing lifetime specifiers
+}
+thread_local! {
+ static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
+ //~^ ERROR missing lifetime specifiers
+ //~| ERROR missing lifetime specifiers
+}
+
+thread_local! {
+ static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+ //~^ ERROR this union takes 2 lifetime arguments but 1 lifetime argument
+ //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+}
+thread_local! {
+ static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR missing lifetime
+ //~| ERROR missing lifetime
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr
new file mode 100644
index 000000000..997bbb5e9
--- /dev/null
+++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr
@@ -0,0 +1,319 @@
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:18:44
+ |
+LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
+ | ^^^ expected 2 lifetime parameters
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefCell::new(HashMap::new());
+ | ++++++++++++++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:18:44
+ |
+LL | / thread_local! {
+LL | | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
+ | | ^^^ expected 2 lifetime parameters
+LL | |
+LL | |
+LL | | }
+ | |_-
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:23:44
+ |
+LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
+ | ^^^^ expected 2 lifetime parameters
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | static b: RefCell<HashMap<i32, Vec<Vec<&'static Bar<'static, 'static>>>>> = RefCell::new(HashMap::new());
+ | +++++++ ++++++++++++++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:23:44
+ |
+LL | / thread_local! {
+LL | | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
+ | | ^^^^ expected 2 lifetime parameters
+ | | |
+ | | expected named lifetime parameter
+LL | |
+LL | |
+LL | | }
+ | |_-
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:28:47
+ |
+LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
+ | ^ expected 2 lifetime parameters
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++++++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:28:47
+ |
+LL | / thread_local! {
+LL | | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
+ | | ^ expected 2 lifetime parameters
+LL | |
+LL | |
+LL | | }
+ | |_-
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:33:44
+ |
+LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
+ | ^ ^ expected 2 lifetime parameters
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++ +++++++++++++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lifetime-specifier.rs:33:44
+ |
+LL | / thread_local! {
+LL | | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
+ | | ^ ^ expected 2 lifetime parameters
+ | | |
+ | | expected named lifetime parameter
+LL | |
+LL | |
+LL | | }
+ | |_-
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetime-specifier.rs:47:44
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetime-specifier.rs:47:44
+ |
+LL | / thread_local! {
+LL | | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | | ^ expected named lifetime parameter
+LL | |
+LL | |
+... |
+LL | |
+LL | | }
+ | |_-
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
+
+error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:39:44
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:11:11
+ |
+LL | pub union Qux<'t, 'k, I> {
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:39:44
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:11:11
+ |
+LL | pub union Qux<'t, 'k, I> {
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:39:44
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:11:11
+ |
+LL | pub union Qux<'t, 'k, I> {
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:39:44
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:11:11
+ |
+LL | pub union Qux<'t, 'k, I> {
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:39:44
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:11:11
+ |
+LL | pub union Qux<'t, 'k, I> {
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:47:45
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:15:7
+ |
+LL | trait Tar<'t, 'k, I> {}
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:47:45
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:15:7
+ |
+LL | trait Tar<'t, 'k, I> {}
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:47:45
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:15:7
+ |
+LL | trait Tar<'t, 'k, I> {}
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:47:45
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:15:7
+ |
+LL | trait Tar<'t, 'k, I> {}
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/missing-lifetime-specifier.rs:47:45
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+ | ^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+ --> $DIR/missing-lifetime-specifier.rs:15:7
+ |
+LL | trait Tar<'t, 'k, I> {}
+ | ^^^ -- --
+help: add missing lifetime argument
+ |
+LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+ | +++++++++
+
+error: aborting due to 20 previous errors
+
+Some errors have detailed explanations: E0106, E0107.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.rs b/tests/ui/suggestions/missing-lt-for-hrtb.rs
new file mode 100644
index 000000000..04ea3d831
--- /dev/null
+++ b/tests/ui/suggestions/missing-lt-for-hrtb.rs
@@ -0,0 +1,13 @@
+struct X<'a>(&'a ());
+struct S<'a>(&'a dyn Fn(&X) -> &X);
+//~^ ERROR missing lifetime specifiers
+struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+//~^ ERROR missing lifetime specifiers
+
+fn main() {
+ let x = S(&|x| {
+ println!("hi");
+ x
+ });
+ x.0(&X(&()));
+}
diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.stderr b/tests/ui/suggestions/missing-lt-for-hrtb.stderr
new file mode 100644
index 000000000..fa5156444
--- /dev/null
+++ b/tests/ui/suggestions/missing-lt-for-hrtb.stderr
@@ -0,0 +1,36 @@
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lt-for-hrtb.rs:2:32
+ |
+LL | struct S<'a>(&'a dyn Fn(&X) -> &X);
+ | -- ^^ expected named lifetime parameter
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
+help: consider using the `'a` lifetime
+ |
+LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X<'a>);
+ | ++ ++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/missing-lt-for-hrtb.rs:4:40
+ |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+ | -- ^^ expected named lifetime parameter
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
+note: these named lifetimes are available to use
+ --> $DIR/missing-lt-for-hrtb.rs:4:10
+ |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+ | ^^ ^^
+help: consider using one of the available lifetimes here
+ |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>);
+ | +++++++++ +++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/missing-trait-item.fixed b/tests/ui/suggestions/missing-trait-item.fixed
new file mode 100644
index 000000000..a1cf359ec
--- /dev/null
+++ b/tests/ui/suggestions/missing-trait-item.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+
+trait T {
+ unsafe fn foo(a: &usize, b: &usize) -> usize;
+ fn bar(&self, a: &usize, b: &usize) -> usize;
+}
+
+mod foo {
+ use super::T;
+ impl T for () { fn bar(&self, _: &usize, _: &usize) -> usize { todo!() }
+ unsafe fn foo(_: &usize, _: &usize) -> usize { todo!() }
+ } //~ ERROR not all trait items
+
+ impl T for usize { //~ ERROR not all trait items
+ fn bar(&self, _: &usize, _: &usize) -> usize { todo!() }
+ unsafe fn foo(_: &usize, _: &usize) -> usize { todo!() }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-trait-item.rs b/tests/ui/suggestions/missing-trait-item.rs
new file mode 100644
index 000000000..b4fca25ba
--- /dev/null
+++ b/tests/ui/suggestions/missing-trait-item.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+
+trait T {
+ unsafe fn foo(a: &usize, b: &usize) -> usize;
+ fn bar(&self, a: &usize, b: &usize) -> usize;
+}
+
+mod foo {
+ use super::T;
+ impl T for () {} //~ ERROR not all trait items
+
+ impl T for usize { //~ ERROR not all trait items
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/missing-trait-item.stderr b/tests/ui/suggestions/missing-trait-item.stderr
new file mode 100644
index 000000000..4a9d7b472
--- /dev/null
+++ b/tests/ui/suggestions/missing-trait-item.stderr
@@ -0,0 +1,25 @@
+error[E0046]: not all trait items implemented, missing: `foo`, `bar`
+ --> $DIR/missing-trait-item.rs:10:5
+ |
+LL | unsafe fn foo(a: &usize, b: &usize) -> usize;
+ | --------------------------------------------- `foo` from trait
+LL | fn bar(&self, a: &usize, b: &usize) -> usize;
+ | --------------------------------------------- `bar` from trait
+...
+LL | impl T for () {}
+ | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
+
+error[E0046]: not all trait items implemented, missing: `foo`, `bar`
+ --> $DIR/missing-trait-item.rs:12:5
+ |
+LL | unsafe fn foo(a: &usize, b: &usize) -> usize;
+ | --------------------------------------------- `foo` from trait
+LL | fn bar(&self, a: &usize, b: &usize) -> usize;
+ | --------------------------------------------- `bar` from trait
+...
+LL | impl T for usize {
+ | ^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.fixed b/tests/ui/suggestions/missing-type-param-used-in-param.fixed
new file mode 100644
index 000000000..be4394031
--- /dev/null
+++ b/tests/ui/suggestions/missing-type-param-used-in-param.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn two_type_params<A, B>(_: B) {}
+
+fn main() {
+ two_type_params::<String, _>(100); //~ ERROR function takes 2 generic arguments
+ two_type_params::<String, _>(100);
+}
diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.rs b/tests/ui/suggestions/missing-type-param-used-in-param.rs
new file mode 100644
index 000000000..d444998d3
--- /dev/null
+++ b/tests/ui/suggestions/missing-type-param-used-in-param.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn two_type_params<A, B>(_: B) {}
+
+fn main() {
+ two_type_params::<String>(100); //~ ERROR function takes 2 generic arguments
+ two_type_params::<String, _>(100);
+}
diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.stderr b/tests/ui/suggestions/missing-type-param-used-in-param.stderr
new file mode 100644
index 000000000..4f7058a64
--- /dev/null
+++ b/tests/ui/suggestions/missing-type-param-used-in-param.stderr
@@ -0,0 +1,21 @@
+error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+ --> $DIR/missing-type-param-used-in-param.rs:6:5
+ |
+LL | two_type_params::<String>(100);
+ | ^^^^^^^^^^^^^^^ ------ supplied 1 generic argument
+ | |
+ | expected 2 generic arguments
+ |
+note: function defined here, with 2 generic parameters: `A`, `B`
+ --> $DIR/missing-type-param-used-in-param.rs:3:4
+ |
+LL | fn two_type_params<A, B>(_: B) {}
+ | ^^^^^^^^^^^^^^^ - -
+help: add missing generic argument
+ |
+LL | two_type_params::<String, _>(100);
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs
new file mode 100644
index 000000000..2f540060a
--- /dev/null
+++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs
@@ -0,0 +1,18 @@
+// Generalizes the suggestion introduced in #100838
+
+trait Foo<T> {
+ fn bar(&self, _: T);
+}
+
+impl Foo<i32> for i32 {
+ fn bar(&self, x: i32) {
+ println!("{}", self + x);
+ }
+}
+
+fn main() {
+ 1.bar::<i32>(0);
+ //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
+ //~| HELP consider moving this generic argument to the `Foo` trait, which takes up to 1 argument
+ //~| HELP remove these generics
+}
diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr
new file mode 100644
index 000000000..9557220f6
--- /dev/null
+++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr
@@ -0,0 +1,24 @@
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/move-generic-to-trait-in-method-with-params.rs:14:7
+ |
+LL | 1.bar::<i32>(0);
+ | ^^^ expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/move-generic-to-trait-in-method-with-params.rs:4:8
+ |
+LL | fn bar(&self, _: T);
+ | ^^^
+help: consider moving this generic argument to the `Foo` trait, which takes up to 1 argument
+ |
+LL | Foo::<i32>::bar(1, 0);
+ | ~~~~~~~~~~~~~~~~~~~~~
+help: remove these generics
+ |
+LL - 1.bar::<i32>(0);
+LL + 1.bar(0);
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/multibyte-escapes.rs b/tests/ui/suggestions/multibyte-escapes.rs
new file mode 100644
index 000000000..c41051862
--- /dev/null
+++ b/tests/ui/suggestions/multibyte-escapes.rs
@@ -0,0 +1,18 @@
+// Regression test for #87397.
+
+fn main() {
+ b'µ';
+ //~^ ERROR: non-ASCII character in byte literal
+ //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape
+ //~| NOTE: must be ASCII
+
+ b'字';
+ //~^ ERROR: non-ASCII character in byte literal
+ //~| NOTE: this multibyte character does not fit into a single byte
+ //~| NOTE: must be ASCII
+
+ b"字";
+ //~^ ERROR: non-ASCII character in byte string literal
+ //~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
+ //~| NOTE: must be ASCII
+}
diff --git a/tests/ui/suggestions/multibyte-escapes.stderr b/tests/ui/suggestions/multibyte-escapes.stderr
new file mode 100644
index 000000000..1e7c43e65
--- /dev/null
+++ b/tests/ui/suggestions/multibyte-escapes.stderr
@@ -0,0 +1,33 @@
+error: non-ASCII character in byte literal
+ --> $DIR/multibyte-escapes.rs:4:7
+ |
+LL | b'µ';
+ | ^ must be ASCII
+ |
+help: if you meant to use the unicode code point for 'µ', use a \xHH escape
+ |
+LL | b'\xB5';
+ | ~~~~
+
+error: non-ASCII character in byte literal
+ --> $DIR/multibyte-escapes.rs:9:7
+ |
+LL | b'字';
+ | ^^
+ | |
+ | must be ASCII
+ | this multibyte character does not fit into a single byte
+
+error: non-ASCII character in byte string literal
+ --> $DIR/multibyte-escapes.rs:14:7
+ |
+LL | b"字";
+ | ^^ must be ASCII
+ |
+help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
+ |
+LL | b"\xE5\xAD\x97";
+ | ~~~~~~~~~~~~
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.rs b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs
new file mode 100644
index 000000000..66e1e77c9
--- /dev/null
+++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs
@@ -0,0 +1,22 @@
+use std::env::args;
+use std::fs::File;
+use std::io::{stdout, Write, BufWriter};
+
+fn main() {
+ let mut args = args();
+ let _ = args.next();
+ let dest = args.next();
+
+ let h1; let h2; let h3;
+
+ let fp: &dyn Write = match dest {
+ Some(path) => { h1 = File::create(path).unwrap(); &h1 },
+ None => { h2 = stdout(); h3 = h2.lock(); &h3 }
+ };
+
+ let fp = BufWriter::new(fp);
+ //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+ //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+
+ writeln!(fp, "hello world").unwrap(); //~ ERROR the method
+}
diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
new file mode 100644
index 000000000..6910b77d9
--- /dev/null
+++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -0,0 +1,40 @@
+error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+ --> $DIR/mut-borrow-needed-by-trait.rs:17:29
+ |
+LL | let fp = BufWriter::new(fp);
+ | -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
+note: required by a bound in `BufWriter::<W>::new`
+ --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+
+error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
+ --> $DIR/mut-borrow-needed-by-trait.rs:17:14
+ |
+LL | let fp = BufWriter::new(fp);
+ | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+ |
+ = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
+note: required by a bound in `BufWriter`
+ --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+
+error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
+ --> $DIR/mut-borrow-needed-by-trait.rs:21:5
+ |
+LL | writeln!(fp, "hello world").unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
+ --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+ |
+ = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
+ |
+ = note: the following trait bounds were not satisfied:
+ `&dyn std::io::Write: std::io::Write`
+ which is required by `BufWriter<&dyn std::io::Write>: std::io::Write`
+ = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/mut-ref-reassignment.rs b/tests/ui/suggestions/mut-ref-reassignment.rs
new file mode 100644
index 000000000..142832493
--- /dev/null
+++ b/tests/ui/suggestions/mut-ref-reassignment.rs
@@ -0,0 +1,17 @@
+fn suggestion(opt: &mut Option<String>) {
+ opt = None; //~ ERROR mismatched types
+}
+
+fn no_suggestion(opt: &mut Result<String, ()>) {
+ opt = None //~ ERROR mismatched types
+}
+
+fn suggestion2(opt: &mut Option<String>) {
+ opt = Some(String::new())//~ ERROR mismatched types
+}
+
+fn no_suggestion2(opt: &mut Option<String>) {
+ opt = Some(42)//~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/mut-ref-reassignment.stderr b/tests/ui/suggestions/mut-ref-reassignment.stderr
new file mode 100644
index 000000000..b3cb6dd06
--- /dev/null
+++ b/tests/ui/suggestions/mut-ref-reassignment.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+ --> $DIR/mut-ref-reassignment.rs:2:11
+ |
+LL | fn suggestion(opt: &mut Option<String>) {
+ | ------------------- expected due to this parameter type
+LL | opt = None;
+ | ^^^^ expected mutable reference, found enum `Option`
+ |
+ = note: expected mutable reference `&mut Option<String>`
+ found enum `Option<_>`
+help: consider dereferencing here to assign to the mutably borrowed value
+ |
+LL | *opt = None;
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/mut-ref-reassignment.rs:6:11
+ |
+LL | fn no_suggestion(opt: &mut Result<String, ()>) {
+ | ----------------------- expected due to this parameter type
+LL | opt = None
+ | ^^^^ expected mutable reference, found enum `Option`
+ |
+ = note: expected mutable reference `&mut Result<String, ()>`
+ found enum `Option<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/mut-ref-reassignment.rs:10:11
+ |
+LL | fn suggestion2(opt: &mut Option<String>) {
+ | ------------------- expected due to this parameter type
+LL | opt = Some(String::new())
+ | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option`
+ |
+ = note: expected mutable reference `&mut Option<String>`
+ found enum `Option<String>`
+help: consider dereferencing here to assign to the mutably borrowed value
+ |
+LL | *opt = Some(String::new())
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/mut-ref-reassignment.rs:14:11
+ |
+LL | fn no_suggestion2(opt: &mut Option<String>) {
+ | ------------------- expected due to this parameter type
+LL | opt = Some(42)
+ | ^^^^^^^^ expected mutable reference, found enum `Option`
+ |
+ = note: expected mutable reference `&mut Option<String>`
+ found enum `Option<{integer}>`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/negative-literal-index.fixed b/tests/ui/suggestions/negative-literal-index.fixed
new file mode 100644
index 000000000..e52714cf9
--- /dev/null
+++ b/tests/ui/suggestions/negative-literal-index.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+
+use std::ops::Index;
+struct X;
+impl Index<i32> for X {
+ type Output = ();
+
+ fn index(&self, _: i32) -> &() {
+ &()
+ }
+}
+
+fn main() {
+ let x = vec![1, 2, 3];
+ x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a
+ let x = [1, 2, 3];
+ x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a
+ let x = &[1, 2, 3];
+ x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a
+ let _ = x;
+ X[-1];
+}
diff --git a/tests/ui/suggestions/negative-literal-index.rs b/tests/ui/suggestions/negative-literal-index.rs
new file mode 100644
index 000000000..d88b66e67
--- /dev/null
+++ b/tests/ui/suggestions/negative-literal-index.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+
+use std::ops::Index;
+struct X;
+impl Index<i32> for X {
+ type Output = ();
+
+ fn index(&self, _: i32) -> &() {
+ &()
+ }
+}
+
+fn main() {
+ let x = vec![1, 2, 3];
+ x[-1]; //~ ERROR negative integers cannot be used to index on a
+ let x = [1, 2, 3];
+ x[-1]; //~ ERROR negative integers cannot be used to index on a
+ let x = &[1, 2, 3];
+ x[-1]; //~ ERROR negative integers cannot be used to index on a
+ let _ = x;
+ X[-1];
+}
diff --git a/tests/ui/suggestions/negative-literal-index.stderr b/tests/ui/suggestions/negative-literal-index.stderr
new file mode 100644
index 000000000..2b51bf7b7
--- /dev/null
+++ b/tests/ui/suggestions/negative-literal-index.stderr
@@ -0,0 +1,35 @@
+error: negative integers cannot be used to index on a `Vec<{integer}>`
+ --> $DIR/negative-literal-index.rs:15:7
+ |
+LL | x[-1];
+ | ^^ cannot use a negative integer for indexing on `Vec<{integer}>`
+ |
+help: to access an element starting from the end of the `Vec<{integer}>`, compute the index
+ |
+LL | x[x.len() -1];
+ | +++++++
+
+error: negative integers cannot be used to index on a `[{integer}; 3]`
+ --> $DIR/negative-literal-index.rs:17:7
+ |
+LL | x[-1];
+ | ^^ cannot use a negative integer for indexing on `[{integer}; 3]`
+ |
+help: to access an element starting from the end of the `[{integer}; 3]`, compute the index
+ |
+LL | x[x.len() -1];
+ | +++++++
+
+error: negative integers cannot be used to index on a `[{integer}; 3]`
+ --> $DIR/negative-literal-index.rs:19:7
+ |
+LL | x[-1];
+ | ^^ cannot use a negative integer for indexing on `[{integer}; 3]`
+ |
+help: to access an element starting from the end of the `[{integer}; 3]`, compute the index
+ |
+LL | x[x.len() -1];
+ | +++++++
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/nested-non-tuple-tuple-struct.rs b/tests/ui/suggestions/nested-non-tuple-tuple-struct.rs
new file mode 100644
index 000000000..308adcf01
--- /dev/null
+++ b/tests/ui/suggestions/nested-non-tuple-tuple-struct.rs
@@ -0,0 +1,18 @@
+pub struct S(f32, f32);
+
+pub enum E {
+ V(f32, f32),
+}
+
+fn main() {
+ let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ //~^ ERROR struct `S` has no field named `x`
+ //~| ERROR struct `S` has no field named `y`
+ //~| ERROR struct `S` has no field named `x`
+ //~| ERROR struct `S` has no field named `y`
+ let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ //~^ ERROR variant `E::V` has no field named `x`
+ //~| ERROR variant `E::V` has no field named `y`
+ //~| ERROR variant `E::V` has no field named `x`
+ //~| ERROR variant `E::V` has no field named `y`
+}
diff --git a/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr
new file mode 100644
index 000000000..948f09fc3
--- /dev/null
+++ b/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr
@@ -0,0 +1,116 @@
+error[E0560]: struct `S` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:19
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:27
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:41
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
+ | ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:49
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
+ | ~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:22
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:30
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:47
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:55
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
+ | ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0559, E0560.
+For more information about an error, try `rustc --explain E0559`.
diff --git a/tests/ui/suggestions/no-extern-crate-in-type.rs b/tests/ui/suggestions/no-extern-crate-in-type.rs
new file mode 100644
index 000000000..bb93ef454
--- /dev/null
+++ b/tests/ui/suggestions/no-extern-crate-in-type.rs
@@ -0,0 +1,7 @@
+// aux-build:foo.rs
+
+extern crate foo;
+
+type Output = Option<Foo>; //~ ERROR cannot find type `Foo`
+
+fn main() {}
diff --git a/tests/ui/suggestions/no-extern-crate-in-type.stderr b/tests/ui/suggestions/no-extern-crate-in-type.stderr
new file mode 100644
index 000000000..876eef2b6
--- /dev/null
+++ b/tests/ui/suggestions/no-extern-crate-in-type.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `Foo` in this scope
+ --> $DIR/no-extern-crate-in-type.rs:5:22
+ |
+LL | type Output = Option<Foo>;
+ | ^^^ not found in this scope
+ |
+help: consider importing this struct
+ |
+LL | use foo::Foo;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
new file mode 100644
index 000000000..a7a3f9818
--- /dev/null
+++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
@@ -0,0 +1,43 @@
+// In rustc_hir_analysis::check::expr::no_such_field_err we recursively
+// look in subfields for the field. This recursive search is limited
+// in depth for compile-time reasons and to avoid infinite recursion
+// in case of cycles. This file tests that the limit in the recursion
+// depth is enforced.
+
+struct Foo {
+ first: Bar,
+ second: u32,
+ third: u32,
+}
+
+struct Bar {
+ bar: C,
+}
+
+struct C {
+ c: D,
+}
+
+struct D {
+ test: E,
+}
+
+struct E {
+ e: F,
+}
+
+struct F {
+ f: u32,
+}
+
+fn main() {
+ let f = F { f: 6 };
+ let e = E { e: f };
+ let d = D { test: e };
+ let c = C { c: d };
+ let bar = Bar { bar: c };
+ let fooer = Foo { first: bar, second: 4, third: 5 };
+
+ let test = fooer.f;
+ //~^ ERROR no field
+}
diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr
new file mode 100644
index 000000000..b294f4da7
--- /dev/null
+++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `f` on type `Foo`
+ --> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22
+ |
+LL | let test = fooer.f;
+ | ^ unknown field
+ |
+ = note: available fields are: `first`, `second`, `third`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.fixed b/tests/ui/suggestions/non-existent-field-present-in-subfield.fixed
new file mode 100644
index 000000000..e58b4e6ca
--- /dev/null
+++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.fixed
@@ -0,0 +1,42 @@
+// run-rustfix
+
+struct Foo {
+ first: Bar,
+ _second: u32,
+ _third: Vec<String>,
+}
+
+struct Bar {
+ bar: C,
+}
+
+struct C {
+ c: D,
+}
+
+struct D {
+ test: E,
+}
+
+struct E {
+ _e: F,
+}
+
+struct F {
+ _f: u32,
+}
+
+fn main() {
+ let f = F { _f: 6 };
+ let e = E { _e: f };
+ let d = D { test: e };
+ let c = C { c: d };
+ let bar = Bar { bar: c };
+ let fooer = Foo { first: bar, _second: 4, _third: Vec::new() };
+
+ let _test = &fooer.first.bar.c;
+ //~^ ERROR no field
+
+ let _test2 = fooer.first.bar.c.test;
+ //~^ ERROR no field
+}
diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.rs b/tests/ui/suggestions/non-existent-field-present-in-subfield.rs
new file mode 100644
index 000000000..7e273ac23
--- /dev/null
+++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.rs
@@ -0,0 +1,42 @@
+// run-rustfix
+
+struct Foo {
+ first: Bar,
+ _second: u32,
+ _third: Vec<String>,
+}
+
+struct Bar {
+ bar: C,
+}
+
+struct C {
+ c: D,
+}
+
+struct D {
+ test: E,
+}
+
+struct E {
+ _e: F,
+}
+
+struct F {
+ _f: u32,
+}
+
+fn main() {
+ let f = F { _f: 6 };
+ let e = E { _e: f };
+ let d = D { test: e };
+ let c = C { c: d };
+ let bar = Bar { bar: c };
+ let fooer = Foo { first: bar, _second: 4, _third: Vec::new() };
+
+ let _test = &fooer.c;
+ //~^ ERROR no field
+
+ let _test2 = fooer.test;
+ //~^ ERROR no field
+}
diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr
new file mode 100644
index 000000000..cc991b915
--- /dev/null
+++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr
@@ -0,0 +1,27 @@
+error[E0609]: no field `c` on type `Foo`
+ --> $DIR/non-existent-field-present-in-subfield.rs:37:24
+ |
+LL | let _test = &fooer.c;
+ | ^ unknown field
+ |
+ = note: available fields are: `first`, `_second`, `_third`
+help: one of the expressions' fields has a field of the same name
+ |
+LL | let _test = &fooer.first.bar.c;
+ | ++++++++++
+
+error[E0609]: no field `test` on type `Foo`
+ --> $DIR/non-existent-field-present-in-subfield.rs:40:24
+ |
+LL | let _test2 = fooer.test;
+ | ^^^^ unknown field
+ |
+ = note: available fields are: `first`, `_second`, `_third`
+help: one of the expressions' fields has a field of the same name
+ |
+LL | let _test2 = fooer.first.bar.c.test;
+ | ++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.rs b/tests/ui/suggestions/object-unsafe-trait-references-self.rs
new file mode 100644
index 000000000..07bf053e9
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-references-self.rs
@@ -0,0 +1,12 @@
+trait Trait {
+ fn baz(&self, _: Self) {}
+ fn bat(&self) -> Self {}
+}
+
+fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object
+
+trait Other: Sized {}
+
+fn foo(x: &dyn Other) {} //~ ERROR the trait `Other` cannot be made into an object
+
+fn main() {}
diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.stderr b/tests/ui/suggestions/object-unsafe-trait-references-self.stderr
new file mode 100644
index 000000000..54f19fe9d
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-references-self.stderr
@@ -0,0 +1,35 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+ --> $DIR/object-unsafe-trait-references-self.rs:6:12
+ |
+LL | fn bar(x: &dyn Trait) {}
+ | ^^^^^^^^^ `Trait` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-references-self.rs:2:22
+ |
+LL | trait Trait {
+ | ----- this trait cannot be made into an object...
+LL | fn baz(&self, _: Self) {}
+ | ^^^^ ...because method `baz` references the `Self` type in this parameter
+LL | fn bat(&self) -> Self {}
+ | ^^^^ ...because method `bat` references the `Self` type in its return type
+ = help: consider moving `baz` to another trait
+ = help: consider moving `bat` to another trait
+
+error[E0038]: the trait `Other` cannot be made into an object
+ --> $DIR/object-unsafe-trait-references-self.rs:10:12
+ |
+LL | fn foo(x: &dyn Other) {}
+ | ^^^^^^^^^ `Other` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-references-self.rs:8:14
+ |
+LL | trait Other: Sized {}
+ | ----- ^^^^^ ...because it requires `Self: Sized`
+ | |
+ | this trait cannot be made into an object...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs
new file mode 100644
index 000000000..75f99075e
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs
@@ -0,0 +1,16 @@
+#![allow(bare_trait_objects)]
+trait A: Sized {
+ fn f(a: A) -> A;
+ //~^ ERROR associated item referring to unboxed trait object for its own trait
+ //~| ERROR the trait `A` cannot be made into an object
+}
+trait B {
+ fn f(a: B) -> B;
+ //~^ ERROR associated item referring to unboxed trait object for its own trait
+ //~| ERROR the trait `B` cannot be made into an object
+}
+trait C {
+ fn f(&self, a: C) -> C;
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr
new file mode 100644
index 000000000..55047b426
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr
@@ -0,0 +1,65 @@
+error: associated item referring to unboxed trait object for its own trait
+ --> $DIR/object-unsafe-trait-should-use-self.rs:3:13
+ |
+LL | trait A: Sized {
+ | - in this trait
+LL | fn f(a: A) -> A;
+ | ^ ^
+ |
+help: you might have meant to use `Self` to refer to the implementing type
+ |
+LL | fn f(a: Self) -> Self;
+ | ~~~~ ~~~~
+
+error[E0038]: the trait `A` cannot be made into an object
+ --> $DIR/object-unsafe-trait-should-use-self.rs:3:13
+ |
+LL | fn f(a: A) -> A;
+ | ^ `A` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-should-use-self.rs:2:10
+ |
+LL | trait A: Sized {
+ | - ^^^^^ ...because it requires `Self: Sized`
+ | |
+ | this trait cannot be made into an object...
+
+error: associated item referring to unboxed trait object for its own trait
+ --> $DIR/object-unsafe-trait-should-use-self.rs:8:13
+ |
+LL | trait B {
+ | - in this trait
+LL | fn f(a: B) -> B;
+ | ^ ^
+ |
+help: you might have meant to use `Self` to refer to the implementing type
+ |
+LL | fn f(a: Self) -> Self;
+ | ~~~~ ~~~~
+
+error[E0038]: the trait `B` cannot be made into an object
+ --> $DIR/object-unsafe-trait-should-use-self.rs:8:13
+ |
+LL | fn f(a: B) -> B;
+ | ^ `B` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-should-use-self.rs:8:8
+ |
+LL | trait B {
+ | - this trait cannot be made into an object...
+LL | fn f(a: B) -> B;
+ | ^ ...because associated function `f` has no `self` parameter
+help: consider turning `f` into a method by giving it a `&self` argument
+ |
+LL | fn f(&self, a: B) -> B;
+ | ++++++
+help: alternatively, consider constraining `f` so it does not apply to trait objects
+ |
+LL | fn f(a: B) -> B where Self: Sized;
+ | +++++++++++++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed
new file mode 100644
index 000000000..69487c565
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+#![allow(unused_variables, dead_code)]
+
+trait Trait {
+ fn foo(&self) where Self: Other, Self: Sized { }
+ fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type
+}
+
+fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object
+
+trait Other {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs
new file mode 100644
index 000000000..38d9aea16
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+#![allow(unused_variables, dead_code)]
+
+trait Trait {
+ fn foo() where Self: Other, { }
+ fn bar(self: ()) {} //~ ERROR invalid `self` parameter type
+}
+
+fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object
+
+trait Other {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
new file mode 100644
index 000000000..c0dc71df0
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr
@@ -0,0 +1,41 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+ --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12
+ |
+LL | fn bar(x: &dyn Trait) {}
+ | ^^^^^^^^^ `Trait` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8
+ |
+LL | trait Trait {
+ | ----- this trait cannot be made into an object...
+LL | fn foo() where Self: Other, { }
+ | ^^^ ...because associated function `foo` has no `self` parameter
+LL | fn bar(self: ()) {}
+ | ^^ ...because method `bar`'s `self` parameter cannot be dispatched on
+help: consider turning `foo` into a method by giving it a `&self` argument
+ |
+LL | fn foo(&self) where Self: Other, { }
+ | +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+ |
+LL | fn foo() where Self: Other, Self: Sized { }
+ | ~~~~~~~~~~~~~
+help: consider changing method `bar`'s `self` parameter to be `&self`
+ |
+LL | fn bar(self: &Self) {}
+ | ~~~~~
+
+error[E0307]: invalid `self` parameter type: ()
+ --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18
+ |
+LL | fn bar(self: ()) {}
+ | ^^
+ |
+ = note: type of `self` must be `Self` or a type that dereferences to it
+ = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0038, E0307.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/suggestions/opaque-type-error.rs b/tests/ui/suggestions/opaque-type-error.rs
new file mode 100644
index 000000000..5e1147403
--- /dev/null
+++ b/tests/ui/suggestions/opaque-type-error.rs
@@ -0,0 +1,24 @@
+// edition:2018
+use core::future::Future;
+
+async fn base_thing() -> Result<(), ()> {
+ Ok(())
+}
+
+fn thing_one() -> impl Future<Output = Result<(), ()>> {
+ base_thing()
+}
+
+fn thing_two() -> impl Future<Output = Result<(), ()>> {
+ base_thing()
+}
+
+async fn thing() -> Result<(), ()> {
+ if true {
+ thing_one()
+ } else {
+ thing_two() //~ ERROR `if` and `else` have incompatible types
+ }.await
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/opaque-type-error.stderr b/tests/ui/suggestions/opaque-type-error.stderr
new file mode 100644
index 000000000..133ffb058
--- /dev/null
+++ b/tests/ui/suggestions/opaque-type-error.stderr
@@ -0,0 +1,31 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/opaque-type-error.rs:20:9
+ |
+LL | fn thing_one() -> impl Future<Output = Result<(), ()>> {
+ | ------------------------------------ the expected opaque type
+...
+LL | fn thing_two() -> impl Future<Output = Result<(), ()>> {
+ | ------------------------------------ the found opaque type
+...
+LL | / if true {
+LL | | thing_one()
+ | | ----------- expected because of this
+LL | | } else {
+LL | | thing_two()
+ | | ^^^^^^^^^^^ expected opaque type, found a different opaque type
+LL | | }.await
+ | |_____- `if` and `else` have incompatible types
+ |
+ = note: expected opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
+ found opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
+ = note: distinct uses of `impl Trait` result in different opaque types
+help: consider `await`ing on both `Future`s
+ |
+LL ~ thing_one().await
+LL | } else {
+LL ~ thing_two().await
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/option-content-move-from-tuple-match.rs b/tests/ui/suggestions/option-content-move-from-tuple-match.rs
new file mode 100644
index 000000000..7f22d8136
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move-from-tuple-match.rs
@@ -0,0 +1,9 @@
+fn foo(a: &Option<String>, b: &Option<String>) {
+ match (a, b) {
+ //~^ ERROR cannot move out of a shared reference
+ (None, &c) => &c.unwrap(),
+ (&Some(ref c), _) => c,
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/option-content-move-from-tuple-match.stderr b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr
new file mode 100644
index 000000000..97d05d9dc
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr
@@ -0,0 +1,20 @@
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/option-content-move-from-tuple-match.rs:2:11
+ |
+LL | match (a, b) {
+ | ^^^^^^
+LL |
+LL | (None, &c) => &c.unwrap(),
+ | -
+ | |
+ | data moved here
+ | move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | (None, &ref c) => &c.unwrap(),
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs
new file mode 100644
index 000000000..46c895b95
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move.rs
@@ -0,0 +1,37 @@
+pub struct LipogramCorpora {
+ selections: Vec<(char, Option<String>)>,
+}
+
+impl LipogramCorpora {
+ pub fn validate_all(&mut self) -> Result<(), char> {
+ for selection in &self.selections {
+ if selection.1.is_some() {
+ if selection.1.unwrap().contains(selection.0) {
+ //~^ ERROR cannot move out of `selection.1`
+ return Err(selection.0);
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+pub struct LipogramCorpora2 {
+ selections: Vec<(char, Result<String, String>)>,
+}
+
+impl LipogramCorpora2 {
+ pub fn validate_all(&mut self) -> Result<(), char> {
+ for selection in &self.selections {
+ if selection.1.is_ok() {
+ if selection.1.unwrap().contains(selection.0) {
+ //~^ ERROR cannot move out of `selection.1`
+ return Err(selection.0);
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr
new file mode 100644
index 000000000..474a72093
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move.stderr
@@ -0,0 +1,35 @@
+error[E0507]: cannot move out of `selection.1` which is behind a shared reference
+ --> $DIR/option-content-move.rs:9:20
+ |
+LL | if selection.1.unwrap().contains(selection.0) {
+ | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
+ | |
+ | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+ | move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
+ |
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+ |
+LL | if selection.1.clone().unwrap().contains(selection.0) {
+ | ++++++++
+
+error[E0507]: cannot move out of `selection.1` which is behind a shared reference
+ --> $DIR/option-content-move.rs:27:20
+ |
+LL | if selection.1.unwrap().contains(selection.0) {
+ | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
+ | |
+ | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+ | move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
+ |
+note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+ |
+LL | if selection.1.clone().unwrap().contains(selection.0) {
+ | ++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/option-content-move2.rs b/tests/ui/suggestions/option-content-move2.rs
new file mode 100644
index 000000000..88e8a5b7a
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move2.rs
@@ -0,0 +1,16 @@
+struct NotCopyable;
+
+fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
+
+fn parse() {
+ let mut var = None;
+ func(|| {
+ // Shouldn't suggest `move ||.as_ref()` here
+ move || {
+ //~^ ERROR: cannot move out of `var`
+ var = Some(NotCopyable);
+ }
+ });
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr
new file mode 100644
index 000000000..1d3dff3be
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move2.stderr
@@ -0,0 +1,20 @@
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+ --> $DIR/option-content-move2.rs:9:9
+ |
+LL | let mut var = None;
+ | ------- captured outer variable
+LL | func(|| {
+ | -- captured by this `FnMut` closure
+LL | // Shouldn't suggest `move ||.as_ref()` here
+LL | move || {
+ | ^^^^^^^ move out of `var` occurs here
+LL |
+LL | var = Some(NotCopyable);
+ | ---
+ | |
+ | variable moved due to use in closure
+ | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/option-to-bool.rs b/tests/ui/suggestions/option-to-bool.rs
new file mode 100644
index 000000000..2a1823b15
--- /dev/null
+++ b/tests/ui/suggestions/option-to-bool.rs
@@ -0,0 +1,9 @@
+#![cfg_attr(let_chains, feature(let_chains))]
+
+fn foo(x: Option<i32>) {
+ if true && x {}
+ //~^ ERROR mismatched types
+ //~| HELP use `Option::is_some` to test if the `Option` has a value
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/option-to-bool.stderr b/tests/ui/suggestions/option-to-bool.stderr
new file mode 100644
index 000000000..4050c7be8
--- /dev/null
+++ b/tests/ui/suggestions/option-to-bool.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/option-to-bool.rs:4:16
+ |
+LL | if true && x {}
+ | ---- ^ expected `bool`, found enum `Option`
+ | |
+ | expected because this is `bool`
+ |
+ = note: expected type `bool`
+ found enum `Option<i32>`
+help: use `Option::is_some` to test if the `Option` has a value
+ |
+LL | if true && x.is_some() {}
+ | ++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.rs b/tests/ui/suggestions/parenthesized-deref-suggestion.rs
new file mode 100644
index 000000000..0b4ccdd5a
--- /dev/null
+++ b/tests/ui/suggestions/parenthesized-deref-suggestion.rs
@@ -0,0 +1,11 @@
+struct Session {
+ opts: u8,
+}
+
+fn main() {
+ let sess: &Session = &Session { opts: 0 };
+ (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
+
+ let x = [0u32];
+ (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
+}
diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr
new file mode 100644
index 000000000..cafddbe26
--- /dev/null
+++ b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr
@@ -0,0 +1,22 @@
+error[E0609]: no field `opts` on type `*const Session`
+ --> $DIR/parenthesized-deref-suggestion.rs:7:30
+ |
+LL | (sess as *const Session).opts;
+ | ^^^^
+ |
+help: `(sess as *const Session)` is a raw pointer; try dereferencing it
+ |
+LL | (*(sess as *const Session)).opts;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0609]: no field `0` on type `[u32; 1]`
+ --> $DIR/parenthesized-deref-suggestion.rs:10:21
+ |
+LL | (x as [u32; 1]).0;
+ | ----------------^
+ | |
+ | help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/suggestions/path-by-value.rs b/tests/ui/suggestions/path-by-value.rs
new file mode 100644
index 000000000..c875ca674
--- /dev/null
+++ b/tests/ui/suggestions/path-by-value.rs
@@ -0,0 +1,6 @@
+use std::path::Path;
+
+fn f(p: Path) { }
+//~^ ERROR E0277
+
+fn main() {}
diff --git a/tests/ui/suggestions/path-by-value.stderr b/tests/ui/suggestions/path-by-value.stderr
new file mode 100644
index 000000000..bbeaa26a9
--- /dev/null
+++ b/tests/ui/suggestions/path-by-value.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/path-by-value.rs:3:6
+ |
+LL | fn f(p: Path) { }
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: within `Path`, the trait `Sized` is not implemented for `[u8]`
+ = note: required because it appears within the type `Path`
+ = 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 | fn f(p: &Path) { }
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/path-display.rs b/tests/ui/suggestions/path-display.rs
new file mode 100644
index 000000000..3a022e6b0
--- /dev/null
+++ b/tests/ui/suggestions/path-display.rs
@@ -0,0 +1,11 @@
+use std::path::{Path, PathBuf};
+
+fn main() {
+ let path = Path::new("/tmp/foo/bar.txt");
+ println!("{}", path);
+ //~^ ERROR E0277
+
+ let path = PathBuf::from("/tmp/foo/bar.txt");
+ println!("{}", path);
+ //~^ ERROR E0277
+}
diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr
new file mode 100644
index 000000000..8359b3658
--- /dev/null
+++ b/tests/ui/suggestions/path-display.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `Path` doesn't implement `std::fmt::Display`
+ --> $DIR/path-display.rs:5:20
+ |
+LL | println!("{}", path);
+ | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `Path`
+ = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `PathBuf` doesn't implement `std::fmt::Display`
+ --> $DIR/path-display.rs:9:20
+ |
+LL | println!("{}", path);
+ | ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `PathBuf`
+ = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/pattern-slice-vec.fixed b/tests/ui/suggestions/pattern-slice-vec.fixed
new file mode 100644
index 000000000..f8144641f
--- /dev/null
+++ b/tests/ui/suggestions/pattern-slice-vec.fixed
@@ -0,0 +1,31 @@
+// Regression test for #87017.
+
+// run-rustfix
+
+fn main() {
+ fn foo() -> Vec<i32> { vec![1, 2, 3] }
+
+ if let [_, _, _] = foo()[..] {}
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+
+ if let [] = &foo()[..] {}
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+
+ if let [] = foo()[..] {}
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+
+ let v = vec![];
+ match &v[..] {
+ //~^ HELP: consider slicing here
+ [5] => {}
+ //~^ ERROR: expected an array or slice
+ _ => {}
+ }
+
+ let [..] = vec![1, 2, 3][..];
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+}
diff --git a/tests/ui/suggestions/pattern-slice-vec.rs b/tests/ui/suggestions/pattern-slice-vec.rs
new file mode 100644
index 000000000..444687c85
--- /dev/null
+++ b/tests/ui/suggestions/pattern-slice-vec.rs
@@ -0,0 +1,31 @@
+// Regression test for #87017.
+
+// run-rustfix
+
+fn main() {
+ fn foo() -> Vec<i32> { vec![1, 2, 3] }
+
+ if let [_, _, _] = foo() {}
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+
+ if let [] = &foo() {}
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+
+ if let [] = foo() {}
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+
+ let v = vec![];
+ match &v {
+ //~^ HELP: consider slicing here
+ [5] => {}
+ //~^ ERROR: expected an array or slice
+ _ => {}
+ }
+
+ let [..] = vec![1, 2, 3];
+ //~^ ERROR: expected an array or slice
+ //~| HELP: consider slicing here
+}
diff --git a/tests/ui/suggestions/pattern-slice-vec.stderr b/tests/ui/suggestions/pattern-slice-vec.stderr
new file mode 100644
index 000000000..f69e7de97
--- /dev/null
+++ b/tests/ui/suggestions/pattern-slice-vec.stderr
@@ -0,0 +1,44 @@
+error[E0529]: expected an array or slice, found `Vec<i32>`
+ --> $DIR/pattern-slice-vec.rs:8:12
+ |
+LL | if let [_, _, _] = foo() {}
+ | ^^^^^^^^^ ----- help: consider slicing here: `foo()[..]`
+ | |
+ | pattern cannot match with input type `Vec<i32>`
+
+error[E0529]: expected an array or slice, found `Vec<i32>`
+ --> $DIR/pattern-slice-vec.rs:12:12
+ |
+LL | if let [] = &foo() {}
+ | ^^ ------ help: consider slicing here: `&foo()[..]`
+ | |
+ | pattern cannot match with input type `Vec<i32>`
+
+error[E0529]: expected an array or slice, found `Vec<i32>`
+ --> $DIR/pattern-slice-vec.rs:16:12
+ |
+LL | if let [] = foo() {}
+ | ^^ ----- help: consider slicing here: `foo()[..]`
+ | |
+ | pattern cannot match with input type `Vec<i32>`
+
+error[E0529]: expected an array or slice, found `Vec<_>`
+ --> $DIR/pattern-slice-vec.rs:23:9
+ |
+LL | match &v {
+ | -- help: consider slicing here: `&v[..]`
+LL |
+LL | [5] => {}
+ | ^^^ pattern cannot match with input type `Vec<_>`
+
+error[E0529]: expected an array or slice, found `Vec<{integer}>`
+ --> $DIR/pattern-slice-vec.rs:28:9
+ |
+LL | let [..] = vec![1, 2, 3];
+ | ^^^^ ------------- help: consider slicing here: `vec![1, 2, 3][..]`
+ | |
+ | pattern cannot match with input type `Vec<{integer}>`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0529`.
diff --git a/tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs
new file mode 100644
index 000000000..5b223a91f
--- /dev/null
+++ b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs
@@ -0,0 +1,35 @@
+use std::ops::Deref;
+
+struct Foo {
+ v: Vec<u32>,
+}
+
+struct Bar {
+ v: Vec<u32>,
+}
+
+impl Deref for Bar {
+ type Target = Vec<u32>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.v
+ }
+}
+
+fn f(foo: &Foo) {
+ match foo {
+ Foo { v: [1, 2] } => {}
+ //~^ ERROR expected an array or slice, found `Vec<u32>
+ _ => {}
+ }
+}
+
+fn bar(bar: &Bar) {
+ match bar {
+ Bar { v: [1, 2] } => {}
+ //~^ ERROR expected an array or slice, found `Vec<u32>
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr
new file mode 100644
index 000000000..5b48a8b18
--- /dev/null
+++ b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr
@@ -0,0 +1,15 @@
+error[E0529]: expected an array or slice, found `Vec<u32>`
+ --> $DIR/pattern-struct-with-slice-vec-field.rs:21:18
+ |
+LL | Foo { v: [1, 2] } => {}
+ | ^^^^^^ pattern cannot match with input type `Vec<u32>`
+
+error[E0529]: expected an array or slice, found `Vec<u32>`
+ --> $DIR/pattern-struct-with-slice-vec-field.rs:29:18
+ |
+LL | Bar { v: [1, 2] } => {}
+ | ^^^^^^ pattern cannot match with input type `Vec<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0529`.
diff --git a/tests/ui/suggestions/private-field.rs b/tests/ui/suggestions/private-field.rs
new file mode 100644
index 000000000..1cc4d2a4d
--- /dev/null
+++ b/tests/ui/suggestions/private-field.rs
@@ -0,0 +1,19 @@
+// compile-flags: --crate-type lib
+pub struct S {
+ pub val: string::MyString,
+}
+
+pub fn test(s: S) {
+ dbg!(s.cap) //~ ERROR: no field `cap` on type `S` [E0609]
+}
+
+pub(crate) mod string {
+
+ pub struct MyString {
+ buf: MyVec,
+ }
+
+ struct MyVec {
+ cap: usize,
+ }
+}
diff --git a/tests/ui/suggestions/private-field.stderr b/tests/ui/suggestions/private-field.stderr
new file mode 100644
index 000000000..c38c795e0
--- /dev/null
+++ b/tests/ui/suggestions/private-field.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `cap` on type `S`
+ --> $DIR/private-field.rs:7:12
+ |
+LL | dbg!(s.cap)
+ | ^^^ unknown field
+ |
+ = note: available fields are: `val`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/suggestions/raw-byte-string-prefix.rs b/tests/ui/suggestions/raw-byte-string-prefix.rs
new file mode 100644
index 000000000..576561c31
--- /dev/null
+++ b/tests/ui/suggestions/raw-byte-string-prefix.rs
@@ -0,0 +1,10 @@
+// `br` and `rb` are easy to confuse; check that we issue a suggestion to help.
+
+// edition:2021
+
+fn main() {
+ rb"abc";
+ //~^ ERROR: prefix `rb` is unknown
+ //~| HELP: use `br` for a raw byte string
+ //~| ERROR: expected one of
+}
diff --git a/tests/ui/suggestions/raw-byte-string-prefix.stderr b/tests/ui/suggestions/raw-byte-string-prefix.stderr
new file mode 100644
index 000000000..4f5106849
--- /dev/null
+++ b/tests/ui/suggestions/raw-byte-string-prefix.stderr
@@ -0,0 +1,20 @@
+error: prefix `rb` is unknown
+ --> $DIR/raw-byte-string-prefix.rs:6:5
+ |
+LL | rb"abc";
+ | ^^ unknown prefix
+ |
+ = note: prefixed identifiers and literals are reserved since Rust 2021
+help: use `br` for a raw byte string
+ |
+LL | br"abc";
+ | ~~
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"abc"`
+ --> $DIR/raw-byte-string-prefix.rs:6:7
+ |
+LL | rb"abc";
+ | ^^^^^ expected one of 8 possible tokens
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/suggestions/raw-name-use-suggestion.rs b/tests/ui/suggestions/raw-name-use-suggestion.rs
new file mode 100644
index 000000000..0a8073c0b
--- /dev/null
+++ b/tests/ui/suggestions/raw-name-use-suggestion.rs
@@ -0,0 +1,9 @@
+mod foo {
+ pub fn r#let() {}
+ pub fn break() {} //~ ERROR expected identifier, found keyword `break`
+}
+
+fn main() {
+ foo::let(); //~ ERROR expected identifier, found keyword `let`
+ r#break(); //~ ERROR cannot find function `r#break` in this scope
+}
diff --git a/tests/ui/suggestions/raw-name-use-suggestion.stderr b/tests/ui/suggestions/raw-name-use-suggestion.stderr
new file mode 100644
index 000000000..95c26b9ad
--- /dev/null
+++ b/tests/ui/suggestions/raw-name-use-suggestion.stderr
@@ -0,0 +1,36 @@
+error: expected identifier, found keyword `break`
+ --> $DIR/raw-name-use-suggestion.rs:3:12
+ |
+LL | pub fn break() {}
+ | ^^^^^ expected identifier, found keyword
+ |
+help: escape `break` to use it as an identifier
+ |
+LL | pub fn r#break() {}
+ | ++
+
+error: expected identifier, found keyword `let`
+ --> $DIR/raw-name-use-suggestion.rs:7:10
+ |
+LL | foo::let();
+ | ^^^ expected identifier, found keyword
+ |
+help: escape `let` to use it as an identifier
+ |
+LL | foo::r#let();
+ | ++
+
+error[E0425]: cannot find function `r#break` in this scope
+ --> $DIR/raw-name-use-suggestion.rs:8:5
+ |
+LL | r#break();
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this function
+ |
+LL | use foo::r#break;
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/recover-from-semicolon-trailing-item.rs b/tests/ui/suggestions/recover-from-semicolon-trailing-item.rs
new file mode 100644
index 000000000..82935af0a
--- /dev/null
+++ b/tests/ui/suggestions/recover-from-semicolon-trailing-item.rs
@@ -0,0 +1,16 @@
+// verify that after encountering a semicolon after an item the parser recovers
+mod M {};
+//~^ ERROR expected item, found `;`
+struct S {};
+//~^ ERROR expected item, found `;`
+fn foo(a: usize) {};
+//~^ ERROR expected item, found `;`
+fn main() {
+ struct X {}; // ok
+ let _: usize = S {};
+ //~^ ERROR mismatched types
+ let _: usize = X {};
+ //~^ ERROR mismatched types
+ foo("");
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
new file mode 100644
index 000000000..9588eedc9
--- /dev/null
+++ b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
@@ -0,0 +1,53 @@
+error: expected item, found `;`
+ --> $DIR/recover-from-semicolon-trailing-item.rs:2:9
+ |
+LL | mod M {};
+ | ^ help: remove this semicolon
+
+error: expected item, found `;`
+ --> $DIR/recover-from-semicolon-trailing-item.rs:4:12
+ |
+LL | struct S {};
+ | ^ help: remove this semicolon
+ |
+ = help: braced struct declarations are not followed by a semicolon
+
+error: expected item, found `;`
+ --> $DIR/recover-from-semicolon-trailing-item.rs:6:20
+ |
+LL | fn foo(a: usize) {};
+ | ^ help: remove this semicolon
+
+error[E0308]: mismatched types
+ --> $DIR/recover-from-semicolon-trailing-item.rs:10:20
+ |
+LL | let _: usize = S {};
+ | ----- ^^^^ expected `usize`, found struct `S`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/recover-from-semicolon-trailing-item.rs:12:20
+ |
+LL | let _: usize = X {};
+ | ----- ^^^^ expected `usize`, found struct `X`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/recover-from-semicolon-trailing-item.rs:14:9
+ |
+LL | foo("");
+ | --- ^^ expected `usize`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/recover-from-semicolon-trailing-item.rs:6:4
+ |
+LL | fn foo(a: usize) {};
+ | ^^^ --------
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/recover-invalid-float.fixed b/tests/ui/suggestions/recover-invalid-float.fixed
new file mode 100644
index 000000000..62389ba61
--- /dev/null
+++ b/tests/ui/suggestions/recover-invalid-float.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+ let _: f32 = 0.3;
+ //~^ ERROR float literals must have an integer part
+ let _: f32 = 0.42f32;
+ //~^ ERROR float literals must have an integer part
+ let _: f64 = 0.5f64;
+ //~^ ERROR float literals must have an integer part
+}
diff --git a/tests/ui/suggestions/recover-invalid-float.rs b/tests/ui/suggestions/recover-invalid-float.rs
new file mode 100644
index 000000000..a5a7efe5e
--- /dev/null
+++ b/tests/ui/suggestions/recover-invalid-float.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+ let _: f32 = .3;
+ //~^ ERROR float literals must have an integer part
+ let _: f32 = .42f32;
+ //~^ ERROR float literals must have an integer part
+ let _: f64 = .5f64;
+ //~^ ERROR float literals must have an integer part
+}
diff --git a/tests/ui/suggestions/recover-invalid-float.stderr b/tests/ui/suggestions/recover-invalid-float.stderr
new file mode 100644
index 000000000..dd24746ea
--- /dev/null
+++ b/tests/ui/suggestions/recover-invalid-float.stderr
@@ -0,0 +1,20 @@
+error: float literals must have an integer part
+ --> $DIR/recover-invalid-float.rs:4:18
+ |
+LL | let _: f32 = .3;
+ | ^^ help: must have an integer part: `0.3`
+
+error: float literals must have an integer part
+ --> $DIR/recover-invalid-float.rs:6:18
+ |
+LL | let _: f32 = .42f32;
+ | ^^^^^^ help: must have an integer part: `0.42f32`
+
+error: float literals must have an integer part
+ --> $DIR/recover-invalid-float.rs:8:18
+ |
+LL | let _: f64 = .5f64;
+ | ^^^^^ help: must have an integer part: `0.5f64`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs
new file mode 100644
index 000000000..333dce390
--- /dev/null
+++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs
@@ -0,0 +1,10 @@
+fn main() {
+ let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
+ //~^ ERROR generic parameters without surrounding angle brackets
+ let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>();
+ //~^ ERROR generic parameters without surrounding angle brackets
+ let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>();
+ //~^ ERROR generic parameters without surrounding angle brackets
+ let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
+ //~^ ERROR generic parameters without surrounding angle brackets
+}
diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
new file mode 100644
index 000000000..618ccba0d
--- /dev/null
+++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
@@ -0,0 +1,46 @@
+error: generic parameters without surrounding angle brackets
+ --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:2:48
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
+ | ^^^^^^
+ |
+help: surround the type parameters with angle brackets
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+ | + +
+
+error: generic parameters without surrounding angle brackets
+ --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:4:48
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>();
+ | ^^^^^^
+ |
+help: surround the type parameters with angle brackets
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+ | + ~
+
+error: generic parameters without surrounding angle brackets
+ --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:6:48
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>();
+ | ^^^^^^
+ |
+help: surround the type parameters with angle brackets
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+ | + ~
+
+error: generic parameters without surrounding angle brackets
+ --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:8:48
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
+ | ^^^^^^
+ |
+help: surround the type parameters with angle brackets
+ |
+LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+ | + ~
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/suggestions/ref-pattern-binding.fixed b/tests/ui/suggestions/ref-pattern-binding.fixed
new file mode 100644
index 000000000..c36040eec
--- /dev/null
+++ b/tests/ui/suggestions/ref-pattern-binding.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+#![allow(unused)]
+
+struct S {
+ f: String,
+}
+
+fn main() {
+ let ref _moved @ ref _from = String::from("foo"); //~ ERROR
+ let ref _moved @ ref _from = String::from("foo"); //~ ERROR
+ let ref _moved @ ref _from = String::from("foo"); //~ ERROR
+ //~^ ERROR
+ let ref _moved @ ref _from = String::from("foo"); // ok
+ let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+ let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+ //~^ ERROR
+ let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok
+ let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+}
diff --git a/tests/ui/suggestions/ref-pattern-binding.rs b/tests/ui/suggestions/ref-pattern-binding.rs
new file mode 100644
index 000000000..c0d4feb03
--- /dev/null
+++ b/tests/ui/suggestions/ref-pattern-binding.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+#![allow(unused)]
+
+struct S {
+ f: String,
+}
+
+fn main() {
+ let _moved @ _from = String::from("foo"); //~ ERROR
+ let _moved @ ref _from = String::from("foo"); //~ ERROR
+ let ref _moved @ _from = String::from("foo"); //~ ERROR
+ //~^ ERROR
+ let ref _moved @ ref _from = String::from("foo"); // ok
+ let _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR
+ let ref _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR
+ //~^ ERROR
+ let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok
+ let _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR
+}
diff --git a/tests/ui/suggestions/ref-pattern-binding.stderr b/tests/ui/suggestions/ref-pattern-binding.stderr
new file mode 100644
index 000000000..10447ba70
--- /dev/null
+++ b/tests/ui/suggestions/ref-pattern-binding.stderr
@@ -0,0 +1,107 @@
+error: borrow of moved value
+ --> $DIR/ref-pattern-binding.rs:10:9
+ |
+LL | let _moved @ ref _from = String::from("foo");
+ | ------^^^---------
+ | | |
+ | | value borrowed here after move
+ | value moved into `_moved` here
+ | move occurs because `_moved` has type `String` which does not implement the `Copy` trait
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | let ref _moved @ ref _from = String::from("foo");
+ | +++
+
+error: cannot move out of value because it is borrowed
+ --> $DIR/ref-pattern-binding.rs:11:9
+ |
+LL | let ref _moved @ _from = String::from("foo");
+ | ----------^^^-----
+ | | |
+ | | value moved into `_from` here
+ | value borrowed, by `_moved`, here
+
+error: cannot move out of value because it is borrowed
+ --> $DIR/ref-pattern-binding.rs:15:9
+ |
+LL | let ref _moved @ S { f } = S { f: String::from("foo") };
+ | ----------^^^^^^^-^^
+ | | |
+ | | value moved into `f` here
+ | value borrowed, by `_moved`, here
+
+error: borrow of moved value
+ --> $DIR/ref-pattern-binding.rs:18:9
+ |
+LL | let _moved @ S { ref f } = S { f: String::from("foo") };
+ | ------^^^^^^^-----^^
+ | | |
+ | | value borrowed here after move
+ | value moved into `_moved` here
+ | move occurs because `_moved` has type `S` which does not implement the `Copy` trait
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | let ref _moved @ S { ref f } = S { f: String::from("foo") };
+ | +++
+
+error[E0382]: use of moved value
+ --> $DIR/ref-pattern-binding.rs:9:9
+ |
+LL | let _moved @ _from = String::from("foo");
+ | ^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait
+ | | |
+ | | value moved here
+ | value used here after move
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | let ref _moved @ ref _from = String::from("foo");
+ | +++ +++
+
+error[E0382]: borrow of moved value
+ --> $DIR/ref-pattern-binding.rs:11:9
+ |
+LL | let ref _moved @ _from = String::from("foo");
+ | ^^^^^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait
+ | | |
+ | | value moved here
+ | value borrowed here after move
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | let ref _moved @ ref _from = String::from("foo");
+ | +++
+
+error[E0382]: use of partially moved value
+ --> $DIR/ref-pattern-binding.rs:14:9
+ |
+LL | let _moved @ S { f } = S { f: String::from("foo") };
+ | ^^^^^^ - value partially moved here
+ | |
+ | value used here after partial move
+ |
+ = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | let ref _moved @ S { ref f } = S { f: String::from("foo") };
+ | +++ +++
+
+error[E0382]: borrow of partially moved value
+ --> $DIR/ref-pattern-binding.rs:15:9
+ |
+LL | let ref _moved @ S { f } = S { f: String::from("foo") };
+ | ^^^^^^^^^^ - value partially moved here
+ | |
+ | value borrowed here after partial move
+ |
+ = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | let ref _moved @ S { ref f } = S { f: String::from("foo") };
+ | +++
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs
new file mode 100644
index 000000000..56aed77c1
--- /dev/null
+++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs
@@ -0,0 +1,30 @@
+struct Wrapper<T>(T);
+
+fn foo<T>(foo: Wrapper<T>)
+//~^ ERROR the size for values of type `T` cannot be known at compilation time
+where
+ T
+ :
+ ?
+ Sized
+{
+ //
+}
+
+fn bar<T>(foo: Wrapper<T>)
+//~^ ERROR the size for values of type `T` cannot be known at compilation time
+where T: ?Sized
+{
+ //
+}
+
+fn qux<T>(foo: Wrapper<T>)
+//~^ ERROR the size for values of type `T` cannot be known at compilation time
+where
+ T: ?Sized
+{
+ //
+}
+
+
+fn main() {}
diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr
new file mode 100644
index 000000000..6071b10d3
--- /dev/null
+++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr
@@ -0,0 +1,83 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:3:16
+ |
+LL | fn foo<T>(foo: Wrapper<T>)
+ | - ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `Wrapper`
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16
+ |
+LL | struct Wrapper<T>(T);
+ | ^ required by this bound in `Wrapper`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16
+ |
+LL | struct Wrapper<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - where
+LL - T
+LL - :
+LL - ?
+LL - Sized
+ |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:14:16
+ |
+LL | fn bar<T>(foo: Wrapper<T>)
+ | - ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `Wrapper`
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16
+ |
+LL | struct Wrapper<T>(T);
+ | ^ required by this bound in `Wrapper`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16
+ |
+LL | struct Wrapper<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - where T: ?Sized
+ |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:21:16
+ |
+LL | fn qux<T>(foo: Wrapper<T>)
+ | - ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `Wrapper`
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16
+ |
+LL | struct Wrapper<T>(T);
+ | ^ required by this bound in `Wrapper`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16
+ |
+LL | struct Wrapper<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - where
+LL - T: ?Sized
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/remove-as_str.rs b/tests/ui/suggestions/remove-as_str.rs
new file mode 100644
index 000000000..289a784ba
--- /dev/null
+++ b/tests/ui/suggestions/remove-as_str.rs
@@ -0,0 +1,21 @@
+fn foo1(s: &str) {
+ s.as_str();
+ //~^ ERROR no method named `as_str` found
+}
+
+fn foo2<'a>(s: &'a str) {
+ s.as_str();
+ //~^ ERROR no method named `as_str` found
+}
+
+fn foo3(s: &mut str) {
+ s.as_str();
+ //~^ ERROR no method named `as_str` found
+}
+
+fn foo4(s: &&str) {
+ s.as_str();
+ //~^ ERROR no method named `as_str` found
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/remove-as_str.stderr b/tests/ui/suggestions/remove-as_str.stderr
new file mode 100644
index 000000000..534c49778
--- /dev/null
+++ b/tests/ui/suggestions/remove-as_str.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `as_str` found for reference `&str` in the current scope
+ --> $DIR/remove-as_str.rs:2:7
+ |
+LL | s.as_str();
+ | -^^^^^^-- help: remove this method call
+
+error[E0599]: no method named `as_str` found for reference `&'a str` in the current scope
+ --> $DIR/remove-as_str.rs:7:7
+ |
+LL | s.as_str();
+ | -^^^^^^-- help: remove this method call
+
+error[E0599]: no method named `as_str` found for mutable reference `&mut str` in the current scope
+ --> $DIR/remove-as_str.rs:12:7
+ |
+LL | s.as_str();
+ | -^^^^^^-- help: remove this method call
+
+error[E0599]: no method named `as_str` found for reference `&&str` in the current scope
+ --> $DIR/remove-as_str.rs:17:7
+ |
+LL | s.as_str();
+ | -^^^^^^-- help: remove this method call
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/restrict-type-argument.rs b/tests/ui/suggestions/restrict-type-argument.rs
new file mode 100644
index 000000000..c4ebfbe92
--- /dev/null
+++ b/tests/ui/suggestions/restrict-type-argument.rs
@@ -0,0 +1,31 @@
+fn is_send<T: Send>(val: T) {}
+
+fn use_impl_sync(val: impl Sync) {
+ is_send(val); //~ ERROR `impl Sync` cannot be sent between threads safely
+}
+
+fn use_where<S>(val: S) where S: Sync {
+ is_send(val); //~ ERROR `S` cannot be sent between threads safely
+}
+
+fn use_bound<S: Sync>(val: S) {
+ is_send(val); //~ ERROR `S` cannot be sent between threads safely
+}
+
+fn use_bound_2<
+ S // Make sure we can synthezise a correct suggestion span for this case
+ :
+ Sync
+>(val: S) {
+ is_send(val); //~ ERROR `S` cannot be sent between threads safely
+}
+
+fn use_bound_and_where<S: Sync>(val: S) where S: std::fmt::Debug {
+ is_send(val); //~ ERROR `S` cannot be sent between threads safely
+}
+
+fn use_unbound<S>(val: S) {
+ is_send(val); //~ ERROR `S` cannot be sent between threads safely
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/restrict-type-argument.stderr b/tests/ui/suggestions/restrict-type-argument.stderr
new file mode 100644
index 000000000..01c2de798
--- /dev/null
+++ b/tests/ui/suggestions/restrict-type-argument.stderr
@@ -0,0 +1,111 @@
+error[E0277]: `impl Sync` cannot be sent between threads safely
+ --> $DIR/restrict-type-argument.rs:4:13
+ |
+LL | is_send(val);
+ | ------- ^^^ `impl Sync` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `is_send`
+ --> $DIR/restrict-type-argument.rs:1:15
+ |
+LL | fn is_send<T: Send>(val: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider further restricting this bound
+ |
+LL | fn use_impl_sync(val: impl Sync + std::marker::Send) {
+ | +++++++++++++++++++
+
+error[E0277]: `S` cannot be sent between threads safely
+ --> $DIR/restrict-type-argument.rs:8:13
+ |
+LL | is_send(val);
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `is_send`
+ --> $DIR/restrict-type-argument.rs:1:15
+ |
+LL | fn is_send<T: Send>(val: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider further restricting this bound
+ |
+LL | fn use_where<S>(val: S) where S: Sync + std::marker::Send {
+ | +++++++++++++++++++
+
+error[E0277]: `S` cannot be sent between threads safely
+ --> $DIR/restrict-type-argument.rs:12:13
+ |
+LL | is_send(val);
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `is_send`
+ --> $DIR/restrict-type-argument.rs:1:15
+ |
+LL | fn is_send<T: Send>(val: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider further restricting this bound
+ |
+LL | fn use_bound<S: Sync + std::marker::Send>(val: S) {
+ | +++++++++++++++++++
+
+error[E0277]: `S` cannot be sent between threads safely
+ --> $DIR/restrict-type-argument.rs:20:13
+ |
+LL | is_send(val);
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `is_send`
+ --> $DIR/restrict-type-argument.rs:1:15
+ |
+LL | fn is_send<T: Send>(val: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider further restricting this bound
+ |
+LL | Sync + std::marker::Send
+ | +++++++++++++++++++
+
+error[E0277]: `S` cannot be sent between threads safely
+ --> $DIR/restrict-type-argument.rs:24:13
+ |
+LL | is_send(val);
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `is_send`
+ --> $DIR/restrict-type-argument.rs:1:15
+ |
+LL | fn is_send<T: Send>(val: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider further restricting this bound
+ |
+LL | fn use_bound_and_where<S: Sync + std::marker::Send>(val: S) where S: std::fmt::Debug {
+ | +++++++++++++++++++
+
+error[E0277]: `S` cannot be sent between threads safely
+ --> $DIR/restrict-type-argument.rs:28:13
+ |
+LL | is_send(val);
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `is_send`
+ --> $DIR/restrict-type-argument.rs:1:15
+ |
+LL | fn is_send<T: Send>(val: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider restricting type parameter `S`
+ |
+LL | fn use_unbound<S: std::marker::Send>(val: S) {
+ | +++++++++++++++++++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/restrict-type-not-param.rs b/tests/ui/suggestions/restrict-type-not-param.rs
new file mode 100644
index 000000000..60f5ba45c
--- /dev/null
+++ b/tests/ui/suggestions/restrict-type-not-param.rs
@@ -0,0 +1,12 @@
+use std::ops::Add;
+
+struct Wrapper<T>(T);
+
+trait Foo {}
+
+fn qux<T>(a: Wrapper<T>, b: T) -> T {
+ a + b
+ //~^ ERROR cannot add `T` to `Wrapper<T>`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/restrict-type-not-param.stderr b/tests/ui/suggestions/restrict-type-not-param.stderr
new file mode 100644
index 000000000..5434472ce
--- /dev/null
+++ b/tests/ui/suggestions/restrict-type-not-param.stderr
@@ -0,0 +1,23 @@
+error[E0369]: cannot add `T` to `Wrapper<T>`
+ --> $DIR/restrict-type-not-param.rs:8:7
+ |
+LL | a + b
+ | - ^ - T
+ | |
+ | Wrapper<T>
+ |
+note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
+ --> $DIR/restrict-type-not-param.rs:3:1
+ |
+LL | struct Wrapper<T>(T);
+ | ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
+note: the trait `Add` must be implemented
+ --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | fn qux<T>(a: Wrapper<T>, b: T) -> T where Wrapper<T>: Add<T, Output = T> {
+ | ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/suggestions/return-bindings-multi.rs b/tests/ui/suggestions/return-bindings-multi.rs
new file mode 100644
index 000000000..8c3bd641e
--- /dev/null
+++ b/tests/ui/suggestions/return-bindings-multi.rs
@@ -0,0 +1,9 @@
+fn a(i: i32) -> i32 {
+ //~^ ERROR mismatched types
+ let j = 2i32;
+}
+
+fn b(i: i32, j: i32) -> i32 {}
+//~^ ERROR mismatched types
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-bindings-multi.stderr b/tests/ui/suggestions/return-bindings-multi.stderr
new file mode 100644
index 000000000..738e3f2f4
--- /dev/null
+++ b/tests/ui/suggestions/return-bindings-multi.stderr
@@ -0,0 +1,34 @@
+error[E0308]: mismatched types
+ --> $DIR/return-bindings-multi.rs:1:17
+ |
+LL | fn a(i: i32) -> i32 {
+ | - ^^^ expected `i32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+note: consider returning one of these bindings
+ --> $DIR/return-bindings-multi.rs:1:6
+ |
+LL | fn a(i: i32) -> i32 {
+ | ^
+LL |
+LL | let j = 2i32;
+ | ^
+
+error[E0308]: mismatched types
+ --> $DIR/return-bindings-multi.rs:6:25
+ |
+LL | fn b(i: i32, j: i32) -> i32 {}
+ | - ^^^ expected `i32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+note: consider returning one of these bindings
+ --> $DIR/return-bindings-multi.rs:6:6
+ |
+LL | fn b(i: i32, j: i32) -> i32 {}
+ | ^ ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/return-bindings.rs b/tests/ui/suggestions/return-bindings.rs
new file mode 100644
index 000000000..fa1bad376
--- /dev/null
+++ b/tests/ui/suggestions/return-bindings.rs
@@ -0,0 +1,51 @@
+#![allow(unused)]
+
+fn a(i: i32) -> i32 {}
+//~^ ERROR mismatched types
+
+fn b(opt_str: Option<String>) {
+ let s: String = if let Some(s) = opt_str {
+ //~^ ERROR mismatched types
+ } else {
+ String::new()
+ };
+}
+
+fn c() -> Option<i32> {
+ //~^ ERROR mismatched types
+ let x = Some(1);
+}
+
+fn d(opt_str: Option<String>) {
+ let s: String = if let Some(s) = opt_str {
+ //~^ ERROR mismatched types
+ } else {
+ String::new()
+ };
+}
+
+fn d2(opt_str: Option<String>) {
+ let s = if let Some(s) = opt_str {
+ } else {
+ String::new()
+ //~^ ERROR `if` and `else` have incompatible types
+ };
+}
+
+fn e(opt_str: Option<String>) {
+ let s: String = match opt_str {
+ Some(s) => {}
+ //~^ ERROR mismatched types
+ None => String::new(),
+ };
+}
+
+fn e2(opt_str: Option<String>) {
+ let s = match opt_str {
+ Some(s) => {}
+ None => String::new(),
+ //~^ ERROR `match` arms have incompatible types
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-bindings.stderr b/tests/ui/suggestions/return-bindings.stderr
new file mode 100644
index 000000000..c14fb3367
--- /dev/null
+++ b/tests/ui/suggestions/return-bindings.stderr
@@ -0,0 +1,110 @@
+error[E0308]: mismatched types
+ --> $DIR/return-bindings.rs:3:17
+ |
+LL | fn a(i: i32) -> i32 {}
+ | - ^^^ expected `i32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+help: consider returning the local binding `i`
+ |
+LL | fn a(i: i32) -> i32 { i }
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/return-bindings.rs:7:46
+ |
+LL | let s: String = if let Some(s) = opt_str {
+ | ______________________________________________^
+LL | |
+LL | | } else {
+ | |_____^ expected struct `String`, found `()`
+ |
+help: consider returning the local binding `s`
+ |
+LL ~ let s: String = if let Some(s) = opt_str {
+LL + s
+LL ~
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/return-bindings.rs:14:11
+ |
+LL | fn c() -> Option<i32> {
+ | - ^^^^^^^^^^^ expected enum `Option`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected enum `Option<i32>`
+ found unit type `()`
+help: consider returning the local binding `x`
+ |
+LL ~ let x = Some(1);
+LL + x
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/return-bindings.rs:20:46
+ |
+LL | let s: String = if let Some(s) = opt_str {
+ | ______________________________________________^
+LL | |
+LL | | } else {
+ | |_____^ expected struct `String`, found `()`
+ |
+help: consider returning the local binding `s`
+ |
+LL ~ let s: String = if let Some(s) = opt_str {
+LL + s
+LL ~
+ |
+
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/return-bindings.rs:30:9
+ |
+LL | let s = if let Some(s) = opt_str {
+ | ______________________________________-
+LL | | } else {
+ | |_____- expected because of this
+LL | String::new()
+ | ^^^^^^^^^^^^^ expected `()`, found struct `String`
+ |
+help: consider returning the local binding `s`
+ |
+LL ~ let s = if let Some(s) = opt_str {
+LL + s
+LL ~ } else {
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/return-bindings.rs:37:20
+ |
+LL | Some(s) => {}
+ | ^^ expected struct `String`, found `()`
+ |
+help: consider returning the local binding `s`
+ |
+LL | Some(s) => { s }
+ | +
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/return-bindings.rs:46:17
+ |
+LL | let s = match opt_str {
+ | _____________-
+LL | | Some(s) => {}
+ | | -- this is found to be of type `()`
+LL | | None => String::new(),
+ | | ^^^^^^^^^^^^^ expected `()`, found struct `String`
+LL | |
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+help: consider returning the local binding `s`
+ |
+LL | Some(s) => { s }
+ | +
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/return-closures.rs b/tests/ui/suggestions/return-closures.rs
new file mode 100644
index 000000000..86c7c1537
--- /dev/null
+++ b/tests/ui/suggestions/return-closures.rs
@@ -0,0 +1,13 @@
+fn foo() {
+ //~^ HELP try adding a return type
+ |x: &i32| 1i32
+ //~^ ERROR mismatched types
+}
+
+fn bar(i: impl Sized) {
+ //~^ HELP a return type might be missing here
+ || i
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr
new file mode 100644
index 000000000..8b856d8de
--- /dev/null
+++ b/tests/ui/suggestions/return-closures.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+ --> $DIR/return-closures.rs:3:5
+ |
+LL | fn foo() {
+ | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32`
+LL |
+LL | |x: &i32| 1i32
+ | ^^^^^^^^^^^^^^ expected `()`, found closure
+ |
+ = note: expected unit type `()`
+ found closure `[closure@$DIR/return-closures.rs:3:5: 3:14]`
+
+error[E0308]: mismatched types
+ --> $DIR/return-closures.rs:9:5
+ |
+LL | fn bar(i: impl Sized) {
+ | - help: a return type might be missing here: `-> _`
+LL |
+LL | || i
+ | ^^^^ expected `()`, found closure
+ |
+ = note: expected unit type `()`
+ found closure `[closure@$DIR/return-closures.rs:9:5: 9:7]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/return-cycle-2.rs b/tests/ui/suggestions/return-cycle-2.rs
new file mode 100644
index 000000000..d6d24be1b
--- /dev/null
+++ b/tests/ui/suggestions/return-cycle-2.rs
@@ -0,0 +1,14 @@
+use std::marker::PhantomData;
+
+struct Token<T>(PhantomData<T>);
+
+impl<T> Token<T> {
+ fn as_ref(_: i32, _: i32) -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with the correct return type
+ Token(PhantomData::<&T>)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-cycle-2.stderr b/tests/ui/suggestions/return-cycle-2.stderr
new file mode 100644
index 000000000..3a1a0f7f4
--- /dev/null
+++ b/tests/ui/suggestions/return-cycle-2.stderr
@@ -0,0 +1,12 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/return-cycle-2.rs:6:34
+ |
+LL | fn as_ref(_: i32, _: i32) -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with the correct return type: `Token<&'static T>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/suggestions/return-cycle.rs b/tests/ui/suggestions/return-cycle.rs
new file mode 100644
index 000000000..60b80e35a
--- /dev/null
+++ b/tests/ui/suggestions/return-cycle.rs
@@ -0,0 +1,14 @@
+use std::marker::PhantomData;
+
+struct Token<T>(PhantomData<T>);
+
+impl<T> Token<T> {
+ fn new() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with the correct return type
+ Token(PhantomData::<()>)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-cycle.stderr b/tests/ui/suggestions/return-cycle.stderr
new file mode 100644
index 000000000..63fa9e040
--- /dev/null
+++ b/tests/ui/suggestions/return-cycle.stderr
@@ -0,0 +1,12 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/return-cycle.rs:6:17
+ |
+LL | fn new() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with the correct return type: `Token<()>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/suggestions/return-elided-lifetime.rs b/tests/ui/suggestions/return-elided-lifetime.rs
new file mode 100644
index 000000000..012d5492a
--- /dev/null
+++ b/tests/ui/suggestions/return-elided-lifetime.rs
@@ -0,0 +1,32 @@
+/* Checks all four scenarios possible in report_elision_failure() of
+ * rustc_resolve::late::lifetimes::LifetimeContext related to returning
+ * borrowed values, in various configurations.
+ */
+
+fn f1() -> &i32 { loop {} }
+//~^ ERROR missing lifetime specifier [E0106]
+fn f1_() -> (&i32, &i32) { loop {} }
+//~^ ERROR missing lifetime specifiers [E0106]
+
+fn f2(a: i32, b: i32) -> &i32 { loop {} }
+//~^ ERROR missing lifetime specifier [E0106]
+fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} }
+//~^ ERROR missing lifetime specifiers [E0106]
+
+struct S<'a, 'b> { a: &'a i32, b: &'b i32 }
+fn f3(s: &S) -> &i32 { loop {} }
+//~^ ERROR missing lifetime specifier [E0106]
+fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} }
+//~^ ERROR missing lifetime specifiers [E0106]
+
+fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} }
+//~^ ERROR missing lifetime specifier [E0106]
+fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} }
+//~^ ERROR missing lifetime specifiers [E0106]
+
+fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} }
+//~^ ERROR missing lifetime specifier [E0106]
+fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} }
+//~^ ERROR missing lifetime specifiers [E0106]
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-elided-lifetime.stderr b/tests/ui/suggestions/return-elided-lifetime.stderr
new file mode 100644
index 000000000..273d95bc7
--- /dev/null
+++ b/tests/ui/suggestions/return-elided-lifetime.stderr
@@ -0,0 +1,143 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-elided-lifetime.rs:6:12
+ |
+LL | fn f1() -> &i32 { loop {} }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn f1() -> &'static i32 { loop {} }
+ | +++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/return-elided-lifetime.rs:8:14
+ |
+LL | fn f1_() -> (&i32, &i32) { loop {} }
+ | ^ ^ expected named lifetime parameter
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn f1_() -> (&'static i32, &'static i32) { loop {} }
+ | +++++++ +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-elided-lifetime.rs:11:26
+ |
+LL | fn f2(a: i32, b: i32) -> &i32 { loop {} }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn f2(a: i32, b: i32) -> &'static i32 { loop {} }
+ | +++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/return-elided-lifetime.rs:13:28
+ |
+LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} }
+ | ^ ^ expected named lifetime parameter
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn f2_(a: i32, b: i32) -> (&'static i32, &'static i32) { loop {} }
+ | +++++++ +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-elided-lifetime.rs:17:17
+ |
+LL | fn f3(s: &S) -> &i32 { loop {} }
+ | -- ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `s`'s 3 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f3<'a>(s: &'a S<'a, 'a>) -> &'a i32 { loop {} }
+ | ++++ ++ ++++++++ ++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/return-elided-lifetime.rs:19:26
+ |
+LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} }
+ | -- -- ^ ^ expected named lifetime parameter
+ | |
+ | 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 one of `s`'s 3 lifetimes or one of `t`'s 3 lifetimes
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f3_<'a>(s: &'a S<'a, 'a>, t: &'a S<'a, 'a>) -> (&'a i32, &'a i32) { loop {} }
+ | ++++ ++ ++++++++ ++ ++++++++ ++ ++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-elided-lifetime.rs:22:42
+ |
+LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} }
+ | ------- ------- ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+note: these named lifetimes are available to use
+ --> $DIR/return-elided-lifetime.rs:22:7
+ |
+LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} }
+ | ^^ ^^
+help: consider using one of the available lifetimes here
+ |
+LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} }
+ | +++++++++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/return-elided-lifetime.rs:24:44
+ |
+LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} }
+ | ------- ------- ^ ^ expected named lifetime parameter
+ | |
+ | expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+note: these named lifetimes are available to use
+ --> $DIR/return-elided-lifetime.rs:24:8
+ |
+LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} }
+ | ^^ ^^
+help: consider using one of the available lifetimes here
+ |
+LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &'lifetime i32) { loop {} }
+ | +++++++++ +++++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-elided-lifetime.rs:27:35
+ |
+LL | fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} }
+ | ------- ---- ^ 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 `a` or `b`
+help: consider using the `'a` lifetime
+ |
+LL | fn f5<'a>(a: &'a i32, b: &i32) -> &'a i32 { loop {} }
+ | ++
+
+error[E0106]: missing lifetime specifiers
+ --> $DIR/return-elided-lifetime.rs:29:37
+ |
+LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} }
+ | ------- ---- ^ ^ expected named lifetime parameter
+ | |
+ | 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 `a` or `b`
+help: consider using the `'a` lifetime
+ |
+LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&'a i32, &'a i32) { loop {} }
+ | ++ ++
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/return-without-lifetime.rs b/tests/ui/suggestions/return-without-lifetime.rs
new file mode 100644
index 000000000..9bfce11be
--- /dev/null
+++ b/tests/ui/suggestions/return-without-lifetime.rs
@@ -0,0 +1,10 @@
+struct Thing<'a>(&'a ());
+struct Foo<'a>(&usize);
+//~^ ERROR missing lifetime specifier
+
+fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
+//~^ ERROR missing lifetime specifier
+fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
+//~^ ERROR missing lifetime specifier
+
+fn main() {}
diff --git a/tests/ui/suggestions/return-without-lifetime.stderr b/tests/ui/suggestions/return-without-lifetime.stderr
new file mode 100644
index 000000000..5028e8d62
--- /dev/null
+++ b/tests/ui/suggestions/return-without-lifetime.stderr
@@ -0,0 +1,38 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-without-lifetime.rs:2:16
+ |
+LL | struct Foo<'a>(&usize);
+ | ^ expected named lifetime parameter
+ |
+help: consider using the `'a` lifetime
+ |
+LL | struct Foo<'a>(&'a usize);
+ | ++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-without-lifetime.rs:5:34
+ |
+LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
+ | --------- ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
+help: consider using the `'a` lifetime
+ |
+LL | fn func1<'a>(_arg: &'a Thing) -> &'a () { unimplemented!() }
+ | ++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/return-without-lifetime.rs:7:35
+ |
+LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
+ | ---------- ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
+help: consider using the `'a` lifetime
+ |
+LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() }
+ | ++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/shadowed-lplace-method-2.rs b/tests/ui/suggestions/shadowed-lplace-method-2.rs
new file mode 100644
index 000000000..dab99fbac
--- /dev/null
+++ b/tests/ui/suggestions/shadowed-lplace-method-2.rs
@@ -0,0 +1,23 @@
+#![allow(unused)]
+
+struct X {
+ x: (),
+}
+pub trait A {
+ fn foo(&mut self, _: usize) -> &mut ();
+}
+impl A for X {
+ fn foo(&mut self, _: usize) -> &mut () {
+ &mut self.x
+ }
+}
+impl X {
+ fn foo(&mut self, _: usize) -> &mut Self {
+ self
+ }
+}
+
+fn main() {
+ let mut x = X { x: () };
+ *x.foo(0) = (); //~ ERROR E0308
+}
diff --git a/tests/ui/suggestions/shadowed-lplace-method-2.stderr b/tests/ui/suggestions/shadowed-lplace-method-2.stderr
new file mode 100644
index 000000000..94eef15f3
--- /dev/null
+++ b/tests/ui/suggestions/shadowed-lplace-method-2.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+ --> $DIR/shadowed-lplace-method-2.rs:22:17
+ |
+LL | *x.foo(0) = ();
+ | --------- ^^ expected struct `X`, found `()`
+ | |
+ | expected due to the type of this binding
+ |
+note: the `foo` call is resolved to the method in `X`, shadowing the method of the same name on trait `A`
+ --> $DIR/shadowed-lplace-method-2.rs:22:8
+ |
+LL | *x.foo(0) = ();
+ | ^^^ refers to `X::foo`
+help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
+ |
+LL | *<_ as A>::foo(&mut x, 0) = ();
+ | ++++++++++++++++++ ~
+help: try wrapping the expression in `X`
+ |
+LL | *x.foo(0) = X { x: () };
+ | ++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/shadowed-lplace-method.fixed b/tests/ui/suggestions/shadowed-lplace-method.fixed
new file mode 100644
index 000000000..740ac77ee
--- /dev/null
+++ b/tests/ui/suggestions/shadowed-lplace-method.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused_imports)]
+use std::borrow::BorrowMut;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+fn main() {
+ let rc = Rc::new(RefCell::new(true));
+ *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308
+}
diff --git a/tests/ui/suggestions/shadowed-lplace-method.rs b/tests/ui/suggestions/shadowed-lplace-method.rs
new file mode 100644
index 000000000..6bf12879e
--- /dev/null
+++ b/tests/ui/suggestions/shadowed-lplace-method.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused_imports)]
+use std::borrow::BorrowMut;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+fn main() {
+ let rc = Rc::new(RefCell::new(true));
+ *rc.borrow_mut() = false; //~ ERROR E0308
+}
diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr
new file mode 100644
index 000000000..91d0d1200
--- /dev/null
+++ b/tests/ui/suggestions/shadowed-lplace-method.stderr
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+ --> $DIR/shadowed-lplace-method.rs:9:24
+ |
+LL | *rc.borrow_mut() = false;
+ | ---------------- ^^^^^ expected struct `Rc`, found `bool`
+ | |
+ | expected due to the type of this binding
+ |
+ = note: expected struct `Rc<RefCell<bool>>`
+ found type `bool`
+note: the `borrow_mut` call is resolved to the method in `std::borrow::BorrowMut`, shadowing the method of the same name on the inherent impl for `std::cell::RefCell<T>`
+ --> $DIR/shadowed-lplace-method.rs:9:9
+ |
+LL | use std::borrow::BorrowMut;
+ | ---------------------- `std::borrow::BorrowMut` imported here
+...
+LL | *rc.borrow_mut() = false;
+ | ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut`
+help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
+ |
+LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false;
+ | +++++++++++++++++++++++++++++++++++++ ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/slice-issue-87994.rs b/tests/ui/suggestions/slice-issue-87994.rs
new file mode 100644
index 000000000..ecb7f54ea
--- /dev/null
+++ b/tests/ui/suggestions/slice-issue-87994.rs
@@ -0,0 +1,16 @@
+fn main() {
+ let v = vec![1i32, 2, 3];
+ for _ in v[1..] {
+ //~^ ERROR [i32]` is not an iterator [E0277]
+ //~^^ ERROR known at compilation time
+ }
+ struct K {
+ n: i32,
+ }
+ let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }];
+ for i2 in v2[1..] {
+ //~^ ERROR [K]` is not an iterator [E0277]
+ //~^^ ERROR known at compilation time
+ i2.n = 2;
+ }
+}
diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr
new file mode 100644
index 000000000..84ecd749b
--- /dev/null
+++ b/tests/ui/suggestions/slice-issue-87994.stderr
@@ -0,0 +1,63 @@
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+ --> $DIR/slice-issue-87994.rs:3:12
+ |
+LL | for _ in v[1..] {
+ | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
+ |
+ = note: the trait bound `[i32]: IntoIterator` is not satisfied
+ = note: required for `[i32]` to implement `IntoIterator`
+help: consider borrowing here
+ |
+LL | for _ in &v[1..] {
+ | +
+LL | for _ in &mut v[1..] {
+ | ++++
+
+error[E0277]: `[i32]` is not an iterator
+ --> $DIR/slice-issue-87994.rs:3:12
+ |
+LL | for _ in v[1..] {
+ | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
+ |
+ = note: the trait bound `[i32]: IntoIterator` is not satisfied
+ = note: required for `[i32]` to implement `IntoIterator`
+help: consider borrowing here
+ |
+LL | for _ in &v[1..] {
+ | +
+LL | for _ in &mut v[1..] {
+ | ++++
+
+error[E0277]: the size for values of type `[K]` cannot be known at compilation time
+ --> $DIR/slice-issue-87994.rs:11:13
+ |
+LL | for i2 in v2[1..] {
+ | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
+ |
+ = note: the trait bound `[K]: IntoIterator` is not satisfied
+ = note: required for `[K]` to implement `IntoIterator`
+help: consider borrowing here
+ |
+LL | for i2 in &v2[1..] {
+ | +
+LL | for i2 in &mut v2[1..] {
+ | ++++
+
+error[E0277]: `[K]` is not an iterator
+ --> $DIR/slice-issue-87994.rs:11:13
+ |
+LL | for i2 in v2[1..] {
+ | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
+ |
+ = note: the trait bound `[K]: IntoIterator` is not satisfied
+ = note: required for `[K]` to implement `IntoIterator`
+help: consider borrowing here
+ |
+LL | for i2 in &v2[1..] {
+ | +
+LL | for i2 in &mut v2[1..] {
+ | ++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.rs b/tests/ui/suggestions/struct-field-type-including-single-colon.rs
new file mode 100644
index 000000000..b7ad6d996
--- /dev/null
+++ b/tests/ui/suggestions/struct-field-type-including-single-colon.rs
@@ -0,0 +1,20 @@
+mod foo {
+ struct A;
+ mod bar {
+ struct B;
+ }
+}
+
+struct Foo {
+ a: foo:A,
+ //~^ ERROR found single colon in a struct field type path
+ //~| expected `,`, or `}`, found `:`
+}
+
+struct Bar {
+ b: foo::bar:B,
+ //~^ ERROR found single colon in a struct field type path
+ //~| expected `,`, or `}`, found `:`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
new file mode 100644
index 000000000..4dd514480
--- /dev/null
+++ b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
@@ -0,0 +1,40 @@
+error: found single colon in a struct field type path
+ --> $DIR/struct-field-type-including-single-colon.rs:9:11
+ |
+LL | a: foo:A,
+ | ^
+ |
+help: write a path separator here
+ |
+LL | a: foo::A,
+ | ~~
+
+error: expected `,`, or `}`, found `:`
+ --> $DIR/struct-field-type-including-single-colon.rs:9:11
+ |
+LL | struct Foo {
+ | --- while parsing this struct
+LL | a: foo:A,
+ | ^
+
+error: found single colon in a struct field type path
+ --> $DIR/struct-field-type-including-single-colon.rs:15:16
+ |
+LL | b: foo::bar:B,
+ | ^
+ |
+help: write a path separator here
+ |
+LL | b: foo::bar::B,
+ | ~~
+
+error: expected `,`, or `}`, found `:`
+ --> $DIR/struct-field-type-including-single-colon.rs:15:16
+ |
+LL | struct Bar {
+ | --- while parsing this struct
+LL | b: foo::bar:B,
+ | ^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/suggestions/struct-initializer-comma.fixed b/tests/ui/suggestions/struct-initializer-comma.fixed
new file mode 100644
index 000000000..6a4ee39b1
--- /dev/null
+++ b/tests/ui/suggestions/struct-initializer-comma.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+
+pub struct Foo {
+ pub first: bool,
+ pub second: u8,
+}
+
+fn main() {
+ let _ = Foo {
+ //~^ ERROR missing field
+ first: true,
+ second: 25
+ //~^ ERROR expected one of
+ };
+}
diff --git a/tests/ui/suggestions/struct-initializer-comma.rs b/tests/ui/suggestions/struct-initializer-comma.rs
new file mode 100644
index 000000000..c137f0594
--- /dev/null
+++ b/tests/ui/suggestions/struct-initializer-comma.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+
+pub struct Foo {
+ pub first: bool,
+ pub second: u8,
+}
+
+fn main() {
+ let _ = Foo {
+ //~^ ERROR missing field
+ first: true
+ second: 25
+ //~^ ERROR expected one of
+ };
+}
diff --git a/tests/ui/suggestions/struct-initializer-comma.stderr b/tests/ui/suggestions/struct-initializer-comma.stderr
new file mode 100644
index 000000000..5eff43f32
--- /dev/null
+++ b/tests/ui/suggestions/struct-initializer-comma.stderr
@@ -0,0 +1,23 @@
+error: expected one of `,`, `.`, `?`, `}`, or an operator, found `second`
+ --> $DIR/struct-initializer-comma.rs:12:9
+ |
+LL | let _ = Foo {
+ | --- while parsing this struct
+LL |
+LL | first: true
+ | -
+ | |
+ | expected one of `,`, `.`, `?`, `}`, or an operator
+ | help: try adding a comma: `,`
+LL | second: 25
+ | ^^^^^^ unexpected token
+
+error[E0063]: missing field `second` in initializer of `Foo`
+ --> $DIR/struct-initializer-comma.rs:9:13
+ |
+LL | let _ = Foo {
+ | ^^^ missing `second`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/tests/ui/suggestions/sugg-else-for-closure.fixed b/tests/ui/suggestions/sugg-else-for-closure.fixed
new file mode 100644
index 000000000..cf381d9da
--- /dev/null
+++ b/tests/ui/suggestions/sugg-else-for-closure.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+ let x = "com.example.app";
+ let y: Option<&str> = None;
+ let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/sugg-else-for-closure.rs b/tests/ui/suggestions/sugg-else-for-closure.rs
new file mode 100644
index 000000000..540ced91f
--- /dev/null
+++ b/tests/ui/suggestions/sugg-else-for-closure.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+ let x = "com.example.app";
+ let y: Option<&str> = None;
+ let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr
new file mode 100644
index 000000000..7f05832bc
--- /dev/null
+++ b/tests/ui/suggestions/sugg-else-for-closure.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+ --> $DIR/sugg-else-for-closure.rs:6:26
+ |
+LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+ | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found closure
+ | |
+ | arguments to this method are incorrect
+ |
+ = note: expected reference `&str`
+ found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
+help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed
+ --> $DIR/sugg-else-for-closure.rs:6:14
+ |
+LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+ | ^^^^^^^^^^^^-------------------------------^
+ | |
+ | this argument influences the return type of `unwrap_or`
+note: associated function defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+help: try calling `unwrap_or_else` instead
+ |
+LL | let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs
new file mode 100644
index 000000000..21ab6830b
--- /dev/null
+++ b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs
@@ -0,0 +1,10 @@
+// When build the suggesttion take in consideration the `:?`
+// https://github.com/rust-lang/rust/issues/100648
+#![deny(warnings)]
+
+fn main () {
+ println!("hello {:?}", world = "world");
+ //~^ ERROR named argument `world` is not used by name
+ //~| HELP use the named argument by name to avoid ambiguity
+ //~| SUGGESTION world
+}
diff --git a/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr
new file mode 100644
index 000000000..850f69f2d
--- /dev/null
+++ b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr
@@ -0,0 +1,21 @@
+error: named argument `world` is not used by name
+ --> $DIR/sugg_with_positional_args_and_debug_fmt.rs:6:28
+ |
+LL | println!("hello {:?}", world = "world");
+ | ---- ^^^^^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `world` by position
+ |
+note: the lint level is defined here
+ --> $DIR/sugg_with_positional_args_and_debug_fmt.rs:3:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(named_arguments_used_positionally)]` implied by `#[deny(warnings)]`
+help: use the named argument by name to avoid ambiguity
+ |
+LL | println!("hello {world:?}", world = "world");
+ | +++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/suggest-add-self.rs b/tests/ui/suggestions/suggest-add-self.rs
new file mode 100644
index 000000000..40692c8df
--- /dev/null
+++ b/tests/ui/suggestions/suggest-add-self.rs
@@ -0,0 +1,15 @@
+struct X(i32);
+
+impl X {
+ pub(crate) fn f() {
+ self.0
+ //~^ ERROR expected value, found module `self`
+ }
+
+ pub fn g() {
+ self.0
+ //~^ ERROR expected value, found module `self`
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-add-self.stderr b/tests/ui/suggestions/suggest-add-self.stderr
new file mode 100644
index 000000000..a5e8f93de
--- /dev/null
+++ b/tests/ui/suggestions/suggest-add-self.stderr
@@ -0,0 +1,29 @@
+error[E0424]: expected value, found module `self`
+ --> $DIR/suggest-add-self.rs:5:9
+ |
+LL | pub(crate) fn f() {
+ | - this function doesn't have a `self` parameter
+LL | self.0
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+ |
+help: add a `self` receiver parameter to make the associated `fn` a method
+ |
+LL | pub(crate) fn f(&self) {
+ | +++++
+
+error[E0424]: expected value, found module `self`
+ --> $DIR/suggest-add-self.rs:10:9
+ |
+LL | pub fn g() {
+ | - this function doesn't have a `self` parameter
+LL | self.0
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+ |
+help: add a `self` receiver parameter to make the associated `fn` a method
+ |
+LL | pub fn g(&self) {
+ | +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0424`.
diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed
new file mode 100644
index 000000000..e9b8a9caa
--- /dev/null
+++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn foo(foo: &mut usize) {
+ todo!()
+}
+
+fn bar(bar: &usize) {
+ todo!()
+}
+
+fn main() {
+ foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
+ bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied
+}
diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs
new file mode 100644
index 000000000..5fae21ccc
--- /dev/null
+++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn foo(foo: &mut usize) {
+ todo!()
+}
+
+fn bar(bar: &usize) {
+ todo!()
+}
+
+fn main() {
+ foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
+ bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied
+}
diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr
new file mode 100644
index 000000000..125a8b44f
--- /dev/null
+++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `&mut usize: Default` is not satisfied
+ --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9
+ |
+LL | foo(Default::default());
+ | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize`
+ |
+help: consider mutably borrowing here
+ |
+LL | foo(&mut Default::default());
+ | ++++
+
+error[E0277]: the trait bound `&usize: Default` is not satisfied
+ --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9
+ |
+LL | bar(Default::default());
+ | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize`
+ |
+help: consider borrowing here
+ |
+LL | bar(&Default::default());
+ | +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed
new file mode 100644
index 000000000..8d96cf590
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+ fn test() -> i32 { 1 }
+}
+
+fn main() {
+ let x = Box::new(Foo(1i32));
+ Foo::<i32>::test();
+ //~^ ERROR no method named `test` found for struct `Box<Foo<i32>>` in the current scope
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.rs b/tests/ui/suggestions/suggest-assoc-fn-call-deref.rs
new file mode 100644
index 000000000..186901f75
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+ fn test() -> i32 { 1 }
+}
+
+fn main() {
+ let x = Box::new(Foo(1i32));
+ x.test();
+ //~^ ERROR no method named `test` found for struct `Box<Foo<i32>>` in the current scope
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr
new file mode 100644
index 000000000..00fb96f03
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `test` found for struct `Box<Foo<i32>>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-deref.rs:13:7
+ |
+LL | x.test();
+ | --^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `Foo::<i32>::test()`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `Foo<T>`
+ --> $DIR/suggest-assoc-fn-call-deref.rs:8:5
+ |
+LL | fn test() -> i32 { 1 }
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs
new file mode 100644
index 000000000..a39b8711d
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs
@@ -0,0 +1,11 @@
+struct GenericAssocMethod<T>(T);
+
+impl<T> GenericAssocMethod<T> {
+ fn default_hello() {}
+}
+
+fn main() {
+ let x = GenericAssocMethod(33);
+ x.default_hello();
+ //~^ ERROR no method named `default_hello` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr
new file mode 100644
index 000000000..c247e73b3
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr
@@ -0,0 +1,22 @@
+error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:9:7
+ |
+LL | struct GenericAssocMethod<T>(T);
+ | ---------------------------- method `default_hello` not found for this struct
+...
+LL | x.default_hello();
+ | --^^^^^^^^^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello()`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:4:5
+ |
+LL | fn default_hello() {}
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
new file mode 100644
index 000000000..f738a1f21
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
@@ -0,0 +1,13 @@
+use std::cell::RefCell;
+
+struct HasAssocMethod;
+
+impl HasAssocMethod {
+ fn hello() {}
+}
+fn main() {
+ let shared_state = RefCell::new(HasAssocMethod);
+ let state = shared_state.borrow_mut();
+ state.hello();
+ //~^ ERROR no method named `hello` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
new file mode 100644
index 000000000..7c9f0b6c2
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMethod>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
+ |
+LL | state.hello();
+ | ------^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `HasAssocMethod::hello()`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `HasAssocMethod`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:6:5
+ |
+LL | fn hello() {}
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed
new file mode 100644
index 000000000..02dd0715c
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed
@@ -0,0 +1,26 @@
+// run-rustfix
+
+struct GenericAssocMethod<T>(T);
+
+impl<T> GenericAssocMethod<T> {
+ fn default_hello() {}
+ fn self_ty_hello(_: Self) {}
+ fn self_ty_ref_hello(_: &Self) {}
+}
+
+fn main() {
+ // Test for inferred types
+ let x = GenericAssocMethod(33);
+ GenericAssocMethod::<_>::self_ty_ref_hello(&x);
+ //~^ ERROR no method named `self_ty_ref_hello` found
+ GenericAssocMethod::<_>::self_ty_hello(x);
+ //~^ ERROR no method named `self_ty_hello` found
+ // Test for known types
+ let y = GenericAssocMethod(33i32);
+ GenericAssocMethod::<i32>::default_hello();
+ //~^ ERROR no method named `default_hello` found
+ GenericAssocMethod::<i32>::self_ty_ref_hello(&y);
+ //~^ ERROR no method named `self_ty_ref_hello` found
+ GenericAssocMethod::<i32>::self_ty_hello(y);
+ //~^ ERROR no method named `self_ty_hello` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
new file mode 100644
index 000000000..1d0ca8e78
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
@@ -0,0 +1,26 @@
+// run-rustfix
+
+struct GenericAssocMethod<T>(T);
+
+impl<T> GenericAssocMethod<T> {
+ fn default_hello() {}
+ fn self_ty_hello(_: Self) {}
+ fn self_ty_ref_hello(_: &Self) {}
+}
+
+fn main() {
+ // Test for inferred types
+ let x = GenericAssocMethod(33);
+ x.self_ty_ref_hello();
+ //~^ ERROR no method named `self_ty_ref_hello` found
+ x.self_ty_hello();
+ //~^ ERROR no method named `self_ty_hello` found
+ // Test for known types
+ let y = GenericAssocMethod(33i32);
+ y.default_hello();
+ //~^ ERROR no method named `default_hello` found
+ y.self_ty_ref_hello();
+ //~^ ERROR no method named `self_ty_ref_hello` found
+ y.self_ty_hello();
+ //~^ ERROR no method named `self_ty_hello` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
new file mode 100644
index 000000000..92b03fc77
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
@@ -0,0 +1,98 @@
+error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7
+ |
+LL | struct GenericAssocMethod<T>(T);
+ | ---------------------------- method `self_ty_ref_hello` not found for this struct
+...
+LL | x.self_ty_ref_hello();
+ | --^^^^^^^^^^^^^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello(&x)`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5
+ |
+LL | fn self_ty_ref_hello(_: &Self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7
+ |
+LL | struct GenericAssocMethod<T>(T);
+ | ---------------------------- method `self_ty_hello` not found for this struct
+...
+LL | x.self_ty_hello();
+ | --^^^^^^^^^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello(x)`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5
+ |
+LL | fn self_ty_hello(_: Self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7
+ |
+LL | struct GenericAssocMethod<T>(T);
+ | ---------------------------- method `default_hello` not found for this struct
+...
+LL | y.default_hello();
+ | --^^^^^^^^^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello()`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5
+ |
+LL | fn default_hello() {}
+ | ^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<i32>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7
+ |
+LL | struct GenericAssocMethod<T>(T);
+ | ---------------------------- method `self_ty_ref_hello` not found for this struct
+...
+LL | y.self_ty_ref_hello();
+ | --^^^^^^^^^^^^^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_ref_hello(&y)`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5
+ |
+LL | fn self_ty_ref_hello(_: &Self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<i32>` in the current scope
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7
+ |
+LL | struct GenericAssocMethod<T>(T);
+ | ---------------------------- method `self_ty_hello` not found for this struct
+...
+LL | y.self_ty_hello();
+ | --^^^^^^^^^^^^^--
+ | | |
+ | | this is an associated function, not a method
+ | help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_hello(y)`
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+ --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5
+ |
+LL | fn self_ty_hello(_: Self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs
new file mode 100644
index 000000000..14fef1b52
--- /dev/null
+++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs
@@ -0,0 +1,58 @@
+// Ensure that the compiler include the blanklet implementation suggestion
+// when inside a `impl` statement are used two local traits.
+//
+// edition:2021
+use std::fmt;
+
+trait LocalTraitOne { }
+
+trait LocalTraitTwo { }
+
+trait GenericTrait<T> {}
+
+impl LocalTraitTwo for LocalTraitOne {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne`
+
+impl fmt::Display for LocalTraitOne {
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ todo!();
+ }
+}
+
+impl fmt::Display for LocalTraitTwo + Send {
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ todo!();
+ }
+}
+
+impl LocalTraitOne for fmt::Display {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display`
+
+
+impl LocalTraitOne for fmt::Display + Send {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send`
+
+
+impl<E> GenericTrait<E> for LocalTraitOne {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP alternatively use a blanket implementation to implement `GenericTrait<E>` for all types that also implement `LocalTraitOne`
+
+trait GenericTraitTwo<T> {}
+
+impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo<E>` for all types that also implement `GenericTrait<T>`
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr
new file mode 100644
index 000000000..398caa98b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr
@@ -0,0 +1,100 @@
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:13:24
+ |
+LL | impl LocalTraitTwo for LocalTraitOne {}
+ | ^^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl LocalTraitTwo for dyn LocalTraitOne {}
+ | +++
+help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne`
+ |
+LL | impl<T: LocalTraitOne> LocalTraitTwo for T {}
+ | ++++++++++++++++++ ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:18:23
+ |
+LL | impl fmt::Display for LocalTraitOne {
+ | ^^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl fmt::Display for dyn LocalTraitOne {
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:26:23
+ |
+LL | impl fmt::Display for LocalTraitTwo + Send {
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl fmt::Display for dyn LocalTraitTwo + Send {
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:34:24
+ |
+LL | impl LocalTraitOne for fmt::Display {}
+ | ^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl LocalTraitOne for dyn fmt::Display {}
+ | +++
+help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display`
+ |
+LL | impl<T: fmt::Display> LocalTraitOne for T {}
+ | +++++++++++++++++ ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:40:24
+ |
+LL | impl LocalTraitOne for fmt::Display + Send {}
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl LocalTraitOne for dyn fmt::Display + Send {}
+ | +++
+help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send`
+ |
+LL | impl<T: fmt::Display + Send> LocalTraitOne for T {}
+ | ++++++++++++++++++++++++ ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:46:29
+ |
+LL | impl<E> GenericTrait<E> for LocalTraitOne {}
+ | ^^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl<E> GenericTrait<E> for dyn LocalTraitOne {}
+ | +++
+help: alternatively use a blanket implementation to implement `GenericTrait<E>` for all types that also implement `LocalTraitOne`
+ |
+LL | impl<E, T: LocalTraitOne> GenericTrait<E> for T {}
+ | ++++++++++++++++++ ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-blanket-impl-local-trait.rs:53:35
+ |
+LL | impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {}
+ | ^^^^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl<T, E> GenericTraitTwo<E> for dyn GenericTrait<T> {}
+ | +++
+help: alternatively use a blanket implementation to implement `GenericTraitTwo<E>` for all types that also implement `GenericTrait<T>`
+ |
+LL | impl<T, E, U: GenericTrait<T>> GenericTraitTwo<E> for U {}
+ | ++++++++++++++++++++ ~
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0782`.
diff --git a/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs b/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs
new file mode 100644
index 000000000..120fc5383
--- /dev/null
+++ b/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs
@@ -0,0 +1,16 @@
+use std::ffi::{OsStr, OsString};
+use std::path::Path;
+
+fn check(p: &dyn AsRef<Path>) {
+ let m = std::fs::metadata(&p);
+ println!("{:?}", &m);
+}
+
+fn main() {
+ let s: OsString = ".".into();
+ let s: &OsStr = &s;
+ check(s);
+ //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+ //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]`
+ //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
+}
diff --git a/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr
new file mode 100644
index 000000000..6ce9bfd9d
--- /dev/null
+++ b/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/suggest-borrow-to-dyn-object.rs:12:11
+ |
+LL | check(s);
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]`
+ = note: required because it appears within the type `OsStr`
+ = note: required for the cast from `OsStr` to the object type `dyn AsRef<Path>`
+help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
+ |
+LL | check(&s);
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-box.fixed b/tests/ui/suggestions/suggest-box.fixed
new file mode 100644
index 000000000..3de02cd0b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-box.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+ let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types
+ Err(())?;
+ Ok(())
+ });
+}
diff --git a/tests/ui/suggestions/suggest-box.rs b/tests/ui/suggestions/suggest-box.rs
new file mode 100644
index 000000000..e680a61db
--- /dev/null
+++ b/tests/ui/suggestions/suggest-box.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+ let _x: Box<dyn Fn() -> Result<(), ()>> = || { //~ ERROR mismatched types
+ Err(())?;
+ Ok(())
+ };
+}
diff --git a/tests/ui/suggestions/suggest-box.stderr b/tests/ui/suggestions/suggest-box.stderr
new file mode 100644
index 000000000..2bdaa4e97
--- /dev/null
+++ b/tests/ui/suggestions/suggest-box.stderr
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-box.rs:4:47
+ |
+LL | let _x: Box<dyn Fn() -> Result<(), ()>> = || {
+ | _____________-------------------------------___^
+ | | |
+ | | expected due to this
+LL | | Err(())?;
+LL | | Ok(())
+LL | | };
+ | |_____^ expected struct `Box`, found closure
+ |
+ = note: expected struct `Box<dyn Fn() -> Result<(), ()>>`
+ found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]`
+ = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+ |
+LL ~ let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| {
+LL | Err(())?;
+LL | Ok(())
+LL ~ });
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/suggest-change-mut.rs b/tests/ui/suggestions/suggest-change-mut.rs
new file mode 100644
index 000000000..47dc7c343
--- /dev/null
+++ b/tests/ui/suggestions/suggest-change-mut.rs
@@ -0,0 +1,21 @@
+#![allow(warnings)]
+
+use std::io::{BufRead, BufReader, Read, Write};
+
+fn issue_81421<T: Read + Write>(mut stream: T) { //~ HELP consider introducing a `where` clause
+ let initial_message = format!("Hello world");
+ let mut buffer: Vec<u8> = Vec::new();
+ let bytes_written = stream.write_all(initial_message.as_bytes());
+ let flush = stream.flush();
+
+ loop {
+ let mut stream_reader = BufReader::new(&stream);
+ //~^ ERROR the trait bound `&T: std::io::Read` is not satisfied [E0277]
+ //~| HELP consider removing the leading `&`-reference
+ //~| HELP consider changing this borrow's mutability
+ stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
+ //~^ ERROR the method `read_until` exists for struct `BufReader<&T>`,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-change-mut.stderr b/tests/ui/suggestions/suggest-change-mut.stderr
new file mode 100644
index 000000000..d194afeaf
--- /dev/null
+++ b/tests/ui/suggestions/suggest-change-mut.stderr
@@ -0,0 +1,41 @@
+error[E0277]: the trait bound `&T: std::io::Read` is not satisfied
+ --> $DIR/suggest-change-mut.rs:12:48
+ |
+LL | let mut stream_reader = BufReader::new(&stream);
+ | -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `BufReader::<R>::new`
+ --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
+help: consider removing the leading `&`-reference
+ |
+LL - let mut stream_reader = BufReader::new(&stream);
+LL + let mut stream_reader = BufReader::new(stream);
+ |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | fn issue_81421<T: Read + Write>(mut stream: T) where &T: std::io::Read {
+ | +++++++++++++++++++++++
+help: consider changing this borrow's mutability
+ |
+LL | let mut stream_reader = BufReader::new(&mut stream);
+ | ~~~~
+
+error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its trait bounds were not satisfied
+ --> $DIR/suggest-change-mut.rs:16:23
+ |
+LL | stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
+ | ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds
+ --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
+ |
+ = note: doesn't satisfy `BufReader<&T>: BufRead`
+ |
+ = note: the following trait bounds were not satisfied:
+ `&T: std::io::Read`
+ which is required by `BufReader<&T>: BufRead`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-closure-return-type-1.rs b/tests/ui/suggestions/suggest-closure-return-type-1.rs
new file mode 100644
index 000000000..8bb421903
--- /dev/null
+++ b/tests/ui/suggestions/suggest-closure-return-type-1.rs
@@ -0,0 +1,7 @@
+fn unbound_drop(_: impl Sized) {}
+
+fn main() {
+ unbound_drop(|| -> _ { [] });
+ //~^ ERROR type annotations needed for `[_; 0]`
+ //~| HELP try giving this closure an explicit return type
+}
diff --git a/tests/ui/suggestions/suggest-closure-return-type-1.stderr b/tests/ui/suggestions/suggest-closure-return-type-1.stderr
new file mode 100644
index 000000000..f4c2eb7ff
--- /dev/null
+++ b/tests/ui/suggestions/suggest-closure-return-type-1.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `[_; 0]`
+ --> $DIR/suggest-closure-return-type-1.rs:4:18
+ |
+LL | unbound_drop(|| -> _ { [] });
+ | ^^^^^^^ -- type must be known at this point
+ |
+help: try giving this closure an explicit return type
+ |
+LL | unbound_drop(|| -> [_; 0] { [] });
+ | ~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/suggestions/suggest-closure-return-type-2.rs b/tests/ui/suggestions/suggest-closure-return-type-2.rs
new file mode 100644
index 000000000..25ed1882e
--- /dev/null
+++ b/tests/ui/suggestions/suggest-closure-return-type-2.rs
@@ -0,0 +1,7 @@
+fn unbound_drop(_: impl Sized) {}
+
+fn main() {
+ unbound_drop(|| { [] })
+ //~^ ERROR type annotations needed for `[_; 0]`
+ //~| HELP try giving this closure an explicit return type
+}
diff --git a/tests/ui/suggestions/suggest-closure-return-type-2.stderr b/tests/ui/suggestions/suggest-closure-return-type-2.stderr
new file mode 100644
index 000000000..88bf26304
--- /dev/null
+++ b/tests/ui/suggestions/suggest-closure-return-type-2.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `[_; 0]`
+ --> $DIR/suggest-closure-return-type-2.rs:4:18
+ |
+LL | unbound_drop(|| { [] })
+ | ^^ -- type must be known at this point
+ |
+help: try giving this closure an explicit return type
+ |
+LL | unbound_drop(|| -> [_; 0] { [] })
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/suggestions/suggest-closure-return-type-3.rs b/tests/ui/suggestions/suggest-closure-return-type-3.rs
new file mode 100644
index 000000000..3de6c55cf
--- /dev/null
+++ b/tests/ui/suggestions/suggest-closure-return-type-3.rs
@@ -0,0 +1,7 @@
+fn unbound_drop(_: impl Sized) {}
+
+fn main() {
+ unbound_drop(|| []);
+ //~^ ERROR type annotations needed for `[_; 0]`
+ //~| HELP try giving this closure an explicit return type
+}
diff --git a/tests/ui/suggestions/suggest-closure-return-type-3.stderr b/tests/ui/suggestions/suggest-closure-return-type-3.stderr
new file mode 100644
index 000000000..bc4107528
--- /dev/null
+++ b/tests/ui/suggestions/suggest-closure-return-type-3.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `[_; 0]`
+ --> $DIR/suggest-closure-return-type-3.rs:4:18
+ |
+LL | unbound_drop(|| []);
+ | ^^ -- type must be known at this point
+ |
+help: try giving this closure an explicit return type
+ |
+LL | unbound_drop(|| -> [_; 0] { [] });
+ | +++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.fixed b/tests/ui/suggestions/suggest-dereferencing-index.fixed
new file mode 100644
index 000000000..dd4ae4eb1
--- /dev/null
+++ b/tests/ui/suggestions/suggest-dereferencing-index.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn main() {
+ let i: &usize = &1;
+ let one_item_please: i32 = [1, 2, 3][*i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize`
+}
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.rs b/tests/ui/suggestions/suggest-dereferencing-index.rs
new file mode 100644
index 000000000..82ebacc49
--- /dev/null
+++ b/tests/ui/suggestions/suggest-dereferencing-index.rs
@@ -0,0 +1,7 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn main() {
+ let i: &usize = &1;
+ let one_item_please: i32 = [1, 2, 3][i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize`
+}
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
new file mode 100644
index 000000000..147dc9234
--- /dev/null
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the type `[{integer}]` cannot be indexed by `&usize`
+ --> $DIR/suggest-dereferencing-index.rs:6:42
+ |
+LL | let one_item_please: i32 = [1, 2, 3][i];
+ | ^ slice indices are of type `usize` or ranges of `usize`
+ |
+ = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
+ = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+ = note: required for `[{integer}]` to implement `Index<&usize>`
+help: dereference this index
+ |
+LL | let one_item_please: i32 = [1, 2, 3][*i];
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs
new file mode 100644
index 000000000..1dfc07866
--- /dev/null
+++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs
@@ -0,0 +1,10 @@
+mod option {
+ pub enum O<T> {
+ Some(T),
+ None,
+ }
+}
+
+fn main() {
+ let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr
new file mode 100644
index 000000000..9b6dba7e9
--- /dev/null
+++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28
+ |
+LL | let _: option::O<()> = ();
+ | ------------- ^^ expected enum `O`, found `()`
+ | |
+ | expected due to this
+ |
+ = note: expected enum `O<()>`
+ found unit type `()`
+help: try wrapping the expression in `option::O::Some`
+ |
+LL | let _: option::O<()> = option::O::Some(());
+ | ++++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs
new file mode 100644
index 000000000..a62669d5b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs
@@ -0,0 +1,23 @@
+trait Trait {}
+
+struct A;
+struct B;
+struct C;
+
+impl Trait for &A {}
+impl Trait for &mut A {}
+
+impl Trait for &B {}
+
+impl Trait for &mut C {}
+
+fn foo<X: Trait>(_: X) {}
+
+fn main() {
+ let a = A;
+ let b = B;
+ let c = C;
+ foo(a); //~ ERROR the trait bound `A: Trait` is not satisfied
+ foo(b); //~ ERROR the trait bound `B: Trait` is not satisfied
+ foo(c); //~ ERROR the trait bound `C: Trait` is not satisfied
+}
diff --git a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr
new file mode 100644
index 000000000..f2eb651ea
--- /dev/null
+++ b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr
@@ -0,0 +1,59 @@
+error[E0277]: the trait bound `A: Trait` is not satisfied
+ --> $DIR/suggest-imm-mut-trait-implementations.rs:20:9
+ |
+LL | foo(a);
+ | --- ^ the trait `Trait` is not implemented for `A`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11
+ |
+LL | fn foo<X: Trait>(_: X) {}
+ | ^^^^^ required by this bound in `foo`
+help: consider borrowing here
+ |
+LL | foo(&a);
+ | +
+LL | foo(&mut a);
+ | ++++
+
+error[E0277]: the trait bound `B: Trait` is not satisfied
+ --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9
+ |
+LL | foo(b);
+ | --- ^ the trait `Trait` is not implemented for `B`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11
+ |
+LL | fn foo<X: Trait>(_: X) {}
+ | ^^^^^ required by this bound in `foo`
+help: consider borrowing here
+ |
+LL | foo(&b);
+ | +
+
+error[E0277]: the trait bound `C: Trait` is not satisfied
+ --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9
+ |
+LL | foo(c);
+ | --- ^ the trait `Trait` is not implemented for `C`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11
+ |
+LL | fn foo<X: Trait>(_: X) {}
+ | ^^^^^ required by this bound in `foo`
+help: consider mutably borrowing here
+ |
+LL | foo(&mut c);
+ | ++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed b/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed
new file mode 100644
index 000000000..589ee1a47
--- /dev/null
+++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+fn foo(d: impl Debug + 'static) {
+//~^ HELP consider adding an explicit lifetime bound...
+ bar(d);
+//~^ ERROR the parameter type `impl Debug` may not live long enough
+//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
+}
+
+fn bar(d: impl Debug + 'static) {
+ println!("{:?}", d)
+}
+
+fn main() {
+ foo("hi");
+}
diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.rs b/tests/ui/suggestions/suggest-impl-trait-lifetime.rs
new file mode 100644
index 000000000..9a87129fb
--- /dev/null
+++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+fn foo(d: impl Debug) {
+//~^ HELP consider adding an explicit lifetime bound...
+ bar(d);
+//~^ ERROR the parameter type `impl Debug` may not live long enough
+//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
+}
+
+fn bar(d: impl Debug + 'static) {
+ println!("{:?}", d)
+}
+
+fn main() {
+ foo("hi");
+}
diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr
new file mode 100644
index 000000000..cf912f4aa
--- /dev/null
+++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0310]: the parameter type `impl Debug` may not live long enough
+ --> $DIR/suggest-impl-trait-lifetime.rs:7:5
+ |
+LL | bar(d);
+ | ^^^^^^ ...so that the type `impl Debug` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn foo(d: impl Debug + 'static) {
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/suggestions/suggest-labels.rs b/tests/ui/suggestions/suggest-labels.rs
new file mode 100644
index 000000000..159f45855
--- /dev/null
+++ b/tests/ui/suggestions/suggest-labels.rs
@@ -0,0 +1,16 @@
+#[allow(unreachable_code, unused_labels)]
+fn main() {
+ 'foo: loop {
+ break 'fo; //~ ERROR use of undeclared label
+ }
+
+ 'bar: loop {
+ continue 'bor; //~ ERROR use of undeclared label
+ }
+
+ 'longlabel: loop {
+ 'longlabel1: loop {
+ break 'longlable; //~ ERROR use of undeclared label
+ }
+ }
+}
diff --git a/tests/ui/suggestions/suggest-labels.stderr b/tests/ui/suggestions/suggest-labels.stderr
new file mode 100644
index 000000000..aac6515b5
--- /dev/null
+++ b/tests/ui/suggestions/suggest-labels.stderr
@@ -0,0 +1,36 @@
+error[E0426]: use of undeclared label `'fo`
+ --> $DIR/suggest-labels.rs:4:15
+ |
+LL | 'foo: loop {
+ | ---- a label with a similar name is reachable
+LL | break 'fo;
+ | ^^^
+ | |
+ | undeclared label `'fo`
+ | help: try using similarly named label: `'foo`
+
+error[E0426]: use of undeclared label `'bor`
+ --> $DIR/suggest-labels.rs:8:18
+ |
+LL | 'bar: loop {
+ | ---- a label with a similar name is reachable
+LL | continue 'bor;
+ | ^^^^
+ | |
+ | undeclared label `'bor`
+ | help: try using similarly named label: `'bar`
+
+error[E0426]: use of undeclared label `'longlable`
+ --> $DIR/suggest-labels.rs:13:19
+ |
+LL | 'longlabel1: loop {
+ | ----------- a label with a similar name is reachable
+LL | break 'longlable;
+ | ^^^^^^^^^^
+ | |
+ | undeclared label `'longlable`
+ | help: try using similarly named label: `'longlabel1`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0426`.
diff --git a/tests/ui/suggestions/suggest-let-for-assignment.fixed b/tests/ui/suggestions/suggest-let-for-assignment.fixed
new file mode 100644
index 000000000..3a25e25ee
--- /dev/null
+++ b/tests/ui/suggestions/suggest-let-for-assignment.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+fn main() {
+ let demo = 1; //~ ERROR cannot find value `demo` in this scope
+ dbg!(demo); //~ ERROR cannot find value `demo` in this scope
+
+ let x = "x"; //~ ERROR cannot find value `x` in this scope
+ println!("x: {}", x); //~ ERROR cannot find value `x` in this scope
+
+ if x == "x" {
+ //~^ ERROR cannot find value `x` in this scope
+ println!("x is 1");
+ }
+
+ let y = 1 + 2; //~ ERROR cannot find value `y` in this scope
+ println!("y: {}", y); //~ ERROR cannot find value `y` in this scope
+}
diff --git a/tests/ui/suggestions/suggest-let-for-assignment.rs b/tests/ui/suggestions/suggest-let-for-assignment.rs
new file mode 100644
index 000000000..67705fe06
--- /dev/null
+++ b/tests/ui/suggestions/suggest-let-for-assignment.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+fn main() {
+ demo = 1; //~ ERROR cannot find value `demo` in this scope
+ dbg!(demo); //~ ERROR cannot find value `demo` in this scope
+
+ x = "x"; //~ ERROR cannot find value `x` in this scope
+ println!("x: {}", x); //~ ERROR cannot find value `x` in this scope
+
+ if x == "x" {
+ //~^ ERROR cannot find value `x` in this scope
+ println!("x is 1");
+ }
+
+ y = 1 + 2; //~ ERROR cannot find value `y` in this scope
+ println!("y: {}", y); //~ ERROR cannot find value `y` in this scope
+}
diff --git a/tests/ui/suggestions/suggest-let-for-assignment.stderr b/tests/ui/suggestions/suggest-let-for-assignment.stderr
new file mode 100644
index 000000000..3f6a3da4b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-let-for-assignment.stderr
@@ -0,0 +1,60 @@
+error[E0425]: cannot find value `demo` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:4:5
+ |
+LL | demo = 1;
+ | ^^^^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let demo = 1;
+ | +++
+
+error[E0425]: cannot find value `demo` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:5:10
+ |
+LL | dbg!(demo);
+ | ^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:7:5
+ |
+LL | x = "x";
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = "x";
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:8:23
+ |
+LL | println!("x: {}", x);
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:10:8
+ |
+LL | if x == "x" {
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:15:5
+ |
+LL | y = 1 + 2;
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let y = 1 + 2;
+ | +++
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:16:23
+ |
+LL | println!("y: {}", y);
+ | ^ not found in this scope
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/suggest-methods.rs b/tests/ui/suggestions/suggest-methods.rs
new file mode 100644
index 000000000..f40b9ed99
--- /dev/null
+++ b/tests/ui/suggestions/suggest-methods.rs
@@ -0,0 +1,30 @@
+struct Foo;
+
+impl Foo {
+ fn bar(self) {}
+ fn baz(&self, x: f64) {}
+}
+
+trait FooT {
+ fn bag(&self);
+}
+
+impl FooT for Foo {
+ fn bag(&self) {}
+}
+
+fn main() {
+ let f = Foo;
+ f.bat(1.0); //~ ERROR no method named
+
+ let s = "foo".to_string();
+ let _ = s.is_emtpy(); //~ ERROR no method named
+
+ // Generates a warning for `count_zeros()`. `count_ones()` is also a close
+ // match, but the former is closer.
+ let _ = 63u32.count_eos(); //~ ERROR no method named
+
+ // Does not generate a warning
+ let _ = 63u32.count_o(); //~ ERROR no method named
+
+}
diff --git a/tests/ui/suggestions/suggest-methods.stderr b/tests/ui/suggestions/suggest-methods.stderr
new file mode 100644
index 000000000..03cb9c779
--- /dev/null
+++ b/tests/ui/suggestions/suggest-methods.stderr
@@ -0,0 +1,30 @@
+error[E0599]: no method named `bat` found for struct `Foo` in the current scope
+ --> $DIR/suggest-methods.rs:18:7
+ |
+LL | struct Foo;
+ | ---------- method `bat` not found for this struct
+...
+LL | f.bat(1.0);
+ | ^^^ help: there is a method with a similar name: `bar`
+
+error[E0599]: no method named `is_emtpy` found for struct `String` in the current scope
+ --> $DIR/suggest-methods.rs:21:15
+ |
+LL | let _ = s.is_emtpy();
+ | ^^^^^^^^ help: there is a method with a similar name: `is_empty`
+
+error[E0599]: no method named `count_eos` found for type `u32` in the current scope
+ --> $DIR/suggest-methods.rs:25:19
+ |
+LL | let _ = 63u32.count_eos();
+ | ^^^^^^^^^ help: there is a method with a similar name: `count_zeros`
+
+error[E0599]: no method named `count_o` found for type `u32` in the current scope
+ --> $DIR/suggest-methods.rs:28:19
+ |
+LL | let _ = 63u32.count_o();
+ | ^^^^^^^ help: there is a method with a similar name: `count_ones`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-move-lifetimes.rs b/tests/ui/suggestions/suggest-move-lifetimes.rs
new file mode 100644
index 000000000..6b26f1214
--- /dev/null
+++ b/tests/ui/suggestions/suggest-move-lifetimes.rs
@@ -0,0 +1,21 @@
+struct A<T, 'a> { //~ ERROR lifetime parameters must be declared
+ t: &'a T,
+}
+
+struct B<T, 'a, U> { //~ ERROR lifetime parameters must be declared
+ t: &'a T,
+ u: U,
+}
+
+struct C<T, U, 'a> { //~ ERROR lifetime parameters must be declared
+ t: &'a T,
+ u: U,
+}
+
+struct D<T, U, 'a, 'b, V, 'c> { //~ ERROR lifetime parameters must be declared
+ t: &'a T,
+ u: &'b U,
+ v: &'c V,
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-move-lifetimes.stderr b/tests/ui/suggestions/suggest-move-lifetimes.stderr
new file mode 100644
index 000000000..b1a49447d
--- /dev/null
+++ b/tests/ui/suggestions/suggest-move-lifetimes.stderr
@@ -0,0 +1,26 @@
+error: lifetime parameters must be declared prior to type and const parameters
+ --> $DIR/suggest-move-lifetimes.rs:1:13
+ |
+LL | struct A<T, 'a> {
+ | ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>`
+
+error: lifetime parameters must be declared prior to type and const parameters
+ --> $DIR/suggest-move-lifetimes.rs:5:13
+ |
+LL | struct B<T, 'a, U> {
+ | ----^^---- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>`
+
+error: lifetime parameters must be declared prior to type and const parameters
+ --> $DIR/suggest-move-lifetimes.rs:10:16
+ |
+LL | struct C<T, U, 'a> {
+ | -------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>`
+
+error: lifetime parameters must be declared prior to type and const parameters
+ --> $DIR/suggest-move-lifetimes.rs:15:16
+ |
+LL | struct D<T, U, 'a, 'b, V, 'c> {
+ | -------^^--^^-----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, 'c, T, U, V>`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/suggestions/suggest-move-types.rs b/tests/ui/suggestions/suggest-move-types.rs
new file mode 100644
index 000000000..27930626a
--- /dev/null
+++ b/tests/ui/suggestions/suggest-move-types.rs
@@ -0,0 +1,91 @@
+#![allow(warnings)]
+
+// This test verifies that the suggestion to move types before associated type bindings
+// is correct.
+
+trait One<T> {
+ type A;
+}
+
+trait OneWithLifetime<'a, T> {
+ type A;
+}
+
+trait Three<T, U, V> {
+ type A;
+ type B;
+ type C;
+}
+
+trait ThreeWithLifetime<'a, 'b, 'c, T, U, V> {
+ type A;
+ type B;
+ type C;
+}
+
+struct A<T, M: One<A=(), T>> {
+//~^ ERROR generic arguments must come before the first constraint
+ m: M,
+ t: T,
+}
+
+
+struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+//~^ ERROR generic arguments must come before the first constraint
+//~^^ ERROR type provided when a lifetime was expected
+ m: M,
+ t: &'a T,
+}
+
+struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
+//~^ ERROR generic arguments must come before the first constraint
+ m: M,
+ t: T,
+ u: U,
+ v: V,
+}
+
+struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+//~^ ERROR generic arguments must come before the first constraint
+//~^^ ERROR type provided when a lifetime was expected
+ m: M,
+ t: &'a T,
+ u: &'b U,
+ v: &'c V,
+}
+
+struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
+//~^ ERROR generic arguments must come before the first constraint
+ m: M,
+ t: T,
+ u: U,
+ v: V,
+}
+
+struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+//~^ ERROR generic arguments must come before the first constraint
+//~^^ ERROR lifetime provided when a type was expected
+ m: M,
+ t: &'a T,
+ u: &'b U,
+ v: &'c V,
+}
+
+struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
+//~^ ERROR generic arguments must come before the first constraint
+ m: M,
+ t: T,
+ u: U,
+ v: V,
+}
+
+struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+//~^ ERROR generic arguments must come before the first constraint
+//~^^ ERROR lifetime provided when a type was expected
+ m: M,
+ t: &'a T,
+ u: &'b U,
+ v: &'c V,
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-move-types.stderr b/tests/ui/suggestions/suggest-move-types.stderr
new file mode 100644
index 000000000..b222e8142
--- /dev/null
+++ b/tests/ui/suggestions/suggest-move-types.stderr
@@ -0,0 +1,137 @@
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:26:26
+ |
+LL | struct A<T, M: One<A=(), T>> {
+ | ---- ^ generic argument
+ | |
+ | constraint
+ |
+help: move the constraint after the generic argument
+ |
+LL | struct A<T, M: One<T, A = ()>> {
+ | ~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:33:43
+ |
+LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+ | ---- ^ ^^ generic arguments
+ | |
+ | constraint
+ |
+help: move the constraint after the generic arguments
+ |
+LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A = ()>> {
+ | ~~~~~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:40:46
+ |
+LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
+ | ---- ---- ---- ^ ^ ^ generic arguments
+ | |
+ | constraints
+ |
+help: move the constraints after the generic arguments
+ |
+LL | struct B<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:48:71
+ |
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+ | ---- ---- ---- ^ ^ ^ ^^ ^^ ^^ generic arguments
+ | |
+ | constraints
+ |
+help: move the constraints after the generic arguments
+ |
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:57:28
+ |
+LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
+ | ^ ---- ---- ---- ^ ^ generic arguments
+ | |
+ | constraints
+ |
+help: move the constraints after the generic arguments
+ |
+LL | struct C<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:65:53
+ |
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+ | ^ ^^ ---- ---- ---- ^ ^^ ^ ^^ generic arguments
+ | |
+ | constraints
+ |
+help: move the constraints after the generic arguments
+ |
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:74:28
+ |
+LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
+ | ^ ---- ---- ^ ---- ^ generic arguments
+ | |
+ | constraints
+ |
+help: move the constraints after the generic arguments
+ |
+LL | struct D<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: generic arguments must come before the first constraint
+ --> $DIR/suggest-move-types.rs:82:53
+ |
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+ | ^ ^^ ---- ---- ^ ^^ ---- ^ ^^ generic arguments
+ | |
+ | constraints
+ |
+help: move the constraints after the generic arguments
+ |
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0747]: type provided when a lifetime was expected
+ --> $DIR/suggest-move-types.rs:33:43
+ |
+LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
+ | ^
+
+error[E0747]: type provided when a lifetime was expected
+ --> $DIR/suggest-move-types.rs:48:71
+ |
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
+ | ^
+
+error[E0747]: lifetime provided when a type was expected
+ --> $DIR/suggest-move-types.rs:65:56
+ |
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
+ | ^^
+ |
+ = note: lifetime arguments must be provided before type arguments
+ = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, 'c, T, U, V>`
+
+error[E0747]: lifetime provided when a type was expected
+ --> $DIR/suggest-move-types.rs:82:56
+ |
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
+ | ^^
+ |
+ = note: lifetime arguments must be provided before type arguments
+ = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, 'c, T, U, V>`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
new file mode 100644
index 000000000..b69bad988
--- /dev/null
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
@@ -0,0 +1,21 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/82081
+
+use std::collections::HashMap;
+
+struct Test {
+ v: u32,
+}
+
+fn main() {
+ let mut map = HashMap::new();
+ map.insert("a", Test { v: 0 });
+
+ for (_k, mut v) in map.iter_mut() {
+ //~^ HELP use mutable method
+ //~| NOTE this iterator yields `&` references
+ v.v += 1;
+ //~^ ERROR cannot assign to `v.v`
+ //~| NOTE `v` is a `&` reference
+ }
+}
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
new file mode 100644
index 000000000..9284410df
--- /dev/null
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
@@ -0,0 +1,21 @@
+// run-rustfix
+// https://github.com/rust-lang/rust/issues/82081
+
+use std::collections::HashMap;
+
+struct Test {
+ v: u32,
+}
+
+fn main() {
+ let mut map = HashMap::new();
+ map.insert("a", Test { v: 0 });
+
+ for (_k, mut v) in map.iter() {
+ //~^ HELP use mutable method
+ //~| NOTE this iterator yields `&` references
+ v.v += 1;
+ //~^ ERROR cannot assign to `v.v`
+ //~| NOTE `v` is a `&` reference
+ }
+}
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
new file mode 100644
index 000000000..74433daa6
--- /dev/null
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to `v.v`, which is behind a `&` reference
+ --> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9
+ |
+LL | for (_k, mut v) in map.iter() {
+ | ----------
+ | | |
+ | | help: use mutable method: `iter_mut()`
+ | this iterator yields `&` references
+...
+LL | v.v += 1;
+ | ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop.rs b/tests/ui/suggestions/suggest-mut-method-for-loop.rs
new file mode 100644
index 000000000..756768bce
--- /dev/null
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop.rs
@@ -0,0 +1,17 @@
+use std::collections::HashMap;
+struct X(usize);
+struct Y {
+ v: u32
+}
+
+fn main() {
+ let mut buzz = HashMap::new();
+ buzz.insert("a", Y { v: 0 });
+
+ for mut t in buzz.values() {
+ //~^ HELP
+ //~| SUGGESTION values_mut()
+ t.v += 1;
+ //~^ ERROR cannot assign
+ }
+}
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop.stderr
new file mode 100644
index 000000000..3eb9e1031
--- /dev/null
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to `t.v`, which is behind a `&` reference
+ --> $DIR/suggest-mut-method-for-loop.rs:14:9
+ |
+LL | for mut t in buzz.values() {
+ | -------------
+ | | |
+ | | help: use mutable method: `values_mut()`
+ | this iterator yields `&` references
+...
+LL | t.v += 1;
+ | ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.rs b/tests/ui/suggestions/suggest-on-bare-closure-call.rs
new file mode 100644
index 000000000..496c305bc
--- /dev/null
+++ b/tests/ui/suggestions/suggest-on-bare-closure-call.rs
@@ -0,0 +1,11 @@
+// edition:2021
+
+#![feature(async_closure)]
+
+fn main() {
+ let _ = ||{}();
+ //~^ ERROR expected function, found `()`
+
+ let _ = async ||{}();
+ //~^ ERROR expected function, found `()`
+}
diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
new file mode 100644
index 000000000..e65a6eb49
--- /dev/null
+++ b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
@@ -0,0 +1,29 @@
+error[E0618]: expected function, found `()`
+ --> $DIR/suggest-on-bare-closure-call.rs:6:15
+ |
+LL | let _ = ||{}();
+ | ^^--
+ | |
+ | call expression requires function
+ |
+help: if you meant to create this closure and immediately call it, surround the closure with parentheses
+ |
+LL | let _ = (||{})();
+ | + +
+
+error[E0618]: expected function, found `()`
+ --> $DIR/suggest-on-bare-closure-call.rs:9:21
+ |
+LL | let _ = async ||{}();
+ | ^^--
+ | |
+ | call expression requires function
+ |
+help: if you meant to create this closure and immediately call it, surround the closure with parentheses
+ |
+LL | let _ = (async ||{})();
+ | + +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/tests/ui/suggestions/suggest-ref-macro.rs b/tests/ui/suggestions/suggest-ref-macro.rs
new file mode 100644
index 000000000..6f780f32a
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ref-macro.rs
@@ -0,0 +1,29 @@
+// run-check
+// aux-build:proc-macro-type-error.rs
+
+extern crate proc_macro_type_error;
+
+use proc_macro_type_error::hello;
+
+#[hello] //~ERROR mismatched types
+fn abc() {}
+
+fn x(_: &mut i32) {}
+
+macro_rules! bla {
+ () => {
+ x(123);
+ //~^ ERROR mismatched types
+ //~| SUGGESTION &mut 123
+ };
+ ($v:expr) => {
+ x($v)
+ }
+}
+
+fn main() {
+ bla!();
+ bla!(456);
+ //~^ ERROR mismatched types
+ //~| SUGGESTION &mut 456
+}
diff --git a/tests/ui/suggestions/suggest-ref-macro.stderr b/tests/ui/suggestions/suggest-ref-macro.stderr
new file mode 100644
index 000000000..17de49fbd
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ref-macro.stderr
@@ -0,0 +1,57 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-ref-macro.rs:8:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+ | |
+ | expected `&mut i32`, found integer
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/suggest-ref-macro.rs:8:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+ = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-ref-macro.rs:15:11
+ |
+LL | x(123);
+ | - ^^^
+ | | |
+ | | expected `&mut i32`, found integer
+ | | help: consider mutably borrowing here: `&mut 123`
+ | arguments to this function are incorrect
+...
+LL | bla!();
+ | ------ in this macro invocation
+ |
+note: function defined here
+ --> $DIR/suggest-ref-macro.rs:11:4
+ |
+LL | fn x(_: &mut i32) {}
+ | ^ -----------
+ = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-ref-macro.rs:26:10
+ |
+LL | x($v)
+ | - arguments to this function are incorrect
+...
+LL | bla!(456);
+ | ^^^
+ | |
+ | expected `&mut i32`, found integer
+ | help: consider mutably borrowing here: `&mut 456`
+ |
+note: function defined here
+ --> $DIR/suggest-ref-macro.rs:11:4
+ |
+LL | fn x(_: &mut i32) {}
+ | ^ -----------
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/suggest-ref-mut.rs b/tests/ui/suggestions/suggest-ref-mut.rs
new file mode 100644
index 000000000..d04113ffc
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ref-mut.rs
@@ -0,0 +1,30 @@
+struct X(usize);
+
+impl X {
+ fn zap(&self) {
+ //~^ HELP
+ //~| SUGGESTION &mut self
+ self.0 = 32;
+ //~^ ERROR
+ }
+}
+
+fn main() {
+ let ref foo = 16;
+ //~^ HELP
+ //~| SUGGESTION ref mut foo
+ *foo = 32;
+ //~^ ERROR
+ if let Some(ref bar) = Some(16) {
+ //~^ HELP
+ //~| SUGGESTION ref mut bar
+ *bar = 32;
+ //~^ ERROR
+ }
+ match 16 {
+ ref quo => { *quo = 32; },
+ //~^ ERROR
+ //~| HELP
+ //~| SUGGESTION ref mut quo
+ }
+}
diff --git a/tests/ui/suggestions/suggest-ref-mut.stderr b/tests/ui/suggestions/suggest-ref-mut.stderr
new file mode 100644
index 000000000..7973759bf
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ref-mut.stderr
@@ -0,0 +1,47 @@
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
+ --> $DIR/suggest-ref-mut.rs:7:9
+ |
+LL | self.0 = 32;
+ | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this to be a mutable reference
+ |
+LL | fn zap(&mut self) {
+ | ~~~~~~~~~
+
+error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
+ --> $DIR/suggest-ref-mut.rs:16:5
+ |
+LL | *foo = 32;
+ | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this to be a mutable reference
+ |
+LL | let ref mut foo = 16;
+ | ~~~~~~~~~~~
+
+error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
+ --> $DIR/suggest-ref-mut.rs:21:9
+ |
+LL | *bar = 32;
+ | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this to be a mutable reference
+ |
+LL | if let Some(ref mut bar) = Some(16) {
+ | ~~~~~~~~~~~
+
+error[E0594]: cannot assign to `*quo`, which is behind a `&` reference
+ --> $DIR/suggest-ref-mut.rs:25:22
+ |
+LL | ref quo => { *quo = 32; },
+ | ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this to be a mutable reference
+ |
+LL | ref mut quo => { *quo = 32; },
+ | ~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-1.fixed b/tests/ui/suggestions/suggest-remove-refs-1.fixed
new file mode 100644
index 000000000..a39e0fbd1
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-1.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, _) in v.iter().enumerate() {
+ //~^ ERROR `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ println!("{}", i);
+ }
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-1.rs b/tests/ui/suggestions/suggest-remove-refs-1.rs
new file mode 100644
index 000000000..6f767f2c1
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-1.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, _) in &v.iter().enumerate() {
+ //~^ ERROR `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ println!("{}", i);
+ }
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr
new file mode 100644
index 000000000..387770535
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ --> $DIR/suggest-remove-refs-1.rs:6:19
+ |
+LL | for (i, _) in &v.iter().enumerate() {
+ | ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing the leading `&`-reference
+ |
+LL - for (i, _) in &v.iter().enumerate() {
+LL + for (i, _) in v.iter().enumerate() {
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-2.fixed b/tests/ui/suggestions/suggest-remove-refs-2.fixed
new file mode 100644
index 000000000..0f9c3abfe
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-2.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, _) in v.iter().enumerate() {
+ //~^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ println!("{}", i);
+ }
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-2.rs b/tests/ui/suggestions/suggest-remove-refs-2.rs
new file mode 100644
index 000000000..6c94b12d2
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-2.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, _) in & & & & &v.iter().enumerate() {
+ //~^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ println!("{}", i);
+ }
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr
new file mode 100644
index 000000000..1632b2abb
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ --> $DIR/suggest-remove-refs-2.rs:6:19
+ |
+LL | for (i, _) in & & & & &v.iter().enumerate() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing 5 leading `&`-references
+ |
+LL - for (i, _) in & & & & &v.iter().enumerate() {
+LL + for (i, _) in v.iter().enumerate() {
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-3.fixed b/tests/ui/suggestions/suggest-remove-refs-3.fixed
new file mode 100644
index 000000000..3148fcbe5
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-3.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, _) in v
+ .iter()
+ .enumerate() {
+ //~^^^^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an
+ println!("{}", i);
+ }
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-3.rs b/tests/ui/suggestions/suggest-remove-refs-3.rs
new file mode 100644
index 000000000..0622adada
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-3.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+
+fn main() {
+ let v = vec![0, 1, 2, 3];
+
+ for (i, _) in & & &
+ & &v
+ .iter()
+ .enumerate() {
+ //~^^^^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an
+ println!("{}", i);
+ }
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr
new file mode 100644
index 000000000..7bf421a77
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr
@@ -0,0 +1,21 @@
+error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ --> $DIR/suggest-remove-refs-3.rs:6:19
+ |
+LL | for (i, _) in & & &
+ | ___________________^
+LL | | & &v
+LL | | .iter()
+LL | | .enumerate() {
+ | |____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+ = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing 5 leading `&`-references
+ |
+LL - for (i, _) in & & &
+LL + for (i, _) in v
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.fixed b/tests/ui/suggestions/suggest-remove-refs-4.fixed
new file mode 100644
index 000000000..dd63d2159
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-4.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let foo = [1,2,3].iter();
+ for _i in foo {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.rs b/tests/ui/suggestions/suggest-remove-refs-4.rs
new file mode 100644
index 000000000..3c3d9b1b3
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-4.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let foo = &[1,2,3].iter();
+ for _i in &foo {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr
new file mode 100644
index 000000000..e4ad17e06
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator
+ --> $DIR/suggest-remove-refs-4.rs:4:15
+ |
+LL | for _i in &foo {}
+ | ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`
+ = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
+help: consider removing 2 leading `&`-references
+ |
+LL ~ let foo = [1,2,3].iter();
+LL ~ for _i in foo {}
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.fixed b/tests/ui/suggestions/suggest-remove-refs-5.fixed
new file mode 100644
index 000000000..9f59f9c19
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-5.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+ let v = &mut Vec::<i32>::new();
+ for _ in v {} //~ ERROR E0277
+
+ let v = &mut [1u8];
+ for _ in v {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.rs b/tests/ui/suggestions/suggest-remove-refs-5.rs
new file mode 100644
index 000000000..d56aa0c9c
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-5.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+ let v = &mut &mut Vec::<i32>::new();
+ for _ in &mut &mut v {} //~ ERROR E0277
+
+ let v = &mut &mut [1u8];
+ for _ in &mut v {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr
new file mode 100644
index 000000000..7de84d612
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr
@@ -0,0 +1,37 @@
+error[E0277]: `Vec<i32>` is not an iterator
+ --> $DIR/suggest-remove-refs-5.rs:4:14
+ |
+LL | for _ in &mut &mut v {}
+ | ^^^^^^^^^^^ `Vec<i32>` is not an iterator; try calling `.into_iter()` or `.iter()`
+ |
+ = help: the trait `Iterator` is not implemented for `Vec<i32>`
+ = note: required for `&mut Vec<i32>` to implement `Iterator`
+ = note: 3 redundant requirements hidden
+ = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
+ = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `IntoIterator`
+help: consider removing 3 leading `&`-references
+ |
+LL ~ let v = &mut Vec::<i32>::new();
+LL ~ for _ in v {}
+ |
+
+error[E0277]: `[u8; 1]` is not an iterator
+ --> $DIR/suggest-remove-refs-5.rs:7:14
+ |
+LL | for _ in &mut v {}
+ | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()`
+ |
+ = help: the trait `Iterator` is not implemented for `[u8; 1]`
+ = note: required for `&mut [u8; 1]` to implement `Iterator`
+ = note: 2 redundant requirements hidden
+ = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
+ = note: required for `&mut &mut &mut [u8; 1]` to implement `IntoIterator`
+help: consider removing 2 leading `&`-references
+ |
+LL ~ let v = &mut [1u8];
+LL ~ for _ in v {}
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed
new file mode 100644
index 000000000..5c55566ff
--- /dev/null
+++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#[allow(dead_code)]
+
+extern "C" {
+ fn foo(); //~ERROR expected `;`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs
new file mode 100644
index 000000000..91971cba3
--- /dev/null
+++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#[allow(dead_code)]
+
+extern "C" {
+ fn foo() //~ERROR expected `;`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr
new file mode 100644
index 000000000..c5df72c4a
--- /dev/null
+++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr
@@ -0,0 +1,10 @@
+error: expected `;`, found `}`
+ --> $DIR/suggest-semicolon-for-fn-in-extern-block.rs:6:11
+ |
+LL | fn foo()
+ | ^ help: add `;` here
+LL | }
+ | - unexpected token
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/suggest-split-at-mut.rs b/tests/ui/suggestions/suggest-split-at-mut.rs
new file mode 100644
index 000000000..d294c20b8
--- /dev/null
+++ b/tests/ui/suggestions/suggest-split-at-mut.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let mut foo = [1, 2, 3, 4];
+ let a = &mut foo[2];
+ let b = &mut foo[3]; //~ ERROR cannot borrow `foo[_]` as mutable more than once at a time
+ *a = 5;
+ *b = 6;
+ println!("{:?} {:?}", a, b);
+}
diff --git a/tests/ui/suggestions/suggest-split-at-mut.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr
new file mode 100644
index 000000000..330f012b2
--- /dev/null
+++ b/tests/ui/suggestions/suggest-split-at-mut.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `foo[_]` as mutable more than once at a time
+ --> $DIR/suggest-split-at-mut.rs:4:13
+ |
+LL | let a = &mut foo[2];
+ | ----------- first mutable borrow occurs here
+LL | let b = &mut foo[3];
+ | ^^^^^^^^^^^ second mutable borrow occurs here
+LL | *a = 5;
+ | ------ first borrow later used here
+ |
+ = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/suggestions/suggest-std-when-using-type.fixed b/tests/ui/suggestions/suggest-std-when-using-type.fixed
new file mode 100644
index 000000000..102c5c186
--- /dev/null
+++ b/tests/ui/suggestions/suggest-std-when-using-type.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+ let pi = std::f32::consts::PI; //~ ERROR ambiguous associated type
+ let bytes = "hello world".as_bytes();
+ let string = std::str::from_utf8(bytes).unwrap();
+ //~^ ERROR no function or associated item named `from_utf8` found
+ println!("{pi} {bytes:?} {string}");
+}
diff --git a/tests/ui/suggestions/suggest-std-when-using-type.rs b/tests/ui/suggestions/suggest-std-when-using-type.rs
new file mode 100644
index 000000000..5abc016de
--- /dev/null
+++ b/tests/ui/suggestions/suggest-std-when-using-type.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+ let pi = f32::consts::PI; //~ ERROR ambiguous associated type
+ let bytes = "hello world".as_bytes();
+ let string = str::from_utf8(bytes).unwrap();
+ //~^ ERROR no function or associated item named `from_utf8` found
+ println!("{pi} {bytes:?} {string}");
+}
diff --git a/tests/ui/suggestions/suggest-std-when-using-type.stderr b/tests/ui/suggestions/suggest-std-when-using-type.stderr
new file mode 100644
index 000000000..6f890b87b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-std-when-using-type.stderr
@@ -0,0 +1,26 @@
+error[E0223]: ambiguous associated type
+ --> $DIR/suggest-std-when-using-type.rs:3:14
+ |
+LL | let pi = f32::consts::PI;
+ | ^^^^^^^^^^^
+ |
+help: you are looking for the module in `std`, not the primitive type
+ |
+LL | let pi = std::f32::consts::PI;
+ | +++++
+
+error[E0599]: no function or associated item named `from_utf8` found for type `str` in the current scope
+ --> $DIR/suggest-std-when-using-type.rs:5:23
+ |
+LL | let string = str::from_utf8(bytes).unwrap();
+ | ^^^^^^^^^ function or associated item not found in `str`
+ |
+help: you are looking for the module in `std`, not the primitive type
+ |
+LL | let string = std::str::from_utf8(bytes).unwrap();
+ | +++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0223, E0599.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs
new file mode 100644
index 000000000..03c7ed347
--- /dev/null
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs
@@ -0,0 +1,22 @@
+// edition:2021
+
+pub trait Trait<'a, T> {}
+
+pub struct Struct<T>;
+pub enum Enum<T> {}
+
+pub union Union<T> {
+ f1: usize,
+}
+
+impl<'a, T> Struct<T> for Trait<'a, T> {}
+//~^ ERROR expected trait, found struct `Struct`
+//~| ERROR trait objects must include the `dyn` keyword
+
+impl<'a, T> Enum<T> for Trait<'a, T> {}
+//~^ ERROR expected trait, found enum `Enum`
+
+impl<'a, T> Union<T> for Trait<'a, T> {}
+//~^ ERROR expected trait, found union `Union`
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr
new file mode 100644
index 000000000..87e716436
--- /dev/null
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr
@@ -0,0 +1,48 @@
+error[E0404]: expected trait, found struct `Struct`
+ --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:13
+ |
+LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
+ | ^^^^^^^^^ not a trait
+ |
+help: `impl` items mention the trait being implemented first and the type it is being implemented for second
+ |
+LL | impl<'a, T> Trait<'a, T> for Struct<T> {}
+ | ~~~~~~~~~~~~ ~~~~~~~~~
+
+error[E0404]: expected trait, found enum `Enum`
+ --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:16:13
+ |
+LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
+ | ^^^^^^^ not a trait
+ |
+help: `impl` items mention the trait being implemented first and the type it is being implemented for second
+ |
+LL | impl<'a, T> Trait<'a, T> for Enum<T> {}
+ | ~~~~~~~~~~~~ ~~~~~~~
+
+error[E0404]: expected trait, found union `Union`
+ --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13
+ |
+LL | impl<'a, T> Union<T> for Trait<'a, T> {}
+ | ^^^^^^^^ not a trait
+ |
+help: `impl` items mention the trait being implemented first and the type it is being implemented for second
+ |
+LL | impl<'a, T> Trait<'a, T> for Union<T> {}
+ | ~~~~~~~~~~~~ ~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:27
+ |
+LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
+ | ^^^^^^^^^^^^
+ |
+help: add `dyn` keyword before this trait
+ |
+LL | impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
+ | +++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0404, E0782.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs
new file mode 100644
index 000000000..947bc2c79
--- /dev/null
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs
@@ -0,0 +1,21 @@
+pub trait Trait<'a, T> {}
+
+pub struct Struct<T>;
+pub enum Enum<T> {}
+
+pub union Union<T> {
+ f1: usize,
+}
+
+impl<'a, T> Struct<T> for Trait<'a, T> {}
+//~^ ERROR expected trait, found struct `Struct`
+//~| WARNING trait objects without an explicit `dyn` are deprecated
+//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+
+impl<'a, T> Enum<T> for Trait<'a, T> {}
+//~^ ERROR expected trait, found enum `Enum`
+
+impl<'a, T> Union<T> for Trait<'a, T> {}
+//~^ ERROR expected trait, found union `Union`
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
new file mode 100644
index 000000000..ffd505fff
--- /dev/null
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
@@ -0,0 +1,50 @@
+error[E0404]: expected trait, found struct `Struct`
+ --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:13
+ |
+LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
+ | ^^^^^^^^^ not a trait
+ |
+help: `impl` items mention the trait being implemented first and the type it is being implemented for second
+ |
+LL | impl<'a, T> Trait<'a, T> for Struct<T> {}
+ | ~~~~~~~~~~~~ ~~~~~~~~~
+
+error[E0404]: expected trait, found enum `Enum`
+ --> $DIR/suggest-swapping-self-ty-and-trait.rs:15:13
+ |
+LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
+ | ^^^^^^^ not a trait
+ |
+help: `impl` items mention the trait being implemented first and the type it is being implemented for second
+ |
+LL | impl<'a, T> Trait<'a, T> for Enum<T> {}
+ | ~~~~~~~~~~~~ ~~~~~~~
+
+error[E0404]: expected trait, found union `Union`
+ --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13
+ |
+LL | impl<'a, T> Union<T> for Trait<'a, T> {}
+ | ^^^^^^^^ not a trait
+ |
+help: `impl` items mention the trait being implemented first and the type it is being implemented for second
+ |
+LL | impl<'a, T> Trait<'a, T> for Union<T> {}
+ | ~~~~~~~~~~~~ ~~~~~~~~
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:27
+ |
+LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
+ | ^^^^^^^^^^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
+help: use `dyn`
+ |
+LL | impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
+ | +++
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/suggestions/suggest-trait-items.rs b/tests/ui/suggestions/suggest-trait-items.rs
new file mode 100644
index 000000000..9d42a7342
--- /dev/null
+++ b/tests/ui/suggestions/suggest-trait-items.rs
@@ -0,0 +1,48 @@
+trait Foo {
+ type Type;
+
+ fn foo();
+ fn bar();
+ fn qux();
+}
+
+struct A;
+
+impl Foo for A {
+//~^ ERROR not all trait items implemented
+ type Typ = ();
+ //~^ ERROR type `Typ` is not a member of trait
+ //~| HELP there is an associated type with a similar name
+
+ fn fooo() {}
+ //~^ ERROR method `fooo` is not a member of trait
+ //~| HELP there is an associated function with a similar name
+
+ fn barr() {}
+ //~^ ERROR method `barr` is not a member of trait
+ //~| HELP there is an associated function with a similar name
+
+ fn quux() {}
+ //~^ ERROR method `quux` is not a member of trait
+ //~| HELP there is an associated function with a similar name
+}
+//~^ HELP implement the missing item
+//~| HELP implement the missing item
+//~| HELP implement the missing item
+//~| HELP implement the missing item
+
+trait Bar {
+ const Const: i32;
+}
+
+struct B;
+
+impl Bar for B {
+//~^ ERROR not all trait items implemented
+ const Cnst: i32 = 0;
+ //~^ ERROR const `Cnst` is not a member of trait
+ //~| HELP there is an associated constant with a similar name
+}
+//~^ HELP implement the missing item
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-trait-items.stderr b/tests/ui/suggestions/suggest-trait-items.stderr
new file mode 100644
index 000000000..8bc3df7b8
--- /dev/null
+++ b/tests/ui/suggestions/suggest-trait-items.stderr
@@ -0,0 +1,74 @@
+error[E0437]: type `Typ` is not a member of trait `Foo`
+ --> $DIR/suggest-trait-items.rs:13:5
+ |
+LL | type Typ = ();
+ | ^^^^^---^^^^^^
+ | | |
+ | | help: there is an associated type with a similar name: `Type`
+ | not a member of trait `Foo`
+
+error[E0407]: method `fooo` is not a member of trait `Foo`
+ --> $DIR/suggest-trait-items.rs:17:5
+ |
+LL | fn fooo() {}
+ | ^^^----^^^^^
+ | | |
+ | | help: there is an associated function with a similar name: `foo`
+ | not a member of trait `Foo`
+
+error[E0407]: method `barr` is not a member of trait `Foo`
+ --> $DIR/suggest-trait-items.rs:21:5
+ |
+LL | fn barr() {}
+ | ^^^----^^^^^
+ | | |
+ | | help: there is an associated function with a similar name: `bar`
+ | not a member of trait `Foo`
+
+error[E0407]: method `quux` is not a member of trait `Foo`
+ --> $DIR/suggest-trait-items.rs:25:5
+ |
+LL | fn quux() {}
+ | ^^^----^^^^^
+ | | |
+ | | help: there is an associated function with a similar name: `qux`
+ | not a member of trait `Foo`
+
+error[E0438]: const `Cnst` is not a member of trait `Bar`
+ --> $DIR/suggest-trait-items.rs:42:5
+ |
+LL | const Cnst: i32 = 0;
+ | ^^^^^^----^^^^^^^^^^
+ | | |
+ | | help: there is an associated constant with a similar name: `Const`
+ | not a member of trait `Bar`
+
+error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `qux`
+ --> $DIR/suggest-trait-items.rs:11:1
+ |
+LL | type Type;
+ | --------- `Type` from trait
+LL |
+LL | fn foo();
+ | --------- `foo` from trait
+LL | fn bar();
+ | --------- `bar` from trait
+LL | fn qux();
+ | --------- `qux` from trait
+...
+LL | impl Foo for A {
+ | ^^^^^^^^^^^^^^ missing `Type`, `foo`, `bar`, `qux` in implementation
+
+error[E0046]: not all trait items implemented, missing: `Const`
+ --> $DIR/suggest-trait-items.rs:40:1
+ |
+LL | const Const: i32;
+ | ---------------- `Const` from trait
+...
+LL | impl Bar for B {
+ | ^^^^^^^^^^^^^^ missing `Const` in implementation
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0046, E0407, E0437, E0438.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.rs b/tests/ui/suggestions/suggest-tryinto-edition-change.rs
new file mode 100644
index 000000000..70c4b210d
--- /dev/null
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.rs
@@ -0,0 +1,32 @@
+// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions
+// Edition 2021 change
+// edition:2018
+
+fn test() {
+ let _i: i16 = 0_i32.try_into().unwrap();
+ //~^ ERROR no method named `try_into` found for type `i32` in the current scope
+ //~| NOTE method not found in `i32`
+ //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+
+ let _i: i16 = TryFrom::try_from(0_i32).unwrap();
+ //~^ ERROR failed to resolve: use of undeclared type
+ //~| NOTE use of undeclared type
+ //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
+ //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
+
+ let _i: i16 = TryInto::try_into(0_i32).unwrap();
+ //~^ ERROR failed to resolve: use of undeclared type
+ //~| NOTE use of undeclared type
+ //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+ //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
+
+ let _v: Vec<_> = FromIterator::from_iter(&[1]);
+ //~^ ERROR failed to resolve: use of undeclared type
+ //~| NOTE use of undeclared type
+ //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
+ //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
+}
+
+fn main() {
+ test();
+}
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
new file mode 100644
index 000000000..018083f9e
--- /dev/null
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
@@ -0,0 +1,69 @@
+error[E0433]: failed to resolve: use of undeclared type `TryFrom`
+ --> $DIR/suggest-tryinto-edition-change.rs:11:19
+ |
+LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap();
+ | ^^^^^^^ use of undeclared type `TryFrom`
+ |
+ = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
+ = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
+help: consider importing one of these items
+ |
+LL | use core::convert::TryFrom;
+ |
+LL | use std::convert::TryFrom;
+ |
+
+error[E0433]: failed to resolve: use of undeclared type `TryInto`
+ --> $DIR/suggest-tryinto-edition-change.rs:17:19
+ |
+LL | let _i: i16 = TryInto::try_into(0_i32).unwrap();
+ | ^^^^^^^ use of undeclared type `TryInto`
+ |
+ = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+ = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021
+help: consider importing one of these items
+ |
+LL | use core::convert::TryInto;
+ |
+LL | use std::convert::TryInto;
+ |
+
+error[E0433]: failed to resolve: use of undeclared type `FromIterator`
+ --> $DIR/suggest-tryinto-edition-change.rs:23:22
+ |
+LL | let _v: Vec<_> = FromIterator::from_iter(&[1]);
+ | ^^^^^^^^^^^^ use of undeclared type `FromIterator`
+ |
+ = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
+ = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
+help: a trait with a similar name exists
+ |
+LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]);
+ | ~~~~~~~~~~~~
+help: consider importing one of these items
+ |
+LL | use core::iter::FromIterator;
+ |
+LL | use std::iter::FromIterator;
+ |
+
+error[E0599]: no method named `try_into` found for type `i32` in the current scope
+ --> $DIR/suggest-tryinto-edition-change.rs:6:25
+ |
+LL | let _i: i16 = 0_i32.try_into().unwrap();
+ | ^^^^^^^^ method not found in `i32`
+ --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ |
+ = note: the method is available for `i32` here
+ |
+ = help: items from traits can only be used if the trait is in scope
+ = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use std::convert::TryInto;
+ |
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0433, E0599.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/tests/ui/suggestions/suggest-using-chars.rs b/tests/ui/suggestions/suggest-using-chars.rs
new file mode 100644
index 000000000..95732881b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-using-chars.rs
@@ -0,0 +1,7 @@
+pub fn main() {
+ let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope
+ let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope
+ let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope
+ let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope
+ let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope
+}
diff --git a/tests/ui/suggestions/suggest-using-chars.stderr b/tests/ui/suggestions/suggest-using-chars.stderr
new file mode 100644
index 000000000..99bcfb08a
--- /dev/null
+++ b/tests/ui/suggestions/suggest-using-chars.stderr
@@ -0,0 +1,48 @@
+error[E0599]: no method named `iter` found for reference `&'static str` in the current scope
+ --> $DIR/suggest-using-chars.rs:2:19
+ |
+LL | let _ = "foo".iter();
+ | ^^^^ method not found in `&'static str`
+ |
+help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
+ |
+LL | let _ = "foo".chars();
+ | ~~~~~
+
+error[E0599]: no method named `foo` found for reference `&'static str` in the current scope
+ --> $DIR/suggest-using-chars.rs:3:19
+ |
+LL | let _ = "foo".foo();
+ | ^^^ method not found in `&'static str`
+
+error[E0599]: no method named `iter` found for struct `String` in the current scope
+ --> $DIR/suggest-using-chars.rs:4:33
+ |
+LL | let _ = String::from("bar").iter();
+ | ^^^^ method not found in `String`
+ |
+help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
+ |
+LL | let _ = String::from("bar").chars();
+ | ~~~~~
+
+error[E0599]: no method named `iter` found for reference `&String` in the current scope
+ --> $DIR/suggest-using-chars.rs:5:36
+ |
+LL | let _ = (&String::from("bar")).iter();
+ | ^^^^ method not found in `&String`
+ |
+help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
+ |
+LL | let _ = (&String::from("bar")).chars();
+ | ~~~~~
+
+error[E0599]: no method named `iter` found for type `{integer}` in the current scope
+ --> $DIR/suggest-using-chars.rs:6:15
+ |
+LL | let _ = 0.iter();
+ | ^^^^ method not found in `{integer}`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-variants.rs b/tests/ui/suggestions/suggest-variants.rs
new file mode 100644
index 000000000..dd05d0f04
--- /dev/null
+++ b/tests/ui/suggestions/suggest-variants.rs
@@ -0,0 +1,18 @@
+#[derive(Debug)]
+enum Shape {
+ Square { size: i32 },
+ Circle { radius: i32 },
+}
+
+struct S {
+ x: usize,
+}
+
+fn main() {
+ println!("My shape is {:?}", Shape::Squareee { size: 5}); //~ ERROR no variant named `Squareee`
+ println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant named `Circl`
+ println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant named `Rombus`
+ Shape::Squareee; //~ ERROR no variant
+ Shape::Circl; //~ ERROR no variant
+ Shape::Rombus; //~ ERROR no variant
+}
diff --git a/tests/ui/suggestions/suggest-variants.stderr b/tests/ui/suggestions/suggest-variants.stderr
new file mode 100644
index 000000000..a422bc656
--- /dev/null
+++ b/tests/ui/suggestions/suggest-variants.stderr
@@ -0,0 +1,63 @@
+error[E0599]: no variant named `Squareee` found for enum `Shape`
+ --> $DIR/suggest-variants.rs:12:41
+ |
+LL | enum Shape {
+ | ---------- variant `Squareee` not found here
+...
+LL | println!("My shape is {:?}", Shape::Squareee { size: 5});
+ | ^^^^^^^^ help: there is a variant with a similar name: `Square`
+
+error[E0599]: no variant named `Circl` found for enum `Shape`
+ --> $DIR/suggest-variants.rs:13:41
+ |
+LL | enum Shape {
+ | ---------- variant `Circl` not found here
+...
+LL | println!("My shape is {:?}", Shape::Circl { size: 5});
+ | ^^^^^ help: there is a variant with a similar name: `Circle`
+
+error[E0599]: no variant named `Rombus` found for enum `Shape`
+ --> $DIR/suggest-variants.rs:14:41
+ |
+LL | enum Shape {
+ | ---------- variant `Rombus` not found here
+...
+LL | println!("My shape is {:?}", Shape::Rombus{ size: 5});
+ | ^^^^^^ variant not found in `Shape`
+
+error[E0599]: no variant or associated item named `Squareee` found for enum `Shape` in the current scope
+ --> $DIR/suggest-variants.rs:15:12
+ |
+LL | enum Shape {
+ | ---------- variant or associated item `Squareee` not found for this enum
+...
+LL | Shape::Squareee;
+ | ^^^^^^^^
+ | |
+ | variant or associated item not found in `Shape`
+ | help: there is a variant with a similar name: `Square`
+
+error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope
+ --> $DIR/suggest-variants.rs:16:12
+ |
+LL | enum Shape {
+ | ---------- variant or associated item `Circl` not found for this enum
+...
+LL | Shape::Circl;
+ | ^^^^^
+ | |
+ | variant or associated item not found in `Shape`
+ | help: there is a variant with a similar name: `Circle`
+
+error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope
+ --> $DIR/suggest-variants.rs:17:12
+ |
+LL | enum Shape {
+ | ---------- variant or associated item `Rombus` not found for this enum
+...
+LL | Shape::Rombus;
+ | ^^^^^^ variant or associated item not found in `Shape`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest_print_over_printf.rs b/tests/ui/suggestions/suggest_print_over_printf.rs
new file mode 100644
index 000000000..124ddec50
--- /dev/null
+++ b/tests/ui/suggestions/suggest_print_over_printf.rs
@@ -0,0 +1,8 @@
+// Suggest print macro when user erroneously uses printf
+
+fn main() {
+ let x = 4;
+ printf("%d", x);
+ //~^ ERROR cannot find function `printf` in this scope
+ //~| HELP you may have meant to use the `print` macro
+}
diff --git a/tests/ui/suggestions/suggest_print_over_printf.stderr b/tests/ui/suggestions/suggest_print_over_printf.stderr
new file mode 100644
index 000000000..1214bec16
--- /dev/null
+++ b/tests/ui/suggestions/suggest_print_over_printf.stderr
@@ -0,0 +1,14 @@
+error[E0425]: cannot find function `printf` in this scope
+ --> $DIR/suggest_print_over_printf.rs:5:5
+ |
+LL | printf("%d", x);
+ | ^^^^^^ not found in this scope
+ |
+help: you may have meant to use the `print` macro
+ |
+LL | print!("%d", x);
+ | ~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/too-many-field-suggestions.rs b/tests/ui/suggestions/too-many-field-suggestions.rs
new file mode 100644
index 000000000..905f9502c
--- /dev/null
+++ b/tests/ui/suggestions/too-many-field-suggestions.rs
@@ -0,0 +1,29 @@
+struct Thing {
+ a0: Foo,
+ a1: Foo,
+ a2: Foo,
+ a3: Foo,
+ a4: Foo,
+ a5: Foo,
+ a6: Foo,
+ a7: Foo,
+ a8: Foo,
+ a9: Foo,
+}
+
+struct Foo {
+ field: Field,
+}
+
+struct Field;
+
+impl Foo {
+ fn bar(&self) {}
+}
+
+fn bar(t: Thing) {
+ t.bar(); //~ ERROR no method named `bar` found for struct `Thing`
+ t.field; //~ ERROR no field `field` on type `Thing`
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/too-many-field-suggestions.stderr b/tests/ui/suggestions/too-many-field-suggestions.stderr
new file mode 100644
index 000000000..63ad6fdb1
--- /dev/null
+++ b/tests/ui/suggestions/too-many-field-suggestions.stderr
@@ -0,0 +1,44 @@
+error[E0599]: no method named `bar` found for struct `Thing` in the current scope
+ --> $DIR/too-many-field-suggestions.rs:25:7
+ |
+LL | struct Thing {
+ | ------------ method `bar` not found for this struct
+...
+LL | t.bar();
+ | ^^^ method not found in `Thing`
+ |
+help: some of the expressions' fields have a method of the same name
+ |
+LL | t.a0.bar();
+ | +++
+LL | t.a1.bar();
+ | +++
+LL | t.a2.bar();
+ | +++
+LL | t.a3.bar();
+ | +++
+ and 6 other candidates
+
+error[E0609]: no field `field` on type `Thing`
+ --> $DIR/too-many-field-suggestions.rs:26:7
+ |
+LL | t.field;
+ | ^^^^^ unknown field
+ |
+ = note: available fields are: `a0`, `a1`, `a2`, `a3`, `a4` ... and 5 others
+help: some of the expressions' fields have a field of the same name
+ |
+LL | t.a0.field;
+ | +++
+LL | t.a1.field;
+ | +++
+LL | t.a2.field;
+ | +++
+LL | t.a3.field;
+ | +++
+ and 6 other candidates
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0599, E0609.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed
new file mode 100644
index 000000000..8ef7e34ab
--- /dev/null
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed
@@ -0,0 +1,43 @@
+// run-rustfix
+#![allow(unused)] // for the fixed file
+
+trait Trait<T = Self> {
+ type A;
+
+ fn func(&self) -> Self::A;
+}
+
+struct S<T>(T);
+impl<K> S<K> {
+ fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) {
+ qux(x.func()) //~ ERROR mismatched types
+ }
+
+ fn ban<T>(x: T) where T: Trait<A = usize> {
+ qux(x.func()) //~ ERROR mismatched types
+ }
+}
+
+fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bar<T: Trait<A = usize>>(x: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn foo2(x: impl Trait<i32, A = usize>) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bar2<T: Trait<i32, A = usize>>(x: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn ban<T>(x: T) where T: Trait<A = usize> {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn qux(_: usize) {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs
new file mode 100644
index 000000000..7bd38d0d4
--- /dev/null
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs
@@ -0,0 +1,43 @@
+// run-rustfix
+#![allow(unused)] // for the fixed file
+
+trait Trait<T = Self> {
+ type A;
+
+ fn func(&self) -> Self::A;
+}
+
+struct S<T>(T);
+impl<K> S<K> {
+ fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait, _: T) {
+ qux(x.func()) //~ ERROR mismatched types
+ }
+
+ fn ban<T>(x: T) where T: Trait {
+ qux(x.func()) //~ ERROR mismatched types
+ }
+}
+
+fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait, _: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bar<T: Trait>(x: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn foo2(x: impl Trait<i32>) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bar2<T: Trait<i32>>(x: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn ban<T>(x: T) where T: Trait {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn qux(_: usize) {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr
new file mode 100644
index 000000000..ac839ff7e
--- /dev/null
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr
@@ -0,0 +1,143 @@
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:13:13
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<impl Trait as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
+ |
+LL | fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:17:13
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait>::A` to `usize`
+ |
+LL | fn ban<T>(x: T) where T: Trait<A = usize> {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:22:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<impl Trait as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
+ |
+LL | fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:26:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait>::A` to `usize`
+ |
+LL | fn bar<T: Trait<A = usize>>(x: T) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:30:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<impl Trait<i32> as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize`
+ |
+LL | fn foo2(x: impl Trait<i32, A = usize>) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:34:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize`
+ |
+LL | fn bar2<T: Trait<i32, A = usize>>(x: T) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:38:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait>::A` to `usize`
+ |
+LL | fn ban<T>(x: T) where T: Trait<A = usize> {
+ | +++++++++++
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs
new file mode 100644
index 000000000..0d90e4495
--- /dev/null
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs
@@ -0,0 +1,44 @@
+// These are all the possible variations of this error I could think of for.
+// `trait-with-missing-associated-type-restriction-fixable.rs` contains the subset of these that
+// can be fixed with `rustfix`.
+
+trait Trait<T = Self> {
+ type A;
+
+ fn func(&self) -> Self::A;
+ fn funk(&self, _: Self::A);
+ fn funq(&self) -> Self::A {} //~ ERROR mismatched types
+}
+
+fn foo(_: impl Trait, x: impl Trait) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bar<T: Trait>(x: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn foo2(x: impl Trait<i32>) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bar2<T: Trait<i32>>(x: T) {
+ x.funk(3); //~ ERROR mismatched types
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn bat(x: &mut dyn Trait<(), A = ()>) {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn ban<T>(x: T) where T: Trait {
+ qux(x.func()) //~ ERROR mismatched types
+}
+
+fn qux(_: usize) {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
new file mode 100644
index 000000000..f520d88c6
--- /dev/null
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
@@ -0,0 +1,177 @@
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:10:31
+ |
+LL | fn funq(&self) -> Self::A {}
+ | ^^ expected associated type, found `()`
+ |
+ = note: expected associated type `<Self as Trait<T>>::A`
+ found unit type `()`
+help: a method is available that returns `<Self as Trait<T>>::A`
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5
+ |
+LL | fn func(&self) -> Self::A;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func`
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<impl Trait as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
+ |
+LL | fn foo(_: impl Trait, x: impl Trait<A = usize>) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:18:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait>::A` to `usize`
+ |
+LL | fn bar<T: Trait<A = usize>>(x: T) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:22:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<impl Trait<i32> as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize`
+ |
+LL | fn foo2(x: impl Trait<i32, A = usize>) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:26:12
+ |
+LL | x.funk(3);
+ | ---- ^ expected associated type, found integer
+ | |
+ | arguments to this method are incorrect
+ |
+ = note: expected associated type `<T as Trait<i32>>::A`
+ found type `{integer}`
+help: some methods are available that return `<T as Trait<i32>>::A`
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5
+ |
+LL | fn func(&self) -> Self::A;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func`
+LL | fn funk(&self, _: Self::A);
+LL | fn funq(&self) -> Self::A {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq`
+note: associated function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8
+ |
+LL | fn funk(&self, _: Self::A);
+ | ^^^^
+help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}`
+ |
+LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) {
+ | +++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:27:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize`
+ |
+LL | fn bar2<T: Trait<i32, A = usize>>(x: T) {
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:31:9
+ |
+LL | fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) {
+ | - this type parameter
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found type parameter `D`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found type parameter `D`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:35:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found `()`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+
+error[E0308]: mismatched types
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:39:9
+ |
+LL | qux(x.func())
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected type `usize`
+ found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
+help: consider constraining the associated type `<T as Trait>::A` to `usize`
+ |
+LL | fn ban<T>(x: T) where T: Trait<A = usize> {
+ | +++++++++++
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs
new file mode 100644
index 000000000..f882a159f
--- /dev/null
+++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs
@@ -0,0 +1,27 @@
+// Regression test for #87051, where a double semicolon was erroneously
+// suggested after a `?` operator.
+
+fn main() -> Result<(), ()> {
+ a(|| {
+ b()
+ //~^ ERROR: mismatched types [E0308]
+ //~| NOTE: expected `()`, found `i32`
+ //~| HELP: consider using a semicolon here
+ })?;
+
+ // Here, we do want to suggest a semicolon:
+ let x = Ok(42);
+ if true {
+ //~^ NOTE: expected this to be `()`
+ x?
+ //~^ ERROR: mismatched types [E0308]
+ //~| NOTE: expected `()`, found integer
+ //~| HELP: consider using a semicolon here
+ }
+ //~^ HELP: consider using a semicolon here
+
+ Ok(())
+}
+
+fn a<F>(f: F) -> Result<(), ()> where F: FnMut() { Ok(()) }
+fn b() -> i32 { 42 }
diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
new file mode 100644
index 000000000..939285498
--- /dev/null
+++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+ --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9
+ |
+LL | b()
+ | ^^^- help: consider using a semicolon here: `;`
+ | |
+ | expected `()`, found `i32`
+
+error[E0308]: mismatched types
+ --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9
+ |
+LL | / if true {
+LL | |
+LL | | x?
+ | | ^^ expected `()`, found integer
+LL | |
+LL | |
+LL | |
+LL | | }
+ | |_____- expected this to be `()`
+ |
+help: consider using a semicolon here
+ |
+LL | x?;
+ | +
+help: consider using a semicolon here
+ |
+LL | };
+ | +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/try-removing-the-field.rs b/tests/ui/suggestions/try-removing-the-field.rs
new file mode 100644
index 000000000..1b7289b22
--- /dev/null
+++ b/tests/ui/suggestions/try-removing-the-field.rs
@@ -0,0 +1,32 @@
+// run-pass
+
+#![allow(dead_code)]
+
+struct Foo {
+ foo: i32,
+ bar: (),
+ baz: (),
+}
+
+fn use_foo(x: Foo) -> i32 {
+ let Foo { foo, bar, .. } = x; //~ WARNING unused variable: `bar`
+ //~| help: try removing the field
+ return foo;
+}
+
+// issue #105028, suggest removing the field only for shorthand
+fn use_match(x: Foo) {
+ match x {
+ Foo { foo: unused, .. } => { //~ WARNING unused variable
+ //~| help: if this is intentional, prefix it with an underscore
+ }
+ }
+
+ match x {
+ Foo { foo, .. } => { //~ WARNING unused variable
+ //~| help: try removing the field
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/try-removing-the-field.stderr b/tests/ui/suggestions/try-removing-the-field.stderr
new file mode 100644
index 000000000..7a6013d4a
--- /dev/null
+++ b/tests/ui/suggestions/try-removing-the-field.stderr
@@ -0,0 +1,26 @@
+warning: unused variable: `bar`
+ --> $DIR/try-removing-the-field.rs:12:20
+ |
+LL | let Foo { foo, bar, .. } = x;
+ | ^^^-
+ | |
+ | help: try removing the field
+ |
+ = note: `#[warn(unused_variables)]` on by default
+
+warning: unused variable: `unused`
+ --> $DIR/try-removing-the-field.rs:20:20
+ |
+LL | Foo { foo: unused, .. } => {
+ | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
+
+warning: unused variable: `foo`
+ --> $DIR/try-removing-the-field.rs:26:15
+ |
+LL | Foo { foo, .. } => {
+ | ^^^-
+ | |
+ | help: try removing the field
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/suggestions/type-ascription-and-other-error.rs b/tests/ui/suggestions/type-ascription-and-other-error.rs
new file mode 100644
index 000000000..99ab2f3c8
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-and-other-error.rs
@@ -0,0 +1,6 @@
+fn main() {
+ not rust; //~ ERROR
+ let _ = 0: i32; // (error hidden by existing error)
+ #[cfg(FALSE)]
+ let _ = 0: i32; // (warning hidden by existing error)
+}
diff --git a/tests/ui/suggestions/type-ascription-and-other-error.stderr b/tests/ui/suggestions/type-ascription-and-other-error.stderr
new file mode 100644
index 000000000..eadf634bb
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-and-other-error.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `rust`
+ --> $DIR/type-ascription-and-other-error.rs:2:9
+ |
+LL | not rust;
+ | ^^^^ expected one of 8 possible tokens
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/type-ascription-instead-of-let.rs b/tests/ui/suggestions/type-ascription-instead-of-let.rs
new file mode 100644
index 000000000..0e1c30750
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-let.rs
@@ -0,0 +1,10 @@
+fn fun(x: i32) -> i32 { x }
+
+fn main() {
+ let closure_annotated = |value: i32| -> i32 {
+ temp: i32 = fun(5i32);
+ //~^ ERROR cannot find value `temp` in this scope
+ temp + value + 1
+ //~^ ERROR cannot find value `temp` in this scope
+ };
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-let.stderr b/tests/ui/suggestions/type-ascription-instead-of-let.stderr
new file mode 100644
index 000000000..92e4b5798
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-let.stderr
@@ -0,0 +1,18 @@
+error[E0425]: cannot find value `temp` in this scope
+ --> $DIR/type-ascription-instead-of-let.rs:5:9
+ |
+LL | temp: i32 = fun(5i32);
+ | ^^^^
+ | |
+ | not found in this scope
+ | help: maybe you meant to write an assignment here: `let temp`
+
+error[E0425]: cannot find value `temp` in this scope
+ --> $DIR/type-ascription-instead-of-let.rs:7:9
+ |
+LL | temp + value + 1
+ | ^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.fixed b/tests/ui/suggestions/type-ascription-instead-of-method.fixed
new file mode 100644
index 000000000..56b740b0d
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-method.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let _ = Box::new("foo".to_string());
+ //~^ ERROR expected type, found
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.rs b/tests/ui/suggestions/type-ascription-instead-of-method.rs
new file mode 100644
index 000000000..a603e09e7
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-method.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let _ = Box:new("foo".to_string());
+ //~^ ERROR expected type, found
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.stderr b/tests/ui/suggestions/type-ascription-instead-of-method.stderr
new file mode 100644
index 000000000..83bc33f41
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-method.stderr
@@ -0,0 +1,12 @@
+error: expected type, found `"foo"`
+ --> $DIR/type-ascription-instead-of-method.rs:3:21
+ |
+LL | let _ = Box:new("foo".to_string());
+ | - ^^^^^ expected type
+ | |
+ | help: maybe write a path separator here: `::`
+ |
+ = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.fixed b/tests/ui/suggestions/type-ascription-instead-of-path-2.fixed
new file mode 100644
index 000000000..787fcc120
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main() -> Result<(), ()> {
+ let _ = vec![Ok(2)].into_iter().collect::<Result<Vec<_>,_>>()?;
+ //~^ ERROR expected `::`, found `(`
+ Ok(())
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.rs b/tests/ui/suggestions/type-ascription-instead-of-path-2.rs
new file mode 100644
index 000000000..934016b3b
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main() -> Result<(), ()> {
+ let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
+ //~^ ERROR expected `::`, found `(`
+ Ok(())
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr
new file mode 100644
index 000000000..970b220b7
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr
@@ -0,0 +1,12 @@
+error: expected `::`, found `(`
+ --> $DIR/type-ascription-instead-of-path-2.rs:3:63
+ |
+LL | let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
+ | - ^ expected `::`
+ | |
+ | help: maybe write a path separator here: `::`
+ |
+ = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs
new file mode 100644
index 000000000..48d19f6dd
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs
@@ -0,0 +1,14 @@
+enum A {
+ B,
+}
+
+fn main() {
+ let _: Vec<A:B> = A::B;
+ //~^ ERROR cannot find trait `B` in this scope
+ //~| HELP you might have meant to write a path instead of an associated type bound
+ //~| ERROR associated type bounds are unstable
+ //~| HELP add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+ //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied
+ //~| HELP add missing generic argument
+ //~| ERROR associated type bindings are not allowed here
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
new file mode 100644
index 000000000..fcff02e09
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
@@ -0,0 +1,41 @@
+error[E0405]: cannot find trait `B` in this scope
+ --> $DIR/type-ascription-instead-of-path-in-type.rs:6:18
+ |
+LL | let _: Vec<A:B> = A::B;
+ | ^ not found in this scope
+ |
+help: you might have meant to write a path instead of an associated type bound
+ |
+LL | let _: Vec<A::B> = A::B;
+ | ~~
+
+error[E0658]: associated type bounds are unstable
+ --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16
+ |
+LL | let _: Vec<A:B> = A::B;
+ | ^^^
+ |
+ = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+ = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+error[E0107]: this struct takes at least 1 generic argument but 0 generic arguments were supplied
+ --> $DIR/type-ascription-instead-of-path-in-type.rs:6:12
+ |
+LL | let _: Vec<A:B> = A::B;
+ | ^^^ expected at least 1 generic argument
+ |
+help: add missing generic argument
+ |
+LL | let _: Vec<T, A:B> = A::B;
+ | ++
+
+error[E0229]: associated type bindings are not allowed here
+ --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16
+ |
+LL | let _: Vec<A:B> = A::B;
+ | ^^^ associated type not allowed here
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0107, E0229, E0405, E0658.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.rs b/tests/ui/suggestions/type-ascription-instead-of-path.rs
new file mode 100644
index 000000000..ce40b55f1
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path.rs
@@ -0,0 +1,5 @@
+fn main() {
+ std:io::stdin();
+ //~^ ERROR failed to resolve: use of undeclared crate or module `io`
+ //~| ERROR expected value, found crate
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.stderr b/tests/ui/suggestions/type-ascription-instead-of-path.stderr
new file mode 100644
index 000000000..518660cfa
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-path.stderr
@@ -0,0 +1,18 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `io`
+ --> $DIR/type-ascription-instead-of-path.rs:2:9
+ |
+LL | std:io::stdin();
+ | ^^ use of undeclared crate or module `io`
+
+error[E0423]: expected value, found crate `std`
+ --> $DIR/type-ascription-instead-of-path.rs:2:5
+ |
+LL | std:io::stdin();
+ | ^^^- help: maybe you meant to write a path separator here: `::`
+ | |
+ | not a value
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0433.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.fixed b/tests/ui/suggestions/type-ascription-instead-of-variant.fixed
new file mode 100644
index 000000000..b3247e128
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-variant.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let _ = Option::Some("");
+ //~^ ERROR expected type, found
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.rs b/tests/ui/suggestions/type-ascription-instead-of-variant.rs
new file mode 100644
index 000000000..6fd2c1954
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-variant.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+ let _ = Option:Some("");
+ //~^ ERROR expected type, found
+}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr
new file mode 100644
index 000000000..f59ba78d4
--- /dev/null
+++ b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr
@@ -0,0 +1,12 @@
+error: expected type, found `""`
+ --> $DIR/type-ascription-instead-of-variant.rs:3:25
+ |
+LL | let _ = Option:Some("");
+ | - ^^ expected type
+ | |
+ | help: maybe write a path separator here: `::`
+ |
+ = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.rs b/tests/ui/suggestions/type-mismatch-byte-literal.rs
new file mode 100644
index 000000000..34199f8c3
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-byte-literal.rs
@@ -0,0 +1,18 @@
+// Tests that a suggestion is issued for type mismatch errors when a
+// u8 is expected and a char literal which is ASCII is supplied.
+
+fn foo(_t: u8) {}
+
+fn main() {
+ let _x: u8 = 'X';
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: if you meant to write a byte literal, prefix with `b`
+
+ foo('#');
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: if you meant to write a byte literal, prefix with `b`
+
+ // Do not issue the suggestion if the char literal isn't ASCII
+ let _t: u8 = '€';
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.stderr b/tests/ui/suggestions/type-mismatch-byte-literal.stderr
new file mode 100644
index 000000000..c9c2e7498
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-byte-literal.stderr
@@ -0,0 +1,42 @@
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-byte-literal.rs:7:18
+ |
+LL | let _x: u8 = 'X';
+ | -- ^^^ expected `u8`, found `char`
+ | |
+ | expected due to this
+ |
+help: if you meant to write a byte literal, prefix with `b`
+ |
+LL | let _x: u8 = b'X';
+ | ~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-byte-literal.rs:11:9
+ |
+LL | foo('#');
+ | --- ^^^ expected `u8`, found `char`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch-byte-literal.rs:4:4
+ |
+LL | fn foo(_t: u8) {}
+ | ^^^ ------
+help: if you meant to write a byte literal, prefix with `b`
+ |
+LL | foo(b'#');
+ | ~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-byte-literal.rs:16:18
+ |
+LL | let _t: u8 = '€';
+ | -- ^^^ expected `u8`, found `char`
+ | |
+ | expected due to this
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
new file mode 100644
index 000000000..2ce122207
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
@@ -0,0 +1,9 @@
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+ let (r, g, c): (f32, f32, f32) = (0., 0., 0.);
+ let _ = RGB { r, g, c };
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR struct `RGB` has no field named `c`
+}
diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
new file mode 100644
index 000000000..12466868f
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
@@ -0,0 +1,32 @@
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
+ |
+LL | let _ = RGB { r, g, c };
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r: r.into(), g, c };
+ | ++ +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
+ |
+LL | let _ = RGB { r, g, c };
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r, g: g.into(), c };
+ | ++ +++++++
+
+error[E0560]: struct `RGB` has no field named `c`
+ --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
+ |
+LL | let _ = RGB { r, g, c };
+ | ^ help: a field with a similar name exists: `b`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0560.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
new file mode 100644
index 000000000..91758c0b2
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+ let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+ let _ = RGB { r: r.into(), g: g.into(), b: b.into() };
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs
new file mode 100644
index 000000000..9d3a17a72
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+ let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+ let _ = RGB { r, g, b };
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
new file mode 100644
index 000000000..72c84d167
--- /dev/null
+++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
@@ -0,0 +1,36 @@
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
+ |
+LL | let _ = RGB { r, g, b };
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r: r.into(), g, b };
+ | ++ +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
+ |
+LL | let _ = RGB { r, g, b };
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r, g: g.into(), b };
+ | ++ +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
+ |
+LL | let _ = RGB { r, g, b };
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r, g, b: b.into() };
+ | ++ +++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/type-not-found-in-adt-field.rs b/tests/ui/suggestions/type-not-found-in-adt-field.rs
new file mode 100644
index 000000000..4cbfe58d3
--- /dev/null
+++ b/tests/ui/suggestions/type-not-found-in-adt-field.rs
@@ -0,0 +1,9 @@
+struct Struct {
+ m: Vec<Someunknownname<String, ()>>, //~ ERROR cannot find type `Someunknownname` in this scope
+ //~^ NOTE not found in this scope
+}
+struct OtherStruct { //~ HELP you might be missing a type parameter
+ m: K, //~ ERROR cannot find type `K` in this scope
+ //~^ NOTE not found in this scope
+}
+fn main() {}
diff --git a/tests/ui/suggestions/type-not-found-in-adt-field.stderr b/tests/ui/suggestions/type-not-found-in-adt-field.stderr
new file mode 100644
index 000000000..934ba87bb
--- /dev/null
+++ b/tests/ui/suggestions/type-not-found-in-adt-field.stderr
@@ -0,0 +1,20 @@
+error[E0412]: cannot find type `Someunknownname` in this scope
+ --> $DIR/type-not-found-in-adt-field.rs:2:12
+ |
+LL | m: Vec<Someunknownname<String, ()>>,
+ | ^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `K` in this scope
+ --> $DIR/type-not-found-in-adt-field.rs:6:8
+ |
+LL | m: K,
+ | ^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | struct OtherStruct<K> {
+ | +++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/suggestions/undeclared-module-alloc.rs b/tests/ui/suggestions/undeclared-module-alloc.rs
new file mode 100644
index 000000000..1defa1cef
--- /dev/null
+++ b/tests/ui/suggestions/undeclared-module-alloc.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc`
+
+fn main() {}
diff --git a/tests/ui/suggestions/undeclared-module-alloc.stderr b/tests/ui/suggestions/undeclared-module-alloc.stderr
new file mode 100644
index 000000000..39169dfa9
--- /dev/null
+++ b/tests/ui/suggestions/undeclared-module-alloc.stderr
@@ -0,0 +1,11 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `alloc`
+ --> $DIR/undeclared-module-alloc.rs:3:5
+ |
+LL | use alloc::rc::Rc;
+ | ^^^^^ use of undeclared crate or module `alloc`
+ |
+ = help: add `extern crate alloc` to use the `alloc` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs
new file mode 100644
index 000000000..f2485041d
--- /dev/null
+++ b/tests/ui/suggestions/unnamable-types.rs
@@ -0,0 +1,39 @@
+// Test that we do not suggest to add type annotations for unnamable types.
+
+#![crate_type="lib"]
+#![feature(generators)]
+
+const A = 5;
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the constant
+
+static B: _ = "abc";
+//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables
+//~| NOTE: not allowed in type signatures
+//~| HELP: replace with the correct type
+
+
+// FIXME: this should also suggest a function pointer, as the closure is non-capturing
+const C: _ = || 42;
+//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants
+//~| NOTE: not allowed in type signatures
+//~| NOTE: however, the inferred type
+
+struct S<T> { t: T }
+const D = S { t: { let i = 0; move || -> i32 { i } } };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
+
+
+fn foo() -> i32 { 42 }
+const E = foo;
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the constant
+const F = S { t: foo };
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the constant
+
+
+const G = || -> i32 { yield 0; return 1; };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr
new file mode 100644
index 000000000..24bedb529
--- /dev/null
+++ b/tests/ui/suggestions/unnamable-types.stderr
@@ -0,0 +1,66 @@
+error: missing type for `const` item
+ --> $DIR/unnamable-types.rs:6:8
+ |
+LL | const A = 5;
+ | ^ help: provide a type for the constant: `: i32`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
+ --> $DIR/unnamable-types.rs:10:11
+ |
+LL | static B: _ = "abc";
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with the correct type: `&str`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+ --> $DIR/unnamable-types.rs:17:10
+ |
+LL | const C: _ = || 42;
+ | ^ not allowed in type signatures
+ |
+note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named
+ --> $DIR/unnamable-types.rs:17:14
+ |
+LL | const C: _ = || 42;
+ | ^^^^^
+
+error: missing type for `const` item
+ --> $DIR/unnamable-types.rs:23:8
+ |
+LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
+ | ^
+ |
+note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named
+ --> $DIR/unnamable-types.rs:23:11
+ |
+LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing type for `const` item
+ --> $DIR/unnamable-types.rs:29:8
+ |
+LL | const E = foo;
+ | ^ help: provide a type for the constant: `: fn() -> i32`
+
+error: missing type for `const` item
+ --> $DIR/unnamable-types.rs:32:8
+ |
+LL | const F = S { t: foo };
+ | ^ help: provide a type for the constant: `: S<fn() -> i32>`
+
+error: missing type for `const` item
+ --> $DIR/unnamable-types.rs:37:8
+ |
+LL | const G = || -> i32 { yield 0; return 1; };
+ | ^
+ |
+note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named
+ --> $DIR/unnamable-types.rs:37:11
+ |
+LL | const G = || -> i32 { yield 0; return 1; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs
new file mode 100644
index 000000000..c1a944562
--- /dev/null
+++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let _: f64 = 0..10; //~ ERROR mismatched types
+ let _: f64 = 1..; //~ ERROR mismatched types
+ let _: f64 = ..10; //~ ERROR mismatched types
+ let _: f64 = std::ops::Range { start: 0, end: 1 }; //~ ERROR mismatched types
+}
diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
new file mode 100644
index 000000000..34eaa8322
--- /dev/null
+++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+ --> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18
+ |
+LL | let _: f64 = 0..10;
+ | --- ^^^^^ expected `f64`, found struct `Range`
+ | |
+ | expected due to this
+ |
+ = note: expected type `f64`
+ found struct `std::ops::Range<{integer}>`
+help: remove the unnecessary `.` operator for a floating point literal
+ |
+LL | let _: f64 = 0.10;
+ | ~
+
+error[E0308]: mismatched types
+ --> $DIR/unnecessary_dot_for_floating_point_literal.rs:3:18
+ |
+LL | let _: f64 = 1..;
+ | --- ^^^ expected `f64`, found struct `RangeFrom`
+ | |
+ | expected due to this
+ |
+ = note: expected type `f64`
+ found struct `RangeFrom<{integer}>`
+help: remove the unnecessary `.` operator for a floating point literal
+ |
+LL | let _: f64 = 1.;
+ | ~
+
+error[E0308]: mismatched types
+ --> $DIR/unnecessary_dot_for_floating_point_literal.rs:4:18
+ |
+LL | let _: f64 = ..10;
+ | --- ^^^^ expected `f64`, found struct `RangeTo`
+ | |
+ | expected due to this
+ |
+ = note: expected type `f64`
+ found struct `RangeTo<{integer}>`
+help: remove the unnecessary `.` operator and add an integer part for a floating point literal
+ |
+LL | let _: f64 = 0.10;
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18
+ |
+LL | let _: f64 = std::ops::Range { start: 0, end: 1 };
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range`
+ | |
+ | expected due to this
+ |
+ = note: expected type `f64`
+ found struct `std::ops::Range<{integer}>`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/unsized-function-parameter.fixed b/tests/ui/suggestions/unsized-function-parameter.fixed
new file mode 100644
index 000000000..18e93cb96
--- /dev/null
+++ b/tests/ui/suggestions/unsized-function-parameter.fixed
@@ -0,0 +1,23 @@
+// run-rustfix
+
+#![allow(dead_code, unused_variables)]
+
+fn foo1(bar: &str) {}
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| HELP the trait `Sized` is not implemented for `str`
+//~| 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
+
+fn foo2(_bar: &str) {}
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| HELP the trait `Sized` is not implemented for `str`
+//~| 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
+
+fn foo3(_: &str) {}
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| HELP the trait `Sized` is not implemented for `str`
+//~| 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
+
+fn main() {}
diff --git a/tests/ui/suggestions/unsized-function-parameter.rs b/tests/ui/suggestions/unsized-function-parameter.rs
new file mode 100644
index 000000000..344ee71c1
--- /dev/null
+++ b/tests/ui/suggestions/unsized-function-parameter.rs
@@ -0,0 +1,23 @@
+// run-rustfix
+
+#![allow(dead_code, unused_variables)]
+
+fn foo1(bar: str) {}
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| HELP the trait `Sized` is not implemented for `str`
+//~| 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
+
+fn foo2(_bar: str) {}
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| HELP the trait `Sized` is not implemented for `str`
+//~| 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
+
+fn foo3(_: str) {}
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| HELP the trait `Sized` is not implemented for `str`
+//~| 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
+
+fn main() {}
diff --git a/tests/ui/suggestions/unsized-function-parameter.stderr b/tests/ui/suggestions/unsized-function-parameter.stderr
new file mode 100644
index 000000000..55d8d1ab1
--- /dev/null
+++ b/tests/ui/suggestions/unsized-function-parameter.stderr
@@ -0,0 +1,42 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-function-parameter.rs:5:9
+ |
+LL | fn foo1(bar: str) {}
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = 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 | fn foo1(bar: &str) {}
+ | +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-function-parameter.rs:11:9
+ |
+LL | fn foo2(_bar: str) {}
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = 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 | fn foo2(_bar: &str) {}
+ | +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-function-parameter.rs:17:9
+ |
+LL | fn foo3(_: str) {}
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = 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 | fn foo3(_: &str) {}
+ | +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/unused-closure-argument.rs b/tests/ui/suggestions/unused-closure-argument.rs
new file mode 100644
index 000000000..677003ebf
--- /dev/null
+++ b/tests/ui/suggestions/unused-closure-argument.rs
@@ -0,0 +1,20 @@
+#![deny(unused_variables)]
+
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+fn main() {
+ let points = vec!(Point { x: 1, y: 2 }, Point { x: 3, y: 4 });
+
+ let _: i32 = points.iter()
+ .map(|Point { x, y }| y)
+ //~^ ERROR unused variable
+ .sum();
+
+ let _: i32 = points.iter()
+ .map(|x| 4)
+ //~^ ERROR unused variable
+ .sum();
+}
diff --git a/tests/ui/suggestions/unused-closure-argument.stderr b/tests/ui/suggestions/unused-closure-argument.stderr
new file mode 100644
index 000000000..55195ce50
--- /dev/null
+++ b/tests/ui/suggestions/unused-closure-argument.stderr
@@ -0,0 +1,20 @@
+error: unused variable: `x`
+ --> $DIR/unused-closure-argument.rs:12:23
+ |
+LL | .map(|Point { x, y }| y)
+ | ^ help: try ignoring the field: `x: _`
+ |
+note: the lint level is defined here
+ --> $DIR/unused-closure-argument.rs:1:9
+ |
+LL | #![deny(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+
+error: unused variable: `x`
+ --> $DIR/unused-closure-argument.rs:17:15
+ |
+LL | .map(|x| 4)
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/suggestions/use-placement-resolve.fixed b/tests/ui/suggestions/use-placement-resolve.fixed
new file mode 100644
index 000000000..afe74cff2
--- /dev/null
+++ b/tests/ui/suggestions/use-placement-resolve.fixed
@@ -0,0 +1,13 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+fn foobar<T: Debug>(x: T) {} //~ ERROR expected trait, found derive macro
diff --git a/tests/ui/suggestions/use-placement-resolve.rs b/tests/ui/suggestions/use-placement-resolve.rs
new file mode 100644
index 000000000..b30ddb3af
--- /dev/null
+++ b/tests/ui/suggestions/use-placement-resolve.rs
@@ -0,0 +1,11 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+fn main() {}
+
+fn foobar<T: Debug>(x: T) {} //~ ERROR expected trait, found derive macro
diff --git a/tests/ui/suggestions/use-placement-resolve.stderr b/tests/ui/suggestions/use-placement-resolve.stderr
new file mode 100644
index 000000000..9da9e8e27
--- /dev/null
+++ b/tests/ui/suggestions/use-placement-resolve.stderr
@@ -0,0 +1,14 @@
+error[E0404]: expected trait, found derive macro `Debug`
+ --> $DIR/use-placement-resolve.rs:11:14
+ |
+LL | fn foobar<T: Debug>(x: T) {}
+ | ^^^^^ not a trait
+ |
+help: consider importing this trait instead
+ |
+LL | use std::fmt::Debug;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/suggestions/use-placement-typeck.fixed b/tests/ui/suggestions/use-placement-typeck.fixed
new file mode 100644
index 000000000..37335da06
--- /dev/null
+++ b/tests/ui/suggestions/use-placement-typeck.fixed
@@ -0,0 +1,21 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+use m::Foo;
+fn main() {
+ let s = m::S;
+ s.abc(); //~ ERROR no method named `abc`
+}
+
+mod m {
+ pub trait Foo {
+ fn abc(&self) {}
+ }
+ pub struct S;
+ impl Foo for S{}
+}
diff --git a/tests/ui/suggestions/use-placement-typeck.rs b/tests/ui/suggestions/use-placement-typeck.rs
new file mode 100644
index 000000000..aab20d2e9
--- /dev/null
+++ b/tests/ui/suggestions/use-placement-typeck.rs
@@ -0,0 +1,20 @@
+// compile-flags: --test
+// run-rustfix
+// Checks that the `use` suggestion appears *below* this inner attribute.
+// There was an issue where the test synthetic #[allow(dead)] attribute on
+// main which has a dummy span caused the suggestion to be placed at the top
+// of the file.
+#![allow(unused)]
+
+fn main() {
+ let s = m::S;
+ s.abc(); //~ ERROR no method named `abc`
+}
+
+mod m {
+ pub trait Foo {
+ fn abc(&self) {}
+ }
+ pub struct S;
+ impl Foo for S{}
+}
diff --git a/tests/ui/suggestions/use-placement-typeck.stderr b/tests/ui/suggestions/use-placement-typeck.stderr
new file mode 100644
index 000000000..3b2749773
--- /dev/null
+++ b/tests/ui/suggestions/use-placement-typeck.stderr
@@ -0,0 +1,21 @@
+error[E0599]: no method named `abc` found for struct `S` in the current scope
+ --> $DIR/use-placement-typeck.rs:11:7
+ |
+LL | s.abc();
+ | ^^^ method not found in `S`
+...
+LL | fn abc(&self) {}
+ | --- the method is available for `S` here
+LL | }
+LL | pub struct S;
+ | ------------ method `abc` not found for this struct
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use m::Foo;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
new file mode 100644
index 000000000..8b6e8cfd7
--- /dev/null
+++ b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
@@ -0,0 +1,13 @@
+pub trait T<X, Y> {
+ type A;
+ type B;
+ type C;
+}
+pub struct Foo {
+ i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
+ //~^ ERROR must be specified
+ //~| ERROR this trait takes 2 generic arguments but 4 generic arguments were supplied
+}
+
+
+fn main() {}
diff --git a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
new file mode 100644
index 000000000..75b919232
--- /dev/null
+++ b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
@@ -0,0 +1,32 @@
+error[E0107]: this trait takes 2 generic arguments but 4 generic arguments were supplied
+ --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
+ |
+LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
+ | ^ expected 2 generic arguments
+ |
+note: trait defined here, with 2 generic parameters: `X`, `Y`
+ --> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11
+ |
+LL | pub trait T<X, Y> {
+ | ^ - -
+help: replace the generic bounds with the associated types
+ |
+LL | i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>,
+ | +++ +++
+
+error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified
+ --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
+ |
+LL | type A;
+ | ------ `A` defined here
+LL | type B;
+LL | type C;
+ | ------ `C` defined here
+...
+LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated types `A`, `C` must be specified
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0191.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/suggestions/while-let-typo.rs b/tests/ui/suggestions/while-let-typo.rs
new file mode 100644
index 000000000..dbbcdee3c
--- /dev/null
+++ b/tests/ui/suggestions/while-let-typo.rs
@@ -0,0 +1,9 @@
+fn main() {
+ let foo = Some(0);
+ let bar = None;
+ while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
+ while Some(foo) = bar {}
+ while 3 = foo {} //~ ERROR mismatched types
+ while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment
+ while x = 5 {} //~ ERROR cannot find value `x` in this scope
+}
diff --git a/tests/ui/suggestions/while-let-typo.stderr b/tests/ui/suggestions/while-let-typo.stderr
new file mode 100644
index 000000000..7cc2ed314
--- /dev/null
+++ b/tests/ui/suggestions/while-let-typo.stderr
@@ -0,0 +1,45 @@
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/while-let-typo.rs:4:16
+ |
+LL | while Some(x) = foo {}
+ | ^ not found in this scope
+ |
+help: you might have meant to use pattern matching
+ |
+LL | while let Some(x) = foo {}
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/while-let-typo.rs:8:11
+ |
+LL | while x = 5 {}
+ | ^ not found in this scope
+ |
+help: you might have meant to use pattern matching
+ |
+LL | while let x = 5 {}
+ | +++
+
+error[E0308]: mismatched types
+ --> $DIR/while-let-typo.rs:6:11
+ |
+LL | while 3 = foo {}
+ | ^^^^^^^ expected `bool`, found `()`
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/while-let-typo.rs:7:19
+ |
+LL | while Some(3) = foo {}
+ | - ^
+ | |
+ | cannot assign to this expression
+ |
+help: you might have meant to use pattern destructuring
+ |
+LL | while let Some(3) = foo {}
+ | +++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0070, E0308, E0425.
+For more information about an error, try `rustc --explain E0070`.