summaryrefslogtreecommitdiffstats
path: root/tests/ui/rfcs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfcs')
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check.rs33
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check.stderr35
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/parse.rs71
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr44
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs19
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs11
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs43
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs24
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr19
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs26
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr19
-rw-r--r--tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014-2.rs (renamed from tests/ui/rfcs/rfc-1014-2.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs (renamed from tests/ui/rfcs/rfc-1014.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs26
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs26
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs26
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs26
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs59
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs26
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs26
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs29
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr18
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs29
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr18
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs29
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr18
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs29
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr18
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr21
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs39
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr8
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs145
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr93
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs19
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs43
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr29
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs47
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr25
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs21
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr25
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs23
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr21
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs19
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs21
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs53
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/rfc1445/eq-allows-match-on-ty-in-macro.rs (renamed from tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/rfc1445/eq-allows-match.rs (renamed from tests/ui/rfcs/rfc1445/eq-allows-match.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs (renamed from tests/ui/rfcs/rfc1623-2.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr (renamed from tests/ui/rfcs/rfc1623-2.stderr)9
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs (renamed from tests/ui/rfcs/rfc1623-3.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr (renamed from tests/ui/rfcs/rfc1623-3.stderr)0
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623.rs (renamed from tests/ui/rfcs/rfc1623.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs (renamed from tests/ui/rfcs/rfc1717/library-override.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs4
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr4
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs7
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr4
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs9
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr8
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs7
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr4
-rw-r--r--tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs (renamed from tests/ui/rfcs/rfc1857-drop-order.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.rs11
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr15
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr15
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs18
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr15
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs11
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-ok.rs (renamed from tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs7
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs10
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs8
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-ok.rs (renamed from tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs)0
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.rs3
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs15
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr12
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs28
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.rs6
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs3
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.rs5
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr11
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs8
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.rs24
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/const.rs17
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/enum-ok.rs45
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs29
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/enum.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.rs28
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/for-ok.rs20
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs23
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr17
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.rs10
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/lit-ok.rs34
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs26
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr25
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.rs11
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/slice-ok.rs25
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs26
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs44
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/monovariants.rs8
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs41
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/unstable.rs60
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs7
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs44
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs18
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.rs11
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum.rs69
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr60
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate.rs18
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs37
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr69
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs29
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs24
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr47
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs48
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs16
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr30
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr75
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr31
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs53
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs273
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr184
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs45
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr30
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/struct.rs49
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/struct.stderr95
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs32
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs32
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.rs38
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.stderr35
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs45
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr35
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs36
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr79
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs51
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr79
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs40
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr79
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs57
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs21
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs34
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr83
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs41
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr64
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs37
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr83
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs47
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs59
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs70
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr38
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/variant.rs33
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/variant.stderr102
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/variants_fictive_visibility.rs12
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs18
-rw-r--r--tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs23
-rw-r--r--tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs68
-rw-r--r--tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs37
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/call-chain.rs30
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs32
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/caller-location-intrinsic.rs27
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/const-caller-location.rs43
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/diverging-caller-location.rs17
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.rs5
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.rs11
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-main.rs4
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs24
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr28
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs7
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/intrinsic-wrapper.rs22
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs10
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/mir-inlined-macro.rs23
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs5
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/pass.rs10
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs64
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/track-caller-attribute.rs40
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs48
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs154
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs62
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr.rs62
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-impls.rs77
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-obj.rs61
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.rs8
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.rs12
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr22
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/enum.rs27
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/enum.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.rs12
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.rs13
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.rs13
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.rs13
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.rs14
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/issue-54467.rs17
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.rs13
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.rs8
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.rs12
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.rs14
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/privacy.rs20
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/projection.rs8
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/reference.rs8
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs39
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr43
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs22
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs22
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs22
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs22
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.rs28
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr52
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.rs13
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.rs13
-rw-r--r--tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.rs11
-rw-r--r--tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.rs4
-rw-r--r--tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs5
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.rs5
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.rs6
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.rs5
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.rs9
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.rs11
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs9
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs26
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs18
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr35
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs74
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr256
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs16
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs16
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs97
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr65
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs41
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs25
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr54
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs18
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs40
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs23
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs16
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr25
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs21
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr28
-rw-r--r--tests/ui/rfcs/rfc-2302-self-struct-ctor/rfc-2302-self-struct-ctor.rs (renamed from tests/ui/rfcs/rfc-2302-self-struct-ctor.rs)0
-rw-r--r--tests/ui/rfcs/rfc-2306-convert-id/convert-id-const-with-gate.rs7
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs69
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr28
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs10
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs7
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr3
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr3
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs12
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs2
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs18
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr78
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs20
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr78
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs21
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr25
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.rs45
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.stderr50
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.rs10
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof/offsetof-alignof-sizeof-pure-can-be-used-as-idents.rs (renamed from tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs)0
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs1
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs3
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs9
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.stderr34
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/idents-normalized.rs7
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs4
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_with_path_allowed.rs6
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_inline_nonascii_allowed.rs7
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs20
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs16
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs6
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout10
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs23
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.rs14
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.rs19
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs340
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr1021
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs369
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr1013
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs54
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr141
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs60
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr106
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs47
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr74
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr115
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs78
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/issue-88498.rs16
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/issue-90722.rs11
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/issue-92145.rs11
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.rs8
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.stderr22
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/issue-99938.rs31
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/no-double-assigments.rs9
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.rs17
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs49
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs16
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs11
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs42
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs21
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.rs6
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr22
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs101
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs174
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr386
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs121
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr122
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs61
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs66
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr176
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs23
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs7
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs8
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs7
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs15
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs7
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs13
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs13
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs11
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs11
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs12
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs22
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs11
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs11
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs15
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs18
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs5
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs12
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs33
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.rs10
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs23
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs29
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs43
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr24
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs24
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs10
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr25
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs29
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.rs26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs46
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs37
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs117
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.rs12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs55
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs25
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs527
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr59
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs27
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr69
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/gate.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/gate.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.rs30
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs22
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.stderr22
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs39
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr23
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-103677.rs5
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs24
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs56
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs39
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs49
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs57
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs39
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.rs16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs63
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr25
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr42
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/static-const-trait-bound.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.rs21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr34
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs23
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs25
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/syntax.rs8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs37
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr45
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs58
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr256
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs6
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.rs6
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs50
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr29
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-method-ptr-in-consts-ice.rs23
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs33
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs41
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs24
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr59
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs6
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr10
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs14
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs3
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr25
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs16
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr31
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rsbin760 -> 767 bytes
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderrbin4477 -> 674 bytes
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs3
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr38
613 files changed, 18916 insertions, 251 deletions
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
new file mode 100644
index 000000000..e29811224
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
@@ -0,0 +1,33 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+enum Void {}
+
+fn main() {}
+
+macro_rules! never {
+ () => { ! }
+}
+
+fn no_arms_or_guards(x: Void) {
+ match None::<Void> {
+ Some(!) => {}
+ //~^ ERROR a never pattern is always unreachable
+ None => {}
+ }
+ match None::<Void> {
+ Some(!) if true,
+ //~^ ERROR guard on a never pattern
+ None => {}
+ }
+ match None::<Void> {
+ Some(!) if true => {}
+ //~^ ERROR a never pattern is always unreachable
+ None => {}
+ }
+ match None::<Void> {
+ Some(never!()) => {},
+ //~^ ERROR a never pattern is always unreachable
+ None => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
new file mode 100644
index 000000000..bfbc7a1b5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
@@ -0,0 +1,35 @@
+error: a never pattern is always unreachable
+ --> $DIR/check.rs:14:20
+ |
+LL | Some(!) => {}
+ | ^^
+ | |
+ | this will never be executed
+ | help: remove this expression
+
+error: a guard on a never pattern will never be run
+ --> $DIR/check.rs:19:20
+ |
+LL | Some(!) if true,
+ | ^^^^ help: remove this guard
+
+error: a never pattern is always unreachable
+ --> $DIR/check.rs:24:28
+ |
+LL | Some(!) if true => {}
+ | ^^
+ | |
+ | this will never be executed
+ | help: remove this expression
+
+error: a never pattern is always unreachable
+ --> $DIR/check.rs:29:27
+ |
+LL | Some(never!()) => {},
+ | ^^
+ | |
+ | this will never be executed
+ | help: remove this expression
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs
new file mode 100644
index 000000000..1b23e60e0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs
@@ -0,0 +1,71 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+enum Void {}
+
+fn main() {}
+
+macro_rules! never {
+ () => { ! }
+}
+
+fn parse(x: Void) {
+ match None::<Void> {
+ None => {}
+ Some(!),
+ }
+ match None::<Void> {
+ Some(!),
+ None => {}
+ }
+ match None::<Void> {
+ None => {}
+ Some(!)
+ }
+ match None::<Void> {
+ Some(!)
+ //~^ ERROR expected `,` following `match` arm
+ None => {}
+ }
+ match None::<Void> {
+ Some(!) if true
+ //~^ ERROR expected `,` following `match` arm
+ //~| ERROR guard on a never pattern
+ None => {}
+ }
+ match None::<Void> {
+ Some(!) if true,
+ //~^ ERROR guard on a never pattern
+ None => {}
+ }
+ match None::<Void> {
+ Some(!) <=
+ //~^ ERROR expected one of
+ }
+ match x {
+ never!(),
+ }
+ match x {
+ never!() if true,
+ //~^ ERROR guard on a never pattern
+ }
+ match x {
+ never!()
+ }
+ match &x {
+ &never!(),
+ }
+ match None::<Void> {
+ Some(never!()),
+ None => {}
+ }
+ match x { ! }
+ match &x { &! }
+
+ let res: Result<bool, Void> = Ok(false);
+ let Ok(_) = res;
+ let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
+ //~^ ERROR top-level or-patterns are not allowed in `let` bindings
+ let (Ok(_) | Err(!)) = &res;
+ let (Ok(_) | Err(&!)) = res.as_ref();
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr
new file mode 100644
index 000000000..e81a13a39
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr
@@ -0,0 +1,44 @@
+error: expected `,` following `match` arm
+ --> $DIR/parse.rs:26:16
+ |
+LL | Some(!)
+ | ^ help: missing a comma here to end this `match` arm: `,`
+
+error: expected `,` following `match` arm
+ --> $DIR/parse.rs:31:24
+ |
+LL | Some(!) if true
+ | ^ help: missing a comma here to end this `match` arm: `,`
+
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `<=`
+ --> $DIR/parse.rs:42:17
+ |
+LL | Some(!) <=
+ | ^^ expected one of `,`, `=>`, `if`, `|`, or `}`
+
+error: top-level or-patterns are not allowed in `let` bindings
+ --> $DIR/parse.rs:67:9
+ |
+LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
+ | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))`
+
+error: a guard on a never pattern will never be run
+ --> $DIR/parse.rs:31:20
+ |
+LL | Some(!) if true
+ | ^^^^ help: remove this guard
+
+error: a guard on a never pattern will never be run
+ --> $DIR/parse.rs:37:20
+ |
+LL | Some(!) if true,
+ | ^^^^ help: remove this guard
+
+error: a guard on a never pattern will never be run
+ --> $DIR/parse.rs:49:21
+ |
+LL | never!() if true,
+ | ^^^^ help: remove this guard
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
new file mode 100644
index 000000000..1e086160f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
@@ -0,0 +1,19 @@
+// Adaptation of existing ui test (from way back in
+// rust-lang/rust#2329), that starts passing with this feature in
+// place.
+
+// run-pass
+
+use std::sync::mpsc::channel;
+
+fn main() {
+ let (tx, rx) = channel();
+ let x = Some(rx);
+ tx.send(false).unwrap();
+ tx.send(false).unwrap();
+ match x {
+ Some(z) if z.recv().unwrap() => { panic!() },
+ Some(z) => { assert!(!z.recv().unwrap()); },
+ None => panic!()
+ }
+}
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs
new file mode 100644
index 000000000..3161d6fbb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs
@@ -0,0 +1,11 @@
+// This test used to emit E0008 but now passed since `bind_by_move_pattern_guards`
+// have been stabilized.
+
+// check-pass
+
+fn main() {
+ match Some("hi".to_string()) {
+ Some(s) if s.len() == 0 => {},
+ _ => {},
+ }
+}
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
new file mode 100644
index 000000000..b716fc870
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
@@ -0,0 +1,43 @@
+// run-pass
+
+struct A { a: Box<i32> }
+
+impl A {
+ fn get(&self) -> i32 { *self.a }
+}
+
+fn foo(n: i32) -> i32 {
+ let x = A { a: Box::new(n) };
+ let y = match x {
+ A { a: v } if *v == 42 => v,
+ _ => Box::new(0),
+ };
+ *y
+}
+
+fn bar(n: i32) -> i32 {
+ let x = A { a: Box::new(n) };
+ let y = match x {
+ A { a: v } if x.get() == 42 => v,
+ _ => Box::new(0),
+ };
+ *y
+}
+
+fn baz(n: i32) -> i32 {
+ let x = A { a: Box::new(n) };
+ let y = match x {
+ A { a: v } if *v.clone() == 42 => v,
+ _ => Box::new(0),
+ };
+ *y
+}
+
+fn main() {
+ assert_eq!(foo(107), 0);
+ assert_eq!(foo(42), 42);
+ assert_eq!(bar(107), 0);
+ assert_eq!(bar(42), 42);
+ assert_eq!(baz(107), 0);
+ assert_eq!(baz(42), 42);
+}
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
new file mode 100644
index 000000000..6f0d2b045
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
@@ -0,0 +1,24 @@
+#![feature(if_let_guard)]
+
+enum VecWrapper { A(Vec<i32>) }
+
+fn if_guard(x: VecWrapper) -> usize {
+ match x {
+ VecWrapper::A(v) if { drop(v); false } => 1,
+ //~^ ERROR cannot move out of `v` in pattern guard
+ VecWrapper::A(v) => v.len()
+ }
+}
+
+fn if_let_guard(x: VecWrapper) -> usize {
+ match x {
+ VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
+ //~^ ERROR cannot move out of `v` in pattern guard
+ VecWrapper::A(v) => v.len()
+ }
+}
+
+fn main() {
+ if_guard(VecWrapper::A(vec![107]));
+ if_let_guard(VecWrapper::A(vec![107]));
+}
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
new file mode 100644
index 000000000..a749361bf
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
@@ -0,0 +1,19 @@
+error[E0507]: cannot move out of `v` in pattern guard
+ --> $DIR/rfc-reject-double-move-across-arms.rs:7:36
+ |
+LL | VecWrapper::A(v) if { drop(v); false } => 1,
+ | ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
+ |
+ = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error[E0507]: cannot move out of `v` in pattern guard
+ --> $DIR/rfc-reject-double-move-across-arms.rs:15:51
+ |
+LL | VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
+ | ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
+ |
+ = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
new file mode 100644
index 000000000..827335f6a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
@@ -0,0 +1,26 @@
+#![feature(if_let_guard)]
+
+struct A { a: Box<i32> }
+
+fn if_guard(n: i32) {
+ let x = A { a: Box::new(n) };
+ let _y = match x {
+ A { a: v } if { drop(v); true } => v,
+ //~^ ERROR cannot move out of `v` in pattern guard
+ _ => Box::new(0),
+ };
+}
+
+fn if_let_guard(n: i32) {
+ let x = A { a: Box::new(n) };
+ let _y = match x {
+ A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
+ //~^ ERROR cannot move out of `v` in pattern guard
+ _ => Box::new(0),
+ };
+}
+
+fn main() {
+ if_guard(107);
+ if_let_guard(107);
+}
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
new file mode 100644
index 000000000..9285492b2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
@@ -0,0 +1,19 @@
+error[E0507]: cannot move out of `v` in pattern guard
+ --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30
+ |
+LL | A { a: v } if { drop(v); true } => v,
+ | ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
+ |
+ = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error[E0507]: cannot move out of `v` in pattern guard
+ --> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45
+ |
+LL | A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
+ | ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
+ |
+ = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/rfcs/rfc-1014-2.rs b/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014-2.rs
index 7dd65701f..7dd65701f 100644
--- a/tests/ui/rfcs/rfc-1014-2.rs
+++ b/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014-2.rs
diff --git a/tests/ui/rfcs/rfc-1014.rs b/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs
index c454dfa4e..c454dfa4e 100644
--- a/tests/ui/rfcs/rfc-1014.rs
+++ b/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
new file mode 100644
index 000000000..1914e1554
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapEmbedded(*const NoDerive);
+
+const WRAP_UNSAFE_EMBEDDED: WrapEmbedded = WrapEmbedded(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_EMBEDDED {
+ WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
new file mode 100644
index 000000000..e713b003b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<X>(*const X);
+
+const WRAP_UNSAFE_PARAM: WrapParam<NoDerive> = WrapParam(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_PARAM {
+ WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
new file mode 100644
index 000000000..04da14c54
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapEmbedded(*const NoDerive);
+
+const WRAP_UNSAFE_EMBEDDED: & &WrapEmbedded = & &WrapEmbedded(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_EMBEDDED {
+ WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
new file mode 100644
index 000000000..8313c25e7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<X>(*const X);
+
+const WRAP_UNSAFE_PARAM: & &WrapParam<NoDerive> = & &WrapParam(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_PARAM {
+ WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs
new file mode 100644
index 000000000..dca8aaef1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs
@@ -0,0 +1,59 @@
+// rust-lang/rust#62614: we want to allow matching on constants of types that
+// have non-structural-match variants, *if* the constant itself does not use
+// any such variant.
+
+// NOTE: for now, deliberately leaving the lint `indirect_structural_match` set
+// to its default, so that we will not issue a diangostic even if
+// rust-lang/rust#62614 remains an open issue.
+
+// run-pass
+
+struct Sum(u32, u32);
+
+impl PartialEq for Sum {
+ fn eq(&self, other: &Self) -> bool { self.0 + self.1 == other.0 + other.1 }
+}
+
+impl Eq for Sum { }
+
+#[derive(PartialEq, Eq)]
+enum Eek {
+ TheConst,
+ UnusedByTheConst(Sum)
+}
+
+const THE_CONST: Eek = Eek::TheConst;
+const SUM_THREE: Eek = Eek::UnusedByTheConst(Sum(3,0));
+
+const EEK_ZERO: &[Eek] = &[];
+const EEK_ONE: &[Eek] = &[THE_CONST];
+
+pub fn main() {
+ match Eek::UnusedByTheConst(Sum(1,2)) {
+ ref sum if sum == &SUM_THREE => { println!("Hello 0"); }
+ _ => { println!("Gbye"); }
+ }
+
+ match Eek::TheConst {
+ THE_CONST => { println!("Hello 1"); }
+ _ => { println!("Gbye"); }
+ }
+
+
+ match & &Eek::TheConst {
+ & & THE_CONST => { println!("Hello 2"); }
+ _ => { println!("Gbye"); }
+ }
+
+ match & & &[][..] {
+ & & EEK_ZERO => { println!("Hello 3"); }
+ & & EEK_ONE => { println!("Gbye"); }
+ _ => { println!("Gbye"); }
+ }
+
+ match & & &[Eek::TheConst][..] {
+ & & EEK_ZERO => { println!("Gby"); }
+ & & EEK_ONE => { println!("Hello 4"); }
+ _ => { println!("Gbye"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
new file mode 100644
index 000000000..7623839fd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
@@ -0,0 +1,26 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline(NoDerive);
+
+const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0));
+
+fn main() {
+ match WRAP_DIRECT_INLINE {
+ WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
new file mode 100644
index 000000000..334bd7618
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
+ |
+LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
new file mode 100644
index 000000000..93022a23d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
@@ -0,0 +1,26 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<T>(T);
+
+const WRAP_DIRECT_PARAM: WrapParam<NoDerive> = WrapParam(NoDerive(0));
+
+fn main() {
+ match WRAP_DIRECT_PARAM {
+ WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
new file mode 100644
index 000000000..58bfcbb45
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
+ |
+LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
new file mode 100644
index 000000000..894739ff7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline<'a>(&'a &'a NoDerive);
+
+const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0));
+
+fn main() {
+ match WRAP_DOUBLY_INDIRECT_INLINE {
+ WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
new file mode 100644
index 000000000..94ee2216e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
@@ -0,0 +1,18 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9
+ |
+LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9
+ |
+LL | #![warn(indirect_structural_match)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
new file mode 100644
index 000000000..1699dae46
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<'a, T>(&'a &'a T);
+
+const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(& & NoDerive(0));
+
+fn main() {
+ match WRAP_DOUBLY_INDIRECT_PARAM {
+ WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
new file mode 100644
index 000000000..666b7b95e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
@@ -0,0 +1,18 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9
+ |
+LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9
+ |
+LL | #![warn(indirect_structural_match)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
new file mode 100644
index 000000000..2672bdd9e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline(NoDerive);
+
+const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0));
+
+fn main() {
+ match WRAP_INDIRECT_INLINE {
+ WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
new file mode 100644
index 000000000..ecbe83f3d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
@@ -0,0 +1,18 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9
+ |
+LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9
+ |
+LL | #![warn(indirect_structural_match)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
new file mode 100644
index 000000000..3489995ae
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<T>(T);
+
+const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
+
+fn main() {
+ match WRAP_INDIRECT_PARAM {
+ WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
new file mode 100644
index 000000000..211990801
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
@@ -0,0 +1,18 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9
+ |
+LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9
+ |
+LL | #![warn(indirect_structural_match)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
new file mode 100644
index 000000000..bd2940479
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
@@ -0,0 +1,21 @@
+error[E0658]: use of unstable library feature 'structural_match'
+ --> $DIR/feature-gate.rs:29:6
+ |
+LL | impl std::marker::StructuralPartialEq for Foo { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
+ = help: add `#![feature(structural_match)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'structural_match'
+ --> $DIR/feature-gate.rs:31:6
+ |
+LL | impl std::marker::StructuralEq for Foo { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
+ = help: add `#![feature(structural_match)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
new file mode 100644
index 000000000..ee6674097
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
@@ -0,0 +1,39 @@
+// Test that use of structural-match traits is only permitted with a feature gate,
+// and that if a feature gate is supplied, it permits the type to be
+// used in a match.
+
+// revisions: with_gate no_gate
+
+// gate-test-structural_match
+
+#![allow(unused)]
+#![feature(rustc_attrs)]
+#![cfg_attr(with_gate, feature(structural_match))]
+
+
+struct Foo {
+ x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+#[rustc_error]
+fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ _ => { }
+ }
+}
+
+impl std::marker::StructuralPartialEq for Foo { }
+//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+impl std::marker::StructuralEq for Foo { }
+//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+
+impl PartialEq<Foo> for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.x == other.x
+ }
+}
+impl Eq for Foo { }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
new file mode 100644
index 000000000..505b7d79c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+ --> $DIR/feature-gate.rs:21:1
+ |
+LL | fn main() {
+ | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
new file mode 100644
index 000000000..e591b2a93
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
@@ -0,0 +1,145 @@
+// run-pass
+
+// This file checks that fn ptrs are considered structurally matchable.
+// See also rust-lang/rust#63479.
+
+fn main() {
+ let mut count = 0;
+
+ // A type which is not structurally matchable:
+ struct NotSM;
+
+ // And one that is:
+ #[derive(PartialEq, Eq)]
+ struct SM;
+
+ fn trivial() {}
+
+ fn sm_to(_: SM) {}
+ fn not_sm_to(_: NotSM) {}
+ fn to_sm() -> SM { SM }
+ fn to_not_sm() -> NotSM { NotSM }
+
+ // To recreate the scenario of interest in #63479, we need to add
+ // a ref-level-of-indirection so that we descend into the type.
+
+ fn r_sm_to(_: &SM) {}
+ fn r_not_sm_to(_: &NotSM) {}
+ fn r_to_r_sm(_: &()) -> &SM { &SM }
+ fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM }
+
+ #[derive(PartialEq, Eq)]
+ struct Wrap<T>(T);
+
+ // In the code below, we put the match input into a local so that
+ // we can assign it an explicit type that is an fn ptr instead of
+ // a singleton type of the fn itself that the type inference would
+ // otherwise assign.
+
+ // Check that fn() is structural-match
+ const CFN1: Wrap<fn()> = Wrap(trivial);
+ let input: Wrap<fn()> = Wrap(trivial);
+ match Wrap(input) {
+ Wrap(CFN1) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn(T) is structural-match when T is too.
+ const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
+ let input: Wrap<fn(SM)> = Wrap(sm_to);
+ match Wrap(input) {
+ Wrap(CFN2) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> T is structural-match when T is too.
+ const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
+ let input: Wrap<fn() -> SM> = Wrap(to_sm);
+ match Wrap(input) {
+ Wrap(CFN3) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn(T) is structural-match even if T is not.
+ const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+ let input: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+ match Wrap(input) {
+ Wrap(CFN4) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> T is structural-match even if T is not.
+ const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+ let input: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+ match Wrap(input) {
+ Wrap(CFN5) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn(&T) is structural-match when T is too.
+ const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
+ let input: Wrap<fn(&SM)> = Wrap(r_sm_to);
+ match Wrap(input) {
+ Wrap(CFN6) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> &T is structural-match when T is too.
+ const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+ let input: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+ match Wrap(input) {
+ Wrap(CFN7) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn(T) is structural-match even if T is not.
+ const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+ let input: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+ match Wrap(input) {
+ Wrap(CFN8) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> T is structural-match even if T is not.
+ const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+ let input: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+ match Wrap(input) {
+ Wrap(CFN9) => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Wrap(_) => {}
+ };
+
+ // Check that a type which has fn ptrs is structural-match.
+ #[derive(PartialEq, Eq)]
+ struct Foo {
+ alpha: fn(NotSM),
+ beta: fn() -> NotSM,
+ gamma: fn(SM),
+ delta: fn() -> SM,
+ }
+
+ const CFOO: Foo = Foo {
+ alpha: not_sm_to,
+ beta: to_not_sm,
+ gamma: sm_to,
+ delta: to_sm,
+ };
+
+ let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm };
+ match input {
+ CFOO => count += 1, //~WARN behave unpredictably
+ //~| previously accepted
+ Foo { .. } => {}
+ };
+
+ // Final count must be 10 now if all
+ assert_eq!(count, 10);
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr
new file mode 100644
index 000000000..080bf5885
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr
@@ -0,0 +1,93 @@
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14
+ |
+LL | Wrap(CFN1) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+ = note: `#[warn(pointer_structural_match)]` on by default
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14
+ |
+LL | Wrap(CFN2) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14
+ |
+LL | Wrap(CFN3) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14
+ |
+LL | Wrap(CFN4) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14
+ |
+LL | Wrap(CFN5) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14
+ |
+LL | Wrap(CFN6) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14
+ |
+LL | Wrap(CFN7) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14
+ |
+LL | Wrap(CFN8) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14
+ |
+LL | Wrap(CFN9) => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9
+ |
+LL | CFOO => count += 1,
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: 10 warnings emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
new file mode 100644
index 000000000..2a915d61e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
@@ -0,0 +1,19 @@
+// Issue 61188 pointed out a case where we hit an ICE during code gen:
+// the compiler assumed that `PartialEq` was always implemented on any
+// use of a `const` item in a pattern context, but the pre-existing
+// structural-match checking was too shallow
+// (see rust-lang/rust#62307), and so we hit cases where we were
+// trying to dispatch to `PartialEq` on types that did not implement
+// that trait.
+
+struct B(i32);
+
+const A: &[B] = &[];
+
+pub fn main() {
+ match &[][..] {
+ A => (),
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => (),
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
new file mode 100644
index 000000000..729e747de
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9
+ |
+LL | A => (),
+ | ^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
new file mode 100644
index 000000000..46d8ee3b6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
@@ -0,0 +1,43 @@
+// RFC 1445 introduced `#[structural_match]`; this attribute must
+// appear on the `struct`/`enum` definition for any `const` used in a
+// pattern.
+//
+// This is our (forever-unstable) way to mark a datatype as having a
+// `PartialEq` implementation that is equivalent to recursion over its
+// substructure. This avoids (at least in the short term) any need to
+// resolve the question of what semantics is used for such matching.
+// (See RFC 1445 for more details and discussion.)
+
+// Issue 62307 pointed out a case where the structural-match checking
+// was too shallow.
+#![warn(indirect_structural_match, nontrivial_structural_match)]
+// run-pass
+
+#[derive(Debug)]
+struct B(i32);
+
+// Overriding `PartialEq` to use this strange notion of "equality" exposes
+// whether `match` is using structural-equality or method-dispatch
+// under the hood, which is the antithesis of rust-lang/rfcs#1445
+impl PartialEq for B {
+ fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 }
+}
+
+fn main() {
+ const RR_B0: & & B = & & B(0);
+ const RR_B1: & & B = & & B(1);
+
+ match RR_B0 {
+ RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { }
+ }
+
+ match RR_B1 {
+ RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
new file mode 100644
index 000000000..435812306
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
@@ -0,0 +1,29 @@
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9
+ |
+LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+note: the lint level is defined here
+ --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
+ |
+LL | #![warn(indirect_structural_match, nontrivial_structural_match)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
+ |
+LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs
new file mode 100644
index 000000000..b05b8c8da
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs
@@ -0,0 +1,47 @@
+// run-pass
+
+// The actual regression test from #63479. (Including this because my
+// first draft at fn-ptr-is-structurally-matchable.rs failed to actually
+// cover the case this hit; I've since expanded it accordingly, but the
+// experience left me wary of leaving this regression test out.)
+
+#![warn(pointer_structural_match)]
+
+#[derive(Eq)]
+struct A {
+ a: i64
+}
+
+impl PartialEq for A {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.a.eq(&other.a)
+ }
+}
+
+type Fn = fn(&[A]);
+
+fn my_fn(_args: &[A]) {
+ println!("hello world");
+}
+
+const TEST: Fn = my_fn;
+const TEST2: (Fn, u8) = (TEST, 0);
+
+struct B(Fn);
+
+fn main() {
+ let s = B(my_fn);
+ match s {
+ B(TEST) => println!("matched"),
+ //~^ WARN behave unpredictably
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => panic!("didn't match")
+ };
+ match (s.0, 0) {
+ TEST2 => println!("matched"),
+ //~^ WARN behave unpredictably
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => panic!("didn't match")
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
new file mode 100644
index 000000000..4fdfce60b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
@@ -0,0 +1,25 @@
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/issue-63479-match-fnptr.rs:36:7
+ |
+LL | B(TEST) => println!("matched"),
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+note: the lint level is defined here
+ --> $DIR/issue-63479-match-fnptr.rs:8:9
+ |
+LL | #![warn(pointer_structural_match)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/issue-63479-match-fnptr.rs:42:5
+ |
+LL | TEST2 => println!("matched"),
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs
new file mode 100644
index 000000000..0260caa82
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs
@@ -0,0 +1,21 @@
+// Matching against NaN should result in a warning
+
+#![allow(unused)]
+#![deny(illegal_floating_point_literal_pattern)]
+
+const NAN: f64 = f64::NAN;
+
+fn main() {
+ let x = NAN;
+ match x {
+ NAN => {}, //~ ERROR floating-point types cannot be used
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => {},
+ };
+
+ match [x, 1.0] {
+ [NAN, _] => {}, //~ ERROR floating-point types cannot be used
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => {},
+ };
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
new file mode 100644
index 000000000..f37255d08
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
@@ -0,0 +1,25 @@
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-6804.rs:11:9
+ |
+LL | NAN => {},
+ | ^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+note: the lint level is defined here
+ --> $DIR/issue-6804.rs:4:9
+ |
+LL | #![deny(illegal_floating_point_literal_pattern)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-6804.rs:17:10
+ |
+LL | [NAN, _] => {},
+ | ^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs
new file mode 100644
index 000000000..7ba0f3a9e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs
@@ -0,0 +1,17 @@
+// Pre-existing behavior has been to reject patterns with consts
+// denoting non-empty arrays of non-`Eq` types, but *accept* empty
+// arrays of such types.
+//
+// See rust-lang/rust#62336.
+
+// run-pass
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+fn main() {
+ const FOO: [B; 0] = [];
+ match [] {
+ FOO => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs
new file mode 100644
index 000000000..59a22c337
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs
@@ -0,0 +1,23 @@
+#[derive(PartialEq)]
+struct Foo {
+ x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { }
+ }
+
+ let x = 0.0;
+ match x {
+ f32::INFINITY => { }
+ //~^ WARNING floating-point types cannot be used in patterns
+ //~| WARNING this was previously accepted by the compiler but is being phased out
+ _ => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
new file mode 100644
index 000000000..c2000df88
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
@@ -0,0 +1,21 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/match-forbidden-without-eq.rs:11:9
+ |
+LL | FOO => { }
+ | ^^^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+warning: floating-point types cannot be used in patterns
+ --> $DIR/match-forbidden-without-eq.rs:18:9
+ |
+LL | f32::INFINITY => { }
+ | ^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+ = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs
new file mode 100644
index 000000000..151a475c9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs
@@ -0,0 +1,19 @@
+// Issue 62307 pointed out a case where the structural-match checking
+// was too shallow.
+//
+// Here we check similar behavior for non-empty arrays of types that
+// do not derive `Eq`.
+//
+// (Current behavior for empty arrays differs and thus is not tested
+// here; see rust-lang/rust#62336.)
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+fn main() {
+ const FOO: [B; 1] = [B(0)];
+ match [B(1)] {
+ FOO => { }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr
new file mode 100644
index 000000000..477789f33
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
+ |
+LL | FOO => { }
+ | ^^^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
new file mode 100644
index 000000000..a8deb8a75
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
@@ -0,0 +1,21 @@
+#[derive(Eq)]
+struct Foo {
+ x: u32
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, _: &Foo) -> bool {
+ false // ha ha!
+ }
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
new file mode 100644
index 000000000..b806046db
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+ |
+LL | FOO => { }
+ | ^^^
+ |
+ = note: the traits must be derived, manual `impl`s are not sufficient
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs
new file mode 100644
index 000000000..50f91420c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs
@@ -0,0 +1,53 @@
+// run-pass
+
+// This file checks that `PhantomData` is considered structurally matchable.
+
+use std::marker::PhantomData;
+
+fn main() {
+ let mut count = 0;
+
+ // A type which is not structurally matchable:
+ struct NotSM;
+
+ // And one that is:
+ #[derive(PartialEq, Eq)]
+ struct SM;
+
+ // Check that SM is structural-match:
+ const CSM: SM = SM;
+ match SM {
+ CSM => count += 1,
+ };
+
+ // Check that PhantomData<T> is structural-match even if T is not.
+ const CPD1: PhantomData<NotSM> = PhantomData;
+ match PhantomData {
+ CPD1 => count += 1,
+ };
+
+ // Check that PhantomData<T> is structural-match when T is.
+ const CPD2: PhantomData<SM> = PhantomData;
+ match PhantomData {
+ CPD2 => count += 1,
+ };
+
+ // Check that a type which has a PhantomData is structural-match.
+ #[derive(PartialEq, Eq, Default)]
+ struct Foo {
+ alpha: PhantomData<NotSM>,
+ beta: PhantomData<SM>,
+ }
+
+ const CFOO: Foo = Foo {
+ alpha: PhantomData,
+ beta: PhantomData,
+ };
+
+ match Foo::default() {
+ CFOO => count += 1,
+ };
+
+ // Final count must be 4 now if all
+ assert_eq!(count, 4);
+}
diff --git a/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/rfc1445/eq-allows-match-on-ty-in-macro.rs
index 17174e22c..17174e22c 100644
--- a/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/rfc1445/eq-allows-match-on-ty-in-macro.rs
diff --git a/tests/ui/rfcs/rfc1445/eq-allows-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/rfc1445/eq-allows-match.rs
index 405a69c94..405a69c94 100644
--- a/tests/ui/rfcs/rfc1445/eq-allows-match.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/rfc1445/eq-allows-match.rs
diff --git a/tests/ui/rfcs/rfc1623-2.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
index c0e13a5f5..c0e13a5f5 100644
--- a/tests/ui/rfcs/rfc1623-2.rs
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
diff --git a/tests/ui/rfcs/rfc1623-2.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
index d183eaaa6..52c700c32 100644
--- a/tests/ui/rfcs/rfc1623-2.stderr
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | f: &id,
| ^^^ one type is more general than the other
|
- = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
- found trait `Fn<(&Foo<'_>,)>`
+ = note: expected trait `for<'a, 'b> Fn(&'a Foo<'b>)`
+ found trait `Fn(&Foo<'_>)`
error[E0308]: mismatched types
--> $DIR/rfc1623-2.rs:28:8
@@ -13,8 +13,9 @@ error[E0308]: mismatched types
LL | f: &id,
| ^^^ one type is more general than the other
|
- = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
- found trait `Fn<(&Foo<'_>,)>`
+ = note: expected trait `for<'a, 'b> Fn(&'a Foo<'b>)`
+ found trait `Fn(&Foo<'_>)`
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: implementation of `FnOnce` is not general enough
--> $DIR/rfc1623-2.rs:28:8
diff --git a/tests/ui/rfcs/rfc1623-3.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs
index 26fa6fdb5..26fa6fdb5 100644
--- a/tests/ui/rfcs/rfc1623-3.rs
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs
diff --git a/tests/ui/rfcs/rfc1623-3.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr
index 77fc3f041..77fc3f041 100644
--- a/tests/ui/rfcs/rfc1623-3.stderr
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr
diff --git a/tests/ui/rfcs/rfc1623.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623.rs
index adaf25c6b..adaf25c6b 100644
--- a/tests/ui/rfcs/rfc1623.rs
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623.rs
diff --git a/tests/ui/rfcs/rfc1717/library-override.rs b/tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs
index 014ccac31..014ccac31 100644
--- a/tests/ui/rfcs/rfc1717/library-override.rs
+++ b/tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs
new file mode 100644
index 000000000..b46d85160
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs
@@ -0,0 +1,4 @@
+// compile-flags: -l foo:bar
+// error-pattern: renaming of the library `foo` was specified
+
+#![crate_type = "lib"]
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr
new file mode 100644
index 000000000..4218ef31e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr
@@ -0,0 +1,4 @@
+error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs
new file mode 100644
index 000000000..106f196b4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs
@@ -0,0 +1,7 @@
+// compile-flags: -l foo:bar -l foo:baz
+// error-pattern: multiple renamings were specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr
new file mode 100644
index 000000000..d931e23c7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr
@@ -0,0 +1,4 @@
+error: multiple renamings were specified for library `foo`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs
new file mode 100644
index 000000000..30f4db718
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs
@@ -0,0 +1,9 @@
+// compile-flags: -l dylib=foo:bar
+// error-pattern: overriding linking modifiers from command line is not supported
+
+#![feature(native_link_modifiers_as_needed)]
+
+#![crate_type = "lib"]
+
+#[link(name = "foo", kind = "dylib", modifiers = "-as-needed")]
+extern "C" {}
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr
new file mode 100644
index 000000000..ce145689f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr
@@ -0,0 +1,8 @@
+error: overriding linking modifiers from command line is not supported
+ --> $DIR/rename-modifiers.rs:9:1
+ |
+LL | extern "C" {}
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs
new file mode 100644
index 000000000..9356c4129
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs
@@ -0,0 +1,7 @@
+// compile-flags: -l foo:
+// error-pattern: an empty renaming target was specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr
new file mode 100644
index 000000000..c208e0503
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr
@@ -0,0 +1,4 @@
+error: an empty renaming target was specified for library `foo`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc1857-drop-order.rs b/tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
index 4c4816c2f..4c4816c2f 100644
--- a/tests/ui/rfcs/rfc1857-drop-order.rs
+++ b/tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.rs b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.rs
new file mode 100644
index 000000000..a75c91cc9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.rs
@@ -0,0 +1,11 @@
+// Check that we don't blindly emit a diagnostic claiming that "`main` has an invalid return type"
+// if we encounter a type that doesn't implement `std::process::Termination` and is not actually
+// the return type of the program entry `main`.
+
+fn receive(_: impl std::process::Termination) {}
+
+struct Something;
+
+fn main() {
+ receive(Something); //~ ERROR the trait bound `Something: Termination` is not satisfied
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr
new file mode 100644
index 000000000..6c3d576cf
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+ --> $DIR/issue-103052-1.rs:10:13
+ |
+LL | receive(Something);
+ | ------- ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `receive`
+ --> $DIR/issue-103052-1.rs:5:20
+ |
+LL | fn receive(_: impl std::process::Termination) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `receive`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr
new file mode 100644
index 000000000..f2727336b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+ --> $DIR/issue-103052-2.rs:15:22
+ |
+LL | fn main() -> Something {
+ | ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+ |
+note: required by a bound in `Main::main::{opaque#0}`
+ --> $DIR/issue-103052-2.rs:9:27
+ |
+LL | fn main() -> impl std::process::Termination;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr
new file mode 100644
index 000000000..4bb420664
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+ --> $DIR/issue-103052-2.rs:15:22
+ |
+LL | fn main() -> Something {
+ | ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+ |
+note: required by a bound in `Main::{opaque#0}`
+ --> $DIR/issue-103052-2.rs:9:27
+ |
+LL | fn main() -> impl std::process::Termination;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs
new file mode 100644
index 000000000..1933a68c2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs
@@ -0,0 +1,18 @@
+#![allow(incomplete_features)]
+
+mod child {
+ trait Main {
+ fn main() -> impl std::process::Termination;
+ }
+
+ struct Something;
+
+ impl Main for () {
+ fn main() -> Something {
+ //~^ ERROR the trait bound `Something: Termination` is not satisfied
+ Something
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
new file mode 100644
index 000000000..3fbbfd0fd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+ --> $DIR/issue-103052-2.rs:11:22
+ |
+LL | fn main() -> Something {
+ | ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+ |
+note: required by a bound in `Main::{opaque#0}`
+ --> $DIR/issue-103052-2.rs:5:27
+ |
+LL | fn main() -> impl std::process::Termination;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs
new file mode 100644
index 000000000..10dc6115d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs
@@ -0,0 +1,11 @@
+// run-fail
+// error-pattern:returned Box<dyn Error> from main()
+// failure-status: 1
+// ignore-emscripten no processes
+
+use std::error::Error;
+use std::io;
+
+fn main() -> Result<(), Box<dyn Error>> {
+ Err(Box::new(io::Error::new(io::ErrorKind::Other, "returned Box<dyn Error> from main()")))
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-ok.rs
index e98582cbc..e98582cbc 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-ok.rs
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs
new file mode 100644
index 000000000..faf2526c8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs
@@ -0,0 +1,7 @@
+// run-fail
+// error-pattern:oh, dear
+// ignore-emscripten no processes
+
+fn main() -> ! {
+ panic!("oh, dear");
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs
new file mode 100644
index 000000000..6a625fb05
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs
@@ -0,0 +1,10 @@
+// run-fail
+// error-pattern:returned Box<Error> from main()
+// failure-status: 1
+// ignore-emscripten no processes
+
+use std::io::{Error, ErrorKind};
+
+fn main() -> Result<(), Box<Error>> {
+ Err(Box::new(Error::new(ErrorKind::Other, "returned Box<Error> from main()")))
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs
new file mode 100644
index 000000000..94f16c6fd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs
@@ -0,0 +1,8 @@
+// run-fail
+// error-pattern: An error message for you
+// failure-status: 1
+// ignore-emscripten no processes
+
+fn main() -> Result<(), &'static str> {
+ Err("An error message for you")
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-ok.rs
index f0591c38c..f0591c38c 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-ok.rs
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.rs
new file mode 100644
index 000000000..3b60cbc57
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.rs
@@ -0,0 +1,3 @@
+// Tests that an `impl Trait` that is not `impl Termination` will not work.
+fn main() -> impl Copy { }
+//~^ ERROR `main` has invalid return type `impl Copy`
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr
new file mode 100644
index 000000000..f562b97c3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `impl Copy`
+ --> $DIR/termination-trait-impl-trait.rs:2:14
+ |
+LL | fn main() -> impl Copy { }
+ | ^^^^^^^^^ `main` can only return types that implement `Termination`
+ |
+ = help: consider using `()`, or a `Result`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs
new file mode 100644
index 000000000..96808a3ed
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs
@@ -0,0 +1,15 @@
+// compile-flags: --test
+
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+#[should_panic]
+fn not_a_num() -> Result<(), ParseIntError> {
+ //~^ ERROR functions using `#[should_panic]` must return `()`
+ let _: u32 = "abc".parse()?;
+ Ok(())
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr
new file mode 100644
index 000000000..534599b74
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr
@@ -0,0 +1,12 @@
+error: functions using `#[should_panic]` must return `()`
+ --> $DIR/termination-trait-in-test-should-panic.rs:11:1
+ |
+LL | / fn not_a_num() -> Result<(), ParseIntError> {
+LL | |
+LL | | let _: u32 = "abc".parse()?;
+LL | | Ok(())
+LL | | }
+ | |_^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
new file mode 100644
index 000000000..43888cece
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
@@ -0,0 +1,28 @@
+// compile-flags: --test
+// run-pass
+// needs-unwind
+
+
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+fn is_a_num() -> Result<(), ParseIntError> {
+ let _: u32 = "22".parse()?;
+ Ok(())
+}
+
+#[bench]
+fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+ Ok(())
+}
+
+#[bench]
+#[should_panic]
+fn test_a_neg_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+ let _: u32 = "abc".parse()?;
+ Ok(())
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.rs
new file mode 100644
index 000000000..10f7d2215
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -0,0 +1,6 @@
+fn main() -> i32 {
+//~^ ERROR `main` has invalid return type `i32`
+//~| NOTE `main` can only return types that implement `Termination`
+//~| HELP consider using `()`, or a `Result`
+ 0
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr
new file mode 100644
index 000000000..fdbb0e655
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `i32`
+ --> $DIR/termination-trait-main-i32.rs:1:14
+ |
+LL | fn main() -> i32 {
+ | ^^^ `main` can only return types that implement `Termination`
+ |
+ = help: consider using `()`, or a `Result`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
new file mode 100644
index 000000000..687d5f144
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
@@ -0,0 +1,3 @@
+fn main() -> char { //~ ERROR
+ ' '
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
new file mode 100644
index 000000000..7ed17dff1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `char`
+ --> $DIR/termination-trait-main-wrong-type.rs:1:14
+ |
+LL | fn main() -> char {
+ | ^^^^ `main` can only return types that implement `Termination`
+ |
+ = help: consider using `()`, or a `Result`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
new file mode 100644
index 000000000..4c6168abb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
@@ -0,0 +1,5 @@
+struct ReturnType {}
+
+fn main() -> ReturnType { //~ ERROR `main` has invalid return type `ReturnType`
+ ReturnType {}
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr
new file mode 100644
index 000000000..1b842c206
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `main` has invalid return type `ReturnType`
+ --> $DIR/termination-trait-not-satisfied.rs:3:14
+ |
+LL | fn main() -> ReturnType {
+ | ^^^^^^^^^^ `main` can only return types that implement `Termination`
+ |
+ = help: consider using `()`, or a `Result`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
new file mode 100644
index 000000000..193a523ae
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
@@ -0,0 +1,8 @@
+// compile-flags: --test
+
+use std::num::ParseFloatError;
+
+#[test]
+fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> { //~ ERROR
+ "0".parse()
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
new file mode 100644
index 000000000..0a703367d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `f32: Termination` is not satisfied
+ --> $DIR/termination-trait-test-wrong-type.rs:6:31
+ |
+LL | #[test]
+ | ------- in this procedural macro expansion
+LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`
+ |
+ = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
+note: required by a bound in `assert_test_result`
+ --> $SRC_DIR/test/src/lib.rs:LL:COL
+ = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.rs
new file mode 100644
index 000000000..54ab9f0ad
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.rs
@@ -0,0 +1,24 @@
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Foo {
+}
+
+impl Foo {
+ fn get(&self) -> Option<&Result<String, String>> {
+ None
+ }
+
+ fn mutate(&mut self) { }
+}
+
+fn main() {
+ let mut foo = Foo { };
+
+ // foo.get() returns type Option<&Result<String, String>>, so
+ // using `string` keeps borrow of `foo` alive. Hence calling
+ // `foo.mutate()` should be an error.
+ while let Some(Ok(string)) = foo.get() {
+ foo.mutate();
+ //~^ ERROR cannot borrow `foo` as mutable
+ println!("foo={:?}", *string);
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr
new file mode 100644
index 000000000..a9c9eb2a5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+ --> $DIR/borrowck-issue-49631.rs:20:9
+ |
+LL | while let Some(Ok(string)) = foo.get() {
+ | --- immutable borrow occurs here
+LL | foo.mutate();
+ | ^^^^^^^^^^^^ mutable borrow occurs here
+LL |
+LL | println!("foo={:?}", *string);
+ | ------- immutable borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/const.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/const.rs
new file mode 100644
index 000000000..93df88040
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/const.rs
@@ -0,0 +1,17 @@
+// FIXME(tschottdorf): this test should pass.
+
+#[derive(PartialEq, Eq)]
+struct Foo {
+ bar: i32,
+}
+
+const FOO: Foo = Foo{bar: 5};
+
+fn main() {
+ let f = Foo{bar:6};
+
+ match &f {
+ FOO => {}, //~ ERROR mismatched types
+ _ => panic!(),
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr
new file mode 100644
index 000000000..1c8e8d5b0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/const.rs:14:9
+ |
+LL | const FOO: Foo = Foo{bar: 5};
+ | -------------- constant defined here
+...
+LL | match &f {
+ | -- this expression has type `&Foo`
+LL | FOO => {},
+ | ^^^
+ | |
+ | expected `&Foo`, found `Foo`
+ | `FOO` is interpreted as a constant, not a new binding
+ | help: introduce a new binding instead: `other_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum-ok.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum-ok.rs
new file mode 100644
index 000000000..52fbb90ed
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum-ok.rs
@@ -0,0 +1,45 @@
+// run-pass
+enum Wrapper {
+ Wrap(i32),
+}
+
+use Wrapper::Wrap;
+
+pub fn main() {
+ let Wrap(x) = &Wrap(3);
+ println!("{}", *x);
+
+ let Wrap(x) = &mut Wrap(3);
+ println!("{}", *x);
+
+ if let Some(x) = &Some(3) {
+ println!("{}", *x);
+ } else {
+ panic!();
+ }
+
+ if let Some(x) = &mut Some(3) {
+ println!("{}", *x);
+ } else {
+ panic!();
+ }
+
+ if let Some(x) = &mut Some(3) {
+ *x += 1;
+ } else {
+ panic!();
+ }
+
+ while let Some(x) = &Some(3) {
+ println!("{}", *x);
+ break;
+ }
+ while let Some(x) = &mut Some(3) {
+ println!("{}", *x);
+ break;
+ }
+ while let Some(x) = &mut Some(3) {
+ *x += 1;
+ break;
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
index 52fbb90ed..4e57769d6 100644
--- a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
@@ -1,4 +1,3 @@
-// run-pass
enum Wrapper {
Wrap(i32),
}
@@ -7,39 +6,17 @@ use Wrapper::Wrap;
pub fn main() {
let Wrap(x) = &Wrap(3);
- println!("{}", *x);
+ *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
- let Wrap(x) = &mut Wrap(3);
- println!("{}", *x);
if let Some(x) = &Some(3) {
- println!("{}", *x);
- } else {
- panic!();
- }
-
- if let Some(x) = &mut Some(3) {
- println!("{}", *x);
- } else {
- panic!();
- }
-
- if let Some(x) = &mut Some(3) {
- *x += 1;
+ *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
} else {
panic!();
}
while let Some(x) = &Some(3) {
- println!("{}", *x);
- break;
- }
- while let Some(x) = &mut Some(3) {
- println!("{}", *x);
- break;
- }
- while let Some(x) = &mut Some(3) {
- *x += 1;
+ *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
break;
}
}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.stderr
new file mode 100644
index 000000000..21e3d3d27
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
+ --> $DIR/enum.rs:9:5
+ |
+LL | *x += 1;
+ | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
+ --> $DIR/enum.rs:13:9
+ |
+LL | *x += 1;
+ | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
+ --> $DIR/enum.rs:19:9
+ |
+LL | *x += 1;
+ | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.rs
new file mode 100644
index 000000000..b8fde2208
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.rs
@@ -0,0 +1,28 @@
+// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
+// final default binding mode mutable.
+
+fn main() {
+ match &&Some(5i32) {
+ Some(n) => {
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
+ let _ = n;
+ }
+ None => {},
+ };
+
+ match &mut &Some(5i32) {
+ Some(n) => {
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
+ let _ = n;
+ }
+ None => {},
+ };
+
+ match &&mut Some(5i32) {
+ Some(n) => {
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
+ let _ = n;
+ }
+ None => {},
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.stderr
new file mode 100644
index 000000000..c3f64f65a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/explicit-mut.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
+ --> $DIR/explicit-mut.rs:7:13
+ |
+LL | *n += 1;
+ | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
+ --> $DIR/explicit-mut.rs:15:13
+ |
+LL | *n += 1;
+ | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
+ --> $DIR/explicit-mut.rs:23:13
+ |
+LL | *n += 1;
+ | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for-ok.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/for-ok.rs
new file mode 100644
index 000000000..a5a24a806
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for-ok.rs
@@ -0,0 +1,20 @@
+// run-pass
+pub fn main() {
+ let mut tups = vec![(0u8, 1u8)];
+
+ for (n, m) in &tups {
+ let _: &u8 = n;
+ let _: &u8 = m;
+ }
+
+ for (n, m) in &mut tups {
+ *n += 1;
+ *m += 2;
+ }
+
+ assert_eq!(tups, vec![(1u8, 3u8)]);
+
+ for (n, m) in tups {
+ println!("{} {}", m, n);
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
index a5a24a806..d6c5a13b1 100644
--- a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
@@ -1,20 +1,9 @@
-// run-pass
-pub fn main() {
- let mut tups = vec![(0u8, 1u8)];
-
- for (n, m) in &tups {
- let _: &u8 = n;
- let _: &u8 = m;
- }
+struct Foo {}
- for (n, m) in &mut tups {
- *n += 1;
- *m += 2;
- }
-
- assert_eq!(tups, vec![(1u8, 3u8)]);
-
- for (n, m) in tups {
- println!("{} {}", m, n);
+pub fn main() {
+ let mut tups = vec![(Foo {}, Foo {})];
+ // The below desugars to &(ref n, mut m).
+ for (n, mut m) in &tups {
+ //~^ ERROR cannot move out of a shared reference
}
}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr
new file mode 100644
index 000000000..8f720daf1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/for.rs:6:23
+ |
+LL | for (n, mut m) in &tups {
+ | ----- ^^^^^
+ | |
+ | data moved here
+ | move occurs because `m` has type `Foo`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | for (n, ref mut m) in &tups {
+ | +++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.rs
new file mode 100644
index 000000000..b4a0d8145
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.rs
@@ -0,0 +1,10 @@
+// FIXME(tschottdorf): This should compile. See #44912.
+
+pub fn main() {
+ let x = &Some((3, 3));
+ let _: &i32 = match x {
+ Some((x, 3)) | &Some((ref x, 5)) => x,
+ //~^ ERROR is bound inconsistently
+ _ => &5i32,
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr
new file mode 100644
index 000000000..84ba69703
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr
@@ -0,0 +1,9 @@
+error[E0409]: variable `x` is bound inconsistently across alternatives separated by `|`
+ --> $DIR/issue-44912-or.rs:6:35
+ |
+LL | Some((x, 3)) | &Some((ref x, 5)) => x,
+ | - first binding ^ bound in different ways
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0409`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit-ok.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit-ok.rs
new file mode 100644
index 000000000..937975359
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit-ok.rs
@@ -0,0 +1,34 @@
+// run-pass
+#![allow(dead_code)]
+fn with_u8() {
+ let s = 5u8;
+ let r = match &s {
+ 4 => false,
+ 5 => true,
+ _ => false,
+ };
+ assert!(r);
+}
+
+// A string literal isn't mistaken for a non-ref pattern (in which case we'd
+// deref `s` and mess things up).
+fn with_str() {
+ let s: &'static str = "abc";
+ match s {
+ "abc" => true,
+ _ => panic!(),
+ };
+}
+
+// Ditto with byte strings.
+fn with_bytes() {
+ let s: &'static [u8] = b"abc";
+ match s {
+ b"abc" => true,
+ _ => panic!(),
+ };
+}
+
+pub fn main() {
+ with_str();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
index 937975359..ce79cfbdc 100644
--- a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
@@ -1,34 +1,24 @@
-// run-pass
-#![allow(dead_code)]
-fn with_u8() {
- let s = 5u8;
- let r = match &s {
- 4 => false,
- 5 => true,
- _ => false,
- };
- assert!(r);
-}
+// FIXME(tschottdorf): we want these to compile, but they don't.
-// A string literal isn't mistaken for a non-ref pattern (in which case we'd
-// deref `s` and mess things up).
fn with_str() {
let s: &'static str = "abc";
- match s {
- "abc" => true,
+
+ match &s {
+ "abc" => true, //~ ERROR mismatched types
_ => panic!(),
};
}
-// Ditto with byte strings.
fn with_bytes() {
let s: &'static [u8] = b"abc";
- match s {
- b"abc" => true,
+
+ match &s {
+ b"abc" => true, //~ ERROR mismatched types
_ => panic!(),
};
}
pub fn main() {
with_str();
+ with_bytes();
}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr
new file mode 100644
index 000000000..970a9c151
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+ --> $DIR/lit.rs:7:13
+ |
+LL | match &s {
+ | -- this expression has type `&&str`
+LL | "abc" => true,
+ | ^^^^^ expected `&&str`, found `&str`
+ |
+ = note: expected reference `&&_`
+ found reference `&'static _`
+
+error[E0308]: mismatched types
+ --> $DIR/lit.rs:16:9
+ |
+LL | match &s {
+ | -- this expression has type `&&[u8]`
+LL | b"abc" => true,
+ | ^^^^^^ expected `&&[u8]`, found `&[u8; 3]`
+ |
+ = note: expected reference `&&[u8]`
+ found reference `&'static [u8; 3]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.rs
new file mode 100644
index 000000000..46fdfd678
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.rs
@@ -0,0 +1,11 @@
+// Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs
+// the error below would be reported twice (once when checking
+// for a non-ref pattern, once when processing the pattern).
+
+fn main() {
+ let foo = 22;
+ match foo {
+ u32::XXX => { } //~ ERROR no associated item named
+ _ => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr
new file mode 100644
index 000000000..6000507c5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no associated item named `XXX` found for type `u32` in the current scope
+ --> $DIR/no-double-error.rs:8:14
+ |
+LL | u32::XXX => { }
+ | ^^^ associated item not found in `u32`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice-ok.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice-ok.rs
new file mode 100644
index 000000000..33229a205
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice-ok.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+fn slice_pat() {
+ let sl: &[u8] = b"foo";
+
+ match sl {
+ [first, remainder @ ..] => {
+ let _: &u8 = first;
+ assert_eq!(first, &b'f');
+ assert_eq!(remainder, b"oo");
+ }
+ [] => panic!(),
+ }
+}
+
+fn slice_pat_omission() {
+ match &[0, 1, 2] {
+ [..] => {}
+ };
+}
+
+fn main() {
+ slice_pat();
+ slice_pat_omission();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
index 33229a205..363a0e3e6 100644
--- a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
@@ -1,25 +1,7 @@
-// run-pass
-
-fn slice_pat() {
+pub fn main() {
let sl: &[u8] = b"foo";
- match sl {
- [first, remainder @ ..] => {
- let _: &u8 = first;
- assert_eq!(first, &b'f');
- assert_eq!(remainder, b"oo");
- }
- [] => panic!(),
- }
-}
-
-fn slice_pat_omission() {
- match &[0, 1, 2] {
- [..] => {}
- };
-}
-
-fn main() {
- slice_pat();
- slice_pat_omission();
+ match sl { //~ ERROR non-exhaustive patterns
+ [first, remainder @ ..] => {},
+ };
}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr
new file mode 100644
index 000000000..a83c58e70
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `&[]` not covered
+ --> $DIR/slice.rs:4:11
+ |
+LL | match sl {
+ | ^^ pattern `&[]` not covered
+ |
+ = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ [first, remainder @ ..] => {},
+LL ~ &[] => todo!(),
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644
index 000000000..cb2b585ab
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -0,0 +1,44 @@
+#![crate_type = "rlib"]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 },
+}
+
+#[non_exhaustive]
+pub enum NestedNonExhaustive {
+ A(NonExhaustiveEnum),
+ B,
+ C,
+}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
+
+pub enum VariantNonExhaustive {
+ #[non_exhaustive]
+ Bar {
+ x: u32,
+ y: u64,
+ },
+ Baz(u32, u16),
+}
+
+#[non_exhaustive]
+pub enum NonExhaustiveSingleVariant {
+ A(bool),
+}
+
+#[repr(u8)]
+pub enum FieldLessWithNonExhaustiveVariant {
+ A,
+ B,
+ #[non_exhaustive]
+ C,
+}
+
+impl Default for FieldLessWithNonExhaustiveVariant {
+ fn default() -> Self { Self::A }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/monovariants.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/monovariants.rs
new file mode 100644
index 000000000..5f86db86d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/monovariants.rs
@@ -0,0 +1,8 @@
+#[non_exhaustive]
+pub enum NonExhaustiveMonovariant {
+ Variant(u32),
+}
+
+pub enum ExhaustiveMonovariant {
+ Variant(u32),
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644
index 000000000..78db6b170
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs
@@ -0,0 +1,41 @@
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub struct FunctionalRecord {
+ pub first_field: u16,
+ pub second_field: u16,
+ pub third_field: bool,
+}
+
+impl Default for FunctionalRecord {
+ fn default() -> FunctionalRecord {
+ FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
+ }
+}
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NestedStruct {
+ pub foo: u16,
+ pub bar: NormalStruct,
+}
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct MixedVisFields {
+ pub a: u16,
+ pub b: bool,
+ pub(crate) foo: bool,
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/unstable.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/unstable.rs
new file mode 100644
index 000000000..11df44461
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/unstable.rs
@@ -0,0 +1,60 @@
+#![feature(staged_api)]
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub enum UnstableEnum {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ Stable,
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ Stable2,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ Unstable,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub enum OnlyUnstableEnum {
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ Unstable,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ Unstable2,
+}
+
+impl OnlyUnstableEnum {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub fn new() -> Self {
+ Self::Unstable
+ }
+}
+
+#[derive(Default)]
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub struct UnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable: bool,
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable2: usize,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub struct OnlyUnstableStruct {
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable2: bool,
+}
+
+impl OnlyUnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub fn new() -> Self {
+ Self {
+ unstable: 0,
+ unstable2: false,
+ }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644
index 000000000..02672d545
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive] Unit,
+ #[non_exhaustive] Tuple(u32),
+ #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
new file mode 100644
index 000000000..b9ff24c76
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
@@ -0,0 +1,44 @@
+// Test that the borrow checker doesn't consider checking an exhaustive pattern
+// as an access.
+
+// check-pass
+
+#![allow(dropping_references)]
+
+// aux-build:monovariants.rs
+extern crate monovariants;
+
+use monovariants::ExhaustiveMonovariant;
+
+enum Local {
+ Variant(u32),
+}
+
+#[non_exhaustive]
+enum LocalNonExhaustive {
+ Variant(u32),
+}
+
+fn main() {
+ let mut x = ExhaustiveMonovariant::Variant(1);
+ let y = &mut x;
+ match x {
+ ExhaustiveMonovariant::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+ let mut x = Local::Variant(1);
+ let y = &mut x;
+ match x {
+ Local::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+ let mut x = LocalNonExhaustive::Variant(1);
+ let y = &mut x;
+ match x {
+ LocalNonExhaustive::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs
new file mode 100644
index 000000000..2ad92b794
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs
@@ -0,0 +1,18 @@
+// Test that the borrow checker considers `#[non_exhaustive]` when checking
+// whether a match contains a discriminant read.
+
+// aux-build:monovariants.rs
+extern crate monovariants;
+
+use monovariants::NonExhaustiveMonovariant;
+
+fn main() {
+ let mut x = NonExhaustiveMonovariant::Variant(1);
+ let y = &mut x;
+ match x {
+ //~^ ERROR cannot use `x` because it was mutably borrowed
+ NonExhaustiveMonovariant::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
new file mode 100644
index 000000000..70f5b2b84
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
@@ -0,0 +1,14 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+ --> $DIR/borrowck-non-exhaustive.rs:12:11
+ |
+LL | let y = &mut x;
+ | ------ `x` is borrowed here
+LL | match x {
+ | ^ use of borrowed `x`
+...
+LL | drop(y);
+ | - borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.rs
new file mode 100644
index 000000000..5dce8180f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.rs
@@ -0,0 +1,11 @@
+// aux-build:enums.rs
+
+extern crate enums;
+
+use enums::FieldLessWithNonExhaustiveVariant;
+
+fn main() {
+ let e = FieldLessWithNonExhaustiveVariant::default();
+ let d = e as u8; //~ ERROR casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid [E0606]
+ assert_eq!(d, 0);
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr
new file mode 100644
index 000000000..c8dad8b80
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr
@@ -0,0 +1,11 @@
+error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid
+ --> $DIR/enum-as-cast.rs:9:13
+ |
+LL | let d = e as u8;
+ | ^^^^^^^
+ |
+ = note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.rs
new file mode 100644
index 000000000..9d2855f5c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.rs
@@ -0,0 +1,69 @@
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::{EmptyNonExhaustiveEnum, NonExhaustiveEnum};
+
+fn empty(x: EmptyNonExhaustiveEnum) {
+ match x {} //~ ERROR type `EmptyNonExhaustiveEnum` is non-empty
+ match x {
+ _ => {}, // ok
+ }
+}
+
+fn main() {
+ let enum_unit = NonExhaustiveEnum::Unit;
+
+ match enum_unit {
+ //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+ NonExhaustiveEnum::Unit => "first",
+ NonExhaustiveEnum::Tuple(_) => "second",
+ NonExhaustiveEnum::Struct { .. } => "third"
+ };
+
+ match enum_unit {};
+ //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+
+ // Everything below this is expected to compile successfully.
+
+ let enum_unit = NonExhaustiveEnum::Unit;
+
+ match enum_unit {
+ NonExhaustiveEnum::Unit => 1,
+ NonExhaustiveEnum::Tuple(_) => 2,
+ // This particular arm tests that an enum marked as non-exhaustive
+ // will not error if its variants are matched exhaustively.
+ NonExhaustiveEnum::Struct { field } => field,
+ _ => 0 // no error with wildcard
+ };
+
+ match enum_unit {
+ _ => "no error with only wildcard"
+ };
+
+ // #53549: Check that variant constructors can still be called normally.
+ match NonExhaustiveEnum::Unit {
+ NonExhaustiveEnum::Unit => {},
+ _ => {}
+ };
+
+ match NonExhaustiveEnum::Tuple(2) {
+ NonExhaustiveEnum::Tuple(2) => {},
+ _ => {}
+ };
+
+ match (NonExhaustiveEnum::Unit {}) {
+ NonExhaustiveEnum::Unit {} => {},
+ _ => {}
+ };
+
+ match (NonExhaustiveEnum::Tuple { 0: 2 }) {
+ NonExhaustiveEnum::Tuple { 0: 2 } => {},
+ _ => {}
+ };
+
+ match (NonExhaustiveEnum::Struct { field: 2 }) {
+ NonExhaustiveEnum::Struct { field: 2 } => {},
+ _ => {}
+ };
+
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr
new file mode 100644
index 000000000..4e7f3098a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr
@@ -0,0 +1,60 @@
+error[E0004]: non-exhaustive patterns: type `EmptyNonExhaustiveEnum` is non-empty
+ --> $DIR/enum.rs:7:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `EmptyNonExhaustiveEnum` defined here
+ --> $DIR/auxiliary/enums.rs:18:1
+ |
+LL | pub enum EmptyNonExhaustiveEnum {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `EmptyNonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/enum.rs:16:11
+ |
+LL | match enum_unit {
+ | ^^^^^^^^^ pattern `_` not covered
+ |
+note: `NonExhaustiveEnum` defined here
+ --> $DIR/auxiliary/enums.rs:4:1
+ |
+LL | pub enum NonExhaustiveEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonExhaustiveEnum`
+ = note: `NonExhaustiveEnum` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ NonExhaustiveEnum::Struct { .. } => "third",
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/enum.rs:23:11
+ |
+LL | match enum_unit {};
+ | ^^^^^^^^^ pattern `_` not covered
+ |
+note: `NonExhaustiveEnum` defined here
+ --> $DIR/auxiliary/enums.rs:4:1
+ |
+LL | pub enum NonExhaustiveEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonExhaustiveEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ match enum_unit {
+LL + _ => todo!(),
+LL ~ };
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate.rs
new file mode 100644
index 000000000..54e42917f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 }
+}
+
+fn main() {
+ let enum_unit = NonExhaustiveEnum::Unit;
+
+ match enum_unit {
+ NonExhaustiveEnum::Unit => "first",
+ NonExhaustiveEnum::Tuple(_) => "second",
+ NonExhaustiveEnum::Struct { .. } => "third",
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
new file mode 100644
index 000000000..69a283c31
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
@@ -0,0 +1,37 @@
+#![deny(unreachable_patterns)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ //~^ not covered
+ Tuple(u32),
+ //~^ not covered
+ Struct { field: u32 }
+ //~^ not covered
+}
+
+pub enum NormalEnum {
+ Unit,
+ //~^ not covered
+ Tuple(u32),
+ //~^ not covered
+ Struct { field: u32 }
+ //~^ not covered
+}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
+
+fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) {
+ match x {}
+ match x {
+ _ => {} //~ ERROR unreachable pattern
+ }
+}
+
+fn main() {
+ match NonExhaustiveEnum::Unit {}
+ //~^ ERROR `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered [E0004]
+ match NormalEnum::Unit {}
+ //~^ ERROR `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered [E0004]
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
new file mode 100644
index 000000000..7386f10a6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
@@ -0,0 +1,69 @@
+error: unreachable pattern
+ --> $DIR/enum_same_crate_empty_match.rs:28:9
+ |
+LL | _ => {}
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/enum_same_crate_empty_match.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
+ --> $DIR/enum_same_crate_empty_match.rs:33:11
+ |
+LL | match NonExhaustiveEnum::Unit {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+note: `NonExhaustiveEnum` defined here
+ --> $DIR/enum_same_crate_empty_match.rs:4:10
+ |
+LL | pub enum NonExhaustiveEnum {
+ | ^^^^^^^^^^^^^^^^^
+LL | Unit,
+ | ---- not covered
+LL |
+LL | Tuple(u32),
+ | ----- not covered
+LL |
+LL | Struct { field: u32 }
+ | ------ not covered
+ = note: the matched value is of type `NonExhaustiveEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match NonExhaustiveEnum::Unit {
+LL + NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_) | NonExhaustiveEnum::Struct { .. } => todo!(),
+LL + }
+ |
+
+error[E0004]: non-exhaustive patterns: `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered
+ --> $DIR/enum_same_crate_empty_match.rs:35:11
+ |
+LL | match NormalEnum::Unit {}
+ | ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered
+ |
+note: `NormalEnum` defined here
+ --> $DIR/enum_same_crate_empty_match.rs:13:10
+ |
+LL | pub enum NormalEnum {
+ | ^^^^^^^^^^
+LL | Unit,
+ | ---- not covered
+LL |
+LL | Tuple(u32),
+ | ----- not covered
+LL |
+LL | Struct { field: u32 }
+ | ------ not covered
+ = note: the matched value is of type `NormalEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match NormalEnum::Unit {
+LL + NormalEnum::Unit | NormalEnum::Tuple(_) | NormalEnum::Struct { .. } => todo!(),
+LL + }
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
new file mode 100644
index 000000000..d6251fcb7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
@@ -0,0 +1,29 @@
+#[non_exhaustive]
+#[repr(C)]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 }
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct TupleStruct (pub u16, pub u16);
+
+#[repr(C)]
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive] Unit,
+ #[non_exhaustive] Tuple(u32),
+ #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
new file mode 100644
index 000000000..15c0c695f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
@@ -0,0 +1,24 @@
+// aux-build:types.rs
+#![deny(improper_ctypes)]
+
+extern crate types;
+
+// This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered
+// improper.
+
+use types::{NonExhaustiveEnum, NonExhaustiveVariants, NormalStruct, TupleStruct, UnitStruct};
+
+extern "C" {
+ pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+ //~^ ERROR `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
+ pub fn non_exhaustive_normal_struct(_: NormalStruct);
+ //~^ ERROR `extern` block uses type `NormalStruct`, which is not FFI-safe
+ pub fn non_exhaustive_unit_struct(_: UnitStruct);
+ //~^ ERROR `extern` block uses type `UnitStruct`, which is not FFI-safe
+ pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+ //~^ ERROR `extern` block uses type `TupleStruct`, which is not FFI-safe
+ pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+ //~^ ERROR `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
new file mode 100644
index 000000000..43c8e1015
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
@@ -0,0 +1,47 @@
+error: `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:12:35
+ |
+LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+ | ^^^^^^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this enum is non-exhaustive
+note: the lint level is defined here
+ --> $DIR/extern_crate_improper.rs:2:9
+ |
+LL | #![deny(improper_ctypes)]
+ | ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `NormalStruct`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:14:44
+ |
+LL | pub fn non_exhaustive_normal_struct(_: NormalStruct);
+ | ^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this struct is non-exhaustive
+
+error: `extern` block uses type `UnitStruct`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:16:42
+ |
+LL | pub fn non_exhaustive_unit_struct(_: UnitStruct);
+ | ^^^^^^^^^^ not FFI-safe
+ |
+ = note: this struct is non-exhaustive
+
+error: `extern` block uses type `TupleStruct`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:18:43
+ |
+LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+ | ^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this struct is non-exhaustive
+
+error: `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:20:38
+ |
+LL | pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this enum has non-exhaustive variants
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
new file mode 100644
index 000000000..fe4ae345d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
@@ -0,0 +1,48 @@
+// check-pass
+#![deny(improper_ctypes)]
+
+// This test checks that non-exhaustive types with `#[repr(C)]` are considered proper within
+// the defining crate.
+
+#[non_exhaustive]
+#[repr(C)]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 },
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[repr(C)]
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive]
+ Unit,
+ #[non_exhaustive]
+ Tuple(u32),
+ #[non_exhaustive]
+ Struct { field: u32 },
+}
+
+extern "C" {
+ // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway.
+ pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+ pub fn non_exhaustive_normal_struct(_: NormalStruct);
+ pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+ pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs
new file mode 100644
index 000000000..143f9a300
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs
@@ -0,0 +1,16 @@
+#[non_exhaustive(anything)]
+//~^ ERROR malformed `non_exhaustive` attribute
+struct Foo;
+
+#[non_exhaustive]
+//~^ ERROR attribute should be applied to a struct or enum [E0701]
+trait Bar { }
+
+#[non_exhaustive]
+//~^ ERROR attribute should be applied to a struct or enum [E0701]
+union Baz {
+ f1: u16,
+ f2: u16
+}
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr
new file mode 100644
index 000000000..136cd763b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr
@@ -0,0 +1,30 @@
+error: malformed `non_exhaustive` attribute input
+ --> $DIR/invalid-attribute.rs:1:1
+ |
+LL | #[non_exhaustive(anything)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]`
+
+error[E0701]: attribute should be applied to a struct or enum
+ --> $DIR/invalid-attribute.rs:5:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+LL |
+LL | trait Bar { }
+ | ------------- not a struct or enum
+
+error[E0701]: attribute should be applied to a struct or enum
+ --> $DIR/invalid-attribute.rs:9:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+LL |
+LL | / union Baz {
+LL | | f1: u16,
+LL | | f2: u16
+LL | | }
+ | |_- not a struct or enum
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0701`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr
new file mode 100644
index 000000000..9192c6614
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr
@@ -0,0 +1,75 @@
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11
+ |
+LL | match val {
+ | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:23:11
+ |
+LL | match val {
+ | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:22:27
+ |
+LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: the lint level must be set on the whole match
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ------------------------------- remove this attribute
+LL | _ => {}
+ | ^
+ |
+ = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+ |
+LL + #[deny(non_exhaustive_omitted_patterns)]
+LL | match val {
+ |
+
+warning: the lint level must be set on the whole match
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:42:9
+ |
+LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+ | ------------------------------- remove this attribute
+LL | _ => {}
+ | ^
+ |
+ = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+ |
+LL + #[deny(non_exhaustive_omitted_patterns)]
+LL | match val {
+ |
+
+warning: the lint level must be set on the whole match
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:50:9
+ |
+LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
+ | ------------------------------- remove this attribute
+LL | _ => {}
+ | ^
+ |
+ = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+ |
+LL + #[warn(non_exhaustive_omitted_patterns)]
+LL | match val {
+ |
+
+error: aborting due to 2 previous errors; 3 warnings emitted
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr
new file mode 100644
index 000000000..2535e0518
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr
@@ -0,0 +1,31 @@
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11
+ |
+LL | match val {
+ | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: the lint level must be set on the whole match
+ --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ------------------------------- remove this attribute
+LL | _ => {}
+ | ^
+ |
+ = help: it no longer has any effect to set the lint level on an individual match arm
+help: set the lint level on the whole match
+ |
+LL + #[deny(non_exhaustive_omitted_patterns)]
+LL | match val {
+ |
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs
new file mode 100644
index 000000000..33f9f56a5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs
@@ -0,0 +1,53 @@
+// revisions: normal lint
+// Test that putting the lint level on a match arm emits a warning, as this was previously
+// meaningful and is no longer.
+#![feature(non_exhaustive_omitted_patterns_lint)]
+
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+ let val = NonExhaustiveEnum::Unit;
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match val {
+ //~^ ERROR some variants are not matched explicitly
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+ match val {
+ //[lint]~^ ERROR some variants are not matched explicitly
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match val {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ WARN lint level must be set on the whole match
+
+ match val {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
+ _ => {}
+ }
+ //[lint]~^^ WARN lint level must be set on the whole match
+
+ match val {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
+ _ => {}
+ }
+ //[lint]~^^ WARN lint level must be set on the whole match
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
new file mode 100644
index 000000000..a6c1dc53f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
@@ -0,0 +1,273 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
+
+#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)]
+#![deny(unreachable_patterns)]
+
+// aux-build:enums.rs
+extern crate enums;
+// aux-build:unstable.rs
+extern crate unstable;
+// aux-build:structs.rs
+extern crate structs;
+
+use enums::{
+ EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
+ VariantNonExhaustive,
+};
+use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct};
+use unstable::{OnlyUnstableEnum, OnlyUnstableStruct, UnstableEnum, UnstableStruct};
+
+#[non_exhaustive]
+#[derive(Default)]
+pub struct Foo {
+ a: u8,
+ b: usize,
+ c: String,
+}
+
+#[non_exhaustive]
+pub enum Bar {
+ A,
+ B,
+ C,
+}
+
+fn no_lint() {
+ let non_enum = NonExhaustiveEnum::Unit;
+ // Ok: without the attribute
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+}
+
+#[deny(non_exhaustive_omitted_patterns)]
+fn main() {
+ let enumeration = Bar::A;
+
+ // Ok: this is a crate local non_exhaustive enum
+ match enumeration {
+ Bar::A => {}
+ Bar::B => {}
+ _ => {}
+ }
+
+ let non_enum = NonExhaustiveEnum::Unit;
+
+ #[allow(non_exhaustive_omitted_patterns)]
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match non_enum {
+ //~^ some variants are not matched explicitly
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match non_enum {
+ //~^ some variants are not matched explicitly
+ NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
+ _ => {}
+ }
+
+ let x = 5;
+ // We ignore the guard.
+ match non_enum {
+ NonExhaustiveEnum::Unit if x > 10 => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ _ => {}
+ }
+
+ match (non_enum, true) {
+ (NonExhaustiveEnum::Unit, true) => {}
+ (NonExhaustiveEnum::Tuple(_), false) => {}
+ (NonExhaustiveEnum::Struct { .. }, false) => {}
+ _ => {}
+ }
+ match (non_enum, true) {
+ //~^ some variants are not matched explicitly
+ (NonExhaustiveEnum::Unit, true) => {}
+ (NonExhaustiveEnum::Tuple(_), false) => {}
+ _ => {}
+ }
+
+ match (true, non_enum) {
+ (true, NonExhaustiveEnum::Unit) => {}
+ (false, NonExhaustiveEnum::Tuple(_)) => {}
+ (false, NonExhaustiveEnum::Struct { .. }) => {}
+ _ => {}
+ }
+ match (true, non_enum) {
+ //~^ some variants are not matched explicitly
+ (true, NonExhaustiveEnum::Unit) => {}
+ (false, NonExhaustiveEnum::Tuple(_)) => {}
+ _ => {}
+ }
+
+ match Some(non_enum) {
+ //~^ some variants are not matched explicitly
+ Some(NonExhaustiveEnum::Unit) => {}
+ Some(NonExhaustiveEnum::Tuple(_)) => {}
+ _ => {}
+ }
+
+ // Ok: all covered and not `unreachable-patterns`
+ #[deny(unreachable_patterns)]
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ _ => {}
+ }
+
+ match NestedNonExhaustive::B {
+ //~^ some variants are not matched explicitly
+ NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
+ NestedNonExhaustive::A(_) => {}
+ NestedNonExhaustive::B => {}
+ _ => {}
+ }
+
+ match VariantNonExhaustive::Baz(1, 2) {
+ VariantNonExhaustive::Baz(_, _) => {}
+ VariantNonExhaustive::Bar { x, .. } => {}
+ }
+ //~^^ some fields are not explicitly listed
+
+ let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ //~^ some fields are not explicitly listed
+
+ // Ok: this is local
+ let Foo { a, b, .. } = Foo::default();
+
+ let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ //~^ some fields are not explicitly listed
+ //~^^ some fields are not explicitly listed
+
+ // Ok: this tests https://github.com/rust-lang/rust/issues/89382
+ let MixedVisFields { a, b, .. } = MixedVisFields::default();
+
+ // Ok: this only has 1 variant
+ match NonExhaustiveSingleVariant::A(true) {
+ NonExhaustiveSingleVariant::A(true) => {}
+ _ => {}
+ }
+
+ // We can't catch the case below, so for consistency we don't catch this one either.
+ match NonExhaustiveSingleVariant::A(true) {
+ _ => {}
+ }
+ // We can't catch this case, because this would require digging fully through all the values of
+ // any type we encounter. We need to be able to only consider present constructors.
+ match &NonExhaustiveSingleVariant::A(true) {
+ _ => {}
+ }
+
+ match Some(NonExhaustiveSingleVariant::A(true)) {
+ Some(_) => {}
+ None => {}
+ }
+ match Some(&NonExhaustiveSingleVariant::A(true)) {
+ Some(_) => {}
+ None => {}
+ }
+
+ // Ok: we don't lint on `if let` expressions
+ if let NonExhaustiveEnum::Tuple(_) = non_enum {}
+
+ match UnstableEnum::Stable {
+ //~^ some variants are not matched explicitly
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ _ => {}
+ }
+
+ // Ok: the feature is on and all variants are matched
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ UnstableEnum::Unstable => {}
+ _ => {}
+ }
+
+ // Ok: the feature is on and both variants are matched
+ match OnlyUnstableEnum::Unstable {
+ OnlyUnstableEnum::Unstable => {}
+ OnlyUnstableEnum::Unstable2 => {}
+ _ => {}
+ }
+
+ match OnlyUnstableEnum::Unstable {
+ //~^ some variants are not matched explicitly
+ OnlyUnstableEnum::Unstable => {}
+ _ => {}
+ }
+
+ let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable fields are matched with feature on
+ let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
+
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable and stable fields are matched with feature on
+ let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
+
+ // Ok: local bindings are allowed
+ let local = NonExhaustiveEnum::Unit;
+
+ // Ok: missing patterns will be blocked by the pattern being refutable
+ let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
+ //~^ refutable pattern in local binding
+
+ // Check that matching on a reference results in a correct diagnostic
+ match &non_enum {
+ //~^ some variants are not matched explicitly
+ //~| pattern `&NonExhaustiveEnum::Struct { .. }` not covered
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match (true, &non_enum) {
+ //~^ some variants are not matched explicitly
+ //~| patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered
+ (true, NonExhaustiveEnum::Unit) => {}
+ _ => {}
+ }
+
+ match (&non_enum, true) {
+ //~^ some variants are not matched explicitly
+ //~| patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered
+ (NonExhaustiveEnum::Unit, true) => {}
+ _ => {}
+ }
+
+ match Some(&non_enum) {
+ //~^ some variants are not matched explicitly
+ //~| pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered
+ Some(NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_)) => {}
+ _ => {}
+ }
+}
+
+#[deny(non_exhaustive_omitted_patterns)]
+// Ok: Pattern in a param is always wildcard
+pub fn takes_non_exhaustive(_: NonExhaustiveEnum) {
+ let _closure = |_: NonExhaustiveEnum| {};
+}
+
+// ICE #117033
+enum Void {}
+#[deny(non_exhaustive_omitted_patterns)]
+pub fn void(v: Void) -> ! {
+ match v {}
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr
new file mode 100644
index 000000000..1037033c4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -0,0 +1,184 @@
+error: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:139:9
+ |
+LL | VariantNonExhaustive::Bar { x, .. } => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:45:8
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:143:9
+ |
+LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:149:29
+ |
+LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:149:9
+ |
+LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:212:9
+ |
+LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:218:9
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:65:11
+ |
+LL | match non_enum {
+ | ^^^^^^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:72:11
+ |
+LL | match non_enum {
+ | ^^^^^^^^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:93:11
+ |
+LL | match (non_enum, true) {
+ | ^^^^^^^^^^^^^^^^ pattern `(NonExhaustiveEnum::Struct { .. }, _)` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `(NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:106:11
+ |
+LL | match (true, non_enum) {
+ | ^^^^^^^^^^^^^^^^ pattern `(_, NonExhaustiveEnum::Struct { .. })` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `(bool, NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:113:11
+ |
+LL | match Some(non_enum) {
+ | ^^^^^^^^^^^^^^ pattern `Some(NonExhaustiveEnum::Struct { .. })` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `Option<NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:129:11
+ |
+LL | match NestedNonExhaustive::B {
+ | ^^^^^^^^^^^^^^^^^^^^^^ patterns `NestedNonExhaustive::C`, `NestedNonExhaustive::A(NonExhaustiveEnum::Tuple(_))` and `NestedNonExhaustive::A(NonExhaustiveEnum::Struct { .. })` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:184:11
+ |
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:206:11
+ |
+LL | match OnlyUnstableEnum::Unstable {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `OnlyUnstableEnum::Unstable2` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/omitted-patterns.rs:228:9
+ |
+LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
+ | ^^^^^^^^^^^^^^^ pattern `_` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ = note: the matched value is of type `NonExhaustiveEnum`
+help: you might want to use `let else` to handle the variant that isn't matched
+ |
+LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit else { todo!() };
+ | ++++++++++++++++
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:232:11
+ |
+LL | match &non_enum {
+ | ^^^^^^^^^ pattern `&NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `&NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:240:11
+ |
+LL | match (true, &non_enum) {
+ | ^^^^^^^^^^^^^^^^^ patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `(bool, &NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:247:11
+ |
+LL | match (&non_enum, true) {
+ | ^^^^^^^^^^^^^^^^^ patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `(&NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:254:11
+ |
+LL | match Some(&non_enum) {
+ | ^^^^^^^^^^^^^^^ pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `Option<&NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: aborting due to 19 previous errors
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
new file mode 100644
index 000000000..1828fdef9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
@@ -0,0 +1,45 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly with variants
+// marked stable and unstable.
+
+#![feature(non_exhaustive_omitted_patterns_lint)]
+
+// aux-build:unstable.rs
+extern crate unstable;
+
+use unstable::{OnlyUnstableEnum, OnlyUnstableStruct, UnstableEnum, UnstableStruct};
+
+fn main() {
+ // OK: this matches all the stable variants
+ #[deny(non_exhaustive_omitted_patterns)]
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match UnstableEnum::Stable {
+ //~^ some variants are not matched explicitly
+ UnstableEnum::Stable => {}
+ _ => {}
+ }
+
+ // Ok: although this is a bit odd, we don't have anything to report
+ // since there is no stable variants and the feature is off
+ #[deny(non_exhaustive_omitted_patterns)]
+ match OnlyUnstableEnum::new() {
+ _ => {}
+ }
+
+ // Ok: Same as the above enum (no fields can be matched on)
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { .. } = OnlyUnstableStruct::new();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: stable field is matched
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
new file mode 100644
index 000000000..2658b20a7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
@@ -0,0 +1,30 @@
+warning: some fields are not explicitly listed
+ --> $DIR/stable-omitted-patterns.rs:39:9
+ |
+LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `stable2` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/stable-omitted-patterns.rs:38:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/stable-omitted-patterns.rs:21:11
+ |
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Stable2` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/stable-omitted-patterns.rs:20:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/struct.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/struct.rs
new file mode 100644
index 000000000..07e093c15
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/struct.rs
@@ -0,0 +1,49 @@
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct, FunctionalRecord};
+
+fn main() {
+ let fr = FunctionalRecord {
+ //~^ ERROR cannot create non-exhaustive struct
+ first_field: 1920,
+ second_field: 1080,
+ ..FunctionalRecord::default()
+ };
+
+ let ns = NormalStruct { first_field: 640, second_field: 480 };
+ //~^ ERROR cannot create non-exhaustive struct
+
+ let NormalStruct { first_field, second_field } = ns;
+ //~^ ERROR `..` required with struct marked as non-exhaustive
+
+ let ts = TupleStruct(640, 480);
+ //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
+
+ let ts_explicit = structs::TupleStruct(640, 480);
+ //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]
+
+ let TupleStruct { 0: first_field, 1: second_field } = ts;
+ //~^ ERROR `..` required with struct marked as non-exhaustive
+
+ let us = UnitStruct;
+ //~^ ERROR expected value, found struct `UnitStruct` [E0423]
+
+ let us_explicit = structs::UnitStruct;
+ //~^ ERROR unit struct `UnitStruct` is private [E0603]
+
+ let UnitStruct { } = us;
+ //~^ ERROR `..` required with struct marked as non-exhaustive
+}
+
+// Everything below this is expected to compile successfully.
+
+// We only test matching here as we cannot create non-exhaustive
+// structs from another crate. ie. they'll never pass in run-pass tests.
+fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) {
+ let NormalStruct { first_field, second_field, .. } = ns;
+
+ let TupleStruct { 0: first, 1: second, .. } = ts;
+
+ let UnitStruct { .. } = us;
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/struct.stderr
new file mode 100644
index 000000000..39b1ef1e0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/struct.stderr
@@ -0,0 +1,95 @@
+error[E0423]: expected value, found struct `UnitStruct`
+ --> $DIR/struct.rs:29:14
+ |
+LL | let us = UnitStruct;
+ | ^^^^^^^^^^ constructor is not visible here due to private fields
+
+error[E0603]: tuple struct constructor `TupleStruct` is private
+ --> $DIR/struct.rs:23:32
+ |
+LL | let ts_explicit = structs::TupleStruct(640, 480);
+ | ^^^^^^^^^^^ private tuple struct constructor
+ |
+note: the tuple struct constructor `TupleStruct` is defined here
+ --> $DIR/auxiliary/structs.rs:12:1
+ |
+LL | #[non_exhaustive]
+ | ----------------- cannot be constructed because it is `#[non_exhaustive]`
+LL | pub struct TupleStruct(pub u16, pub u16);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0603]: unit struct `UnitStruct` is private
+ --> $DIR/struct.rs:32:32
+ |
+LL | let us_explicit = structs::UnitStruct;
+ | ^^^^^^^^^^ private unit struct
+ |
+note: the unit struct `UnitStruct` is defined here
+ --> $DIR/auxiliary/structs.rs:9:1
+ |
+LL | #[non_exhaustive]
+ | ----------------- cannot be constructed because it is `#[non_exhaustive]`
+LL | pub struct UnitStruct;
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0639]: cannot create non-exhaustive struct using struct expression
+ --> $DIR/struct.rs:7:14
+ |
+LL | let fr = FunctionalRecord {
+ | ______________^
+LL | |
+LL | | first_field: 1920,
+LL | | second_field: 1080,
+LL | | ..FunctionalRecord::default()
+LL | | };
+ | |_____^
+
+error[E0639]: cannot create non-exhaustive struct using struct expression
+ --> $DIR/struct.rs:14:14
+ |
+LL | let ns = NormalStruct { first_field: 640, second_field: 480 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+ --> $DIR/struct.rs:17:9
+ |
+LL | let NormalStruct { first_field, second_field } = ns;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | let NormalStruct { first_field, second_field , .. } = ns;
+ | ~~~~~~
+
+error[E0423]: cannot initialize a tuple struct which contains private fields
+ --> $DIR/struct.rs:20:14
+ |
+LL | let ts = TupleStruct(640, 480);
+ | ^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+ --> $DIR/struct.rs:26:9
+ |
+LL | let TupleStruct { 0: first_field, 1: second_field } = ts;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts;
+ | ~~~~~~
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+ --> $DIR/struct.rs:35:9
+ |
+LL | let UnitStruct { } = us;
+ | ^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | let UnitStruct { .. } = us;
+ | ~~~~
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0423, E0603, E0638, E0639.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs
new file mode 100644
index 000000000..5f76b0cb2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/structs_same_crate.rs
@@ -0,0 +1,32 @@
+// run-pass
+
+#![allow(unused_variables)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
+
+fn main() {
+ let ns = NormalStruct { first_field: 640, second_field: 480 };
+
+ let NormalStruct { first_field, second_field } = ns;
+
+ let ts = TupleStruct { 0: 340, 1: 480 };
+ let ts_constructor = TupleStruct(340, 480);
+
+ let TupleStruct { 0: first, 1: second } = ts;
+ let TupleStruct(first, second) = ts_constructor;
+
+ let us = UnitStruct {};
+ let us_constructor = UnitStruct;
+
+ let UnitStruct { } = us;
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
new file mode 100644
index 000000000..a2735d4cb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
@@ -0,0 +1,32 @@
+#![crate_type = "rlib"]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub enum PartiallyInhabitedVariants {
+ Tuple(u8),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+
+pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+
+pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+
+pub struct IndirectUninhabitedVariants(UninhabitedVariants);
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.rs
new file mode 100644
index 000000000..80b9dc4c1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.rs
@@ -0,0 +1,38 @@
+// aux-build:uninhabited.rs
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+// This test checks that uninhabited non-exhaustive types cannot coerce to any type, as the never
+// type can.
+
+struct A;
+
+fn can_coerce_never_type_to_anything(x: !) -> A {
+ x
+}
+
+fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
new file mode 100644
index 000000000..c209caab5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:23:5
+ |
+LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedEnum`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:27:5
+ |
+LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedTupleStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:31:5
+ |
+LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:35:5
+ |
+LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedVariants`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs
new file mode 100644
index 000000000..6b911dd98
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs
@@ -0,0 +1,45 @@
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+struct A;
+
+// This test checks that uninhabited non-exhaustive types defined in the same crate cannot coerce
+// to any type, as the never type can.
+
+fn can_coerce_never_type_to_anything(x: !) -> A {
+ x
+}
+
+fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
new file mode 100644
index 000000000..289433edf
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:30:5
+ |
+LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedEnum`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:34:5
+ |
+LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedTupleStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:38:5
+ |
+LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:42:5
+ |
+LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected `A`, found `UninhabitedVariants`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs
new file mode 100644
index 000000000..98a7fdbc5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs
@@ -0,0 +1,36 @@
+// aux-build:uninhabited.rs
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ IndirectUninhabitedEnum,
+ IndirectUninhabitedStruct,
+ IndirectUninhabitedTupleStruct,
+ IndirectUninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
+// indirection from an extern crate will not compile.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
new file mode 100644
index 000000000..66e93291c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
+ --> $DIR/indirect_match.rs:19:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:26:1
+ |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
+ --> $DIR/indirect_match.rs:23:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:28:1
+ |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
+ --> $DIR/indirect_match.rs:27:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:30:1
+ |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
+ --> $DIR/indirect_match.rs:33:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:32:1
+ |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
new file mode 100644
index 000000000..8f090fe88
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
@@ -0,0 +1,51 @@
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+
+pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+
+pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+
+pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
+// indirection from the defining crate will not compile without `#![feature(exhaustive_patterns)]`.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
new file mode 100644
index 000000000..c12190541
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:34:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedEnum` defined here
+ --> $DIR/indirect_match_same_crate.rs:20:12
+ |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:38:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedStruct` defined here
+ --> $DIR/indirect_match_same_crate.rs:22:12
+ |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:42:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedTupleStruct` defined here
+ --> $DIR/indirect_match_same_crate.rs:24:12
+ |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:48:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedVariants` defined here
+ --> $DIR/indirect_match_same_crate.rs:26:12
+ |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
new file mode 100644
index 000000000..be86519ec
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
@@ -0,0 +1,40 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ IndirectUninhabitedEnum,
+ IndirectUninhabitedStruct,
+ IndirectUninhabitedTupleStruct,
+ IndirectUninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
+// indirection from an extern crate will not compile. In particular, this enables the
+// `exhaustive_patterns` feature as this can change the branch used in the compiler to determine
+// this.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
new file mode 100644
index 000000000..ef97c1fa1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:23:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:26:1
+ |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:28:1
+ |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:30:1
+ |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:32:1
+ |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
new file mode 100644
index 000000000..60289aa78
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
@@ -0,0 +1,57 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+
+pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+
+pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+
+pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
+// will compile. In particular, this enables the `exhaustive_patterns` feature as this can
+// change the branch used in the compiler to determine this.
+// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
new file mode 100644
index 000000000..230ac7529
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
@@ -0,0 +1,21 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::PartiallyInhabitedVariants;
+
+// This test checks a redundant/useless pattern of a non-exhaustive enum/variant is still
+// warned against.
+
+pub fn foo(x: PartiallyInhabitedVariants) {
+ match x {
+ PartiallyInhabitedVariants::Struct { .. } => {},
+ PartiallyInhabitedVariants::Struct { .. } => {},
+ //~^ ERROR unreachable pattern
+ _ => {},
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
new file mode 100644
index 000000000..3034a67dc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/issue-65157-repeated-match-arm.rs:15:9
+ |
+LL | PartiallyInhabitedVariants::Struct { .. } => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-65157-repeated-match-arm.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs
new file mode 100644
index 000000000..e54098d4d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs
@@ -0,0 +1,34 @@
+// aux-build:uninhabited.rs
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate
+// will not compile.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
new file mode 100644
index 000000000..c125756a6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
@@ -0,0 +1,83 @@
+error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
+ --> $DIR/match.rs:19:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:5:1
+ |
+LL | pub enum UninhabitedEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
+ --> $DIR/match.rs:23:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:9:1
+ |
+LL | pub struct UninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
+ --> $DIR/match.rs:27:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:14:1
+ |
+LL | pub struct UninhabitedTupleStruct(!);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ --> $DIR/match.rs:31:11
+ |
+LL | match x {}
+ | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ |
+note: `UninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:16:1
+ |
+LL | pub enum UninhabitedVariants {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[non_exhaustive] Tuple(!),
+ | ----- not covered
+LL | #[non_exhaustive] Struct { x: ! }
+ | ------ not covered
+ = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match x {
+LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
new file mode 100644
index 000000000..ebbdfba15
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
@@ -0,0 +1,41 @@
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
+// will compile.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
new file mode 100644
index 000000000..7a12aca85
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
@@ -0,0 +1,64 @@
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
+ --> $DIR/match_same_crate.rs:30:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedStruct` defined here
+ --> $DIR/match_same_crate.rs:8:12
+ |
+LL | pub struct UninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
+ --> $DIR/match_same_crate.rs:34:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedTupleStruct` defined here
+ --> $DIR/match_same_crate.rs:13:12
+ |
+LL | pub struct UninhabitedTupleStruct(!);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ --> $DIR/match_same_crate.rs:38:11
+ |
+LL | match x {}
+ | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ |
+note: `UninhabitedVariants` defined here
+ --> $DIR/match_same_crate.rs:15:10
+ |
+LL | pub enum UninhabitedVariants {
+ | ^^^^^^^^^^^^^^^^^^^
+LL | #[non_exhaustive] Tuple(!),
+ | ----- not covered
+LL | #[non_exhaustive] Struct { x: ! }
+ | ------ not covered
+ = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match x {
+LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
new file mode 100644
index 000000000..900dfff65
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
@@ -0,0 +1,37 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate
+// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can
+// change the branch used in the compiler to determine this.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
new file mode 100644
index 000000000..19e2546b0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -0,0 +1,83 @@
+error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
+ --> $DIR/match_with_exhaustive_patterns.rs:22:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:5:1
+ |
+LL | pub enum UninhabitedEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
+ --> $DIR/match_with_exhaustive_patterns.rs:26:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:9:1
+ |
+LL | pub struct UninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
+ --> $DIR/match_with_exhaustive_patterns.rs:30:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:14:1
+ |
+LL | pub struct UninhabitedTupleStruct(!);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ --> $DIR/match_with_exhaustive_patterns.rs:34:11
+ |
+LL | match x {}
+ | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ |
+note: `UninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:16:1
+ |
+LL | pub enum UninhabitedVariants {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[non_exhaustive] Tuple(!),
+ | ----- not covered
+LL | #[non_exhaustive] Struct { x: ! }
+ | ------ not covered
+ = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match x {
+LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
new file mode 100644
index 000000000..de5530485
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
@@ -0,0 +1,47 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
+// will compile. In particular, this enables the `exhaustive_patterns` feature as this can
+// change the branch used in the compiler to determine this.
+// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
new file mode 100644
index 000000000..221b5cf6b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
@@ -0,0 +1,59 @@
+// aux-build:uninhabited.rs
+// build-pass (FIXME(62277): could be check-pass?)
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ PartiallyInhabitedVariants,
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+fn uninhabited_enum() -> Option<UninhabitedEnum> {
+ None
+}
+
+fn uninhabited_variant() -> Option<UninhabitedVariants> {
+ None
+}
+
+fn partially_inhabited_variant() -> PartiallyInhabitedVariants {
+ PartiallyInhabitedVariants::Tuple(3)
+}
+
+fn uninhabited_struct() -> Option<UninhabitedStruct> {
+ None
+}
+
+fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> {
+ None
+}
+
+// This test checks that non-exhaustive types that would normally be considered uninhabited within
+// the defining crate are not considered uninhabited from extern crates.
+
+fn main() {
+ match uninhabited_enum() {
+ Some(_x) => (), // This line would normally error.
+ None => (),
+ }
+
+ match uninhabited_variant() {
+ Some(_x) => (), // This line would normally error.
+ None => (),
+ }
+
+ // This line would normally error.
+ while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {
+ }
+
+ while let Some(_x) = uninhabited_struct() { // This line would normally error.
+ }
+
+ while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error.
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
new file mode 100644
index 000000000..ffc496a97
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
@@ -0,0 +1,70 @@
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub enum PartiallyInhabitedVariants {
+ Tuple(u8),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+fn uninhabited_enum() -> Option<UninhabitedEnum> {
+ None
+}
+
+fn uninhabited_variant() -> Option<UninhabitedVariants> {
+ None
+}
+
+fn partially_inhabited_variant() -> PartiallyInhabitedVariants {
+ PartiallyInhabitedVariants::Tuple(3)
+}
+
+fn uninhabited_struct() -> Option<UninhabitedStruct> {
+ None
+}
+
+fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> {
+ None
+}
+
+// This test checks that non-exhaustive types that would normally be considered uninhabited within
+// the defining crate are still considered uninhabited.
+
+fn main() {
+ match uninhabited_enum() {
+ Some(_x) => (), //~ ERROR unreachable pattern
+ None => (),
+ }
+
+ match uninhabited_variant() {
+ Some(_x) => (), //~ ERROR unreachable pattern
+ None => (),
+ }
+
+ while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
+ //~^ ERROR unreachable pattern
+ }
+
+ while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern
+ }
+
+ while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
new file mode 100644
index 000000000..8bfd6e91f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
@@ -0,0 +1,38 @@
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:52:9
+ |
+LL | Some(_x) => (),
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/patterns_same_crate.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:57:9
+ |
+LL | Some(_x) => (),
+ | ^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:61:15
+ |
+LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:65:15
+ |
+LL | while let Some(_x) = uninhabited_struct() {
+ | ^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:68:15
+ |
+LL | while let Some(_x) = uninhabited_tuple_struct() {
+ | ^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/variant.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/variant.rs
new file mode 100644
index 000000000..bc346aea5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/variant.rs
@@ -0,0 +1,33 @@
+// aux-build:variants.rs
+
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+fn main() {
+ let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+ //~^ ERROR cannot create non-exhaustive variant
+
+ let variant_tuple = NonExhaustiveVariants::Tuple(640);
+ //~^ ERROR tuple variant `Tuple` is private [E0603]
+
+ let variant_unit = NonExhaustiveVariants::Unit;
+ //~^ ERROR unit variant `Unit` is private [E0603]
+
+ match variant_struct {
+ NonExhaustiveVariants::Unit => "",
+ //~^ ERROR unit variant `Unit` is private [E0603]
+ NonExhaustiveVariants::Tuple(fe_tpl) => "",
+ //~^ ERROR tuple variant `Tuple` is private [E0603]
+ NonExhaustiveVariants::Struct { field } => ""
+ //~^ ERROR `..` required with variant marked as non-exhaustive
+ };
+
+ if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
+ //~^ ERROR tuple variant `Tuple` is private [E0603]
+ }
+
+ if let NonExhaustiveVariants::Struct { field } = variant_struct {
+ //~^ ERROR `..` required with variant marked as non-exhaustive
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/variant.stderr
new file mode 100644
index 000000000..4083f57a9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/variant.stderr
@@ -0,0 +1,102 @@
+error[E0603]: tuple variant `Tuple` is private
+ --> $DIR/variant.rs:11:48
+ |
+LL | let variant_tuple = NonExhaustiveVariants::Tuple(640);
+ | ^^^^^ private tuple variant
+ |
+note: the tuple variant `Tuple` is defined here
+ --> $DIR/auxiliary/variants.rs:5:23
+ |
+LL | #[non_exhaustive] Tuple(u32),
+ | ----------------- ^^^^^
+ | |
+ | cannot be constructed because it is `#[non_exhaustive]`
+
+error[E0603]: unit variant `Unit` is private
+ --> $DIR/variant.rs:14:47
+ |
+LL | let variant_unit = NonExhaustiveVariants::Unit;
+ | ^^^^ private unit variant
+ |
+note: the unit variant `Unit` is defined here
+ --> $DIR/auxiliary/variants.rs:4:23
+ |
+LL | #[non_exhaustive] Unit,
+ | ----------------- ^^^^
+ | |
+ | cannot be constructed because it is `#[non_exhaustive]`
+
+error[E0603]: unit variant `Unit` is private
+ --> $DIR/variant.rs:18:32
+ |
+LL | NonExhaustiveVariants::Unit => "",
+ | ^^^^ private unit variant
+ |
+note: the unit variant `Unit` is defined here
+ --> $DIR/auxiliary/variants.rs:4:23
+ |
+LL | #[non_exhaustive] Unit,
+ | ----------------- ^^^^
+ | |
+ | cannot be constructed because it is `#[non_exhaustive]`
+
+error[E0603]: tuple variant `Tuple` is private
+ --> $DIR/variant.rs:20:32
+ |
+LL | NonExhaustiveVariants::Tuple(fe_tpl) => "",
+ | ^^^^^ private tuple variant
+ |
+note: the tuple variant `Tuple` is defined here
+ --> $DIR/auxiliary/variants.rs:5:23
+ |
+LL | #[non_exhaustive] Tuple(u32),
+ | ----------------- ^^^^^
+ | |
+ | cannot be constructed because it is `#[non_exhaustive]`
+
+error[E0603]: tuple variant `Tuple` is private
+ --> $DIR/variant.rs:26:35
+ |
+LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
+ | ^^^^^ private tuple variant
+ |
+note: the tuple variant `Tuple` is defined here
+ --> $DIR/auxiliary/variants.rs:5:23
+ |
+LL | #[non_exhaustive] Tuple(u32),
+ | ----------------- ^^^^^
+ | |
+ | cannot be constructed because it is `#[non_exhaustive]`
+
+error[E0639]: cannot create non-exhaustive variant using struct expression
+ --> $DIR/variant.rs:8:26
+ |
+LL | let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with variant marked as non-exhaustive
+ --> $DIR/variant.rs:22:9
+ |
+LL | NonExhaustiveVariants::Struct { field } => ""
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | NonExhaustiveVariants::Struct { field , .. } => ""
+ | ~~~~~~
+
+error[E0638]: `..` required with variant marked as non-exhaustive
+ --> $DIR/variant.rs:30:12
+ |
+LL | if let NonExhaustiveVariants::Struct { field } = variant_struct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct {
+ | ~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0603, E0638, E0639.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/variants_fictive_visibility.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
new file mode 100644
index 000000000..dacaf489a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
@@ -0,0 +1,12 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:variants.rs
+
+extern crate variants;
+
+const S: u8 = 0;
+
+// OK, `Struct` in value namespace is crate-private, so it's filtered away
+// and there's no conflict with the previously defined `const S`.
+use variants::NonExhaustiveVariants::Struct as S;
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs
new file mode 100644
index 000000000..5f2816ec6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/variants_same_crate.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive] Unit,
+ #[non_exhaustive] Tuple(u32),
+ #[non_exhaustive] Struct { field: u32 }
+}
+
+fn main() {
+ let variant_tuple = NonExhaustiveVariants::Tuple(340);
+ let _variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+ match variant_tuple {
+ NonExhaustiveVariants::Unit => "",
+ NonExhaustiveVariants::Tuple(_fe_tpl) => "",
+ NonExhaustiveVariants::Struct { field: _ } => ""
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs
new file mode 100644
index 000000000..fa04f4b12
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs
@@ -0,0 +1,23 @@
+// Check that we if we get ahold of an object unsafe trait
+// object with auto traits and lifetimes, we can downcast it
+//
+// check-pass
+
+#![feature(object_safe_for_dispatch)]
+
+trait Trait: Sized {}
+
+fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait {
+ t
+}
+
+fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't))
+ -> &'b (dyn Trait + 't)
+where
+ 'a: 'b,
+ 't: 'a + 'b,
+{
+ t
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
new file mode 100644
index 000000000..c7665affb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
@@ -0,0 +1,68 @@
+// Check that we can manually implement an object-unsafe trait for its trait object.
+
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+// run-pass
+
+#![feature(object_safe_for_dispatch)]
+
+trait Bad {
+ fn stat() -> char {
+ 'A'
+ }
+ fn virt(&self) -> char {
+ 'B'
+ }
+ fn indirect(&self) -> char {
+ Self::stat()
+ }
+}
+
+trait Good {
+ fn good_virt(&self) -> char {
+ panic!()
+ }
+ fn good_indirect(&self) -> char {
+ panic!()
+ }
+}
+
+impl<'a> Bad for dyn Bad + 'a {
+ fn stat() -> char {
+ 'C'
+ }
+ fn virt(&self) -> char {
+ 'D'
+ }
+}
+
+struct Struct {}
+
+impl Bad for Struct {}
+
+impl Good for Struct {}
+
+fn main() {
+ let s = Struct {};
+
+ let mut res = String::new();
+
+ // Directly call static.
+ res.push(Struct::stat()); // "A"
+ res.push(<dyn Bad>::stat()); // "AC"
+
+ let good: &dyn Good = &s;
+
+ // These look similar enough...
+ let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) };
+
+ // Call virtual.
+ res.push(s.virt()); // "ACB"
+ res.push(bad.virt()); // "ACBD"
+
+ // Indirectly call static.
+ res.push(s.indirect()); // "ACBDA"
+ res.push(bad.indirect()); // "ACBDAC"
+
+ assert_eq!(&res, "ACBDAC");
+}
diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs
new file mode 100644
index 000000000..df97d2c13
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs
@@ -0,0 +1,37 @@
+// Check that we can statically dispatch methods for object
+// unsafe trait objects, directly and indirectly
+//
+// check-pass
+
+#![feature(object_safe_for_dispatch)]
+
+trait Statics {
+ fn plain() {}
+ fn generic<T>() {}
+}
+
+trait Trait: Sized {}
+
+impl<'a> Statics for dyn Trait + 'a {}
+
+fn static_poly<T: Statics + ?Sized>() {
+ T::plain();
+ T::generic::<usize>();
+}
+
+fn inferred_poly<T: Statics + ?Sized>(t: &T) {
+ static_poly::<T>();
+ T::plain();
+ T::generic::<usize>();
+}
+
+fn call(t: &dyn Trait) {
+ static_poly::<dyn Trait>();
+ inferred_poly(t);
+}
+
+fn main() {
+ static_poly::<dyn Trait>();
+ <dyn Trait>::plain();
+ <dyn Trait>::generic::<usize>()
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/call-chain.rs b/tests/ui/rfcs/rfc-2091-track-caller/call-chain.rs
new file mode 100644
index 000000000..a8814ce28
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/call-chain.rs
@@ -0,0 +1,30 @@
+// run-pass
+// revisions: default mir-opt
+//[default] compile-flags: -Zinline-mir=false
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+use std::panic::Location;
+
+struct Foo;
+
+impl Foo {
+ #[inline(always)]
+ #[track_caller]
+ fn check_loc(&self, line: u32, col: u32) -> &Self {
+ let loc = Location::caller();
+ assert_eq!(loc.file(), file!(), "file mismatch");
+ assert_eq!(loc.line(), line, "line mismatch");
+ assert_eq!(loc.column(), col, "column mismatch");
+ self
+ }
+}
+
+fn main() {
+ // Tests that when `Location::caller` is used in a method chain,
+ // it points to the start of the correct call (the first character after the dot)
+ // instead of to the very first expression in the chain
+ let foo = Foo;
+ foo.
+ check_loc(line!(), 9).check_loc(line!(), 31)
+ .check_loc(line!(), 10);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
new file mode 100644
index 000000000..a3bed707e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
@@ -0,0 +1,32 @@
+// Ensure that a `#[track_caller]` function, returning `caller_location()`,
+// which coerced (to a function pointer) and called, inside a `const fn`,
+// in turn called, results in the same output irrespective of whether
+// we're in a const or runtime context.
+
+// run-pass
+// compile-flags: -Z unleash-the-miri-inside-of-you
+
+#![feature(core_intrinsics, const_caller_location)]
+
+type L = &'static std::panic::Location<'static>;
+
+#[track_caller]
+const fn attributed() -> L {
+ std::intrinsics::caller_location()
+}
+
+const fn calling_attributed() -> L {
+ // We need `-Z unleash-the-miri-inside-of-you` for this as we don't have `const fn` pointers.
+ let ptr: fn() -> L = attributed;
+ ptr()
+}
+
+fn main() {
+ const CONSTANT: L = calling_attributed();
+ let runtime = calling_attributed();
+
+ assert_eq!(
+ (runtime.file(), runtime.line(), runtime.column()),
+ (CONSTANT.file(), CONSTANT.line(), CONSTANT.column()),
+ );
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr
new file mode 100644
index 000000000..cf8ca5771
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr
@@ -0,0 +1,10 @@
+warning: skipping const checks
+ |
+help: skipping check that does not even have a feature gate
+ --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5
+ |
+LL | ptr()
+ | ^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-intrinsic.rs b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-intrinsic.rs
new file mode 100644
index 000000000..e5754d355
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-intrinsic.rs
@@ -0,0 +1,27 @@
+// run-pass
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+#[inline(never)]
+#[track_caller]
+fn codegen_caller_loc() -> &'static core::panic::Location<'static> {
+ core::panic::Location::caller()
+}
+
+macro_rules! caller_location_from_macro {
+ () => (codegen_caller_loc());
+}
+
+fn main() {
+ let loc = codegen_caller_loc();
+ assert_eq!(loc.file(), file!());
+ assert_eq!(loc.line(), 16);
+ assert_eq!(loc.column(), 15);
+
+ // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
+ // i.e. point to where the macro was invoked, instead of the macro itself.
+ let loc2 = caller_location_from_macro!();
+ assert_eq!(loc2.file(), file!());
+ assert_eq!(loc2.line(), 23);
+ assert_eq!(loc2.column(), 16);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/const-caller-location.rs b/tests/ui/rfcs/rfc-2091-track-caller/const-caller-location.rs
new file mode 100644
index 000000000..6e15cf3fe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/const-caller-location.rs
@@ -0,0 +1,43 @@
+// run-pass
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+#![feature(const_caller_location)]
+
+use std::panic::Location;
+
+const LOCATION: &Location = Location::caller();
+
+const TRACKED: &Location = tracked();
+#[track_caller]
+const fn tracked() -> &'static Location <'static> {
+ Location::caller()
+}
+
+const NESTED: &Location = nested_location();
+const fn nested_location() -> &'static Location<'static> {
+ Location::caller()
+}
+
+const CONTAINED: &Location = contained();
+const fn contained() -> &'static Location<'static> {
+ tracked()
+}
+
+fn main() {
+ assert_eq!(LOCATION.file(), file!());
+ assert_eq!(LOCATION.line(), 9);
+ assert_eq!(LOCATION.column(), 29);
+
+ assert_eq!(TRACKED.file(), file!());
+ assert_eq!(TRACKED.line(), 11);
+ assert_eq!(TRACKED.column(), 28);
+
+ assert_eq!(NESTED.file(), file!());
+ assert_eq!(NESTED.line(), 19);
+ assert_eq!(NESTED.column(), 5);
+
+ assert_eq!(CONTAINED.file(), file!());
+ assert_eq!(CONTAINED.line(), 24);
+ assert_eq!(CONTAINED.column(), 5);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/diverging-caller-location.rs b/tests/ui/rfcs/rfc-2091-track-caller/diverging-caller-location.rs
new file mode 100644
index 000000000..668111955
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/diverging-caller-location.rs
@@ -0,0 +1,17 @@
+// run-fail
+
+//! This test ensures that `#[track_caller]` can be applied directly to diverging functions, as
+//! the tracking issue says: https://github.com/rust-lang/rust/issues/47809#issue-292138490.
+//! Because the annotated function must diverge and a panic keeps that faster than an infinite loop,
+//! we don't inspect the location returned -- it would be difficult to distinguish between the
+//! explicit panic and a failed assertion. That it compiles and runs is enough for this one.
+
+#[track_caller]
+fn doesnt_return() -> ! {
+ let _location = core::panic::Location::caller();
+ panic!("huzzah");
+}
+
+fn main() {
+ doesnt_return();
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.rs
new file mode 100644
index 000000000..6f4290e2a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.rs
@@ -0,0 +1,5 @@
+#[track_caller(1)]
+fn f() {}
+//~^^ ERROR malformed `track_caller` attribute input
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr
new file mode 100644
index 000000000..e22d812c8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr
@@ -0,0 +1,8 @@
+error: malformed `track_caller` attribute input
+ --> $DIR/error-odd-syntax.rs:1:1
+ |
+LL | #[track_caller(1)]
+ | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.rs
new file mode 100644
index 000000000..074e1ceb7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.rs
@@ -0,0 +1,11 @@
+#[track_caller]
+extern "C" fn f() {}
+//~^^ ERROR `#[track_caller]` requires Rust ABI
+
+extern "C" {
+ #[track_caller]
+ fn g();
+ //~^^ ERROR `#[track_caller]` requires Rust ABI
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.stderr
new file mode 100644
index 000000000..bcc0c8170
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.stderr
@@ -0,0 +1,15 @@
+error[E0737]: `#[track_caller]` requires Rust ABI
+ --> $DIR/error-with-invalid-abi.rs:1:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error[E0737]: `#[track_caller]` requires Rust ABI
+ --> $DIR/error-with-invalid-abi.rs:6:5
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0737`.
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.rs
new file mode 100644
index 000000000..b2ea31bb5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.rs
@@ -0,0 +1,4 @@
+#[track_caller] //~ ERROR `main` function is not allowed to be
+fn main() {
+ panic!("{}: oh no", std::panic::Location::caller());
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr
new file mode 100644
index 000000000..4626544a5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr
@@ -0,0 +1,10 @@
+error: `main` function is not allowed to be `#[track_caller]`
+ --> $DIR/error-with-main.rs:1:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^ help: remove this annotation
+LL | fn main() {
+ | --------- `main` function is not allowed to be `#[track_caller]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs
new file mode 100644
index 000000000..43e33cbb1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs
@@ -0,0 +1,24 @@
+// needs-asm-support
+#![feature(naked_functions)]
+
+use std::arch::asm;
+
+#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
+//~^ ERROR `#[track_caller]` requires Rust ABI
+#[naked]
+extern "C" fn f() {
+ asm!("", options(noreturn));
+}
+
+struct S;
+
+impl S {
+ #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
+ //~^ ERROR `#[track_caller]` requires Rust ABI
+ #[naked]
+ extern "C" fn g() {
+ asm!("", options(noreturn));
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr
new file mode 100644
index 000000000..3f7d0df42
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr
@@ -0,0 +1,28 @@
+error[E0736]: cannot use `#[track_caller]` with `#[naked]`
+ --> $DIR/error-with-naked.rs:6:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error[E0736]: cannot use `#[track_caller]` with `#[naked]`
+ --> $DIR/error-with-naked.rs:16:5
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error[E0737]: `#[track_caller]` requires Rust ABI
+ --> $DIR/error-with-naked.rs:6:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error[E0737]: `#[track_caller]` requires Rust ABI
+ --> $DIR/error-with-naked.rs:16:5
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0736, E0737.
+For more information about an error, try `rustc --explain E0736`.
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs
new file mode 100644
index 000000000..f0e111b57
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs
@@ -0,0 +1,7 @@
+#![feature(start)]
+
+#[start]
+#[track_caller] //~ ERROR `#[start]` function is not allowed to be `#[track_caller]`
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
+ panic!("{}: oh no", std::panic::Location::caller());
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr
new file mode 100644
index 000000000..2738444f2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr
@@ -0,0 +1,10 @@
+error: `#[start]` function is not allowed to be `#[track_caller]`
+ --> $DIR/error-with-start.rs:4:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+LL | fn start(_argc: isize, _argv: *const *const u8) -> isize {
+ | -------------------------------------------------------- `#[start]` function is not allowed to be `#[track_caller]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/intrinsic-wrapper.rs b/tests/ui/rfcs/rfc-2091-track-caller/intrinsic-wrapper.rs
new file mode 100644
index 000000000..23d2a4b0a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/intrinsic-wrapper.rs
@@ -0,0 +1,22 @@
+// run-pass
+// revisions: default mir-opt
+//[default] compile-flags: -Zinline-mir=no
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+macro_rules! caller_location_from_macro {
+ () => (core::panic::Location::caller());
+}
+
+fn main() {
+ let loc = core::panic::Location::caller();
+ assert_eq!(loc.file(), file!());
+ assert_eq!(loc.line(), 11);
+ assert_eq!(loc.column(), 15);
+
+ // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
+ // i.e. point to where the macro was invoked, instead of the macro itself.
+ let loc2 = caller_location_from_macro!();
+ assert_eq!(loc2.file(), file!());
+ assert_eq!(loc2.line(), 18);
+ assert_eq!(loc2.column(), 16);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs b/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs
new file mode 100644
index 000000000..6ca09fac8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+// See https://github.com/rust-lang/rust/issues/95151
+#[track_caller]
+macro_rules! _foo {
+ () => {};
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/mir-inlined-macro.rs b/tests/ui/rfcs/rfc-2091-track-caller/mir-inlined-macro.rs
new file mode 100644
index 000000000..a2e8eb27e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/mir-inlined-macro.rs
@@ -0,0 +1,23 @@
+// run-pass
+// revisions: default mir-opt
+//[default] compile-flags: -Zinline-mir=no
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+use std::panic::Location;
+
+macro_rules! f {
+ () => {
+ Location::caller()
+ };
+}
+
+#[inline(always)]
+fn g() -> &'static Location<'static> {
+ f!()
+}
+
+fn main() {
+ let loc = g();
+ assert_eq!(loc.line(), 16);
+ assert_eq!(loc.column(), 5);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs
new file mode 100644
index 000000000..2d2b01b6f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs
@@ -0,0 +1,5 @@
+#[track_caller]
+struct S;
+//~^^ ERROR attribute should be applied to a function definition
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr
new file mode 100644
index 000000000..f976b7f52
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr
@@ -0,0 +1,11 @@
+error[E0739]: attribute should be applied to a function definition
+ --> $DIR/only-for-fns.rs:1:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+LL | struct S;
+ | --------- not a function definition
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0739`.
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/pass.rs b/tests/ui/rfcs/rfc-2091-track-caller/pass.rs
new file mode 100644
index 000000000..1b13ea3e9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/pass.rs
@@ -0,0 +1,10 @@
+// run-pass
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+#[track_caller]
+fn f() {}
+
+fn main() {
+ f();
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs b/tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
new file mode 100644
index 000000000..f11456250
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
@@ -0,0 +1,64 @@
+// run-pass
+// needs-unwind
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+#![allow(unconditional_panic)]
+
+//! Test that panic locations for `#[track_caller]` functions in std have the correct
+//! location reported.
+
+use std::cell::RefCell;
+use std::collections::{BTreeMap, HashMap, VecDeque};
+use std::ops::{Index, IndexMut};
+use std::panic::{AssertUnwindSafe, UnwindSafe};
+
+fn main() {
+ // inspect the `PanicInfo` we receive to ensure the right file is the source
+ std::panic::set_hook(Box::new(|info| {
+ let actual = info.location().unwrap();
+ if actual.file() != file!() {
+ eprintln!("expected a location in the test file, found {:?}", actual);
+ panic!();
+ }
+ }));
+
+ fn assert_panicked(f: impl FnOnce() + UnwindSafe) {
+ std::panic::catch_unwind(f).unwrap_err();
+ }
+
+ let nope: Option<()> = None;
+ assert_panicked(|| nope.unwrap());
+ assert_panicked(|| nope.expect(""));
+
+ let oops: Result<(), ()> = Err(());
+ assert_panicked(|| oops.unwrap());
+ assert_panicked(|| oops.expect(""));
+
+ let fine: Result<(), ()> = Ok(());
+ assert_panicked(|| fine.unwrap_err());
+ assert_panicked(|| fine.expect_err(""));
+
+ let mut small = [0]; // the implementation backing str, vec, etc
+ assert_panicked(move || { small.index(1); });
+ assert_panicked(move || { small[1]; });
+ assert_panicked(move || { small.index_mut(1); });
+ assert_panicked(move || { small[1] += 1; });
+
+ let sorted: BTreeMap<bool, bool> = Default::default();
+ assert_panicked(|| { sorted.index(&false); });
+ assert_panicked(|| { sorted[&false]; });
+
+ let unsorted: HashMap<bool, bool> = Default::default();
+ assert_panicked(|| { unsorted.index(&false); });
+ assert_panicked(|| { unsorted[&false]; });
+
+ let weirdo: VecDeque<()> = Default::default();
+ assert_panicked(|| { weirdo.index(1); });
+ assert_panicked(|| { weirdo[1]; });
+
+ let refcell: RefCell<()> = Default::default();
+ let _conflicting = refcell.borrow_mut();
+ assert_panicked(AssertUnwindSafe(|| { refcell.borrow(); }));
+ assert_panicked(AssertUnwindSafe(|| { refcell.borrow_mut(); }));
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/track-caller-attribute.rs b/tests/ui/rfcs/rfc-2091-track-caller/track-caller-attribute.rs
new file mode 100644
index 000000000..9d28eb9de
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/track-caller-attribute.rs
@@ -0,0 +1,40 @@
+// run-pass
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+use std::panic::Location;
+
+#[track_caller]
+fn tracked() -> &'static Location<'static> {
+ Location::caller()
+}
+
+fn nested_intrinsic() -> &'static Location<'static> {
+ Location::caller()
+}
+
+fn nested_tracked() -> &'static Location<'static> {
+ tracked()
+}
+
+fn main() {
+ let location = Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), 21);
+ assert_eq!(location.column(), 20);
+
+ let tracked = tracked();
+ assert_eq!(tracked.file(), file!());
+ assert_eq!(tracked.line(), 26);
+ assert_eq!(tracked.column(), 19);
+
+ let nested = nested_intrinsic();
+ assert_eq!(nested.file(), file!());
+ assert_eq!(nested.line(), 13);
+ assert_eq!(nested.column(), 5);
+
+ let contained = nested_tracked();
+ assert_eq!(contained.file(), file!());
+ assert_eq!(contained.line(), 17);
+ assert_eq!(contained.column(), 5);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs b/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs
new file mode 100644
index 000000000..5115f687c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+use std::panic::Location;
+
+extern "Rust" {
+ #[track_caller]
+ fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>;
+ fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static>;
+}
+
+fn rust_track_caller_ffi_test_nested_tracked() -> &'static Location<'static> {
+ unsafe { rust_track_caller_ffi_test_tracked() }
+}
+
+mod provides {
+ use std::panic::Location;
+ #[track_caller] // UB if we did not have this!
+ #[no_mangle]
+ fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static> {
+ Location::caller()
+ }
+ #[no_mangle]
+ fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static> {
+ Location::caller()
+ }
+}
+
+fn main() {
+ let location = Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), 29);
+ assert_eq!(location.column(), 20);
+
+ let tracked = unsafe { rust_track_caller_ffi_test_tracked() };
+ assert_eq!(tracked.file(), file!());
+ assert_eq!(tracked.line(), 34);
+ assert_eq!(tracked.column(), 28);
+
+ let untracked = unsafe { rust_track_caller_ffi_test_untracked() };
+ assert_eq!(untracked.file(), file!());
+ assert_eq!(untracked.line(), 24);
+ assert_eq!(untracked.column(), 9);
+
+ let contained = rust_track_caller_ffi_test_nested_tracked();
+ assert_eq!(contained.file(), file!());
+ assert_eq!(contained.line(), 12);
+ assert_eq!(contained.column(), 14);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
new file mode 100644
index 000000000..86bcf1f6f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
@@ -0,0 +1,154 @@
+// run-pass
+
+#![feature(stmt_expr_attributes)]
+#![feature(closure_track_caller)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+use std::panic::Location;
+
+type Loc = &'static Location<'static>;
+
+#[track_caller]
+fn mono_invoke_fn<F: Fn(&'static str, bool) -> (&'static str, bool, Loc)>(
+ val: &F
+) -> (&'static str, bool, Loc) {
+ val("from_mono", false)
+}
+
+#[track_caller]
+fn mono_invoke_fn_once<F: FnOnce(&'static str, bool) -> (&'static str, bool, Loc)>(
+ val: F
+) -> (&'static str, bool, Loc) {
+ val("from_mono", false)
+}
+
+#[track_caller]
+fn dyn_invoke_fn_mut(
+ val: &mut dyn FnMut(&'static str, bool) -> (&'static str, bool, Loc)
+) -> (&'static str, bool, Loc) {
+ val("from_dyn", false)
+}
+
+#[track_caller]
+fn dyn_invoke_fn_once(
+ val: Box<dyn FnOnce(&'static str, bool) -> (&'static str, bool, Loc)>
+) -> (&'static str, bool, Loc) {
+ val("from_dyn", false)
+}
+
+
+fn test_closure() {
+ let mut track_closure = #[track_caller] |first: &'static str, second: bool| {
+ (first, second, Location::caller())
+ };
+ let (first_arg, first_bool, first_loc) = track_closure("first_arg", true);
+ let first_line = line!() - 1;
+ assert_eq!(first_arg, "first_arg");
+ assert_eq!(first_bool, true);
+ assert_eq!(first_loc.file(), file!());
+ assert_eq!(first_loc.line(), first_line);
+ assert_eq!(first_loc.column(), 46);
+
+ let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_mut(&mut track_closure);
+ assert_eq!(dyn_arg, "from_dyn");
+ assert_eq!(dyn_bool, false);
+ // `FnMut::call_mut` does not have `#[track_caller]`,
+ // so this will not match
+ assert_ne!(dyn_loc.file(), file!());
+
+ let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_once(Box::new(track_closure));
+ assert_eq!(dyn_arg, "from_dyn");
+ assert_eq!(dyn_bool, false);
+ // `FnOnce::call_once` does not have `#[track_caller]`
+ // so this will not match
+ assert_ne!(dyn_loc.file(), file!());
+
+
+ let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn(&track_closure);
+ let mono_line = line!() - 1;
+ assert_eq!(mono_arg, "from_mono");
+ assert_eq!(mono_bool, false);
+ assert_eq!(mono_loc.file(), file!());
+ assert_eq!(mono_loc.line(), mono_line);
+ assert_eq!(mono_loc.column(), 43);
+
+ let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn_once(track_closure);
+ let mono_line = line!() - 1;
+ assert_eq!(mono_arg, "from_mono");
+ assert_eq!(mono_bool, false);
+ assert_eq!(mono_loc.file(), file!());
+ assert_eq!(mono_loc.line(), mono_line);
+ assert_eq!(mono_loc.column(), 43);
+
+ let non_tracked_caller = || Location::caller();
+ let non_tracked_line = line!() - 1; // This is the line of the closure, not its caller
+ let non_tracked_loc = non_tracked_caller();
+ assert_eq!(non_tracked_loc.file(), file!());
+ assert_eq!(non_tracked_loc.line(), non_tracked_line);
+ assert_eq!(non_tracked_loc.column(), 33);
+}
+
+
+#[track_caller]
+fn mono_coroutine<F: Coroutine<String, Yield = (&'static str, String, Loc), Return = ()>>(
+ val: Pin<&mut F>
+) -> (&'static str, String, Loc) {
+ match val.resume("Mono".to_string()) {
+ CoroutineState::Yielded(val) => val,
+ _ => unreachable!()
+ }
+}
+
+#[track_caller]
+fn dyn_coroutine(
+ val: Pin<&mut dyn Coroutine<String, Yield = (&'static str, String, Loc), Return = ()>>
+) -> (&'static str, String, Loc) {
+ match val.resume("Dyn".to_string()) {
+ CoroutineState::Yielded(val) => val,
+ _ => unreachable!()
+ }
+}
+
+fn test_coroutine() {
+ let coroutine = #[track_caller] |arg: String| {
+ yield ("first", arg.clone(), Location::caller());
+ yield ("second", arg.clone(), Location::caller());
+ };
+
+ let mut pinned = Box::pin(coroutine);
+ let (dyn_ret, dyn_arg, dyn_loc) = dyn_coroutine(pinned.as_mut());
+ assert_eq!(dyn_ret, "first");
+ assert_eq!(dyn_arg, "Dyn".to_string());
+ // The `Coroutine` trait does not have `#[track_caller]` on `resume`, so
+ // this will not match.
+ assert_ne!(dyn_loc.file(), file!());
+
+
+ let (mono_ret, mono_arg, mono_loc) = mono_coroutine(pinned.as_mut());
+ let mono_line = line!() - 1;
+ assert_eq!(mono_ret, "second");
+ // The coroutine ignores the argument to the second `resume` call
+ assert_eq!(mono_arg, "Dyn".to_string());
+ assert_eq!(mono_loc.file(), file!());
+ assert_eq!(mono_loc.line(), mono_line);
+ assert_eq!(mono_loc.column(), 42);
+
+ let non_tracked_coroutine = || { yield Location::caller(); };
+ let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller
+ let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) {
+ CoroutineState::Yielded(val) => val,
+ _ => unreachable!()
+ };
+ assert_eq!(non_tracked_loc.file(), file!());
+ assert_eq!(non_tracked_loc.line(), non_tracked_line);
+ assert_eq!(non_tracked_loc.column(), 44);
+
+}
+
+fn main() {
+ test_closure();
+ test_coroutine();
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
new file mode 100644
index 000000000..658812578
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
@@ -0,0 +1,62 @@
+// run-pass
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+fn pass_to_ptr_call<T>(f: fn(T), x: T) {
+ f(x);
+}
+
+#[track_caller]
+fn tracked_unit(_: ()) {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+}
+
+trait Trait {
+ fn trait_tracked_unit(_: ());
+}
+
+impl Trait for () {
+ #[track_caller]
+ fn trait_tracked_unit(_: ()) {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+ }
+}
+
+trait TrackedTrait {
+ #[track_caller]
+ fn trait_tracked_unit_default(_: ()) {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+ }
+}
+
+impl TrackedTrait for () {}
+
+trait BlanketTrackedTrait {
+ #[track_caller]
+ fn tracked_blanket(_: ());
+}
+
+impl BlanketTrackedTrait for () {
+ fn tracked_blanket(_: ()) {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+ }
+}
+
+fn main() {
+ pass_to_ptr_call(tracked_unit, ());
+ pass_to_ptr_call(<() as Trait>::trait_tracked_unit, ());
+ pass_to_ptr_call(<() as TrackedTrait>::trait_tracked_unit_default, ());
+ pass_to_ptr_call(<() as BlanketTrackedTrait>::tracked_blanket, ());
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr.rs
new file mode 100644
index 000000000..8bb4dd288
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-fn-ptr.rs
@@ -0,0 +1,62 @@
+// run-pass
+// revisions: default mir-opt
+//[mir-opt] compile-flags: -Zmir-opt-level=4
+
+fn ptr_call(f: fn()) {
+ f();
+}
+
+#[track_caller]
+fn tracked() {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+}
+
+trait Trait {
+ fn trait_tracked();
+}
+
+impl Trait for () {
+ #[track_caller]
+ fn trait_tracked() {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+ }
+}
+
+trait TrackedTrait {
+ #[track_caller]
+ fn trait_tracked_default() {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+ }
+}
+
+impl TrackedTrait for () {}
+
+trait TraitBlanketTracked {
+ #[track_caller]
+ fn tracked_blanket();
+}
+
+impl TraitBlanketTracked for () {
+ fn tracked_blanket() {
+ let expected_line = line!() - 1;
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+ }
+}
+
+fn main() {
+ ptr_call(tracked);
+ ptr_call(<() as Trait>::trait_tracked);
+ ptr_call(<() as TrackedTrait>::trait_tracked_default);
+ ptr_call(<() as TraitBlanketTracked>::tracked_blanket);
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-impls.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-impls.rs
new file mode 100644
index 000000000..4db4c29e5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-impls.rs
@@ -0,0 +1,77 @@
+// run-pass
+
+macro_rules! assert_expansion_site_is_tracked {
+ () => {{
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_ne!(location.line(), line!(), "line should be outside this fn");
+ }}
+}
+
+trait Tracked {
+ fn local_tracked(&self);
+
+ #[track_caller]
+ fn blanket_tracked(&self);
+
+ #[track_caller]
+ fn default_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+}
+
+impl Tracked for () {
+ #[track_caller]
+ fn local_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+
+ fn blanket_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+}
+
+impl Tracked for bool {
+ #[track_caller]
+ fn local_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+
+ fn blanket_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+
+ fn default_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+}
+
+impl Tracked for u8 {
+ #[track_caller]
+ fn local_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+
+ fn blanket_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+
+ #[track_caller]
+ fn default_tracked(&self) {
+ assert_expansion_site_is_tracked!();
+ }
+}
+
+fn main() {
+ ().local_tracked();
+ ().default_tracked();
+ ().blanket_tracked();
+
+ true.local_tracked();
+ true.default_tracked();
+ true.blanket_tracked();
+
+ 0u8.local_tracked();
+ 0u8.default_tracked();
+ 0u8.blanket_tracked();
+}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-obj.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-obj.rs
new file mode 100644
index 000000000..06883a857
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-trait-obj.rs
@@ -0,0 +1,61 @@
+// run-pass
+
+trait Tracked {
+ #[track_caller]
+ fn track_caller_trait_method(&self, line: u32, col: u32) {
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ // The trait method definition is annotated with `#[track_caller]`,
+ // so caller location information will work through a method
+ // call on a trait object
+ assert_eq!(location.line(), line, "Bad line");
+ assert_eq!(location.column(), col, "Bad col");
+ }
+
+ fn track_caller_not_on_trait_method(&self);
+
+ #[track_caller]
+ fn track_caller_through_self(self: Box<Self>, line: u32, col: u32);
+}
+
+impl Tracked for () {
+ // We have `#[track_caller]` on the implementation of the method,
+ // but not on the definition of the method in the trait. Therefore,
+ // caller location information will *not* work through a method call
+ // on a trait object. Instead, we will get the location of this method
+ #[track_caller]
+ fn track_caller_not_on_trait_method(&self) {
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), line!() - 3);
+ assert_eq!(location.column(), 5);
+ }
+
+ // We don't have a `#[track_caller]` attribute, but
+ // `#[track_caller]` is present on the trait definition,
+ // so we'll still get location information
+ fn track_caller_through_self(self: Box<Self>, line: u32, col: u32) {
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ // The trait method definition is annotated with `#[track_caller]`,
+ // so caller location information will work through a method
+ // call on a trait object
+ assert_eq!(location.line(), line, "Bad line");
+ assert_eq!(location.column(), col, "Bad col");
+ }
+}
+
+fn main() {
+ let tracked: &dyn Tracked = &();
+ // The column is the start of 'track_caller_trait_method'
+ tracked.track_caller_trait_method(line!(), 13);
+
+ const TRACKED: &dyn Tracked = &();
+ // The column is the start of 'track_caller_trait_method'
+ TRACKED.track_caller_trait_method(line!(), 13);
+ TRACKED.track_caller_not_on_trait_method();
+
+ // The column is the start of `track_caller_through_self`
+ let boxed: Box<dyn Tracked> = Box::new(());
+ boxed.track_caller_through_self(line!(), 11);
+}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.rs
new file mode 100644
index 000000000..a9bfeabf1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T> { //~ ERROR rustc_outlives
+ bar: std::slice::IterMut<'a, T>
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr
new file mode 100644
index 000000000..e2a92cf72
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/cross-crate.rs:4:1
+ |
+LL | struct Foo<'a, T> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.rs
new file mode 100644
index 000000000..d3940b13b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.rs
@@ -0,0 +1,12 @@
+/*
+ * We don't infer `T: 'static` outlives relationships.
+ */
+
+struct Foo<U> {
+ bar: Bar<U> //~ ERROR the parameter type `U` may not live long enough [E0310]
+}
+struct Bar<T: 'static> {
+ x: T,
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr
new file mode 100644
index 000000000..b0f1d7b33
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -0,0 +1,22 @@
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/dont-infer-static.rs:6:10
+ |
+LL | bar: Bar<U>
+ | ^^^^^^
+ | |
+ | the parameter type `U` must be valid for the static lifetime...
+ | ...so that the type `U` will meet its required lifetime bounds...
+ |
+note: ...that is required by this bound
+ --> $DIR/dont-infer-static.rs:8:15
+ |
+LL | struct Bar<T: 'static> {
+ | ^^^^^^^
+help: consider adding an explicit lifetime bound
+ |
+LL | struct Foo<U: 'static> {
+ | +++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/enum.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/enum.rs
new file mode 100644
index 000000000..71d2d3222
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/enum.rs
@@ -0,0 +1,27 @@
+#![feature(rustc_attrs)]
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type T needs to outlive lifetime 'a.
+#[rustc_outlives]
+enum Foo<'a, T> { //~ ERROR rustc_outlives
+ One(Bar<'a, T>)
+}
+
+// Type U needs to outlive lifetime 'b
+#[rustc_outlives]
+struct Bar<'b, U> { //~ ERROR rustc_outlives
+ field2: &'b U
+}
+
+// Type K needs to outlive lifetime 'c.
+#[rustc_outlives]
+enum Ying<'c, K> { //~ ERROR rustc_outlives
+ One(&'c Yang<K>)
+}
+
+struct Yang<V> {
+ field2: V
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/enum.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/enum.stderr
new file mode 100644
index 000000000..b6ce2450e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/enum.stderr
@@ -0,0 +1,26 @@
+error: rustc_outlives
+ --> $DIR/enum.rs:7:1
+ |
+LL | enum Foo<'a, T> {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: rustc_outlives
+ --> $DIR/enum.rs:13:1
+ |
+LL | struct Bar<'b, U> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: U: 'b
+
+error: rustc_outlives
+ --> $DIR/enum.rs:19:1
+ |
+LL | enum Ying<'c, K> {
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: K: 'c
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.rs
new file mode 100644
index 000000000..419fb0a0e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.rs
@@ -0,0 +1,12 @@
+#![feature(rustc_attrs)]
+
+trait Trait<'x, T> where T: 'x {
+}
+
+#[rustc_outlives]
+struct Foo<'a, A> //~ ERROR rustc_outlives
+{
+ foo: Box<dyn Trait<'a, A>>
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr
new file mode 100644
index 000000000..30d1b3e77
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/explicit-dyn.rs:7:1
+ |
+LL | struct Foo<'a, A>
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: A: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.rs
new file mode 100644
index 000000000..c330c27fe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+enum Foo<'a, U> { //~ ERROR rustc_outlives
+ One(Bar<'a, U>)
+}
+
+struct Bar<'x, T> where T: 'x {
+ x: &'x (),
+ y: T,
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr
new file mode 100644
index 000000000..afc044d88
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/explicit-enum.rs:4:1
+ |
+LL | enum Foo<'a, U> {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: U: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.rs
new file mode 100644
index 000000000..00b895288
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+trait Trait<'x, T> where T: 'x {
+ type Type;
+}
+
+#[rustc_outlives]
+struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives
+{
+ foo: <A as Trait<'a, B>>::Type
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr
new file mode 100644
index 000000000..1c39c984a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/explicit-projection.rs:8:1
+ |
+LL | struct Foo<'a, A, B> where A: Trait<'a, B>
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: B: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.rs
new file mode 100644
index 000000000..3d5e610b9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'b, U> { //~ ERROR rustc_outlives
+ bar: Bar<'b, U>
+}
+
+struct Bar<'a, T> where T: 'a {
+ x: &'a (),
+ y: T,
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr
new file mode 100644
index 000000000..4ec3087ac
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/explicit-struct.rs:4:1
+ |
+LL | struct Foo<'b, U> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: U: 'b
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.rs
new file mode 100644
index 000000000..871208b5b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.rs
@@ -0,0 +1,14 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+union Foo<'b, U: Copy> { //~ ERROR rustc_outlives
+ bar: Bar<'b, U>
+}
+
+#[derive(Clone, Copy)]
+union Bar<'a, T: Copy> where T: 'a {
+ x: &'a (),
+ y: T,
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr
new file mode 100644
index 000000000..bbb48ef1f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/explicit-union.rs:4:1
+ |
+LL | union Foo<'b, U: Copy> {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: U: 'b
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/issue-54467.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/issue-54467.rs
new file mode 100644
index 000000000..c712f15e3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/issue-54467.rs
@@ -0,0 +1,17 @@
+// Regression test for #54467:
+//
+// Here, the trait object has an "inferred outlives" requirement that
+// `<Self as MyIterator<'a>>::Item: 'a`; but since we don't know what
+// `Self` is, we were (incorrectly) messing things up, leading to
+// strange errors. This test ensures that we do not give compilation
+// errors.
+//
+// check-pass
+
+trait MyIterator<'a>: Iterator where Self::Item: 'a { }
+
+struct MyStruct<'a, A> {
+ item: Box<dyn MyIterator<'a, Item = A>>
+}
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.rs
new file mode 100644
index 000000000..0cd706e7a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+enum Foo<'a, T> { //~ ERROR rustc_outlives
+
+ One(Bar<'a, T>)
+}
+
+struct Bar<'b, U> {
+ field2: &'b U
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr
new file mode 100644
index 000000000..b584d17ae
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/nested-enum.rs:4:1
+ |
+LL | enum Foo<'a, T> {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.rs
new file mode 100644
index 000000000..a01c50681
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
+ x: &'a &'b T
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr
new file mode 100644
index 000000000..59df869c4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr
@@ -0,0 +1,12 @@
+error: rustc_outlives
+ --> $DIR/nested-regions.rs:4:1
+ |
+LL | struct Foo<'a, 'b, T> {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: 'b: 'a
+ = note: T: 'a
+ = note: T: 'b
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.rs
new file mode 100644
index 000000000..ac6817d22
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.rs
@@ -0,0 +1,12 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T> { //~ ERROR rustc_outlives
+ field1: Bar<'a, T>
+}
+
+struct Bar<'b, U> {
+ field2: &'b U
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr
new file mode 100644
index 000000000..7e5af7fe6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/nested-structs.rs:4:1
+ |
+LL | struct Foo<'a, T> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.rs
new file mode 100644
index 000000000..27ebd0b54
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.rs
@@ -0,0 +1,14 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+union Foo<'a, T: Copy> { //~ ERROR rustc_outlives
+ field1: Bar<'a, T>
+}
+
+// Type U needs to outlive lifetime 'b
+#[derive(Clone, Copy)]
+union Bar<'b, U: Copy> {
+ field2: &'b U
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr
new file mode 100644
index 000000000..bb0eea027
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/nested-union.rs:4:1
+ |
+LL | union Foo<'a, T: Copy> {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/privacy.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/privacy.rs
new file mode 100644
index 000000000..180f5ac6c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/privacy.rs
@@ -0,0 +1,20 @@
+// Test that we do not get a privacy error here. Initially, we did,
+// because we inferred an outlives predciate of `<Foo<'a> as
+// Private>::Out: 'a`, but the private trait is -- well -- private,
+// and hence it was not something that a pub trait could refer to.
+//
+// run-pass
+
+#![allow(dead_code)]
+
+pub struct Foo<'a> {
+ field: Option<&'a <Foo<'a> as Private>::Out>
+}
+
+trait Private {
+ type Out: ?Sized;
+}
+
+impl<T: ?Sized> Private for T { type Out = Self; }
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/projection.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/projection.rs
new file mode 100644
index 000000000..411c86da1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/projection.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives
+ bar: &'a T::Item
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr
new file mode 100644
index 000000000..47f3458e0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/projection.rs:4:1
+ |
+LL | struct Foo<'a, T: Iterator> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: <T as Iterator>::Item: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/reference.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/reference.rs
new file mode 100644
index 000000000..a48a3315a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/reference.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, T> { //~ ERROR rustc_outlives
+ bar: &'a T,
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr
new file mode 100644
index 000000000..329d5ff06
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/reference.rs:4:1
+ |
+LL | struct Foo<'a, T> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs
new file mode 100644
index 000000000..8b491ee4e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs
@@ -0,0 +1,39 @@
+// Various examples of structs whose fields are not well-formed.
+
+#![allow(dead_code)]
+
+trait Dummy<'a> {
+ type Out;
+}
+impl<'a, T> Dummy<'a> for T
+where
+ T: 'a,
+{
+ type Out = ();
+}
+type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
+
+enum Ref1<'a, T> {
+ Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
+}
+
+enum Ref2<'a, T> {
+ Ref2Variant1,
+ Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
+}
+
+enum RefOk<'a, T: 'a> {
+ RefOkVariant1(&'a T),
+}
+
+// This is now well formed. RFC 2093
+enum RefIndirect<'a, T> {
+ RefIndirectVariant1(isize, RefOk<'a, T>),
+}
+
+enum RefDouble<'a, 'b, T> {
+ RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+ //~^ the parameter type `T` may not live long enough [E0309]
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
new file mode 100644
index 000000000..5b605f3ee
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -0,0 +1,43 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-enum-not-wf.rs:17:18
+ |
+LL | enum Ref1<'a, T> {
+ | -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
+LL | Ref1Variant1(RequireOutlives<'a, T>),
+ | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound
+ |
+LL | enum Ref1<'a, T: 'a> {
+ | ++++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-enum-not-wf.rs:22:25
+ |
+LL | enum Ref2<'a, T> {
+ | -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
+LL | Ref2Variant1,
+LL | Ref2Variant2(isize, RequireOutlives<'a, T>),
+ | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound
+ |
+LL | enum Ref2<'a, T: 'a> {
+ | ++++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-enum-not-wf.rs:35:23
+ |
+LL | enum RefDouble<'a, 'b, T> {
+ | -- the parameter type `T` must be valid for the lifetime `'b` as defined here...
+LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound
+ |
+LL | enum RefDouble<'a, 'b, T: 'b> {
+ | ++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs
new file mode 100644
index 000000000..36b024d2e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod rev_variant_struct_region {
+ struct Foo<'a> {
+ x: fn(&'a i32),
+ }
+ trait Trait<'a, 'b> {
+ type Out;
+ }
+ impl<'a, 'b> Trait<'a, 'b> for usize {
+ type Out = &'a Foo<'b>; //~ ERROR reference has a longer lifetime
+ }
+}
+
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr
new file mode 100644
index 000000000..591585c88
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:20
+ |
+LL | type Out = &'a Foo<'b>;
+ | ^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime `'a` as defined here
+ --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined here
+ --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:14
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs
new file mode 100644
index 000000000..47a38f7c4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod variant_struct_region {
+ struct Foo<'a> {
+ x: &'a i32,
+ }
+ trait Trait<'a, 'b> {
+ type Out;
+ }
+ impl<'a, 'b> Trait<'a, 'b> for usize {
+ type Out = &'a Foo<'b>; //~ ERROR reference has a longer lifetime
+ }
+}
+
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr
new file mode 100644
index 000000000..0404b52d9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-outlives-nominal-type-region.rs:17:20
+ |
+LL | type Out = &'a Foo<'b>;
+ | ^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime `'a` as defined here
+ --> $DIR/regions-outlives-nominal-type-region.rs:16:10
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined here
+ --> $DIR/regions-outlives-nominal-type-region.rs:16:14
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs
new file mode 100644
index 000000000..083ba8948
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod variant_struct_type {
+ struct Foo<T> {
+ x: fn(T)
+ }
+ trait Trait<'a, 'b> {
+ type Out;
+ }
+ impl<'a, 'b> Trait<'a, 'b> for usize {
+ type Out = &'a Foo<&'b i32>; //~ ERROR reference has a longer lifetime
+ }
+}
+
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr
new file mode 100644
index 000000000..62415e250
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:20
+ |
+LL | type Out = &'a Foo<&'b i32>;
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime `'a` as defined here
+ --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined here
+ --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:14
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs
new file mode 100644
index 000000000..f3e4e39ac
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs
@@ -0,0 +1,22 @@
+// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
+// arguments (like `'a`) outlive `'b`.
+//
+// Rule OutlivesNominalType from RFC 1214.
+
+
+#![allow(dead_code)]
+
+mod variant_struct_type {
+ struct Foo<T> {
+ x: T
+ }
+ trait Trait<'a, 'b> {
+ type Out;
+ }
+ impl<'a, 'b> Trait<'a, 'b> for usize {
+ type Out = &'a Foo<&'b i32>; //~ ERROR reference has a longer lifetime
+ }
+}
+
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr
new file mode 100644
index 000000000..464d7968b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-outlives-nominal-type-type.rs:17:20
+ |
+LL | type Out = &'a Foo<&'b i32>;
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime `'a` as defined here
+ --> $DIR/regions-outlives-nominal-type-type.rs:16:10
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined here
+ --> $DIR/regions-outlives-nominal-type-type.rs:16:14
+ |
+LL | impl<'a, 'b> Trait<'a, 'b> for usize {
+ | ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.rs
new file mode 100644
index 000000000..552c6cf00
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.rs
@@ -0,0 +1,28 @@
+// Various examples of structs whose fields are not well-formed.
+
+#![allow(dead_code)]
+
+trait Trait<'a, T> {
+ type Out;
+}
+trait Trait1<'a, 'b, T> {
+ type Out;
+}
+
+impl<'a, T> Trait<'a, T> for usize {
+ type Out = &'a T; //~ ERROR `T` may not live long enough
+}
+
+struct RefOk<'a, T:'a> {
+ field: &'a T
+}
+
+impl<'a, T> Trait<'a, T> for u32 {
+ type Out = RefOk<'a, T>; //~ ERROR `T` may not live long enough
+}
+
+impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 {
+ type Out = &'a &'b T; //~ ERROR reference has a longer lifetime than the data
+}
+
+fn main() { }
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
new file mode 100644
index 000000000..eb17ce736
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
@@ -0,0 +1,52 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-struct-not-wf.rs:13:16
+ |
+LL | impl<'a, T> Trait<'a, T> for usize {
+ | -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
+LL | type Out = &'a T;
+ | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
+ |
+help: consider adding an explicit lifetime bound
+ |
+LL | impl<'a, T: 'a> Trait<'a, T> for usize {
+ | ++++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-struct-not-wf.rs:21:16
+ |
+LL | impl<'a, T> Trait<'a, T> for u32 {
+ | -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
+LL | type Out = RefOk<'a, T>;
+ | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+ |
+note: ...that is required by this bound
+ --> $DIR/regions-struct-not-wf.rs:16:20
+ |
+LL | struct RefOk<'a, T:'a> {
+ | ^^
+help: consider adding an explicit lifetime bound
+ |
+LL | impl<'a, T: 'a> Trait<'a, T> for u32 {
+ | ++++
+
+error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
+ --> $DIR/regions-struct-not-wf.rs:25:16
+ |
+LL | type Out = &'a &'b T;
+ | ^^^^^^^^^
+ |
+note: the pointer is valid for the lifetime `'a` as defined here
+ --> $DIR/regions-struct-not-wf.rs:24:6
+ |
+LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 {
+ | ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined here
+ --> $DIR/regions-struct-not-wf.rs:24:10
+ |
+LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 {
+ | ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0309, E0491.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.rs
new file mode 100644
index 000000000..c53d6c18f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+trait Trait<'x, 's, T> where T: 'x,
+ 's: {
+}
+
+#[rustc_outlives]
+struct Foo<'a, 'b, A> //~ ERROR rustc_outlives
+{
+ foo: Box<dyn Trait<'a, 'b, A>>
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr
new file mode 100644
index 000000000..8f8ee9205
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/self-dyn.rs:8:1
+ |
+LL | struct Foo<'a, 'b, A>
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: A: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.rs
new file mode 100644
index 000000000..8f2d29d6f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_outlives]
+struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
+ field1: dyn Bar<'a, 'b, T>
+}
+
+trait Bar<'x, 's, U>
+ where U: 'x,
+ Self:'s
+{}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr
new file mode 100644
index 000000000..7fef81c26
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr
@@ -0,0 +1,10 @@
+error: rustc_outlives
+ --> $DIR/self-structs.rs:4:1
+ |
+LL | struct Foo<'a, 'b, T> {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: T: 'a
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.rs b/tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.rs
new file mode 100644
index 000000000..79f6b0dfe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.rs
@@ -0,0 +1,11 @@
+struct S;
+
+pub mod m {
+ fn f() {
+ let s = ::m::crate::S; //~ ERROR failed to resolve
+ let s1 = ::crate::S; //~ ERROR failed to resolve
+ let s2 = crate::S; // no error
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.stderr b/tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.stderr
new file mode 100644
index 000000000..7e7ee3ce0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-crate-paths/crate-path-non-absolute.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: `crate` in paths can only be used in start position
+ --> $DIR/crate-path-non-absolute.rs:5:22
+ |
+LL | let s = ::m::crate::S;
+ | ^^^^^ `crate` in paths can only be used in start position
+
+error[E0433]: failed to resolve: global paths cannot start with `crate`
+ --> $DIR/crate-path-non-absolute.rs:6:20
+ |
+LL | let s1 = ::crate::S;
+ | ^^^^^ global paths cannot start with `crate`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.rs b/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
new file mode 100644
index 000000000..019ef8e9d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let crate = 0;
+ //~^ ERROR expected unit struct, unit variant or constant, found module `crate`
+}
diff --git a/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr b/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr
new file mode 100644
index 000000000..771a09abe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected unit struct, unit variant or constant, found module `crate`
+ --> $DIR/keyword-crate-as-identifier.rs:2:9
+ |
+LL | let crate = 0;
+ | ^^^^^ not a unit struct, unit variant or constant
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs
new file mode 100644
index 000000000..c4d444764
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs
@@ -0,0 +1,5 @@
+#[derive(Debug)]
+pub struct S;
+
+#[derive(Debug)]
+pub struct Z;
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.rs b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.rs
new file mode 100644
index 000000000..9c0e0bef4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+use xcrate::S; //~ ERROR unresolved import `xcrate`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr
new file mode 100644
index 000000000..1047dbe10
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `xcrate`
+ --> $DIR/non-existent-1.rs:3:5
+ |
+LL | use xcrate::S;
+ | ^^^^^^ use of undeclared crate or module `xcrate`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.rs b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.rs
new file mode 100644
index 000000000..def60feb5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.rs
@@ -0,0 +1,6 @@
+// edition:2018
+
+fn main() {
+ let s = ::xcrate::S;
+ //~^ ERROR failed to resolve: could not find `xcrate` in the list of imported crates
+}
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr
new file mode 100644
index 000000000..e3875fd84
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: could not find `xcrate` in the list of imported crates
+ --> $DIR/non-existent-2.rs:4:15
+ |
+LL | let s = ::xcrate::S;
+ | ^^^^^^ could not find `xcrate` in the list of imported crates
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.rs b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.rs
new file mode 100644
index 000000000..486159c0e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+use ycrate; //~ ERROR unresolved import `ycrate`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr
new file mode 100644
index 000000000..c321f3ede
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `ycrate`
+ --> $DIR/non-existent-3.rs:3:5
+ |
+LL | use ycrate;
+ | ^^^^^^ no external crate `ycrate`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.rs b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.rs
new file mode 100644
index 000000000..acb4bbebe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+// Tests that arbitrary crates (other than `core`, `std` and `meta`)
+// aren't allowed without `--extern`, even if they're in the sysroot.
+use alloc; //~ ERROR unresolved import `alloc`
+use test; // OK, imports the built-in attribute macro `#[test]`, but not the `test` crate.
+use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate.
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr
new file mode 100644
index 000000000..7f989c15f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `alloc`
+ --> $DIR/not-allowed.rs:5:5
+ |
+LL | use alloc;
+ | ^^^^^ no external crate `alloc`
+ |
+help: consider importing one of these items instead
+ |
+LL | use core::alloc;
+ | ~~~~~~~~~~~
+LL | use std::alloc;
+ | ~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.rs b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.rs
new file mode 100644
index 000000000..72e50d78b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.rs
@@ -0,0 +1,11 @@
+// aux-build:xcrate.rs
+// compile-flags:--extern xcrate
+// edition:2018
+
+use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
+use *; //~ ERROR cannot glob-import all possible crates
+
+fn main() {
+ let s = ::xcrate; //~ ERROR expected value, found crate `xcrate`
+ //~^ NOTE not a value
+}
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.stderr
new file mode 100644
index 000000000..253cc1bc5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/single-segment.stderr
@@ -0,0 +1,21 @@
+error: crate root imports need to be explicitly named: `use crate as name;`
+ --> $DIR/single-segment.rs:5:5
+ |
+LL | use crate;
+ | ^^^^^
+
+error: cannot glob-import all possible crates
+ --> $DIR/single-segment.rs:6:5
+ |
+LL | use *;
+ | ^
+
+error[E0423]: expected value, found crate `xcrate`
+ --> $DIR/single-segment.rs:9:13
+ |
+LL | let s = ::xcrate;
+ | ^^^^^^^^ not a value
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs
new file mode 100644
index 000000000..1f32e4af1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.rs
@@ -0,0 +1,9 @@
+#![feature(if_let_guard)]
+
+fn main() {
+ match Some(None) {
+ Some(x) if let Some(y) = x => (x, y),
+ _ => y, //~ ERROR cannot find value `y`
+ }
+ y //~ ERROR cannot find value `y`
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr
new file mode 100644
index 000000000..2463b7f3e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/bindings.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/bindings.rs:6:14
+ |
+LL | _ => y,
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/bindings.rs:8:5
+ |
+LL | y
+ | ^ 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/rfcs/rfc-2294-if-let-guard/const-expr.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
new file mode 100644
index 000000000..5c42c0d8b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
@@ -0,0 +1,26 @@
+// Ensure if let guards can be used in constant expressions.
+// build-pass
+
+#![feature(if_let_guard)]
+
+const fn match_if_let(x: Option<i32>, y: Option<i32>) -> i32 {
+ match x {
+ None if let Some(a @ 5) = y => a,
+ Some(z) if let (Some(_), 12) = (y, z) => 2,
+ _ => 3,
+ }
+}
+
+const ASSERTS: usize = {
+ assert!(match_if_let(None, Some(5)) == 5);
+ assert!(match_if_let(Some(12), Some(3)) == 2);
+ assert!(match_if_let(None, Some(4)) == 3);
+ assert!(match_if_let(Some(11), Some(3)) == 3);
+ assert!(match_if_let(Some(12), None) == 3);
+ assert!(match_if_let(None, None) == 3);
+ 0
+};
+
+fn main() {
+ let _: [(); ASSERTS];
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs
new file mode 100644
index 000000000..b4eb54139
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs
@@ -0,0 +1,18 @@
+#![feature(if_let_guard)]
+#![allow(irrefutable_let_patterns)]
+
+fn match_option(x: Option<u32>) {
+ match x {
+ //~^ ERROR non-exhaustive patterns: `None` not covered
+ Some(_) => {}
+ None if let y = x => {}
+ }
+}
+
+fn main() {
+ let x = ();
+ match x {
+ //~^ ERROR non-exhaustive patterns: `()` not covered
+ y if let z = y => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr
new file mode 100644
index 000000000..ddd08854f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr
@@ -0,0 +1,35 @@
+error[E0004]: non-exhaustive patterns: `None` not covered
+ --> $DIR/exhaustive.rs:5:11
+ |
+LL | match x {
+ | ^ pattern `None` not covered
+ |
+note: `Option<u32>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<u32>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ None if let y = x => {},
+LL + None => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `()` not covered
+ --> $DIR/exhaustive.rs:14:11
+ |
+LL | match x {
+ | ^ pattern `()` not covered
+ |
+ = note: the matched value is of type `()`
+ = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ y if let z = y => {},
+LL + () => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
new file mode 100644
index 000000000..b8c0eb3e6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -0,0 +1,74 @@
+// gate-test-if_let_guard
+
+use std::ops::Range;
+
+fn _if_let_guard() {
+ match () {
+ () if let 0 = 1 => {}
+ //~^ ERROR `if let` guards are experimental
+
+ () if (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if true && let 0 = 1 => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+
+ () if let 0 = 1 && true => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+
+ () if (let 0 = 1) && true => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if true && (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+
+ () if (let 0 = 1) && (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+ //~| ERROR `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+
+ () if let Range { start: _, end: _ } = (true..true) && false => {}
+ //~^ ERROR `if let` guards are experimental
+ //~| ERROR `let` expressions in this position are unstable
+
+ _ => {}
+ }
+}
+
+fn _macros() {
+ macro_rules! use_expr {
+ ($e:expr) => {
+ match () {
+ () if $e => {}
+ _ => {}
+ }
+ }
+ }
+ use_expr!((let 0 = 1 && 0 == 0));
+ //~^ ERROR expected expression, found `let` statement
+ use_expr!((let 0 = 1));
+ //~^ ERROR expected expression, found `let` statement
+ match () {
+ #[cfg(FALSE)]
+ () if let 0 = 1 => {}
+ //~^ ERROR `if let` guards are experimental
+ _ => {}
+ }
+ use_expr!(let 0 = 1);
+ //~^ ERROR no rules expected the token `let`
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
new file mode 100644
index 000000000..62534b555
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
@@ -0,0 +1,256 @@
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:13:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:13:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:24:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:24:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:27:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:27:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:30:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:30:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:30:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:30:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:34:55
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:34:68
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/feature-gate.rs:34:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:60:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:62:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: no rules expected the token `let`
+ --> $DIR/feature-gate.rs:70:15
+ |
+LL | macro_rules! use_expr {
+ | --------------------- when calling this macro
+...
+LL | use_expr!(let 0 = 1);
+ | ^^^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr`
+ --> $DIR/feature-gate.rs:53:10
+ |
+LL | ($e:expr) => {
+ | ^^^^^^^
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:7:12
+ |
+LL | () if let 0 = 1 => {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:16:12
+ |
+LL | () if true && let 0 = 1 => {}
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:20:12
+ |
+LL | () if let 0 = 1 && true => {}
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:34:12
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:43:12
+ |
+LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `if let` guards are experimental
+ --> $DIR/feature-gate.rs:66:12
+ |
+LL | () if let 0 = 1 => {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:16:23
+ |
+LL | () if true && let 0 = 1 => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:20:15
+ |
+LL | () if let 0 = 1 && true => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:34:15
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:34:28
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:43:15
+ |
+LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error: aborting due to 23 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs
new file mode 100644
index 000000000..792225e65
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs
@@ -0,0 +1,15 @@
+// References to by-move bindings in an if-let guard *cannot* be used after the guard.
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let x: Option<Option<String>> = Some(Some(String::new()));
+ match x {
+ Some(mut y) if let Some(ref z) = y => {
+ //~^ ERROR: cannot move out of `x.0` because it is borrowed
+ let _z: &String = z;
+ let _y: Option<String> = y;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr
new file mode 100644
index 000000000..741ae7c92
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr
@@ -0,0 +1,15 @@
+error[E0505]: cannot move out of `x.0` because it is borrowed
+ --> $DIR/guard-lifetime-1.rs:8:14
+ |
+LL | Some(mut y) if let Some(ref z) = y => {
+ | ^^^^^
+ | |
+ | move out of `x.0` occurs here
+ | borrow of `x.0` occurs here
+LL |
+LL | let _z: &String = z;
+ | - borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs
new file mode 100644
index 000000000..aa2154e3e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs
@@ -0,0 +1,16 @@
+// References to by-mutable-ref bindings in an if-let guard *can* be used after the guard.
+
+// check-pass
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let mut x: Option<Option<String>> = Some(Some(String::new()));
+ match x {
+ Some(ref mut y) if let Some(ref z) = *y => {
+ let _z: &String = z;
+ let _y: &mut Option<String> = y;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs
new file mode 100644
index 000000000..9353c9d92
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs
@@ -0,0 +1,14 @@
+// Check mutable bindings cannot be mutated by an if-let guard.
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let x: Option<Option<i32>> = Some(Some(6));
+ match x {
+ Some(mut y) if let Some(ref mut z) = y => {
+ //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ let _: &mut i32 = z;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr
new file mode 100644
index 000000000..98285f5c3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ --> $DIR/guard-mutability-1.rs:8:33
+ |
+LL | Some(mut y) if let Some(ref mut z) = y => {
+ | ^^^^^^^^^ cannot borrow as mutable
+ |
+ = note: variables bound in patterns are immutable until the end of the pattern guard
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs
new file mode 100644
index 000000000..4efa02f57
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs
@@ -0,0 +1,14 @@
+// Check mutable reference bindings cannot be mutated by an if-let guard.
+
+#![feature(if_let_guard)]
+
+fn main() {
+ let mut x: Option<Option<i32>> = Some(Some(6));
+ match x {
+ Some(ref mut y) if let Some(ref mut z) = *y => {
+ //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ let _: &mut i32 = z;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr
new file mode 100644
index 000000000..31df8a922
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard
+ --> $DIR/guard-mutability-2.rs:8:37
+ |
+LL | Some(ref mut y) if let Some(ref mut z) = *y => {
+ | ^^^^^^^^^ cannot borrow as mutable
+ |
+ = note: variables bound in patterns are immutable until the end of the pattern guard
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs
new file mode 100644
index 000000000..423a2cd53
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs
@@ -0,0 +1,16 @@
+// Expression macros can't expand to a let match guard.
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+macro_rules! m {
+ ($e:expr) => { let Some(x) = $e }
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn main() {
+ match () {
+ () if m!(Some(5)) => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr
new file mode 100644
index 000000000..b8065b9f5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr
@@ -0,0 +1,14 @@
+error: expected expression, found `let` statement
+ --> $DIR/macro-expanded.rs:7:20
+ |
+LL | ($e:expr) => { let Some(x) = $e }
+ | ^^^
+...
+LL | () if m!(Some(5)) => {}
+ | ----------- in this macro invocation
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs
new file mode 100644
index 000000000..5c333cd77
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs
@@ -0,0 +1,97 @@
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+#![allow(irrefutable_let_patterns)]
+
+fn same_pattern(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, 2) if let y = x && c => (),
+ (1, 2) if let z = x => (), //~ ERROR use of moved value: `x`
+ _ => (),
+ }
+}
+
+fn same_pattern_ok(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, 2) if c && let y = x => (),
+ (1, 2) if let z = x => (),
+ _ => (),
+ }
+}
+
+fn different_patterns(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, _) if let y = x && c => (),
+ (_, 2) if let z = x => (), //~ ERROR use of moved value: `x`
+ _ => (),
+ }
+}
+
+fn different_patterns_ok(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, _) if c && let y = x => (),
+ (_, 2) if let z = x => (),
+ _ => (),
+ }
+}
+
+fn or_pattern(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, _) | (_, 2) if let y = x && c => (), //~ ERROR use of moved value: `x`
+ _ => (),
+ }
+}
+
+fn or_pattern_ok(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, _) | (_, 2) if c && let y = x => (),
+ _ => (),
+ }
+}
+
+fn use_in_arm(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, 2) if let y = x && c => false,
+ _ => { *x == 1 }, //~ ERROR use of moved value: `x`
+ };
+}
+
+fn use_in_arm_ok(c: bool) {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, 2) if c && let y = x => false,
+ _ => { *x == 1 },
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr
new file mode 100644
index 000000000..087e54244
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr
@@ -0,0 +1,65 @@
+error[E0382]: use of moved value: `x`
+ --> $DIR/move-guard-if-let-chain.rs:12:23
+ |
+LL | let x: Box<_> = Box::new(1);
+ | - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+...
+LL | (1, 2) if let y = x && c => (),
+ | - value moved here
+LL | (1, 2) if let z = x => (),
+ | ^ value used here after move
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | (1, 2) if let ref y = x && c => (),
+ | +++
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/move-guard-if-let-chain.rs:36:23
+ |
+LL | let x: Box<_> = Box::new(1);
+ | - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+...
+LL | (1, _) if let y = x && c => (),
+ | - value moved here
+LL | (_, 2) if let z = x => (),
+ | ^ value used here after move
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | (1, _) if let ref y = x && c => (),
+ | +++
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/move-guard-if-let-chain.rs:59:32
+ |
+LL | let x: Box<_> = Box::new(1);
+ | - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+...
+LL | (1, _) | (_, 2) if let y = x && c => (),
+ | ^ value used here after move
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | (1, _) | (_, 2) if let ref y = x && c => (),
+ | +++
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/move-guard-if-let-chain.rs:82:16
+ |
+LL | let x: Box<_> = Box::new(1);
+ | - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+...
+LL | (1, 2) if let y = x && c => false,
+ | - value moved here
+LL | _ => { *x == 1 },
+ | ^^ value used here after move
+ |
+help: borrow this binding in the pattern to avoid moving the value
+ |
+LL | (1, 2) if let ref y = x && c => false,
+ | +++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
new file mode 100644
index 000000000..071b86e2e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
@@ -0,0 +1,41 @@
+// Check that borrowck knows that moves in the pattern for if-let guards
+// only happen when the pattern is matched.
+
+// build-pass
+
+#![feature(if_let_guard)]
+#![allow(irrefutable_let_patterns)]
+
+fn same_pattern() {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, 2) if let y = x => (),
+ (1, 2) if let z = x => (),
+ _ => (),
+ }
+}
+
+fn or_pattern() {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, _) | (_, 2) if let y = x => (),
+ _ => (),
+ }
+}
+
+fn main() {
+ let x: Box<_> = Box::new(1);
+
+ let v = (1, 2);
+
+ match v {
+ (1, 2) if let y = x => false,
+ _ => { *x == 1 },
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
new file mode 100644
index 000000000..f12824db9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
@@ -0,0 +1,25 @@
+// Parenthesised let "expressions" are not allowed in guards
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+#[cfg(FALSE)]
+fn un_cfged() {
+ match () {
+ () if let 0 = 1 => {}
+ () if (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR expected expression, found `let` statement
+ }
+}
+
+fn main() {
+ match () {
+ () if let 0 = 1 => {}
+ () if (let 0 = 1) => {}
+ //~^ ERROR expected expression, found `let` statement
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR expected expression, found `let` statement
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr
new file mode 100644
index 000000000..0c16d9c54
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr
@@ -0,0 +1,54 @@
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:12:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:12:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:20:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:20:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/parens.rs:22:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/parens.rs:22:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs
new file mode 100644
index 000000000..d91b3a358
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs
@@ -0,0 +1,18 @@
+// Macros can be used for (parts of) the pattern and expression in an if let guard
+// check-pass
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+macro_rules! m {
+ (pattern $i:ident) => { Some($i) };
+ (expression $e:expr) => { $e };
+}
+
+fn main() {
+ match () {
+ () if let m!(pattern x) = m!(expression Some(4)) => {}
+ () if let [m!(pattern y)] = [Some(8 + m!(expression 4))] => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs
new file mode 100644
index 000000000..a303a0d1f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/run-pass.rs
@@ -0,0 +1,40 @@
+// run-pass
+
+#![feature(if_let_guard)]
+
+enum Foo {
+ Bar,
+ Baz,
+ Qux(u8),
+}
+
+fn bar(x: bool) -> Foo {
+ if x { Foo::Baz } else { Foo::Bar }
+}
+
+fn baz(x: u8) -> Foo {
+ if x % 2 == 0 { Foo::Bar } else { Foo::Baz }
+}
+
+fn qux(x: u8) -> Foo {
+ Foo::Qux(x.rotate_left(1))
+}
+
+fn main() {
+ match Some((true, 3)) {
+ Some((x, _)) if let Foo::Bar = bar(x) => panic!(),
+ Some((_, x)) if let Foo::Baz = baz(x) => {},
+ _ => panic!(),
+ }
+ match Some(42) {
+ Some(x) if let Foo::Qux(y) = qux(x) => assert_eq!(y, 84),
+ _ => panic!(),
+ }
+
+ // issue #88015
+ #[allow(irrefutable_let_patterns)]
+ match () {
+ () | () if let x = 42 => assert_eq!(x, 42),
+ _ => panic!()
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs
new file mode 100644
index 000000000..dba292ef9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs
@@ -0,0 +1,23 @@
+// Check shadowing in if let guards works as expected.
+// check-pass
+
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+
+fn main() {
+ let x: Option<Option<i32>> = Some(Some(6));
+ match x {
+ Some(x) if let Some(x) = x => {
+ let _: i32 = x;
+ }
+ _ => {}
+ }
+
+ let y: Option<Option<Option<i32>>> = Some(Some(Some(-24)));
+ match y {
+ Some(y) if let Some(y) = y && let Some(y) = y => {
+ let _: i32 = y;
+ }
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
new file mode 100644
index 000000000..ef7a772e6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(if_let_guard)]
+
+struct S;
+
+fn get<T>() -> Option<T> {
+ None
+}
+
+fn main() {
+ match get() {
+ x if let Some(S) = x => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs
new file mode 100644
index 000000000..ad178dfa4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs
@@ -0,0 +1,15 @@
+#![feature(if_let_guard)]
+
+fn ok() -> Result<Option<bool>, ()> {
+ Ok(Some(true))
+}
+
+fn main() {
+ match ok() {
+ Ok(x) if let Err(_) = x => {},
+ //~^ ERROR mismatched types
+ Ok(x) if let 0 = x => {},
+ //~^ ERROR mismatched types
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr
new file mode 100644
index 000000000..4ce97a68a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+ --> $DIR/typeck.rs:9:22
+ |
+LL | Ok(x) if let Err(_) = x => {},
+ | ^^^^^^ - this expression has type `Option<bool>`
+ | |
+ | expected `Option<bool>`, found `Result<_, _>`
+ |
+ = note: expected enum `Option<bool>`
+ found enum `Result<_, _>`
+
+error[E0308]: mismatched types
+ --> $DIR/typeck.rs:11:22
+ |
+LL | Ok(x) if let 0 = x => {},
+ | ^ - this expression has type `Option<bool>`
+ | |
+ | expected `Option<bool>`, found integer
+ |
+ = note: expected enum `Option<bool>`
+ found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs
new file mode 100644
index 000000000..3ad1a50c6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs
@@ -0,0 +1,21 @@
+#![feature(if_let_guard)]
+
+#[deny(irrefutable_let_patterns)]
+fn irrefutable_let_guard() {
+ match Some(()) {
+ Some(x) if let () = x => {}
+ //~^ ERROR irrefutable `if let` guard
+ _ => {}
+ }
+}
+
+#[deny(unreachable_patterns)]
+fn unreachable_pattern() {
+ match Some(()) {
+ x if let None | None = x => {}
+ //~^ ERROR unreachable pattern
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
new file mode 100644
index 000000000..75f22ac8d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr
@@ -0,0 +1,28 @@
+error: irrefutable `if let` guard pattern
+ --> $DIR/warns.rs:6:24
+ |
+LL | Some(x) if let () = x => {}
+ | ^^
+ |
+ = note: this pattern will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
+note: the lint level is defined here
+ --> $DIR/warns.rs:3:8
+ |
+LL | #[deny(irrefutable_let_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/warns.rs:15:25
+ |
+LL | x if let None | None = x => {}
+ | ^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/warns.rs:12:8
+ |
+LL | #[deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs b/tests/ui/rfcs/rfc-2302-self-struct-ctor/rfc-2302-self-struct-ctor.rs
index 1ec20c500..1ec20c500 100644
--- a/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs
+++ b/tests/ui/rfcs/rfc-2302-self-struct-ctor/rfc-2302-self-struct-ctor.rs
diff --git a/tests/ui/rfcs/rfc-2306-convert-id/convert-id-const-with-gate.rs b/tests/ui/rfcs/rfc-2306-convert-id/convert-id-const-with-gate.rs
new file mode 100644
index 000000000..762dfbe48
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2306-convert-id/convert-id-const-with-gate.rs
@@ -0,0 +1,7 @@
+// This test should pass since 'identity' is const fn.
+
+// build-pass (FIXME(62277): could be check-pass?)
+
+fn main() {
+ const _FOO: u8 = ::std::convert::identity(42u8);
+}
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
new file mode 100644
index 000000000..542be3942
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -0,0 +1,69 @@
+// run-pass
+// check-run-results
+
+// Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
+// as well as some compile time properties we expect.
+
+#![allow(dropping_copy_types)]
+
+#[derive(Copy, Clone, Debug)]
+struct Unit;
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+struct Point<T> {
+ x: T,
+ y: T,
+}
+
+#[derive(Debug, PartialEq)]
+struct NoCopy(usize);
+
+fn main() {
+ let a: Unit = dbg!(Unit);
+ let _: Unit = dbg!(a);
+ // We can move `a` because it's Copy.
+ drop(a);
+
+ // `Point<T>` will be faithfully formatted according to `{:#?}`.
+ let a = Point { x: 42, y: 24 };
+ let b: Point<u8> = dbg!(Point { x: 42, y: 24 }); // test stringify!(..)
+ let c: Point<u8> = dbg!(b);
+ // Identity conversion:
+ assert_eq!(a, b);
+ assert_eq!(a, c);
+ // We can move `b` because it's Copy.
+ drop(b);
+
+ // Without parameters works as expected.
+ let _: () = dbg!();
+
+ // Test that we can borrow and that successive applications is still identity.
+ let a = NoCopy(1337);
+ let b: &NoCopy = dbg!(dbg!(&a));
+ assert_eq!(&a, b);
+
+ // Test involving lifetimes of temporaries:
+ fn f<'a>(x: &'a u8) -> &'a u8 { x }
+ let a: &u8 = dbg!(f(&42));
+ assert_eq!(a, &42);
+
+ // Test side effects:
+ let mut foo = 41;
+ assert_eq!(7331, dbg!({
+ foo += 1;
+ eprintln!("before");
+ 7331
+ }));
+ assert_eq!(foo, 42);
+
+ // Test trailing comma:
+ assert_eq!(("Yeah",), dbg!(("Yeah",)));
+
+ // Test multiple arguments:
+ assert_eq!((1u8, 2u32), dbg!(1,
+ 2));
+
+ // Test multiple arguments + trailing comma:
+ assert_eq!((1u8, 2u32, "Yeah"), dbg!(1u8, 2u32,
+ "Yeah",));
+}
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
new file mode 100644
index 000000000..2c018ca87
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
@@ -0,0 +1,28 @@
+[$DIR/dbg-macro-expected-behavior.rs:22:19] Unit = Unit
+[$DIR/dbg-macro-expected-behavior.rs:23:19] a = Unit
+[$DIR/dbg-macro-expected-behavior.rs:29:24] Point { x: 42, y: 24 } = Point {
+ x: 42,
+ y: 24,
+}
+[$DIR/dbg-macro-expected-behavior.rs:30:24] b = Point {
+ x: 42,
+ y: 24,
+}
+[$DIR/dbg-macro-expected-behavior.rs:38:17]
+[$DIR/dbg-macro-expected-behavior.rs:42:27] &a = NoCopy(
+ 1337,
+)
+[$DIR/dbg-macro-expected-behavior.rs:42:22] dbg!(&a) = NoCopy(
+ 1337,
+)
+[$DIR/dbg-macro-expected-behavior.rs:47:18] f(&42) = 42
+before
+[$DIR/dbg-macro-expected-behavior.rs:52:22] { foo += 1; eprintln!("before"); 7331 } = 7331
+[$DIR/dbg-macro-expected-behavior.rs:60:27] ("Yeah",) = (
+ "Yeah",
+)
+[$DIR/dbg-macro-expected-behavior.rs:63:29] 1 = 1
+[$DIR/dbg-macro-expected-behavior.rs:63:29] 2 = 2
+[$DIR/dbg-macro-expected-behavior.rs:67:37] 1u8 = 1
+[$DIR/dbg-macro-expected-behavior.rs:67:37] 2u32 = 2
+[$DIR/dbg-macro-expected-behavior.rs:67:37] "Yeah" = "Yeah"
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs
new file mode 100644
index 000000000..9f3c567b6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs
@@ -0,0 +1,10 @@
+// Test ensuring that `dbg!(expr)` will take ownership of the argument.
+
+#[derive(Debug)]
+struct NoCopy(usize);
+
+fn main() {
+ let a = NoCopy(0);
+ let _ = dbg!(a);
+ let _ = dbg!(a); //~ ERROR use of moved value
+}
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
new file mode 100644
index 000000000..c2b9899e2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `a`
+ --> $DIR/dbg-macro-move-semantics.rs:9:13
+ |
+LL | let a = NoCopy(0);
+ | - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
+LL | let _ = dbg!(a);
+ | ------- value moved here
+LL | let _ = dbg!(a);
+ | ^^^^^^^ value used here after move
+ |
+ = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs
new file mode 100644
index 000000000..f2fb62d76
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs
@@ -0,0 +1,7 @@
+// Test ensuring that `dbg!(expr)` requires the passed type to implement `Debug`.
+
+struct NotDebug;
+
+fn main() {
+ let _: NotDebug = dbg!(NotDebug); //~ ERROR `NotDebug` doesn't implement `Debug`
+}
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
new file mode 100644
index 000000000..7ec018a95
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `NotDebug` doesn't implement `Debug`
+ --> $DIR/dbg-macro-requires-debug.rs:6:23
+ |
+LL | let _: NotDebug = dbg!(NotDebug);
+ | ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}`
+ |
+ = help: the trait `Debug` is not implemented for `NotDebug`
+ = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug`
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider annotating `NotDebug` with `#[derive(Debug)]`
+ |
+LL + #[derive(Debug)]
+LL | struct NotDebug;
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr
index 18917fd25..06c6c9053 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr
@@ -9,6 +9,6 @@ LL | fn foo() {}
= note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable
-error: aborting due to previous error
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
index b0ac5dc44..7bbd4e158 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
@@ -13,12 +13,11 @@ LL | let foo: fn() = foo;
found fn item `fn() {foo}`
= note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
- = note: when the arguments and return types match, functions can be coerced to function pointers
help: consider casting to a fn pointer
|
LL | let foo: fn() = foo as fn();
| ~~~~~~~~~~~
-error: aborting due to previous error
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
index b0ac5dc44..7bbd4e158 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
@@ -13,12 +13,11 @@ LL | let foo: fn() = foo;
found fn item `fn() {foo}`
= note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
- = note: when the arguments and return types match, functions can be coerced to function pointers
help: consider casting to a fn pointer
|
LL | let foo: fn() = foo as fn();
| ~~~~~~~~~~~
-error: aborting due to previous error
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs
index 43bda4962..1374ad935 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs
@@ -21,14 +21,14 @@ fn call_once(f: impl FnOnce()) {
}
fn main() {
- call(foo); //~ ERROR expected a `Fn<()>` closure, found `fn() {foo}`
- call_mut(foo); //~ ERROR expected a `FnMut<()>` closure, found `fn() {foo}`
- call_once(foo); //~ ERROR expected a `FnOnce<()>` closure, found `fn() {foo}`
+ call(foo); //~ ERROR expected a `Fn()` closure, found `fn() {foo}`
+ call_mut(foo); //~ ERROR expected a `FnMut()` closure, found `fn() {foo}`
+ call_once(foo); //~ ERROR expected a `FnOnce()` closure, found `fn() {foo}`
call(foo_unsafe);
- //~^ ERROR expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+ //~^ ERROR expected a `Fn()` closure, found `unsafe fn() {foo_unsafe}`
call_mut(foo_unsafe);
- //~^ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+ //~^ ERROR expected a `FnMut()` closure, found `unsafe fn() {foo_unsafe}`
call_once(foo_unsafe);
- //~^ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+ //~^ ERROR expected a `FnOnce()` closure, found `unsafe fn() {foo_unsafe}`
}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
index fc7bf2277..100f20482 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
@@ -1,8 +1,8 @@
-error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}`
+error[E0277]: expected a `Fn()` closure, found `fn() {foo}`
--> $DIR/fn-traits.rs:24:10
|
LL | call(foo);
- | ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+ | ---- ^^^ expected an `Fn()` closure, found `fn() {foo}`
| |
| required by a bound introduced by this call
|
@@ -15,11 +15,11 @@ note: required by a bound in `call`
LL | fn call(f: impl Fn()) {
| ^^^^ required by this bound in `call`
-error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}`
+error[E0277]: expected a `FnMut()` closure, found `fn() {foo}`
--> $DIR/fn-traits.rs:25:14
|
LL | call_mut(foo);
- | -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+ | -------- ^^^ expected an `FnMut()` closure, found `fn() {foo}`
| |
| required by a bound introduced by this call
|
@@ -32,11 +32,11 @@ note: required by a bound in `call_mut`
LL | fn call_mut(f: impl FnMut()) {
| ^^^^^^^ required by this bound in `call_mut`
-error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}`
+error[E0277]: expected a `FnOnce()` closure, found `fn() {foo}`
--> $DIR/fn-traits.rs:26:15
|
LL | call_once(foo);
- | --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+ | --------- ^^^ expected an `FnOnce()` closure, found `fn() {foo}`
| |
| required by a bound introduced by this call
|
@@ -49,7 +49,7 @@ note: required by a bound in `call_once`
LL | fn call_once(f: impl FnOnce()) {
| ^^^^^^^^ required by this bound in `call_once`
-error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+error[E0277]: expected a `Fn()` closure, found `unsafe fn() {foo_unsafe}`
--> $DIR/fn-traits.rs:28:10
|
LL | call(foo_unsafe);
@@ -58,6 +58,7 @@ LL | call(foo_unsafe);
| required by a bound introduced by this call
|
= help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+ = note: unsafe function cannot be called generically without an unsafe block
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call`
@@ -66,7 +67,7 @@ note: required by a bound in `call`
LL | fn call(f: impl Fn()) {
| ^^^^ required by this bound in `call`
-error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+error[E0277]: expected a `FnMut()` closure, found `unsafe fn() {foo_unsafe}`
--> $DIR/fn-traits.rs:30:14
|
LL | call_mut(foo_unsafe);
@@ -75,6 +76,7 @@ LL | call_mut(foo_unsafe);
| required by a bound introduced by this call
|
= help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+ = note: unsafe function cannot be called generically without an unsafe block
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_mut`
@@ -83,7 +85,7 @@ note: required by a bound in `call_mut`
LL | fn call_mut(f: impl FnMut()) {
| ^^^^^^^ required by this bound in `call_mut`
-error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+error[E0277]: expected a `FnOnce()` closure, found `unsafe fn() {foo_unsafe}`
--> $DIR/fn-traits.rs:32:15
|
LL | call_once(foo_unsafe);
@@ -92,6 +94,7 @@ LL | call_once(foo_unsafe);
| required by a bound introduced by this call
|
= help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+ = note: unsafe function cannot be called generically without an unsafe block
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_once`
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr
index cfafbd522..57ad1cc8d 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr
@@ -4,5 +4,5 @@ error: `main` function is not allowed to have `#[target_feature]`
LL | fn main() {}
| ^^^^^^^^^ `main` function is not allowed to have `#[target_feature]`
-error: aborting due to previous error
+error: aborting due to 1 previous error
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs
index 50e8ce2fd..221c0416d 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs
@@ -5,5 +5,5 @@
#[start]
#[target_feature(enable = "avx2")]
-//~^ ERROR `start` is not allowed to have `#[target_feature]`
+//~^ ERROR `#[start]` function is not allowed to have `#[target_feature]`
fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 }
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr
index 07687f3c7..d0a67c4f6 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr
@@ -1,11 +1,11 @@
-error: `start` is not allowed to have `#[target_feature]`
+error: `#[start]` function is not allowed to have `#[target_feature]`
--> $DIR/issue-108645-target-feature-on-start.rs:7:1
|
LL | #[target_feature(enable = "avx2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 }
- | -------------------------------------------------------- `start` is not allowed to have `#[target_feature]`
+ | -------------------------------------------------------- `#[start]` function is not allowed to have `#[target_feature]`
-error: aborting due to previous error
+error: aborting due to 1 previous error
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs
new file mode 100644
index 000000000..bc8864000
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs
@@ -0,0 +1,18 @@
+// Tests #108655: closures in `#[target_feature]` functions can still be marked #[inline(always)]
+
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+#[target_feature(enable = "avx")]
+pub unsafe fn test() {
+ ({
+ #[inline(always)]
+ move || {}
+ })();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr
index 0ef7b8b09..cabc475fa 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr
@@ -1,83 +1,115 @@
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:23:5
+ --> $DIR/safe-calls.rs:28:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:26:5
+ --> $DIR/safe-calls.rs:31:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:29:5
+ --> $DIR/safe-calls.rs:34:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:36:5
+ --> $DIR/safe-calls.rs:41:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:39:5
+ --> $DIR/safe-calls.rs:44:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:46:5
+ --> $DIR/safe-calls.rs:51:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:49:5
+ --> $DIR/safe-calls.rs:54:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: bmi2
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:52:5
+ --> $DIR/safe-calls.rs:57:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: bmi2
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:60:5
+ --> $DIR/safe-calls.rs:65:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:65:18
+ --> $DIR/safe-calls.rs:70:15
|
-LL | const name: () = sse2();
- | ^^^^^^ call to function with `#[target_feature]`
+LL | const _: () = sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
-error: aborting due to 10 previous errors
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:74:15
+ |
+LL | const _: () = sse2_and_fxsr();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr
+ = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
+
+error: call to function with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+ --> $DIR/safe-calls.rs:82:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
+note: an unsafe function restricts its caller, but its body is safe by default
+ --> $DIR/safe-calls.rs:81:1
+ |
+LL | unsafe fn needs_unsafe_block() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/safe-calls.rs:78:8
+ |
+LL | #[deny(unsafe_op_in_unsafe_fn)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
index cebc6f947..f17dab269 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
@@ -7,6 +7,11 @@
#[target_feature(enable = "sse2")]
const fn sse2() {}
+#[target_feature(enable = "sse2")]
+#[target_feature(enable = "fxsr")]
+const fn sse2_and_fxsr() {}
+
+
#[target_feature(enable = "avx")]
#[target_feature(enable = "bmi2")]
fn avx_bmi2() {}
@@ -62,8 +67,21 @@ fn qux() {
//[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
}
-const name: () = sse2();
+const _: () = sse2();
//[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
//[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+const _: () = sse2_and_fxsr();
+//[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+//[thir]~^^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe
+
+#[deny(unsafe_op_in_unsafe_fn)]
+#[target_feature(enable = "avx")]
+#[target_feature(enable = "bmi2")]
+unsafe fn needs_unsafe_block() {
+ sse2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+}
+
fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr
index c75ac6e8b..13b58fde8 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr
@@ -1,83 +1,115 @@
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:23:5
+ --> $DIR/safe-calls.rs:28:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:26:5
+ --> $DIR/safe-calls.rs:31:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:29:5
+ --> $DIR/safe-calls.rs:34:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:36:5
+ --> $DIR/safe-calls.rs:41:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:39:5
+ --> $DIR/safe-calls.rs:44:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:46:5
+ --> $DIR/safe-calls.rs:51:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:49:5
+ --> $DIR/safe-calls.rs:54:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: bmi2
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:52:5
+ --> $DIR/safe-calls.rs:57:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: bmi2
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:60:5
+ --> $DIR/safe-calls.rs:65:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:65:18
+ --> $DIR/safe-calls.rs:70:15
|
-LL | const name: () = sse2();
- | ^^^^^^ call to function with `#[target_feature]`
+LL | const _: () = sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
|
- = note: can only be called if the required target features are available
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
-error: aborting due to 10 previous errors
+error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:74:15
+ |
+LL | const _: () = sse2_and_fxsr();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr
+ = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
+
+error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+ --> $DIR/safe-calls.rs:82:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = help: in order for the call to be safe, the context requires the following additional target feature: sse2
+ = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
+note: an unsafe function restricts its caller, but its body is safe by default
+ --> $DIR/safe-calls.rs:81:1
+ |
+LL | unsafe fn needs_unsafe_block() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/safe-calls.rs:78:8
+ |
+LL | #[deny(unsafe_op_in_unsafe_fn)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
new file mode 100644
index 000000000..5053c115b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
@@ -0,0 +1,21 @@
+#![feature(do_not_recommend)]
+
+pub trait Foo {
+}
+
+impl Foo for i32 {
+}
+
+pub trait Bar {
+}
+
+#[do_not_recommend]
+impl<T: Foo> Bar for T {
+}
+
+fn stuff<T: Bar>(_: T) {}
+
+fn main() {
+ stuff(1u8);
+ //~^ the trait bound `u8: Foo` is not satisfied
+}
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
new file mode 100644
index 000000000..6af1d4533
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `u8: Foo` is not satisfied
+ --> $DIR/feature-gate-do_not_recommend.rs:19:11
+ |
+LL | stuff(1u8);
+ | ----- ^^^ the trait `Foo` is not implemented for `u8`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Foo` is implemented for `i32`
+note: required for `u8` to implement `Bar`
+ --> $DIR/feature-gate-do_not_recommend.rs:13:14
+ |
+LL | impl<T: Foo> Bar for T {
+ | --- ^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `stuff`
+ --> $DIR/feature-gate-do_not_recommend.rs:16:13
+ |
+LL | fn stuff<T: Bar>(_: T) {}
+ | ^^^ required by this bound in `stuff`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.rs b/tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.rs
new file mode 100644
index 000000000..91863f5e4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.rs
@@ -0,0 +1,45 @@
+#![feature(do_not_recommend)]
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+const CONST: () = ();
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+static Static: () = ();
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+type Type = ();
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+enum Enum {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+extern {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+fn fun() {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+struct Struct {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+trait Trait {
+}
+
+#[do_not_recommend]
+impl Trait for i32 {
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.stderr
new file mode 100644
index 000000000..01ebc23c8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/incorrect-locations.stderr
@@ -0,0 +1,50 @@
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:3:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:7:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:11:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:15:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:20:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:25:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:30:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+ --> $DIR/incorrect-locations.rs:35:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.rs b/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.rs
new file mode 100644
index 000000000..f0c5c222e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.rs
@@ -0,0 +1,10 @@
+trait Foo {
+}
+
+#[do_not_recommend]
+//~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature
+impl Foo for i32 {
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr
new file mode 100644
index 000000000..b2c1406d0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr
@@ -0,0 +1,12 @@
+error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature
+ --> $DIR/unstable-feature.rs:4:1
+ |
+LL | #[do_not_recommend]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51992 <https://github.com/rust-lang/rust/issues/51992> for more information
+ = help: add `#![feature(do_not_recommend)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs b/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof/offsetof-alignof-sizeof-pure-can-be-used-as-idents.rs
index 6d7bca4da..6d7bca4da 100644
--- a/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs
+++ b/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof/offsetof-alignof-sizeof-pure-can-be-used-as-idents.rs
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs
new file mode 100644
index 000000000..e373b6438
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs
@@ -0,0 +1 @@
+pub trait Foo {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs
new file mode 100644
index 000000000..c07ba54af
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs
@@ -0,0 +1,3 @@
+extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr
new file mode 100644
index 000000000..cb663401e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr
@@ -0,0 +1,8 @@
+error: cannot load a crate with a non-ascii name `ьаг`
+ --> $DIR/crate_name_nonascii_forbidden.rs:1:1
+ |
+LL | extern crate ьаг;
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs
new file mode 100644
index 000000000..ad6825404
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs
@@ -0,0 +1,9 @@
+#![feature(extern_types)]
+
+extern "C" {
+ type 一; //~ items in `extern` blocks cannot use non-ascii identifiers
+ fn 二(); //~ items in `extern` blocks cannot use non-ascii identifiers
+ static 三: usize; //~ items in `extern` blocks cannot use non-ascii identifiers
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.stderr
new file mode 100644
index 000000000..ca1b8a6e7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.stderr
@@ -0,0 +1,34 @@
+error: items in `extern` blocks cannot use non-ascii identifiers
+ --> $DIR/extern_block_nonascii_forbidden.rs:4:10
+ |
+LL | extern "C" {
+ | ---------- in this `extern` block
+LL | type 一;
+ | ^^
+ |
+ = note: this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
+
+error: items in `extern` blocks cannot use non-ascii identifiers
+ --> $DIR/extern_block_nonascii_forbidden.rs:5:8
+ |
+LL | extern "C" {
+ | ---------- in this `extern` block
+LL | type 一;
+LL | fn 二();
+ | ^^
+ |
+ = note: this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
+
+error: items in `extern` blocks cannot use non-ascii identifiers
+ --> $DIR/extern_block_nonascii_forbidden.rs:6:12
+ |
+LL | extern "C" {
+ | ---------- in this `extern` block
+...
+LL | static 三: usize;
+ | ^^
+ |
+ = note: this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/idents-normalized.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/idents-normalized.rs
new file mode 100644
index 000000000..1023fee37
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/idents-normalized.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+struct Résumé; // ['LATIN SMALL LETTER E WITH ACUTE']
+
+fn main() {
+ let _ = Résumé; // ['LATIN SMALL LETTER E', 'COMBINING ACUTE ACCENT']
+}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs
new file mode 100644
index 000000000..e949e2319
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs
@@ -0,0 +1,4 @@
+mod řųśť; //~ trying to load file for
+//~^ file not found for
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.stderr
new file mode 100644
index 000000000..8ca6a37c6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.stderr
@@ -0,0 +1,21 @@
+error[E0583]: file not found for module `řųśť`
+ --> $DIR/mod_file_nonascii_forbidden.rs:1:1
+ |
+LL | mod řųśť;
+ | ^^^^^^^^^
+ |
+ = help: to create the module `řųśť`, create file "$DIR/řųśť.rs" or "$DIR/řųśť/mod.rs"
+ = note: if there is a `mod řųśť` elsewhere in the crate already, import it with `use crate::...` instead
+
+error[E0754]: trying to load file for module `řųśť` with non-ascii identifier name
+ --> $DIR/mod_file_nonascii_forbidden.rs:1:5
+ |
+LL | mod řųśť;
+ | ^^^^
+ |
+ = help: consider using the `#[path]` attribute to specify filesystem path
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0583, E0754.
+For more information about an error, try `rustc --explain E0583`.
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_with_path_allowed.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_with_path_allowed.rs
new file mode 100644
index 000000000..94327846d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_with_path_allowed.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+#[path="auxiliary/mod_file_nonascii_with_path_allowed-aux.rs"]
+mod řųśť;
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_inline_nonascii_allowed.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_inline_nonascii_allowed.rs
new file mode 100644
index 000000000..e1d836b7c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_inline_nonascii_allowed.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+mod řųśť {
+ const IS_GREAT: bool = true;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs
new file mode 100644
index 000000000..f4c126a6e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs
@@ -0,0 +1,20 @@
+#[no_mangle]
+pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier
+
+pub struct Foo;
+
+impl Foo {
+ #[no_mangle]
+ pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier
+}
+
+trait Bar {
+ fn řųśť();
+}
+
+impl Bar for Foo {
+ #[no_mangle]
+ fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.stderr
new file mode 100644
index 000000000..459d5d6b5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.stderr
@@ -0,0 +1,21 @@
+error[E0754]: `#[no_mangle]` requires ASCII identifier
+ --> $DIR/no_mangle_nonascii_forbidden.rs:2:1
+ |
+LL | pub fn řųśť() {}
+ | ^^^^^^^^^^^^^
+
+error[E0754]: `#[no_mangle]` requires ASCII identifier
+ --> $DIR/no_mangle_nonascii_forbidden.rs:8:5
+ |
+LL | pub fn řųśť() {}
+ | ^^^^^^^^^^^^^
+
+error[E0754]: `#[no_mangle]` requires ASCII identifier
+ --> $DIR/no_mangle_nonascii_forbidden.rs:17:5
+ |
+LL | fn řųśť() {}
+ | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0754`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs
new file mode 100644
index 000000000..d851fac8e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+#![feature(let_chains)]
+#![allow(irrefutable_let_patterns)]
+
+fn main() {
+ let first = Some(1);
+ let second = Some(2);
+ let mut n = 0;
+ if let x = first && let y = second && 1 == 1 {
+ assert_eq!(x, first);
+ assert_eq!(y, second);
+ n = 1;
+ }
+ assert_eq!(n, 1);
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs
new file mode 100644
index 000000000..69bc189dd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+fn main() {
+ if let 0 = 1 {}
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout
new file mode 100644
index 000000000..e737ef26e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout
@@ -0,0 +1,10 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+fn main() { if let 0 = 1 {} }
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs
new file mode 100644
index 000000000..cb3be59be
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs
@@ -0,0 +1,23 @@
+#![feature(let_chains)]
+
+fn let_or_guard(x: Result<Option<i32>, ()>) {
+ match x {
+ Ok(opt) if let Some(4) = opt || false => {}
+ //~^ ERROR expected expression, found `let` statement
+ _ => {}
+ }
+}
+
+fn hiding_unsafe_mod(x: Result<Option<i32>, ()>) {
+ match x {
+ Ok(opt)
+ if {
+ unsafe mod a {};
+ //~^ ERROR module cannot be declared unsafe
+ false
+ } => {}
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr
new file mode 100644
index 000000000..4b85fdd50
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr
@@ -0,0 +1,21 @@
+error: expected expression, found `let` statement
+ --> $DIR/ast-validate-guards.rs:5:20
+ |
+LL | Ok(opt) if let Some(4) = opt || false => {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+ --> $DIR/ast-validate-guards.rs:5:38
+ |
+LL | Ok(opt) if let Some(4) = opt || false => {}
+ | ^^
+
+error: module cannot be declared unsafe
+ --> $DIR/ast-validate-guards.rs:15:17
+ |
+LL | unsafe mod a {};
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.rs
new file mode 100644
index 000000000..530458064
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.rs
@@ -0,0 +1,14 @@
+// Regression test for #104172
+
+const N: usize = {
+ struct U;
+ !let y = 42;
+ //~^ ERROR expected expression, found `let` statement
+ 3
+};
+
+struct S {
+ x: [(); N]
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr
new file mode 100644
index 000000000..606f808f0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr
@@ -0,0 +1,10 @@
+error: expected expression, found `let` statement
+ --> $DIR/avoid-invalid-mir.rs:5:6
+ |
+LL | !let y = 42;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.rs
new file mode 100644
index 000000000..2c0571a7b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+fn and_chain() {
+ let z;
+ if true && { z = 3; true} && z == 3 {}
+}
+
+fn and_chain_2() {
+ let z;
+ true && { z = 3; true} && z == 3;
+}
+
+fn or_chain() {
+ let z;
+ if false || { z = 3; false} || z == 3 {}
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs
new file mode 100644
index 000000000..096036bb1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs
@@ -0,0 +1,340 @@
+// Check that we don't suggest enabling a feature for code that's
+// not accepted even with that feature.
+
+#![allow(irrefutable_let_patterns)]
+
+use std::ops::Range;
+
+fn main() {}
+
+fn _if() {
+ if (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if (((let 0 = 1))) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if (let 0 = 1) && true {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if true && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if (let 0 = 1) && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+}
+
+fn _while() {
+ while (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while (((let 0 = 1))) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while (let 0 = 1) && true {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while true && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while (let 0 = 1) && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+}
+
+fn _macros() {
+ macro_rules! use_expr {
+ ($e:expr) => {
+ if $e {}
+ while $e {}
+ }
+ }
+ use_expr!((let 0 = 1 && 0 == 0));
+ //~^ ERROR expected expression, found `let` statement
+ use_expr!((let 0 = 1));
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn nested_within_if_expr() {
+ if &let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if !let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ if *let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ if -let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ fn _check_try_binds_tighter() -> Result<(), ()> {
+ if let 0 = 0? {}
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ Ok(())
+ }
+ if (let 0 = 0)? {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if true || let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ if (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ if true && (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ if true || (true && let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ if x = let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if true..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ if ..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ if (let 0 = 0).. {}
+ //~^ ERROR expected expression, found `let` statement
+
+ // Binds as `(let ... = true)..true &&/|| false`.
+ if let Range { start: _, end: _ } = true..true && false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ if let Range { start: _, end: _ } = true..true || false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: F, end } = F)..(|| true)`.
+ const F: fn() -> bool = || true;
+ if let Range { start: F, end } = F..|| true {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: true, end } = t)..(&&false)`.
+ let t = &&true;
+ if let Range { start: true, end } = t..&&false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ if let true = let true = true {}
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn nested_within_while_expr() {
+ while &let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while !let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ while *let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ while -let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ fn _check_try_binds_tighter() -> Result<(), ()> {
+ while let 0 = 0? {}
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ Ok(())
+ }
+ while (let 0 = 0)? {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while true || let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ while (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ while true && (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ while true || (true && let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ while x = let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while true..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ while ..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ while (let 0 = 0).. {}
+ //~^ ERROR expected expression, found `let` statement
+
+ // Binds as `(let ... = true)..true &&/|| false`.
+ while let Range { start: _, end: _ } = true..true && false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ while let Range { start: _, end: _ } = true..true || false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: F, end } = F)..(|| true)`.
+ const F: fn() -> bool = || true;
+ while let Range { start: F, end } = F..|| true {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: true, end } = t)..(&&false)`.
+ let t = &&true;
+ while let Range { start: true, end } = t..&&false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ while let true = let true = true {}
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn not_error_because_clarified_intent() {
+ if let Range { start: _, end: _ } = (true..true || false) { }
+
+ if let Range { start: _, end: _ } = (true..true && false) { }
+
+ while let Range { start: _, end: _ } = (true..true || false) { }
+
+ while let Range { start: _, end: _ } = (true..true && false) { }
+}
+
+fn outside_if_and_while_expr() {
+ &let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+
+ !let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ *let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ -let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ let _ = let _ = 3;
+ //~^ ERROR expected expression, found `let` statement
+
+ fn _check_try_binds_tighter() -> Result<(), ()> {
+ let 0 = 0?;
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ Ok(())
+ }
+ (let 0 = 0)?;
+ //~^ ERROR expected expression, found `let` statement
+
+ true || let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ (true || let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+ true && (true || let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ x = let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+
+ true..(let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+ ..(let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+ (let 0 = 0)..;
+ //~^ ERROR expected expression, found `let` statement
+
+ (let Range { start: _, end: _ } = true..true || false);
+ //~^ ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ (let true = let true = true);
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ {
+ #[cfg(FALSE)]
+ let x = true && let y = 1;
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ #[cfg(FALSE)]
+ {
+ [1, 2, 3][let _ = ()]
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ // Check function tail position.
+ &let 0 = 0
+ //~^ ERROR expected expression, found `let` statement
+}
+
+// Let's make sure that `let` inside const generic arguments are considered.
+fn inside_const_generic_arguments() {
+ struct A<const B: bool>;
+ impl<const B: bool> A<{B}> { const O: u32 = 5; }
+
+ if let A::<{
+ true && let 1 = 1
+ //~^ ERROR expected expression, found `let` statement
+ }>::O = 5 {}
+
+ while let A::<{
+ true && let 1 = 1
+ //~^ ERROR expected expression, found `let` statement
+ }>::O = 5 {}
+
+ if A::<{
+ true && let 1 = 1
+ //~^ ERROR expected expression, found `let` statement
+ }>::O == 5 {}
+
+ // In the cases above we have `ExprKind::Block` to help us out.
+ // Below however, we would not have a block and so an implementation might go
+ // from visiting expressions to types without banning `let` expressions down the tree.
+ // This tests ensures that we are not caught by surprise should the parser
+ // admit non-IDENT expressions in const generic arguments.
+
+ if A::<
+ true && let 1 = 1
+ //~^ ERROR expressions must be enclosed in braces
+ //~| ERROR expected expression, found `let` statement
+ >::O == 5 {}
+}
+
+fn with_parenthesis() {
+ let opt = Some(Some(1i32));
+
+ if (let Some(a) = opt && true) {
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ if (let Some(a) = opt) && true {
+ //~^ ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt) && (let Some(b) = a) {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+
+ if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt && (let Some(b) = a)) && true {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt && (true)) && true {
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ #[cfg(FALSE)]
+ let x = (true && let y = 1);
+ //~^ ERROR expected expression, found `let` statement
+
+ #[cfg(FALSE)]
+ {
+ ([1, 2, 3][let _ = ()])
+ //~^ ERROR expected expression, found `let` statement
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr
new file mode 100644
index 000000000..31f389512
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr
@@ -0,0 +1,1021 @@
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:11:9
+ |
+LL | if (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:11:9
+ |
+LL | if (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:14:11
+ |
+LL | if (((let 0 = 1))) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:14:11
+ |
+LL | if (((let 0 = 1))) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:17:9
+ |
+LL | if (let 0 = 1) && true {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:17:9
+ |
+LL | if (let 0 = 1) && true {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:20:17
+ |
+LL | if true && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:20:17
+ |
+LL | if true && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:23:9
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:23:9
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:23:24
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:23:24
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:27:9
+ |
+LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:27:9
+ |
+LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:27:22
+ |
+LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:27:9
+ |
+LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:27:35
+ |
+LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:27:9
+ |
+LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:34:12
+ |
+LL | while (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:34:12
+ |
+LL | while (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:37:14
+ |
+LL | while (((let 0 = 1))) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:37:14
+ |
+LL | while (((let 0 = 1))) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:40:12
+ |
+LL | while (let 0 = 1) && true {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:40:12
+ |
+LL | while (let 0 = 1) && true {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:43:20
+ |
+LL | while true && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:43:20
+ |
+LL | while true && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:46:12
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:46:12
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:46:27
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:46:27
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:50:12
+ |
+LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:50:12
+ |
+LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:50:25
+ |
+LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:50:12
+ |
+LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:50:38
+ |
+LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:50:12
+ |
+LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:70:9
+ |
+LL | if &let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:73:9
+ |
+LL | if !let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:75:9
+ |
+LL | if *let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:77:9
+ |
+LL | if -let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:85:9
+ |
+LL | if (let 0 = 0)? {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:88:16
+ |
+LL | if true || let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+ --> $DIR/disallowed-positions-without-feature-gate.rs:88:13
+ |
+LL | if true || let 0 = 0 {}
+ | ^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:90:17
+ |
+LL | if (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:92:25
+ |
+LL | if true && (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:94:25
+ |
+LL | if true || (true && let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:98:12
+ |
+LL | if x = let 0 = 0 {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:101:15
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:104:11
+ |
+LL | if ..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:106:9
+ |
+LL | if (let 0 = 0).. {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:110:8
+ |
+LL | if let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:113:8
+ |
+LL | if let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:119:8
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:125:8
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:129:19
+ |
+LL | if let true = let true = true {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:134:12
+ |
+LL | while &let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:137:12
+ |
+LL | while !let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:139:12
+ |
+LL | while *let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:141:12
+ |
+LL | while -let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:149:12
+ |
+LL | while (let 0 = 0)? {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:152:19
+ |
+LL | while true || let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+ --> $DIR/disallowed-positions-without-feature-gate.rs:152:16
+ |
+LL | while true || let 0 = 0 {}
+ | ^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:154:20
+ |
+LL | while (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:156:28
+ |
+LL | while true && (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:158:28
+ |
+LL | while true || (true && let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:162:15
+ |
+LL | while x = let 0 = 0 {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:165:18
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:168:14
+ |
+LL | while ..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:170:12
+ |
+LL | while (let 0 = 0).. {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:174:11
+ |
+LL | while let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:177:11
+ |
+LL | while let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:183:11
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:189:11
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:193:22
+ |
+LL | while let true = let true = true {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:208:6
+ |
+LL | &let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:211:6
+ |
+LL | !let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:213:6
+ |
+LL | *let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:215:6
+ |
+LL | -let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:217:13
+ |
+LL | let _ = let _ = 3;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:225:6
+ |
+LL | (let 0 = 0)?;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:228:13
+ |
+LL | true || let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:230:14
+ |
+LL | (true || let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:232:22
+ |
+LL | true && (true || let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:236:9
+ |
+LL | x = let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:239:12
+ |
+LL | true..(let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:241:8
+ |
+LL | ..(let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:243:6
+ |
+LL | (let 0 = 0)..;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:246:6
+ |
+LL | (let Range { start: _, end: _ } = true..true || false);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:250:6
+ |
+LL | (let true = let true = true);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:250:17
+ |
+LL | (let true = let true = true);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:256:25
+ |
+LL | let x = true && let y = 1;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:262:19
+ |
+LL | [1, 2, 3][let _ = ()]
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:267:6
+ |
+LL | &let 0 = 0
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:277:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:282:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:287:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:298:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expressions must be enclosed in braces to be used as const generic arguments
+ --> $DIR/disallowed-positions-without-feature-gate.rs:298:9
+ |
+LL | true && let 1 = 1
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: enclose the `const` expression in braces
+ |
+LL | { true && let 1 = 1 }
+ | + +
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:307:9
+ |
+LL | if (let Some(a) = opt && true) {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:307:9
+ |
+LL | if (let Some(a) = opt && true) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:311:9
+ |
+LL | if (let Some(a) = opt) && true {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:311:9
+ |
+LL | if (let Some(a) = opt) && true {
+ | ^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:314:9
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:314:9
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:314:32
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:314:32
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:319:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:319:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:319:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:319:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:323:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:323:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:323:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:323:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:327:9
+ |
+LL | if (let Some(a) = opt && (true)) && true {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions-without-feature-gate.rs:327:9
+ |
+LL | if (let Some(a) = opt && (true)) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:332:22
+ |
+LL | let x = (true && let y = 1);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:337:20
+ |
+LL | ([1, 2, 3][let _ = ()])
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:63:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions-without-feature-gate.rs:65:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:101:8
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:110:12
+ |
+LL | if let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:113:12
+ |
+LL | if let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:119:12
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
+ | |
+ | expected fn pointer, found `Range<_>`
+ |
+ = note: expected fn pointer `fn() -> bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:125:12
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions-without-feature-gate.rs:81:20
+ |
+LL | if let 0 = 0? {}
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:165:11
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:174:15
+ |
+LL | while let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:177:15
+ |
+LL | while let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:183:15
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
+ | |
+ | expected fn pointer, found `Range<_>`
+ |
+ = note: expected fn pointer `fn() -> bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:189:15
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions-without-feature-gate.rs:145:23
+ |
+LL | while let 0 = 0? {}
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions-without-feature-gate.rs:246:10
+ |
+LL | (let Range { start: _, end: _ } = true..true || false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions-without-feature-gate.rs:221:17
+ |
+LL | let 0 = 0?;
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error: aborting due to 105 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
new file mode 100644
index 000000000..4ac3ea53a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -0,0 +1,369 @@
+// Here we test that `lowering` behaves correctly wrt. `let $pats = $expr` expressions.
+//
+// We want to make sure that `let` is banned in situations other than:
+//
+// expr =
+// | ...
+// | "if" expr_with_let block {"else" block}?
+// | {label ":"}? while" expr_with_let block
+// ;
+//
+// expr_with_let =
+// | "let" top_pats "=" expr
+// | expr_with_let "&&" expr_with_let
+// | "(" expr_with_let ")"
+// | expr
+// ;
+//
+// To that end, we check some positions which is not part of the language above.
+
+#![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test.
+
+#![allow(irrefutable_let_patterns)]
+
+use std::ops::Range;
+
+fn main() {}
+
+fn _if() {
+ if (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if (((let 0 = 1))) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if (let 0 = 1) && true {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if true && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if (let 0 = 1) && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+}
+
+fn _while() {
+ while (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while (((let 0 = 1))) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while (let 0 = 1) && true {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while true && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while (let 0 = 1) && (let 0 = 1) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+}
+
+fn _macros() {
+ macro_rules! use_expr {
+ ($e:expr) => {
+ if $e {}
+ while $e {}
+ }
+ }
+ use_expr!((let 0 = 1 && 0 == 0));
+ //~^ ERROR expected expression, found `let` statement
+ use_expr!((let 0 = 1));
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn nested_within_if_expr() {
+ if &let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if !let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ if *let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ if -let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ fn _check_try_binds_tighter() -> Result<(), ()> {
+ if let 0 = 0? {}
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ Ok(())
+ }
+ if (let 0 = 0)? {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if true || let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ if (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ if true && (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ if true || (true && let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ if x = let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ if true..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ if ..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ if (let 0 = 0).. {}
+ //~^ ERROR expected expression, found `let` statement
+
+ // Binds as `(let ... = true)..true &&/|| false`.
+ if let Range { start: _, end: _ } = true..true && false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ if let Range { start: _, end: _ } = true..true || false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: F, end } = F)..(|| true)`.
+ const F: fn() -> bool = || true;
+ if let Range { start: F, end } = F..|| true {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: true, end } = t)..(&&false)`.
+ let t = &&true;
+ if let Range { start: true, end } = t..&&false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ if let true = let true = true {}
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn nested_within_while_expr() {
+ while &let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while !let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ while *let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ while -let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ fn _check_try_binds_tighter() -> Result<(), ()> {
+ while let 0 = 0? {}
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ Ok(())
+ }
+ while (let 0 = 0)? {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while true || let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+ while (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ while true && (true || let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ while true || (true && let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ while x = let 0 = 0 {}
+ //~^ ERROR expected expression, found `let` statement
+
+ while true..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ while ..(let 0 = 0) {}
+ //~^ ERROR expected expression, found `let` statement
+ while (let 0 = 0).. {}
+ //~^ ERROR expected expression, found `let` statement
+
+ // Binds as `(let ... = true)..true &&/|| false`.
+ while let Range { start: _, end: _ } = true..true && false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+ while let Range { start: _, end: _ } = true..true || false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: F, end } = F)..(|| true)`.
+ const F: fn() -> bool = || true;
+ while let Range { start: F, end } = F..|| true {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: true, end } = t)..(&&false)`.
+ let t = &&true;
+ while let Range { start: true, end } = t..&&false {}
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR mismatched types
+
+ while let true = let true = true {}
+ //~^ ERROR expected expression, found `let` statement
+}
+
+fn not_error_because_clarified_intent() {
+ if let Range { start: _, end: _ } = (true..true || false) { }
+
+ if let Range { start: _, end: _ } = (true..true && false) { }
+
+ while let Range { start: _, end: _ } = (true..true || false) { }
+
+ while let Range { start: _, end: _ } = (true..true && false) { }
+}
+
+fn outside_if_and_while_expr() {
+ &let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+
+ !let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ *let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ -let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+
+ fn _check_try_binds_tighter() -> Result<(), ()> {
+ let 0 = 0?;
+ //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+ Ok(())
+ }
+ (let 0 = 0)?;
+ //~^ ERROR expected expression, found `let` statement
+
+ true || let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+ (true || let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+ true && (true || let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ x = let 0 = 0;
+ //~^ ERROR expected expression, found `let` statement
+
+ true..(let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+ ..(let 0 = 0);
+ //~^ ERROR expected expression, found `let` statement
+ (let 0 = 0)..;
+ //~^ ERROR expected expression, found `let` statement
+
+ (let Range { start: _, end: _ } = true..true || false);
+ //~^ ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ (let true = let true = true);
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+
+ {
+ #[cfg(FALSE)]
+ let x = true && let y = 1;
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ #[cfg(FALSE)]
+ {
+ [1, 2, 3][let _ = ()]
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ // Check function tail position.
+ &let 0 = 0
+ //~^ ERROR expected expression, found `let` statement
+}
+
+// Let's make sure that `let` inside const generic arguments are considered.
+fn inside_const_generic_arguments() {
+ struct A<const B: bool>;
+ impl<const B: bool> A<{B}> { const O: u32 = 5; }
+
+ if let A::<{
+ true && let 1 = 1
+ //~^ ERROR expected expression, found `let` statement
+ }>::O = 5 {}
+
+ while let A::<{
+ true && let 1 = 1
+ //~^ ERROR expected expression, found `let` statement
+ }>::O = 5 {}
+
+ if A::<{
+ true && let 1 = 1
+ //~^ ERROR expected expression, found `let` statement
+ }>::O == 5 {}
+
+ // In the cases above we have `ExprKind::Block` to help us out.
+ // Below however, we would not have a block and so an implementation might go
+ // from visiting expressions to types without banning `let` expressions down the tree.
+ // This tests ensures that we are not caught by surprise should the parser
+ // admit non-IDENT expressions in const generic arguments.
+
+ if A::<
+ true && let 1 = 1
+ //~^ ERROR expressions must be enclosed in braces
+ //~| ERROR expected expression, found `let` statement
+ >::O == 5 {}
+}
+
+fn with_parenthesis() {
+ let opt = Some(Some(1i32));
+
+ if (let Some(a) = opt && true) {
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ if (let Some(a) = opt) && true {
+ //~^ ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt) && (let Some(b) = a) {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if let Some(a) = opt && (true && true) {
+ }
+
+ if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt && (let Some(b) = a)) && true {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt && (true)) && true {
+ //~^ ERROR expected expression, found `let` statement
+ }
+
+ if (true && (true)) && let Some(a) = opt {
+ }
+ if (true) && let Some(a) = opt {
+ }
+ if true && let Some(a) = opt {
+ }
+
+ let fun = || true;
+ if let true = (true && fun()) && (true) {
+ }
+
+ #[cfg(FALSE)]
+ let x = (true && let y = 1);
+ //~^ ERROR expected expression, found `let` statement
+
+ #[cfg(FALSE)]
+ {
+ ([1, 2, 3][let _ = ()])
+ //~^ ERROR expected expression, found `let` statement
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr
new file mode 100644
index 000000000..ab58abf4d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -0,0 +1,1013 @@
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:29:9
+ |
+LL | if (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:29:9
+ |
+LL | if (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:32:11
+ |
+LL | if (((let 0 = 1))) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:32:11
+ |
+LL | if (((let 0 = 1))) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:35:9
+ |
+LL | if (let 0 = 1) && true {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:35:9
+ |
+LL | if (let 0 = 1) && true {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:38:17
+ |
+LL | if true && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:38:17
+ |
+LL | if true && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:41:9
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:41:9
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:41:24
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:41:24
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:45:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:45:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:45:48
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:45:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:45:61
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:45:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:52:12
+ |
+LL | while (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:52:12
+ |
+LL | while (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:55:14
+ |
+LL | while (((let 0 = 1))) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:55:14
+ |
+LL | while (((let 0 = 1))) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:58:12
+ |
+LL | while (let 0 = 1) && true {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:58:12
+ |
+LL | while (let 0 = 1) && true {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:61:20
+ |
+LL | while true && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:61:20
+ |
+LL | while true && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:64:12
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:64:12
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:64:27
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:64:27
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:68:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:68:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:68:51
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:68:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:68:64
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:68:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:88:9
+ |
+LL | if &let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:91:9
+ |
+LL | if !let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:93:9
+ |
+LL | if *let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:95:9
+ |
+LL | if -let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:103:9
+ |
+LL | if (let 0 = 0)? {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:106:16
+ |
+LL | if true || let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+ --> $DIR/disallowed-positions.rs:106:13
+ |
+LL | if true || let 0 = 0 {}
+ | ^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:108:17
+ |
+LL | if (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:110:25
+ |
+LL | if true && (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:112:25
+ |
+LL | if true || (true && let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:116:12
+ |
+LL | if x = let 0 = 0 {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:119:15
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:122:11
+ |
+LL | if ..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:124:9
+ |
+LL | if (let 0 = 0).. {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:128:8
+ |
+LL | if let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:131:8
+ |
+LL | if let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:137:8
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:143:8
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:147:19
+ |
+LL | if let true = let true = true {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:152:12
+ |
+LL | while &let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:155:12
+ |
+LL | while !let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:157:12
+ |
+LL | while *let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:159:12
+ |
+LL | while -let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:167:12
+ |
+LL | while (let 0 = 0)? {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:170:19
+ |
+LL | while true || let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+ --> $DIR/disallowed-positions.rs:170:16
+ |
+LL | while true || let 0 = 0 {}
+ | ^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:172:20
+ |
+LL | while (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:174:28
+ |
+LL | while true && (true || let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:176:28
+ |
+LL | while true || (true && let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:180:15
+ |
+LL | while x = let 0 = 0 {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:183:18
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:186:14
+ |
+LL | while ..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:188:12
+ |
+LL | while (let 0 = 0).. {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:192:11
+ |
+LL | while let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:195:11
+ |
+LL | while let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:201:11
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:207:11
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:211:22
+ |
+LL | while let true = let true = true {}
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:226:6
+ |
+LL | &let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:229:6
+ |
+LL | !let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:231:6
+ |
+LL | *let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:233:6
+ |
+LL | -let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:241:6
+ |
+LL | (let 0 = 0)?;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:244:13
+ |
+LL | true || let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:246:14
+ |
+LL | (true || let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:248:22
+ |
+LL | true && (true || let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:252:9
+ |
+LL | x = let 0 = 0;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:255:12
+ |
+LL | true..(let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:257:8
+ |
+LL | ..(let 0 = 0);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:259:6
+ |
+LL | (let 0 = 0)..;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:262:6
+ |
+LL | (let Range { start: _, end: _ } = true..true || false);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:266:6
+ |
+LL | (let true = let true = true);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:266:17
+ |
+LL | (let true = let true = true);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:272:25
+ |
+LL | let x = true && let y = 1;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:278:19
+ |
+LL | [1, 2, 3][let _ = ()]
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:283:6
+ |
+LL | &let 0 = 0
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:293:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:298:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:303:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:314:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expressions must be enclosed in braces to be used as const generic arguments
+ --> $DIR/disallowed-positions.rs:314:9
+ |
+LL | true && let 1 = 1
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: enclose the `const` expression in braces
+ |
+LL | { true && let 1 = 1 }
+ | + +
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:323:9
+ |
+LL | if (let Some(a) = opt && true) {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:323:9
+ |
+LL | if (let Some(a) = opt && true) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:327:9
+ |
+LL | if (let Some(a) = opt) && true {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:327:9
+ |
+LL | if (let Some(a) = opt) && true {
+ | ^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:330:9
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:330:9
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:330:32
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:330:32
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:337:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:337:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:337:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:337:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:341:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:341:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:341:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:341:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:345:9
+ |
+LL | if (let Some(a) = opt && (true)) && true {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+ --> $DIR/disallowed-positions.rs:345:9
+ |
+LL | if (let Some(a) = opt && (true)) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:361:22
+ |
+LL | let x = (true && let y = 1);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:366:20
+ |
+LL | ([1, 2, 3][let _ = ()])
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:81:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:83:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:119:8
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:128:12
+ |
+LL | if let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:131:12
+ |
+LL | if let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:137:12
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
+ | |
+ | expected fn pointer, found `Range<_>`
+ |
+ = note: expected fn pointer `fn() -> bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:143:12
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:99:20
+ |
+LL | if let 0 = 0? {}
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:183:11
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:192:15
+ |
+LL | while let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:195:15
+ |
+LL | while let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:201:15
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
+ | |
+ | expected fn pointer, found `Range<_>`
+ |
+ = note: expected fn pointer `fn() -> bool`
+ found struct `std::ops::Range<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:207:15
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:163:23
+ |
+LL | while let 0 = 0? {}
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:262:10
+ |
+LL | (let Range { start: _, end: _ } = true..true || false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
+ | |
+ | expected `bool`, found `Range<_>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<_>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:237:17
+ |
+LL | let 0 = 0?;
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error: aborting due to 104 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
new file mode 100644
index 000000000..3c572054e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
@@ -0,0 +1,54 @@
+#![feature(let_chains)]
+
+fn main() {
+ let opt = Some(1i32);
+
+ let Some(n) = opt else {
+ return;
+ };
+ let Some(n) = opt && n == 1 else {
+ //~^ ERROR a `&&` expression cannot be directly assigned in `let...else`
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ return;
+ };
+ let Some(n) = opt && let another = n else {
+ //~^ ERROR a `&&` expression cannot be directly assigned in `let...else`
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+ return;
+ };
+
+ if let Some(n) = opt else {
+ //~^ ERROR this `if` expression is missing a block after the condition
+ return;
+ };
+ if let Some(n) = opt && n == 1 else {
+ //~^ ERROR this `if` expression is missing a block after the condition
+ return;
+ };
+ if let Some(n) = opt && let another = n else {
+ //~^ ERROR this `if` expression is missing a block after the condition
+ return;
+ };
+
+ {
+ while let Some(n) = opt else {
+ //~^ ERROR expected `{`, found keyword `else`
+ return;
+ };
+ }
+ {
+ while let Some(n) = opt && n == 1 else {
+ //~^ ERROR expected `{`, found keyword `else`
+ return;
+ };
+ }
+ {
+ while let Some(n) = opt && let another = n else {
+ //~^ ERROR expected `{`, found keyword `else`
+ return;
+ };
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
new file mode 100644
index 000000000..0442f1218
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
@@ -0,0 +1,141 @@
+error: a `&&` expression cannot be directly assigned in `let...else`
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
+ |
+LL | let Some(n) = opt && n == 1 else {
+ | ^^^^^^^^^^^^^
+ |
+help: wrap the expression in parentheses
+ |
+LL | let Some(n) = (opt && n == 1) else {
+ | + +
+
+error: expected expression, found `let` statement
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26
+ |
+LL | let Some(n) = opt && let another = n else {
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: a `&&` expression cannot be directly assigned in `let...else`
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
+ |
+LL | let Some(n) = opt && let another = n else {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: wrap the expression in parentheses
+ |
+LL | let Some(n) = (opt && let another = n) else {
+ | + +
+
+error: this `if` expression is missing a block after the condition
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5
+ |
+LL | if let Some(n) = opt else {
+ | ^^
+ |
+help: add a block here
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25
+ |
+LL | if let Some(n) = opt else {
+ | ^
+help: remove the `if` if you meant to write a `let...else` statement
+ |
+LL - if let Some(n) = opt else {
+LL + let Some(n) = opt else {
+ |
+
+error: this `if` expression is missing a block after the condition
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5
+ |
+LL | if let Some(n) = opt && n == 1 else {
+ | ^^
+ |
+help: add a block here
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35
+ |
+LL | if let Some(n) = opt && n == 1 else {
+ | ^
+
+error: this `if` expression is missing a block after the condition
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5
+ |
+LL | if let Some(n) = opt && let another = n else {
+ | ^^
+ |
+help: add a block here
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44
+ |
+LL | if let Some(n) = opt && let another = n else {
+ | ^
+
+error: expected `{`, found keyword `else`
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33
+ |
+LL | while let Some(n) = opt else {
+ | ----- ----------------- ^^^^ expected `{`
+ | | |
+ | | this `while` condition successfully parsed
+ | while parsing the body of this `while` expression
+
+error: expected `{`, found keyword `else`
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:43:43
+ |
+LL | while let Some(n) = opt && n == 1 else {
+ | ----- --------------------------- ^^^^ expected `{`
+ | | |
+ | | this `while` condition successfully parsed
+ | while parsing the body of this `while` expression
+
+error: expected `{`, found keyword `else`
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:49:52
+ |
+LL | while let Some(n) = opt && let another = n else {
+ | ----- ------------------------------------ ^^^^ expected `{`
+ | | |
+ | | this `while` condition successfully parsed
+ | while parsing the body of this `while` expression
+
+error[E0308]: mismatched types
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
+ |
+LL | let Some(n) = opt && n == 1 else {
+ | ^^^ expected `bool`, found `Option<i32>`
+ |
+ = note: expected type `bool`
+ found enum `Option<i32>`
+
+error[E0308]: mismatched types
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:9
+ |
+LL | let Some(n) = opt && n == 1 else {
+ | ^^^^^^^ ------------- this expression has type `bool`
+ | |
+ | expected `bool`, found `Option<_>`
+ |
+ = note: expected type `bool`
+ found enum `Option<_>`
+
+error[E0308]: mismatched types
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
+ |
+LL | let Some(n) = opt && let another = n else {
+ | ^^^ expected `bool`, found `Option<i32>`
+ |
+ = note: expected type `bool`
+ found enum `Option<i32>`
+
+error[E0308]: mismatched types
+ --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:9
+ |
+LL | let Some(n) = opt && let another = n else {
+ | ^^^^^^^ ---------------------- this expression has type `bool`
+ | |
+ | expected `bool`, found `Option<_>`
+ |
+ = note: expected type `bool`
+ found enum `Option<_>`
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
new file mode 100644
index 000000000..bca7564ef
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
@@ -0,0 +1,60 @@
+// gate-test-let_chains
+
+// Here we test feature gating for ´let_chains`.
+// See `disallowed-positions.rs` for the grammar
+// defining the language for gated allowed positions.
+
+#![allow(irrefutable_let_patterns)]
+
+use std::ops::Range;
+
+fn _if() {
+ if let 0 = 1 {} // Stable!
+
+ if true && let 0 = 1 {}
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+
+ if let 0 = 1 && true {}
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+
+ if let Range { start: _, end: _ } = (true..true) && false {}
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+
+ if let 1 = 1 && let true = { true } && false {
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+ //~| ERROR `let` expressions in this position are unstable [E0658]
+ }
+}
+
+fn _while() {
+ while let 0 = 1 {} // Stable!
+
+ while true && let 0 = 1 {}
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+
+ while let 0 = 1 && true {}
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+
+ while let Range { start: _, end: _ } = (true..true) && false {}
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+}
+
+fn _macros() {
+ macro_rules! noop_expr { ($e:expr) => {}; }
+
+ noop_expr!((let 0 = 1));
+ //~^ ERROR expected expression, found `let` statement
+
+ macro_rules! use_expr {
+ ($e:expr) => {
+ if $e {}
+ while $e {}
+ }
+ }
+ #[cfg(FALSE)] (let 0 = 1);
+ //~^ ERROR expected expression, found `let` statement
+ use_expr!(let 0 = 1);
+ //~^ ERROR no rules expected the token `let`
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
new file mode 100644
index 000000000..6f7473675
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
@@ -0,0 +1,106 @@
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:54:20
+ |
+LL | #[cfg(FALSE)] (let 0 = 1);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:45:17
+ |
+LL | noop_expr!((let 0 = 1));
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: no rules expected the token `let`
+ --> $DIR/feature-gate.rs:56:15
+ |
+LL | macro_rules! use_expr {
+ | --------------------- when calling this macro
+...
+LL | use_expr!(let 0 = 1);
+ | ^^^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr`
+ --> $DIR/feature-gate.rs:49:10
+ |
+LL | ($e:expr) => {
+ | ^^^^^^^
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:14:16
+ |
+LL | if true && let 0 = 1 {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:17:8
+ |
+LL | if let 0 = 1 && true {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:20:8
+ |
+LL | if let Range { start: _, end: _ } = (true..true) && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:23:8
+ |
+LL | if let 1 = 1 && let true = { true } && false {
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:23:21
+ |
+LL | if let 1 = 1 && let true = { true } && false {
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:32:19
+ |
+LL | while true && let 0 = 1 {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:35:11
+ |
+LL | while let 0 = 1 && true {}
+ | ^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:38:11
+ |
+LL | while let Range { start: _, end: _ } = (true..true) && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
new file mode 100644
index 000000000..dce1c19ff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
@@ -0,0 +1,47 @@
+#![feature(let_chains)]
+
+fn main() {
+ let _opt = Some(1i32);
+
+ #[cfg(FALSE)]
+ {
+ let _ = &&let Some(x) = Some(42);
+ //~^ ERROR expected expression, found `let` statement
+ }
+ #[cfg(FALSE)]
+ {
+ if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ true
+ }
+ }
+
+ #[cfg(FALSE)]
+ {
+ if let Some(elem) = _opt && {
+ [1, 2, 3][let _ = ()];
+ //~^ ERROR expected expression, found `let` statement
+ true
+ } {
+ }
+ }
+
+ #[cfg(FALSE)]
+ {
+ if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
+ //~^ ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ true
+ }
+ }
+ #[cfg(FALSE)]
+ {
+ if let a = 1 && {
+ let x = let y = 1;
+ //~^ ERROR expected expression, found `let` statement
+ } {
+ }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr
new file mode 100644
index 000000000..f3726166e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr
@@ -0,0 +1,74 @@
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:8:19
+ |
+LL | let _ = &&let Some(x) = Some(42);
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:13:47
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:13:57
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:13:12
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+help: you might have meant to compare for equality
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] == 1 {
+ | +
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:24:23
+ |
+LL | [1, 2, 3][let _ = ()];
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:33:47
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:33:12
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+help: you might have meant to compare for equality
+ |
+LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] == 1 {
+ | +
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:42:21
+ |
+LL | let x = let y = 1;
+ | ^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
new file mode 100644
index 000000000..be4a52315
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
@@ -0,0 +1,115 @@
+error: leading irrefutable pattern in let chain
+ --> $DIR/irrefutable-lets.rs:13:8
+ |
+LL | if let first = &opt && let Some(ref second) = first && let None = second.start {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this pattern will always match
+ = help: consider moving it outside of the construct
+note: the lint level is defined here
+ --> $DIR/irrefutable-lets.rs:6:30
+ |
+LL | #![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable `if let` patterns
+ --> $DIR/irrefutable-lets.rs:19:8
+ |
+LL | if let first = &opt && let (a, b) = (1, 2) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: these patterns will always match, so the `if let` is useless
+ = help: consider replacing the `if let` with a `let`
+
+error: leading irrefutable pattern in let chain
+ --> $DIR/irrefutable-lets.rs:22:8
+ |
+LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this pattern will always match
+ = help: consider moving it outside of the construct
+
+error: trailing irrefutable pattern in let chain
+ --> $DIR/irrefutable-lets.rs:22:87
+ |
+LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: this pattern will always match
+ = help: consider moving it into the body
+
+error: trailing irrefutable patterns in let chain
+ --> $DIR/irrefutable-lets.rs:26:37
+ |
+LL | if let Some(ref first) = opt && let second = first && let _third = second {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: these patterns will always match
+ = help: consider moving them into the body
+
+error: leading irrefutable pattern in let chain
+ --> $DIR/irrefutable-lets.rs:29:8
+ |
+LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this pattern will always match
+ = help: consider moving it outside of the construct
+
+error: leading irrefutable pattern in let chain
+ --> $DIR/irrefutable-lets.rs:32:8
+ |
+LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this pattern will always match
+ = help: consider moving it outside of the construct
+
+error: leading irrefutable pattern in let chain
+ --> $DIR/irrefutable-lets.rs:35:8
+ |
+LL | if let first = &opt && let None = Some(1) {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this pattern will always match
+ = help: consider moving it outside of the construct
+
+error: irrefutable `if let` guard patterns
+ --> $DIR/irrefutable-lets.rs:44:28
+ |
+LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: these patterns will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
+
+error: trailing irrefutable patterns in let chain
+ --> $DIR/irrefutable-lets.rs:59:16
+ |
+LL | && let v = local_end && let w = v => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: these patterns will always match
+ = help: consider moving them into the body
+
+error: irrefutable `while let` patterns
+ --> $DIR/irrefutable-lets.rs:68:11
+ |
+LL | while let first = &opt && let (a, b) = (1, 2) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: these patterns will always match, so the loop will never exit
+ = help: consider instead using a `loop { ... }` with a `let` inside it
+
+error: trailing irrefutable patterns in let chain
+ --> $DIR/irrefutable-lets.rs:71:40
+ |
+LL | while let Some(ref first) = opt && let second = first && let _third = second {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: these patterns will always match
+ = help: consider moving them into the body
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs
new file mode 100644
index 000000000..9afb6853b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs
@@ -0,0 +1,78 @@
+// revisions: allowed disallowed
+//[allowed] check-pass
+
+#![feature(if_let_guard, let_chains)]
+#![cfg_attr(allowed, allow(irrefutable_let_patterns))]
+#![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
+
+use std::ops::Range;
+
+fn main() {
+ let opt = Some(None..Some(1));
+
+ if let first = &opt && let Some(ref second) = first && let None = second.start {}
+ //[disallowed]~^ ERROR leading irrefutable pattern in let chain
+
+ // No lint as the irrefutable pattern is surrounded by other stuff
+ if 4 * 2 == 0 && let first = &opt && let Some(ref second) = first && let None = second.start {}
+
+ if let first = &opt && let (a, b) = (1, 2) {}
+ //[disallowed]~^ ERROR irrefutable `if let` patterns
+
+ if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
+ //[disallowed]~^ ERROR leading irrefutable pattern in let chain
+ //[disallowed]~^^ ERROR trailing irrefutable pattern in let chain
+
+ if let Some(ref first) = opt && let second = first && let _third = second {}
+ //[disallowed]~^ ERROR trailing irrefutable patterns in let chain
+
+ if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {}
+ //[disallowed]~^ ERROR leading irrefutable pattern in let chain
+
+ if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {}
+ //[disallowed]~^ ERROR leading irrefutable pattern in let chain
+
+ if let first = &opt && let None = Some(1) {}
+ //[disallowed]~^ ERROR leading irrefutable pattern in let chain
+
+ if let Some(ref first) = opt
+ && let Range { start: local_start, end: _ } = first
+ && let None = local_start {
+ }
+
+ match opt {
+ Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
+ //[disallowed]~^ ERROR irrefutable `if let` guard patterns
+ _ => {}
+ }
+
+ // No error about leading irrefutable patterns: the expr on the rhs might
+ // use the bindings created by the match.
+ match opt {
+ Some(ref first) if let Range { start: local_start, end: _ } = first
+ && let None = local_start => {},
+ _ => {}
+ }
+
+ match opt {
+ Some(ref first) if let Range { start: Some(_), end: local_end } = first
+ && let v = local_end && let w = v => {},
+ //[disallowed]~^ ERROR trailing irrefutable patterns in let chain
+ _ => {}
+ }
+
+ // No error, despite the prefix being irrefutable: moving out could change the behaviour,
+ // due to possible side effects of the operation.
+ while let first = &opt && let Some(ref second) = first && let None = second.start {}
+
+ while let first = &opt && let (a, b) = (1, 2) {}
+ //[disallowed]~^ ERROR irrefutable `while let` patterns
+
+ while let Some(ref first) = opt && let second = first && let _third = second {}
+ //[disallowed]~^ ERROR trailing irrefutable patterns in let chain
+
+ while let Some(ref first) = opt
+ && let Range { start: local_start, end: _ } = first
+ && let None = local_start {
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/issue-88498.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-88498.rs
new file mode 100644
index 000000000..3eb8a9ad0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-88498.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+pub enum UnOp {
+ Not(Vec<()>),
+}
+
+pub fn foo() {
+ if let Some(x) = None {
+ match x {
+ UnOp::Not(_) => {}
+ }
+ }
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/issue-90722.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-90722.rs
new file mode 100644
index 000000000..6b7d88356
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-90722.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(let_chains)]
+
+fn main() {
+ let x = Some(vec!["test"]);
+
+ if let Some(v) = x && v.is_empty() {
+ println!("x == Some([])");
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/issue-92145.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-92145.rs
new file mode 100644
index 000000000..7c7e31f4d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-92145.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(let_chains)]
+
+fn main() {
+ let opt = Some("foo bar");
+
+ if true && let Some(x) = opt {
+ println!("{}", x);
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.rs
new file mode 100644
index 000000000..f90b9ab0d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.rs
@@ -0,0 +1,8 @@
+fn main() {
+ match true {
+ _ if let true = true && true => {}
+ //~^ ERROR `if let` guards are
+ //~| ERROR `let` expressions in this
+ _ => {}
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.stderr
new file mode 100644
index 000000000..b25f299a2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-93150.stderr
@@ -0,0 +1,22 @@
+error[E0658]: `if let` guards are experimental
+ --> $DIR/issue-93150.rs:3:11
+ |
+LL | _ if let true = true && true => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+ = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+ = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
+
+error[E0658]: `let` expressions in this position are unstable
+ --> $DIR/issue-93150.rs:3:14
+ |
+LL | _ if let true = true && true => {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+ = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/issue-99938.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-99938.rs
new file mode 100644
index 000000000..bd81ce0b1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/issue-99938.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Zvalidate-mir -C opt-level=3
+// build-pass
+#![feature(let_chains)]
+struct TupleIter<T, I: Iterator<Item = T>> {
+ inner: I,
+}
+
+impl<T, I: Iterator<Item = T>> Iterator for TupleIter<T, I> {
+ type Item = (T, T, T);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let inner = &mut self.inner;
+
+ if let Some(first) = inner.next()
+ && let Some(second) = inner.next()
+ && let Some(third) = inner.next()
+ {
+ Some((first, second, third))
+ } else {
+ None
+ }
+ }
+}
+
+fn main() {
+ let vec: Vec<u8> = Vec::new();
+ let mut tup_iter = TupleIter {
+ inner: vec.into_iter(),
+ };
+ tup_iter.next();
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/no-double-assigments.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/no-double-assigments.rs
new file mode 100644
index 000000000..6b91c455e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/no-double-assigments.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+fn main() {
+ loop {
+ // [1][0] should leave top scope
+ if true && [1][0] == 1 && true {
+ }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.rs
new file mode 100644
index 000000000..fcc09b159
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![allow(irrefutable_let_patterns)]
+
+fn main() {
+ let x: bool;
+ // This should associate as: `(x = (true && false));`.
+ x = true && false;
+ assert!(!x);
+
+ fn _f1() -> bool {
+ // Should associate as `(let _ = (return (true && false)))`.
+ if let _ = return true && false {};
+ //~^ WARNING unreachable block in `if`
+ }
+ assert!(!_f1());
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.stderr
new file mode 100644
index 000000000..24b35a2ab
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/protect-precedences.stderr
@@ -0,0 +1,12 @@
+warning: unreachable block in `if` or `while` expression
+ --> $DIR/protect-precedences.rs:13:41
+ |
+LL | if let _ = return true && false {};
+ | -------------------- ^^ unreachable block in `if` or `while` expression
+ | |
+ | any code following this expression is unreachable
+ |
+ = note: `#[warn(unreachable_code)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs
new file mode 100644
index 000000000..e061174f6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/then-else-blocks.rs
@@ -0,0 +1,49 @@
+// run-pass
+
+#![feature(if_let_guard, let_chains)]
+
+fn check_if_let(opt: Option<Option<Option<i32>>>, value: i32) -> bool {
+ if let Some(first) = opt
+ && let Some(second) = first
+ && let Some(third) = second
+ && third == value
+ {
+ true
+ }
+ else {
+ false
+ }
+}
+
+fn check_let_guard(opt: Option<Option<Option<i32>>>, value: i32) -> bool {
+ match opt {
+ Some(first) if let Some(second) = first && let Some(third) = second && third == value => {
+ true
+ }
+ _ => {
+ false
+ }
+ }
+}
+
+fn check_while_let(opt: Option<Option<Option<i32>>>, value: i32) -> bool {
+ while let Some(first) = opt
+ && let Some(second) = first
+ && let Some(third) = second
+ && third == value
+ {
+ return true;
+ }
+ false
+}
+
+fn main() {
+ assert_eq!(check_if_let(Some(Some(Some(1))), 1), true);
+ assert_eq!(check_if_let(Some(Some(Some(1))), 9), false);
+
+ assert_eq!(check_let_guard(Some(Some(Some(1))), 1), true);
+ assert_eq!(check_let_guard(Some(Some(Some(1))), 9), false);
+
+ assert_eq!(check_while_let(Some(Some(Some(1))), 1), true);
+ assert_eq!(check_while_let(Some(Some(Some(1))), 9), false);
+}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
index 831731ba4..86f2d9b6e 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
@@ -4,9 +4,9 @@ error[E0308]: mismatched types
LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
| ^^^^^^^^^^^^ expected `P<T>`, found `&P<T>`
|
- = note: expected struct `P<T>`
- found reference `&P<T>`
+ = note: expected struct `P<_>`
+ found reference `&P<_>`
-error: aborting due to previous error
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
index 1c26eb880..8ae7691a4 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
@@ -13,6 +13,6 @@ LL | let m2: Machine<'static, State1> = Machine {
LL | }
| - `s` dropped here while still borrowed
-error: aborting due to previous error
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs
new file mode 100644
index 000000000..eeb2191ba
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs
@@ -0,0 +1,16 @@
+#[cfg(FALSE)]
+impl S {
+ fn f(#[attr]) {} //~ ERROR expected parameter name, found `)`
+}
+
+#[cfg(FALSE)]
+impl T for S {
+ fn f(#[attr]) {} //~ ERROR expected parameter name, found `)`
+}
+
+#[cfg(FALSE)]
+trait T {
+ fn f(#[attr]); //~ ERROR expected argument name, found `)`
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr
new file mode 100644
index 000000000..26dff4d4b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr
@@ -0,0 +1,20 @@
+error: expected parameter name, found `)`
+ --> $DIR/attr-without-param.rs:3:17
+ |
+LL | fn f(#[attr]) {}
+ | ^ expected parameter name
+
+error: expected parameter name, found `)`
+ --> $DIR/attr-without-param.rs:8:17
+ |
+LL | fn f(#[attr]) {}
+ | ^ expected parameter name
+
+error: expected argument name, found `)`
+ --> $DIR/attr-without-param.rs:13:17
+ |
+LL | fn f(#[attr]);
+ | ^ expected argument name
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs
new file mode 100644
index 000000000..b62cf3120
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs
@@ -0,0 +1,11 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn id(_: TokenStream, input: TokenStream) -> TokenStream { input }
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs
new file mode 100644
index 000000000..67de50a1d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs
@@ -0,0 +1,42 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+macro_rules! checker {
+ ($attr_name:ident, $expected:literal) => {
+ #[proc_macro_attribute]
+ pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream {
+ assert_eq!(input.to_string(), $expected);
+ TokenStream::new()
+ }
+ }
+}
+
+checker!(attr_extern, r#"extern "C" { fn ffi(#[a1] arg1: i32, #[a2] ...); }"#);
+checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) {}"#);
+checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...);");
+checker!(attr_free, "fn free(#[a1] arg1: u8) { let lam = |#[a2] W(x), #[a3] y| (); }");
+checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) {}");
+checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) {}");
+checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) {}");
+checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) {}");
+checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) {}");
+checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);");
+checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);");
+checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);");
+checker!(attr_trait_4, r#"fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);"#);
+checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);");
+checker!(rename_params, r#"impl Foo
+{
+ fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) {}
+ fn
+ hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, #[angery(true)] c: u32)
+ {} fn
+ hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32, #[what = "how"] b: i32,
+ #[angery(true)] c: u32) {}
+}"#);
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs b/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
new file mode 100644
index 000000000..670303906
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
@@ -0,0 +1,21 @@
+// aux-build:param-attrs.rs
+
+// check-pass
+
+extern crate param_attrs;
+
+use param_attrs::rename_params;
+
+#[rename_params(send_help)]
+impl Foo {
+ fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) {}
+ fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, #[angery(true)] c: u32) {}
+ fn hello_self(
+ #[a1] #[a2] &self,
+ #[a1] #[a2] a: i32,
+ #[what = "how"] b: i32,
+ #[angery(true)] c: u32
+ ) {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.rs
new file mode 100644
index 000000000..a6f693bd5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.rs
@@ -0,0 +1,6 @@
+// edition:2018
+
+trait Trait2015 { fn foo(#[allow(C)] i32); }
+//~^ ERROR expected one of `:`, `@`, or `|`, found `)`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr
new file mode 100644
index 000000000..0c269a23f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr
@@ -0,0 +1,22 @@
+error: expected one of `:`, `@`, or `|`, found `)`
+ --> $DIR/param-attrs-2018.rs:3:41
+ |
+LL | trait Trait2015 { fn foo(#[allow(C)] i32); }
+ | ^ 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 | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
+ | +++++
+help: if this is a parameter name, give it a type
+ |
+LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
+ | ++++++++++
+help: if this is a type, explicitly ignore the parameter name
+ |
+LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); }
+ | ++
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs
new file mode 100644
index 000000000..2de37c859
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs
@@ -0,0 +1,101 @@
+// check-pass
+// compile-flags: --cfg something
+
+#![deny(unused_mut)]
+
+extern "C" {
+ fn ffi(
+ #[allow(unused_mut)] a: i32,
+ #[cfg(something)] b: i32,
+ #[cfg_attr(something, cfg(nothing))] c: i32,
+ #[forbid(unused_mut)] d: i32,
+ #[deny(unused_mut)] #[warn(unused_mut)] ...
+ );
+}
+
+type FnType = fn(
+ #[allow(unused_mut)] a: i32,
+ #[cfg(something)] b: i32,
+ #[cfg_attr(something, cfg(nothing))] c: i32,
+ #[forbid(unused_mut)] d: i32,
+ #[deny(unused_mut)] #[warn(unused_mut)] e: i32
+);
+
+pub fn foo(
+ #[allow(unused_mut)] a: i32,
+ #[cfg(something)] b: i32,
+ #[cfg_attr(something, cfg(nothing))] c: i32,
+ #[forbid(unused_mut)] d: i32,
+ #[deny(unused_mut)] #[warn(unused_mut)] _e: i32
+) {}
+
+// self
+
+struct SelfStruct {}
+impl SelfStruct {
+ fn foo(
+ #[allow(unused_mut)] self,
+ #[cfg(something)] a: i32,
+ #[cfg_attr(something, cfg(nothing))]
+ #[deny(unused_mut)] b: i32,
+ ) {}
+}
+
+struct RefStruct {}
+impl RefStruct {
+ fn foo(
+ #[allow(unused_mut)] &self,
+ #[cfg(something)] a: i32,
+ #[cfg_attr(something, cfg(nothing))]
+ #[deny(unused_mut)] b: i32,
+ ) {}
+}
+trait RefTrait {
+ fn foo(
+ #[forbid(unused_mut)] &self,
+ #[warn(unused_mut)] a: i32
+ ) {}
+}
+impl RefTrait for RefStruct {
+ fn foo(
+ #[forbid(unused_mut)] &self,
+ #[warn(unused_mut)] a: i32
+ ) {}
+}
+
+// Box<Self>
+
+struct BoxSelfStruct {}
+impl BoxSelfStruct {
+ fn foo(
+ #[allow(unused_mut)] self: Box<Self>,
+ #[cfg(something)] a: i32,
+ #[cfg_attr(something, cfg(nothing))]
+ #[deny(unused_mut)] b: i32,
+ ) {}
+}
+trait BoxSelfTrait {
+ fn foo(
+ #[forbid(unused_mut)] self: Box<Self>,
+ #[warn(unused_mut)] a: i32
+ ) {}
+}
+impl BoxSelfTrait for BoxSelfStruct {
+ fn foo(
+ #[forbid(unused_mut)] self: Box<Self>,
+ #[warn(unused_mut)] a: i32
+ ) {}
+}
+
+fn main() {
+ let _: unsafe extern "C" fn(_, _, _, ...) = ffi;
+ let _: fn(_, _, _, _) = foo;
+ let _: FnType = |_, _, _, _| {};
+ let c = |
+ #[allow(unused_mut)] a: u32,
+ #[cfg(something)] b: i32,
+ #[cfg_attr(something, cfg(nothing))]
+ #[deny(unused_mut)] c: i32,
+ | {};
+ c(1, 2);
+}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
new file mode 100644
index 000000000..151659e35
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
@@ -0,0 +1,174 @@
+extern "C" {
+ fn ffi(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ );
+}
+
+type FnType = fn(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: u32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+);
+
+pub fn foo(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: u32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+) {}
+
+struct SelfStruct {}
+impl SelfStruct {
+ fn foo(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ self,
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Qux
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ ) {}
+
+ fn issue_64682_associated_fn(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Qux
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ ) {}
+}
+
+struct RefStruct {}
+impl RefStruct {
+ fn foo(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ &self,
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Qux
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ ) {}
+}
+trait RefTrait {
+ fn foo(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ &self,
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Qux
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ ) {}
+
+ fn issue_64682_associated_fn(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Qux
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ ) {}
+}
+
+impl RefTrait for RefStruct {
+ fn foo(
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ &self,
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: i32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Qux
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32,
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ ) {}
+}
+
+fn main() {
+ let _ = |
+ /// Foo
+ //~^ ERROR documentation comments cannot be applied to function
+ #[test] a: u32,
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ /// Bar
+ //~^ ERROR documentation comments cannot be applied to function
+ #[must_use]
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ /// Baz
+ //~^ ERROR documentation comments cannot be applied to function
+ #[no_mangle] b: i32
+ //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ | {};
+}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
new file mode 100644
index 000000000..7573e39d8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
@@ -0,0 +1,386 @@
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:5:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:21:7
+ |
+LL | #[test] a: u32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:36:7
+ |
+LL | #[test] a: u32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:56:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:71:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:92:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:111:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:126:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:146:11
+ |
+LL | #[test] a: i32,
+ | ^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `test`
+ --> $DIR/param-attrs-builtin-attrs.rs:163:11
+ |
+LL | #[test] a: u32,
+ | ^^^^ not a non-macro attribute
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:3:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:7:9
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:9:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:11:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:13:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:19:5
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:23:5
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:25:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:27:5
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:29:5
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:34:5
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:38:5
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:40:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:42:5
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:44:5
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:51:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:54:9
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:58:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:60:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:62:9
+ |
+LL | /// Qux
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:64:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:69:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:73:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:75:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:77:9
+ |
+LL | /// Qux
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:79:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:87:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:90:9
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:94:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:96:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:98:9
+ |
+LL | /// Qux
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:100:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:106:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:109:9
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:113:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:115:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:117:9
+ |
+LL | /// Qux
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:119:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:124:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:128:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:130:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:132:9
+ |
+LL | /// Qux
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:134:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:141:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:144:9
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:148:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:150:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:152:9
+ |
+LL | /// Qux
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:154:9
+ |
+LL | #[no_mangle] b: i32,
+ | ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:161:9
+ |
+LL | /// Foo
+ | ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:165:9
+ |
+LL | /// Bar
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:167:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:169:9
+ |
+LL | /// Baz
+ | ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+ --> $DIR/param-attrs-builtin-attrs.rs:171:9
+ |
+LL | #[no_mangle] b: i32
+ | ^^^^^^^^^^^^
+
+error: aborting due to 64 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs
new file mode 100644
index 000000000..14539d4b6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs
@@ -0,0 +1,121 @@
+// compile-flags: --cfg something
+// edition:2018
+
+#![feature(async_closure)]
+#![deny(unused_variables)]
+
+extern "C" {
+ fn ffi(
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ #[cfg_attr(something, cfg(nothing))] c: i32,
+ #[cfg_attr(nothing, cfg(nothing))] ...
+ );
+}
+
+type FnType = fn(
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+);
+
+async fn foo_async(
+ #[cfg(something)] a: i32,
+ //~^ ERROR unused variable: `a`
+ #[cfg(nothing)] b: i32,
+) {}
+fn foo(
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+) {}
+
+struct RefStruct {}
+impl RefStruct {
+ async fn bar_async(
+ &self,
+ #[cfg(something)] a: i32,
+ //~^ ERROR unused variable: `a`
+ #[cfg(nothing)] b: i32,
+ ) {}
+ fn bar(
+ &self,
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ ) {}
+ fn issue_64682_associated_fn(
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ ) {}
+}
+trait RefTrait {
+ fn bar(
+ &self,
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ ) {}
+ fn issue_64682_associated_fn(
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ ) {}
+}
+impl RefTrait for RefStruct {
+ fn bar(
+ &self,
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ ) {}
+ fn issue_64682_associated_fn(
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ ) {}
+}
+
+fn main() {
+ let _: unsafe extern "C" fn(_, ...) = ffi;
+ let _: fn(_, _) = foo;
+ let _: FnType = |_, _| {};
+ let a = async move |
+ #[cfg(something)] a: i32,
+ //~^ ERROR unused variable: `a`
+ #[cfg(nothing)] b: i32,
+ | {};
+ let c = |
+ #[cfg(nothing)] a: i32,
+ #[cfg(something)] b: i32,
+ //~^ ERROR unused variable: `b`
+ #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ //~^ ERROR unused variable: `c`
+ #[cfg_attr(something, cfg(nothing))] d: i32,
+ | {};
+ a(1);
+ c(1, 2);
+}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr
new file mode 100644
index 000000000..16e1af460
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr
@@ -0,0 +1,122 @@
+error: unused variable: `a`
+ --> $DIR/param-attrs-cfg.rs:24:23
+ |
+LL | #[cfg(something)] a: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/param-attrs-cfg.rs:5:9
+ |
+LL | #![deny(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+
+error: unused variable: `a`
+ --> $DIR/param-attrs-cfg.rs:41:27
+ |
+LL | #[cfg(something)] a: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:30:23
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:32:40
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:48:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:50:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:56:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:58:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:67:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:69:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:75:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:77:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:86:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:88:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:94:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:96:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: unused variable: `a`
+ --> $DIR/param-attrs-cfg.rs:107:27
+ |
+LL | #[cfg(something)] a: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/param-attrs-cfg.rs:113:27
+ |
+LL | #[cfg(something)] b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `c`
+ --> $DIR/param-attrs-cfg.rs:115:44
+ |
+LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_c`
+
+error: aborting due to 19 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs
new file mode 100644
index 000000000..1183ac65b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs
@@ -0,0 +1,61 @@
+// aux-build:param-attrs.rs
+
+// check-pass
+
+#![feature(c_variadic)]
+
+extern crate param_attrs;
+
+use param_attrs::*;
+
+struct W(u8);
+
+#[attr_extern]
+extern "C" { fn ffi(#[a1] arg1: i32, #[a2] ...); }
+
+#[attr_extern_cvar]
+unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) {}
+
+#[attr_alias]
+type Alias = fn(#[a1] u8, #[a2] ...);
+
+#[attr_free]
+fn free(#[a1] arg1: u8) {
+ let lam = |#[a2] W(x), #[a3] y| ();
+}
+
+impl W {
+ #[attr_inherent_1]
+ fn inherent1(#[a1] self, #[a2] arg1: u8) {}
+
+ #[attr_inherent_2]
+ fn inherent2(#[a1] &self, #[a2] arg1: u8) {}
+
+ #[attr_inherent_3]
+ fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) {}
+
+ #[attr_inherent_4]
+ fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) {}
+
+ #[attr_inherent_issue_64682]
+ fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) {}
+}
+
+trait A {
+ #[attr_trait_1]
+ fn trait1(#[a1] self, #[a2] arg1: u8);
+
+ #[attr_trait_2]
+ fn trait2(#[a1] &self, #[a2] arg1: u8);
+
+ #[attr_trait_3]
+ fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);
+
+ #[attr_trait_4]
+ fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);
+
+ #[attr_trait_issue_64682]
+ fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
new file mode 100644
index 000000000..54f2f451b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
@@ -0,0 +1,66 @@
+// aux-build:ident-mac.rs
+
+#![feature(c_variadic)]
+#![allow(anonymous_parameters)]
+
+extern crate ident_mac;
+use ident_mac::id;
+
+struct W(u8);
+
+extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
+//~^ ERROR expected non-macro attribute, found attribute macro
+//~| ERROR expected non-macro attribute, found attribute macro
+
+unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {}
+//~^ ERROR expected non-macro attribute, found attribute macro
+
+type Alias = extern "C" fn(#[id] u8, #[id] ...);
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+
+fn free(#[id] arg1: u8) {
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ let lam = |#[id] W(x), #[id] y: usize| ();
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+}
+
+impl W {
+ fn inherent1(#[id] self, #[id] arg1: u8) {}
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn inherent2(#[id] &self, #[id] arg1: u8) {}
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+}
+
+trait A {
+ fn trait1(#[id] self, #[id] arg1: u8);
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn trait2(#[id] &self, #[id] arg1: u8);
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+ fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
+ //~^ ERROR expected non-macro attribute, found attribute macro
+ //~| ERROR expected non-macro attribute, found attribute macro
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
new file mode 100644
index 000000000..e74d05d49
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
@@ -0,0 +1,176 @@
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:11:23
+ |
+LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:11:40
+ |
+LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:15:40
+ |
+LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:18:30
+ |
+LL | type Alias = extern "C" fn(#[id] u8, #[id] ...);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:18:40
+ |
+LL | type Alias = extern "C" fn(#[id] u8, #[id] ...);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:22:11
+ |
+LL | fn free(#[id] arg1: u8) {
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:24:18
+ |
+LL | let lam = |#[id] W(x), #[id] y: usize| ();
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:24:30
+ |
+LL | let lam = |#[id] W(x), #[id] y: usize| ();
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:30:20
+ |
+LL | fn inherent1(#[id] self, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:30:32
+ |
+LL | fn inherent1(#[id] self, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:33:20
+ |
+LL | fn inherent2(#[id] &self, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:33:33
+ |
+LL | fn inherent2(#[id] &self, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:36:24
+ |
+LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:36:44
+ |
+LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:39:24
+ |
+LL | fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:39:47
+ |
+LL | fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:42:40
+ |
+LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:42:56
+ |
+LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:48:17
+ |
+LL | fn trait1(#[id] self, #[id] arg1: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:48:29
+ |
+LL | fn trait1(#[id] self, #[id] arg1: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:51:17
+ |
+LL | fn trait2(#[id] &self, #[id] arg1: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:51:30
+ |
+LL | fn trait2(#[id] &self, #[id] arg1: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:54:21
+ |
+LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:54:41
+ |
+LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:57:21
+ |
+LL | fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:57:44
+ |
+LL | fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:57:60
+ |
+LL | fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:61:40
+ |
+LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
+ | ^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `id`
+ --> $DIR/proc-macro-cannot-be-used.rs:61:56
+ |
+LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
+ | ^^ not a non-macro attribute
+
+error: aborting due to 29 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
new file mode 100644
index 000000000..880907b24
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
@@ -0,0 +1,23 @@
+// Tests that dlltool failing to generate an import library will raise an error.
+
+// only-gnu
+// only-windows
+// needs-dlltool
+// compile-flags: --crate-type lib --emit link
+// normalize-stderr-test: "[^ ']*/dlltool.exe" -> "$$DLLTOOL"
+// normalize-stderr-test: "[^ ]*/foo.def" -> "$$DEF_FILE"
+// normalize-stderr-test: "[^ ]*/foo.lib" -> "$$LIB_FILE"
+// normalize-stderr-test: "-m [^ ]*" -> "$$TARGET_MACHINE"
+// normalize-stderr-test: "-f [^ ]*" -> "$$ASM_FLAGS"
+// normalize-stderr-test: "--temp-prefix [^ ]*/foo.dll" -> "$$TEMP_PREFIX"
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+ // `@1` is an invalid name to export, as it usually indicates that something
+ // is being exported via ordinal.
+ #[link_name = "@1"]
+ fn f(x: i32);
+}
+
+pub fn lib_main() {
+ unsafe { f(42); }
+}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
new file mode 100644
index 000000000..0c5a06e68
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
@@ -0,0 +1,6 @@
+error: Dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX:
+
+ $DLLTOOL: Syntax error in def file $DEF_FILE:1
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs
new file mode 100644
index 000000000..7bc44d65b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs
@@ -0,0 +1,7 @@
+// only-windows
+// only-x86
+#[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+//~^ ERROR import name type must be of the form `import_name_type = "string"`
+extern "C" { }
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr
new file mode 100644
index 000000000..d2cf7a0ba
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr
@@ -0,0 +1,8 @@
+error: import name type must be of the form `import_name_type = "string"`
+ --> $DIR/import-name-type-invalid-format.rs:3:42
+ |
+LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs
new file mode 100644
index 000000000..b96f61a26
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs
@@ -0,0 +1,8 @@
+// ignore-tidy-linelength
+// only-windows
+// only-x86
+#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+//~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute
+extern "C" { }
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr
new file mode 100644
index 000000000..8e65baf65
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr
@@ -0,0 +1,8 @@
+error: multiple `import_name_type` arguments in a single `#[link]` attribute
+ --> $DIR/import-name-type-multiple.rs:4:74
+ |
+LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs
new file mode 100644
index 000000000..067e82a17
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs
@@ -0,0 +1,7 @@
+// only-windows
+// only-x86
+#[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+//~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
+extern "C" { }
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr
new file mode 100644
index 000000000..4b8b90eb6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr
@@ -0,0 +1,8 @@
+error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
+ --> $DIR/import-name-type-unknown-value.rs:3:42
+ |
+LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs
new file mode 100644
index 000000000..34e907bde
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs
@@ -0,0 +1,15 @@
+// only-windows
+// only-x86
+#[link(name = "foo", import_name_type = "decorated")]
+//~^ ERROR import name type can only be used with link kind `raw-dylib`
+extern "C" { }
+
+#[link(name = "bar", kind = "static", import_name_type = "decorated")]
+//~^ ERROR import name type can only be used with link kind `raw-dylib`
+extern "C" { }
+
+// Specifying `import_name_type` before `kind` shouldn't raise an error.
+#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
+extern "C" { }
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr
new file mode 100644
index 000000000..75cadc471
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr
@@ -0,0 +1,14 @@
+error: import name type can only be used with link kind `raw-dylib`
+ --> $DIR/import-name-type-unsupported-link-kind.rs:3:22
+ |
+LL | #[link(name = "foo", import_name_type = "decorated")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: import name type can only be used with link kind `raw-dylib`
+ --> $DIR/import-name-type-unsupported-link-kind.rs:7:39
+ |
+LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs
new file mode 100644
index 000000000..346ea18a8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs
@@ -0,0 +1,7 @@
+// only-windows
+// ignore-x86
+#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
+//~^ ERROR import name type is only supported on x86
+extern "C" { }
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr
new file mode 100644
index 000000000..757f1f799
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr
@@ -0,0 +1,8 @@
+error: import name type is only supported on x86
+ --> $DIR/import-name-type-x86-only.rs:3:42
+ |
+LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs
new file mode 100644
index 000000000..a07be9d92
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs
@@ -0,0 +1,13 @@
+// Tests that failing to run dlltool will raise an error.
+
+// only-gnu
+// only-windows
+// compile-flags: --crate-type lib --emit link -Cdlltool=does_not_exit.exe
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+ fn f(x: i32);
+}
+
+pub fn lib_main() {
+ unsafe { f(42); }
+}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr
new file mode 100644
index 000000000..9dbeee49f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr
@@ -0,0 +1,4 @@
+error: Error calling dlltool 'does_not_exit.exe': program not found
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs
new file mode 100644
index 000000000..b04c2facb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs
@@ -0,0 +1,13 @@
+#[link(name="foo")]
+extern "C" {
+ #[link_name="foo"]
+ #[link_ordinal(42)]
+ //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]`
+ fn foo();
+ #[link_name="foo"]
+ #[link_ordinal(5)]
+ //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]`
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr
new file mode 100644
index 000000000..f1e54d378
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr
@@ -0,0 +1,14 @@
+error: cannot use `#[link_name]` with `#[link_ordinal]`
+ --> $DIR/link-ordinal-and-name.rs:4:5
+ |
+LL | #[link_ordinal(42)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: cannot use `#[link_name]` with `#[link_ordinal]`
+ --> $DIR/link-ordinal-and-name.rs:8:5
+ |
+LL | #[link_ordinal(5)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
new file mode 100644
index 000000000..9b7e8d707
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
@@ -0,0 +1,11 @@
+#[link(name = "foo")]
+extern "C" {
+ #[link_ordinal("JustMonika")]
+ //~^ ERROR illegal ordinal format in `link_ordinal`
+ fn foo();
+ #[link_ordinal("JustMonika")]
+ //~^ ERROR illegal ordinal format in `link_ordinal`
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr
new file mode 100644
index 000000000..6341e57a0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr
@@ -0,0 +1,18 @@
+error: illegal ordinal format in `link_ordinal`
+ --> $DIR/link-ordinal-invalid-format.rs:3:5
+ |
+LL | #[link_ordinal("JustMonika")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: an unsuffixed integer value, e.g., `1`, is expected
+
+error: illegal ordinal format in `link_ordinal`
+ --> $DIR/link-ordinal-invalid-format.rs:6:5
+ |
+LL | #[link_ordinal("JustMonika")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: an unsuffixed integer value, e.g., `1`, is expected
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs
new file mode 100644
index 000000000..6b8cd4956
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs
@@ -0,0 +1,11 @@
+#[link(name = "foo")]
+extern "C" {
+ #[link_ordinal()]
+ //~^ ERROR incorrect number of arguments to `#[link_ordinal]`
+ fn foo();
+ #[link_ordinal()]
+ //~^ ERROR incorrect number of arguments to `#[link_ordinal]`
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr
new file mode 100644
index 000000000..1b04bb228
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr
@@ -0,0 +1,18 @@
+error: incorrect number of arguments to `#[link_ordinal]`
+ --> $DIR/link-ordinal-missing-argument.rs:3:5
+ |
+LL | #[link_ordinal()]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: the attribute requires exactly one argument
+
+error: incorrect number of arguments to `#[link_ordinal]`
+ --> $DIR/link-ordinal-missing-argument.rs:6:5
+ |
+LL | #[link_ordinal()]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: the attribute requires exactly one argument
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs
new file mode 100644
index 000000000..8842cb944
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs
@@ -0,0 +1,12 @@
+// only-windows
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+ #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes
+ #[link_ordinal(2)]
+ fn foo();
+ #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes
+ #[link_ordinal(2)]
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr
new file mode 100644
index 000000000..2e6cf3761
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr
@@ -0,0 +1,26 @@
+error: multiple `link_ordinal` attributes
+ --> $DIR/link-ordinal-multiple.rs:4:5
+ |
+LL | #[link_ordinal(1)]
+ | ^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/link-ordinal-multiple.rs:5:5
+ |
+LL | #[link_ordinal(2)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: multiple `link_ordinal` attributes
+ --> $DIR/link-ordinal-multiple.rs:7:5
+ |
+LL | #[link_ordinal(1)]
+ | ^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/link-ordinal-multiple.rs:8:5
+ |
+LL | #[link_ordinal(2)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs
new file mode 100644
index 000000000..f33a3d62e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs
@@ -0,0 +1,22 @@
+#[link_ordinal(123)]
+//~^ ERROR attribute should be applied to a foreign function or static
+struct Foo {}
+
+#[link_ordinal(123)]
+//~^ ERROR attribute should be applied to a foreign function or static
+fn test() {}
+
+#[link_ordinal(42)]
+//~^ ERROR attribute should be applied to a foreign function or static
+static mut imported_val: i32 = 123;
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern {
+ #[link_ordinal(13)]
+ fn imported_function();
+
+ #[link_ordinal(42)]
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr
new file mode 100644
index 000000000..8f2795087
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr
@@ -0,0 +1,20 @@
+error: attribute should be applied to a foreign function or static
+ --> $DIR/link-ordinal-not-foreign-fn.rs:1:1
+ |
+LL | #[link_ordinal(123)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: attribute should be applied to a foreign function or static
+ --> $DIR/link-ordinal-not-foreign-fn.rs:5:1
+ |
+LL | #[link_ordinal(123)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: attribute should be applied to a foreign function or static
+ --> $DIR/link-ordinal-not-foreign-fn.rs:9:1
+ |
+LL | #[link_ordinal(42)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs
new file mode 100644
index 000000000..9d741630f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs
@@ -0,0 +1,11 @@
+#[link(name = "foo")]
+extern "C" {
+ #[link_ordinal(72436)]
+ //~^ ERROR ordinal value in `link_ordinal` is too large: `72436`
+ fn foo();
+ #[link_ordinal(72436)]
+ //~^ ERROR ordinal value in `link_ordinal` is too large: `72436`
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr
new file mode 100644
index 000000000..811145e77
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr
@@ -0,0 +1,18 @@
+error: ordinal value in `link_ordinal` is too large: `72436`
+ --> $DIR/link-ordinal-too-large.rs:3:5
+ |
+LL | #[link_ordinal(72436)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the value may not exceed `u16::MAX`
+
+error: ordinal value in `link_ordinal` is too large: `72436`
+ --> $DIR/link-ordinal-too-large.rs:6:5
+ |
+LL | #[link_ordinal(72436)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the value may not exceed `u16::MAX`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs
new file mode 100644
index 000000000..9988115fd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs
@@ -0,0 +1,11 @@
+#[link(name = "foo")]
+extern "C" {
+ #[link_ordinal(3, 4)]
+ //~^ ERROR incorrect number of arguments to `#[link_ordinal]`
+ fn foo();
+ #[link_ordinal(3, 4)]
+ //~^ ERROR incorrect number of arguments to `#[link_ordinal]`
+ static mut imported_variable: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr
new file mode 100644
index 000000000..d5ce8aff3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr
@@ -0,0 +1,18 @@
+error: incorrect number of arguments to `#[link_ordinal]`
+ --> $DIR/link-ordinal-too-many-arguments.rs:3:5
+ |
+LL | #[link_ordinal(3, 4)]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the attribute requires exactly one argument
+
+error: incorrect number of arguments to `#[link_ordinal]`
+ --> $DIR/link-ordinal-too-many-arguments.rs:6:5
+ |
+LL | #[link_ordinal(3, 4)]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the attribute requires exactly one argument
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs
new file mode 100644
index 000000000..14e915d60
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs
@@ -0,0 +1,15 @@
+#[link(name = "foo")]
+extern "C" {
+ #[link_ordinal(3)]
+ //~^ ERROR `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+ fn foo();
+}
+
+#[link(name = "bar", kind = "static")]
+extern "C" {
+ #[link_ordinal(3)]
+ //~^ ERROR `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+ fn bar();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr
new file mode 100644
index 000000000..200b8f628
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr
@@ -0,0 +1,14 @@
+error: `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+ --> $DIR/link-ordinal-unsupported-link-kind.rs:3:5
+ |
+LL | #[link_ordinal(3)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+ --> $DIR/link-ordinal-unsupported-link-kind.rs:10:5
+ |
+LL | #[link_ordinal(3)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs
new file mode 100644
index 000000000..b4173f3b6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs
@@ -0,0 +1,18 @@
+// only-x86
+// only-windows
+// compile-flags: --crate-type lib --emit link
+#![allow(clashing_extern_declarations)]
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+ fn f(x: i32);
+}
+
+pub fn lib_main() {
+ #[link(name = "foo", kind = "raw-dylib")]
+ extern "stdcall" {
+ fn f(x: i32);
+ //~^ ERROR multiple declarations of external function `f` from library `foo.dll` have different calling conventions
+ }
+
+ unsafe { f(42); }
+}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr
new file mode 100644
index 000000000..7866af594
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr
@@ -0,0 +1,8 @@
+error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions
+ --> $DIR/multiple-declarations.rs:13:9
+ |
+LL | fn f(x: i32);
+ | ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
new file mode 100644
index 000000000..d4c6658a3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
@@ -0,0 +1,5 @@
+// ignore-windows
+// compile-flags: --crate-type lib
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ ERROR: link kind `raw-dylib` is only supported on Windows targets
+extern "C" {}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
new file mode 100644
index 000000000..ede20cb8c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
@@ -0,0 +1,9 @@
+error[E0455]: link kind `raw-dylib` is only supported on Windows targets
+ --> $DIR/raw-dylib-windows-only.rs:3:29
+ |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+ | ^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0455`.
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs
new file mode 100644
index 000000000..2f5a23e47
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs
@@ -0,0 +1,12 @@
+// only-x86_64
+// only-windows
+// compile-flags: --crate-type lib --emit link
+#[link(name = "foo", kind = "raw-dylib")]
+extern "stdcall" {
+ fn f(x: i32);
+ //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+}
+
+pub fn lib_main() {
+ unsafe { f(42); }
+}
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr
new file mode 100644
index 000000000..d7c7344b5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr
@@ -0,0 +1,8 @@
+error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+ --> $DIR/unsupported-abi.rs:6:5
+ |
+LL | fn f(x: i32);
+ | ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
new file mode 100644
index 000000000..f41c1051f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
@@ -0,0 +1,15 @@
+// known-bug: #110395
+// FIXME check-pass
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Foo {
+ type Assoc: ~const Foo;
+ fn foo() {}
+}
+
+const fn foo<T: ~const Foo>() {
+ <T as Foo>::Assoc::foo();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr
new file mode 100644
index 000000000..1b8883998
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr
@@ -0,0 +1,20 @@
+error: `~const` is not allowed here
+ --> $DIR/assoc-type-const-bound-usage.rs:7:17
+ |
+LL | type Assoc: ~const Foo;
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error[E0308]: mismatched types
+ --> $DIR/assoc-type-const-bound-usage.rs:12:5
+ |
+LL | <T as Foo>::Assoc::foo();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true`
+ |
+ = note: expected constant `host`
+ found constant `true`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
new file mode 100644
index 000000000..96790a873
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
@@ -0,0 +1,33 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+struct NonConstAdd(i32);
+
+impl std::ops::Add for NonConstAdd {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ NonConstAdd(self.0 + rhs.0)
+ }
+}
+
+#[const_trait]
+trait Foo {
+ type Bar: ~const std::ops::Add;
+}
+
+impl const Foo for NonConstAdd {
+ type Bar = NonConstAdd;
+}
+
+#[const_trait]
+trait Baz {
+ type Qux: std::ops::Add;
+}
+
+impl const Baz for NonConstAdd {
+ type Qux = NonConstAdd; // OK
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
new file mode 100644
index 000000000..290ef6e2f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -0,0 +1,16 @@
+error: `~const` is not allowed here
+ --> $DIR/assoc-type.rs:17:15
+ |
+LL | type Bar: ~const std::ops::Add;
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/assoc-type.rs:17:22
+ |
+LL | type Bar: ~const std::ops::Add;
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.rs
new file mode 100644
index 000000000..01ac74fef
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.rs
@@ -0,0 +1,10 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait A {
+ #[const_trait] //~ ERROR attribute should be applied
+ fn foo(self);
+}
+
+#[const_trait] //~ ERROR attribute should be applied
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.stderr
new file mode 100644
index 000000000..998958ced
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.stderr
@@ -0,0 +1,18 @@
+error: attribute should be applied to a trait
+ --> $DIR/attr-misuse.rs:9:1
+ |
+LL | #[const_trait]
+ | ^^^^^^^^^^^^^^
+LL | fn main() {}
+ | ------------ not a trait
+
+error: attribute should be applied to a trait
+ --> $DIR/attr-misuse.rs:5:5
+ |
+LL | #[const_trait]
+ | ^^^^^^^^^^^^^^
+LL | fn foo(self);
+ | ------------- not a trait
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
new file mode 100644
index 000000000..f40dc27cb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
@@ -0,0 +1,23 @@
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+pub trait MyTrait {
+ fn defaulted_func(&self) {}
+ fn func(self);
+}
+
+pub struct NonConst;
+
+impl MyTrait for NonConst {
+ fn func(self) {
+
+ }
+}
+
+pub struct Const;
+
+impl const MyTrait for Const {
+ fn func(self) {
+
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
new file mode 100644
index 000000000..687cb128b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
@@ -0,0 +1,19 @@
+#![feature(const_trait_impl, effects)]
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
+pub trait MyTrait {
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn func();
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Unstable;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "unstable", issue = "none")]
+impl const MyTrait for Unstable {
+ fn func() {}
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
new file mode 100644
index 000000000..771c35cf6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+pub trait Plus {
+ fn plus(self, rhs: Self) -> Self;
+}
+
+impl const Plus for i32 {
+ fn plus(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Plus for u32 {
+ fn plus(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+pub const fn add_i32(a: i32, b: i32) -> i32 {
+ a.plus(b) // ok
+}
+
+pub const fn add_u32(a: u32, b: u32) -> u32 {
+ a.plus(b)
+ //~^ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
new file mode 100644
index 000000000..93d520f29
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
+ --> $DIR/call-const-trait-method-fail.rs:25:5
+ |
+LL | a.plus(b)
+ | ^ the trait `~const Plus` is not implemented for `u32`
+ |
+ = help: the trait `Plus` is implemented for `u32`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
new file mode 100644
index 000000000..ae0c2e6bc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
@@ -0,0 +1,43 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+struct Int(i32);
+
+impl const std::ops::Add for Int {
+ type Output = Int;
+
+ fn add(self, rhs: Self) -> Self {
+ Int(self.0.plus(rhs.0))
+ }
+}
+
+impl const PartialEq for Int {
+ fn eq(&self, rhs: &Self) -> bool {
+ self.0 == rhs.0
+ }
+ fn ne(&self, other: &Self) -> bool {
+ !self.eq(other)
+ }
+}
+
+#[const_trait]
+pub trait Plus {
+ fn plus(self, rhs: Self) -> Self;
+}
+
+impl const Plus for i32 {
+ fn plus(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+pub const fn add_i32(a: i32, b: i32) -> i32 {
+ a.plus(b)
+}
+
+const ADD_INT: Int = Int(1i32) + Int(2i32);
+
+fn main() {
+ assert!(ADD_INT == Int(3i32));
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr
new file mode 100644
index 000000000..60cd000f2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr
@@ -0,0 +1,24 @@
+error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions
+ --> $DIR/call-const-trait-method-pass.rs:36:7
+ |
+LL | a.plus(b)
+ | ^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error[E0015]: cannot call non-const operator in constants
+ --> $DIR/call-const-trait-method-pass.rs:39:22
+ |
+LL | const ADD_INT: Int = Int(1i32) + Int(2i32);
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: impl defined here, but it is not `const`
+ --> $DIR/call-const-trait-method-pass.rs:7:1
+ |
+LL | impl const std::ops::Add for Int {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs
new file mode 100644
index 000000000..50c465790
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs
@@ -0,0 +1,15 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait MyPartialEq {
+ fn eq(&self, other: &Self) -> bool;
+}
+
+impl<T: ~const PartialEq> const MyPartialEq for T {
+ fn eq(&self, other: &Self) -> bool {
+ PartialEq::eq(self, other)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs
new file mode 100644
index 000000000..0df370bff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs
@@ -0,0 +1,28 @@
+//! Basic test for calling methods on generic type parameters in `const fn`.
+
+// check-pass
+
+#![feature(const_trait_impl, effects)]
+
+struct S;
+
+impl const PartialEq for S {
+ fn eq(&self, _: &S) -> bool {
+ true
+ }
+ fn ne(&self, other: &S) -> bool {
+ !self.eq(other)
+ }
+}
+
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+ *t == *t
+}
+
+const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
+ equals_self(t)
+}
+
+pub const EQ: bool = equals_self_wrapper(&S);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
new file mode 100644
index 000000000..b0d5d0685
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+#![feature(const_trait_impl, effects)]
+
+struct S;
+
+impl const PartialEq for S {
+ fn eq(&self, _: &S) -> bool {
+ true
+ }
+ fn ne(&self, other: &S) -> bool {
+ !self.eq(other)
+ }
+}
+
+// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const
+// bound.
+const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
+ *t == *t
+}
+
+trait A: PartialEq {}
+impl<T: PartialEq> A for T {}
+
+const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+ *t == *t
+}
+
+pub const EQ: bool = equals_self(&S) && equals_self2(&S);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs
new file mode 100644
index 000000000..043939750
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl, effects)]
+
+pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
+ *t == *t
+ //~^ ERROR mismatched types
+ // FIXME(effects): diagnostic
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
new file mode 100644
index 000000000..5074c4a22
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/call-generic-method-fail.rs:4:5
+ |
+LL | *t == *t
+ | ^^^^^^^^ expected `host`, found `true`
+ |
+ = note: expected constant `host`
+ found constant `true`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
new file mode 100644
index 000000000..e197c8b73
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+struct S;
+
+impl PartialEq for S {
+ fn eq(&self, _: &S) -> bool {
+ true
+ }
+}
+
+const fn equals_self<T: PartialEq>(t: &T) -> bool {
+ true
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
new file mode 100644
index 000000000..76bc73812
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -0,0 +1,26 @@
+#![feature(const_trait_impl, effects)]
+
+struct S;
+
+#[const_trait]
+trait Foo {
+ fn eq(&self, _: &Self) -> bool;
+}
+
+impl Foo for S {
+ fn eq(&self, _: &S) -> bool {
+ true
+ }
+}
+
+const fn equals_self<T: ~const Foo>(t: &T) -> bool {
+ true
+}
+
+// Calling `equals_self` with something that has a non-const impl should throw an error, despite
+// it not using the impl.
+
+pub const EQ: bool = equals_self(&S);
+//~^ ERROR: the trait bound `S: ~const Foo` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
new file mode 100644
index 000000000..aea9a39b2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+ --> $DIR/call-generic-method-nonconst.rs:23:34
+ |
+LL | pub const EQ: bool = equals_self(&S);
+ | ----------- ^^ the trait `~const Foo` is not implemented for `S`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Foo` is implemented for `S`
+note: required by a bound in `equals_self`
+ --> $DIR/call-generic-method-nonconst.rs:16:25
+ |
+LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
+ | ^^^^^^^^^^ required by this bound in `equals_self`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs
new file mode 100644
index 000000000..abd5d2fdb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs
@@ -0,0 +1,24 @@
+//! Basic test for calling methods on generic type parameters in `const fn`.
+
+// check-pass
+
+#![feature(const_trait_impl, effects)]
+
+struct S;
+
+impl const PartialEq for S {
+ fn eq(&self, _: &S) -> bool {
+ true
+ }
+ fn ne(&self, other: &S) -> bool {
+ !self.eq(other)
+ }
+}
+
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+ *t == *t
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs
new file mode 100644
index 000000000..5f48c2353
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![feature(const_closures, const_trait_impl)]
+#![allow(incomplete_features)]
+
+pub const _: () = {
+ assert!((const || true)());
+};
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
new file mode 100644
index 000000000..9ba19e800
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
@@ -0,0 +1,31 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+pub struct Int(i32);
+
+impl const std::ops::Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl std::ops::Add for Int {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ Int(self.0 + rhs.0)
+ }
+}
+
+impl const std::ops::Add for Int {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ Int(self.0 + rhs.0)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
new file mode 100644
index 000000000..54bc43477
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
@@ -0,0 +1,25 @@
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
+ --> $DIR/const-and-non-const-impl.rs:7:1
+ |
+LL | impl const std::ops::Add for i32 {
+ | ^^^^^^^^^^^-------------^^^^^---
+ | | | |
+ | | | `i32` is not defined in the current crate
+ | | `i32` is not defined in the current crate
+ | impl doesn't use only types from inside the current crate
+ |
+ = note: define and implement a trait or new type instead
+
+error[E0119]: conflicting implementations of trait `Add` for type `Int`
+ --> $DIR/const-and-non-const-impl.rs:23:1
+ |
+LL | impl std::ops::Add for Int {
+ | -------------------------- first implementation here
+...
+LL | impl const std::ops::Add for Int {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0117, E0119.
+For more information about an error, try `rustc --explain E0117`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs
new file mode 100644
index 000000000..0025449c4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs
@@ -0,0 +1,28 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait MyTrait {
+ fn do_something(&self);
+}
+
+trait OtherTrait {
+ fn do_something_else() where Self: ~const MyTrait;
+ //~^ ERROR `~const` is not allowed here
+}
+
+struct MyStruct<T>(T);
+
+impl const MyTrait for u32 {
+ fn do_something(&self) {}
+}
+
+impl<T> MyStruct<T> {
+ pub fn foo(&self) where T: ~const MyTrait {
+ //~^ ERROR `~const` is not allowed here
+ self.0.do_something();
+ }
+}
+
+fn main() {
+ MyStruct(0u32).foo();
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr
new file mode 100644
index 000000000..db48c170d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr
@@ -0,0 +1,26 @@
+error: `~const` is not allowed here
+ --> $DIR/const-bound-on-not-const-associated-fn.rs:9:40
+ |
+LL | fn do_something_else() where Self: ~const MyTrait;
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/const-bound-on-not-const-associated-fn.rs:9:8
+ |
+LL | fn do_something_else() where Self: ~const MyTrait;
+ | ^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/const-bound-on-not-const-associated-fn.rs:20:32
+ |
+LL | pub fn foo(&self) where T: ~const MyTrait {
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/const-bound-on-not-const-associated-fn.rs:20:12
+ |
+LL | pub fn foo(&self) where T: ~const MyTrait {
+ | ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
new file mode 100644
index 000000000..4854f41bf
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
@@ -0,0 +1,16 @@
+#![feature(const_trait_impl, effects)]
+
+struct S;
+#[const_trait]
+trait T {
+ fn foo();
+}
+
+fn non_const() {}
+
+impl const T for S {
+ fn foo() { non_const() }
+ //~^ ERROR cannot call non-const fn
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
new file mode 100644
index 000000000..ae035b26e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `non_const` in constant functions
+ --> $DIR/const-check-fns-in-const-impl.rs:12:16
+ |
+LL | fn foo() { non_const() }
+ | ^^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
new file mode 100644
index 000000000..15f062edf
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
@@ -0,0 +1,11 @@
+// known-bug: #110395
+// FIXME check-pass
+
+#![feature(const_trait_impl, const_closures)]
+#![allow(incomplete_features)]
+
+const fn test() -> impl ~const Fn() {
+ const move || {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr
new file mode 100644
index 000000000..fc9b5557a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closure-parse-not-item.rs:7:32
+ |
+LL | const fn test() -> impl ~const Fn() {
+ | ^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs
new file mode 100644
index 000000000..b4cc7a9e1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs
@@ -0,0 +1,20 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+ fn a(self) -> i32;
+}
+
+impl Tr for () {
+ fn a(self) -> i32 { 42 }
+}
+
+const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+ x(())
+}
+
+const _: () = assert!(need_const_closure(Tr::a) == 42);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
new file mode 100644
index 000000000..73ee0f215
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closure-trait-method-fail.rs:14:39
+ |
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs
new file mode 100644
index 000000000..fd9f28725
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs
@@ -0,0 +1,20 @@
+// known-bug: #110395
+// FIXME check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+ fn a(self) -> i32;
+}
+
+impl const Tr for () {
+ fn a(self) -> i32 { 42 }
+}
+
+const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+ x(())
+}
+
+const _: () = assert!(need_const_closure(Tr::a) == 42);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr
new file mode 100644
index 000000000..33ae7131b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closure-trait-method.rs:14:39
+ |
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs
new file mode 100644
index 000000000..1fe4044d5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs
@@ -0,0 +1,31 @@
+// known-bug: #110395
+// FIXME check-pass
+
+#![feature(const_trait_impl)]
+
+const fn answer_p1<F>(f: &F) -> u8
+ where
+ F: ~const FnOnce() -> u8,
+ F: ~const FnMut() -> u8,
+ F: ~const Fn() -> u8,
+{
+ f() * 7
+}
+
+const fn three() -> u8 {
+ 3
+}
+
+const fn answer_p2() -> u8 {
+ answer_p1(&three)
+}
+
+const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
+ f() + f()
+}
+
+const ANSWER: u8 = answer(&answer_p2);
+
+fn main() {
+ assert_eq!(ANSWER, 42)
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr
new file mode 100644
index 000000000..6d61b23e4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr
@@ -0,0 +1,26 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closures.rs:8:19
+ |
+LL | F: ~const FnOnce() -> u8,
+ | ^^^^^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closures.rs:9:19
+ |
+LL | F: ~const FnMut() -> u8,
+ | ^^^^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closures.rs:10:19
+ |
+LL | F: ~const Fn() -> u8,
+ | ^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-closures.rs:23:27
+ |
+LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
+ | ^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs
new file mode 100644
index 000000000..be668b4f1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait ConstDefaultFn: Sized {
+ fn b(self);
+
+ fn a(self) {
+ self.b();
+ }
+}
+
+struct NonConstImpl;
+struct ConstImpl;
+
+impl ConstDefaultFn for NonConstImpl {
+ fn b(self) {}
+}
+
+impl const ConstDefaultFn for ConstImpl {
+ fn b(self) {}
+}
+
+const fn test() {
+ NonConstImpl.a();
+ //~^ ERROR the trait bound
+ ConstImpl.a();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
new file mode 100644
index 000000000..f39e6dcad
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
+ --> $DIR/const-default-method-bodies.rs:24:18
+ |
+LL | NonConstImpl.a();
+ | ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+ |
+ = help: the trait `ConstDefaultFn` is implemented for `NonConstImpl`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.rs
new file mode 100644
index 000000000..7f89c1280
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.rs
@@ -0,0 +1,26 @@
+// known-bug: #110395
+// FIXME check-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_precise_live_drops)]
+
+use std::marker::Destruct;
+
+const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
+ match res {
+ Ok(t) => Some(t),
+ Err(_e) => None,
+ }
+}
+
+pub struct Foo<T>(T);
+
+const fn baz<T, E>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>>
+where
+ T: ~const Destruct,
+ E: ~const Destruct,
+{
+ foo(res)
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr
new file mode 100644
index 000000000..16ed61590
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr
@@ -0,0 +1,9 @@
+error[E0493]: destructor of `E` cannot be evaluated at compile-time
+ --> $DIR/const-drop-bound.rs:12:13
+ |
+LL | Err(_e) => None,
+ | ^^ the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr
new file mode 100644
index 000000000..13350a6d1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr
@@ -0,0 +1,26 @@
+error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
+ --> $DIR/const-drop-fail-2.rs:23:25
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ | ^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-drop-fail-2.rs:29:26
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^^^^^^^^
+
+error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
+ --> $DIR/const-drop-fail-2.rs:39:25
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+ | ^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs
new file mode 100644
index 000000000..747ccbf0f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs
@@ -0,0 +1,46 @@
+// known-bug: #110395
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::{Destruct, PhantomData};
+
+struct NonTrivialDrop;
+
+impl Drop for NonTrivialDrop {
+ fn drop(&mut self) {
+ println!("Non trivial drop");
+ }
+}
+
+#[const_trait]
+trait A { fn a() { } }
+
+impl A for NonTrivialDrop {}
+
+const fn check<T: ~const Destruct>(_: T) {}
+
+
+/* FIXME(effects)
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ fn drop(&mut self) {
+ T::a();
+ }
+}
+
+const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
+ ConstDropImplWithBounds(PhantomData)
+);
+*/
+
+struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+ fn drop(&mut self) {
+ T::a();
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr
new file mode 100644
index 000000000..6f75924f0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr
@@ -0,0 +1,11 @@
+error[E0493]: destructor of `T` cannot be evaluated at compile-time
+ --> $DIR/const-drop-fail-2.rs:21:36
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^ - value is dropped here
+ | |
+ | the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr
new file mode 100644
index 000000000..13350a6d1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr
@@ -0,0 +1,26 @@
+error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
+ --> $DIR/const-drop-fail-2.rs:23:25
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ | ^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-drop-fail-2.rs:29:26
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^^^^^^^^
+
+error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
+ --> $DIR/const-drop-fail-2.rs:39:25
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+ | ^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
new file mode 100644
index 000000000..8997e7ade
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -0,0 +1,9 @@
+error[E0493]: destructor of `T` cannot be evaluated at compile-time
+ --> $DIR/const-drop-fail.rs:24:36
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^ the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs
new file mode 100644
index 000000000..1c37648ff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -0,0 +1,37 @@
+// known-bug: #110395
+
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::{Destruct, PhantomData};
+
+struct NonTrivialDrop;
+
+impl Drop for NonTrivialDrop {
+ fn drop(&mut self) {
+ println!("Non trivial drop");
+ }
+}
+
+struct ConstImplWithDropGlue(NonTrivialDrop);
+
+impl const Drop for ConstImplWithDropGlue {
+ fn drop(&mut self) {}
+}
+
+const fn check<T: ~const Destruct>(_: T) {}
+
+macro_rules! check_all {
+ ($($exp:expr),*$(,)?) => {$(
+ const _: () = check($exp);
+ )*};
+}
+
+check_all! {
+ NonTrivialDrop,
+ ConstImplWithDropGlue(NonTrivialDrop),
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
new file mode 100644
index 000000000..09ebf55c5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -0,0 +1,11 @@
+error[E0493]: destructor of `T` cannot be evaluated at compile-time
+ --> $DIR/const-drop-fail.rs:24:36
+ |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+ | ^ - value is dropped here
+ | |
+ | the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr
new file mode 100644
index 000000000..daaba08d7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr
@@ -0,0 +1,10 @@
+error: `~const` is not allowed here
+ --> $DIR/const-drop.rs:67:38
+ |
+LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs
new file mode 100644
index 000000000..9da84cdb0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs
@@ -0,0 +1,117 @@
+// FIXME run-pass
+// known-bug: #110395
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(never_type)]
+// #![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::Destruct;
+
+struct S<'a>(&'a mut u8);
+
+impl<'a> const Drop for S<'a> {
+ fn drop(&mut self) {
+ *self.0 += 1;
+ }
+}
+
+const fn a<T: ~const Destruct>(_: T) {}
+//FIXME ~^ ERROR destructor of
+
+const fn b() -> u8 {
+ let mut c = 0;
+ let _ = S(&mut c);
+ //FIXME ~^ ERROR destructor of
+ a(S(&mut c));
+ c
+}
+
+const C: u8 = b();
+
+macro_rules! implements_const_drop {
+ ($($exp:expr),*$(,)?) => {
+ $(
+ const _: () = a($exp);
+ )*
+ }
+}
+
+#[allow(dead_code)]
+mod t {
+ pub struct Foo;
+ pub enum Bar { A }
+ pub fn foo() {}
+ pub struct ConstDrop;
+
+ impl const Drop for ConstDrop {
+ fn drop(&mut self) {}
+ }
+
+ pub struct HasConstDrop(pub ConstDrop);
+ pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+
+ #[const_trait]
+ pub trait SomeTrait {
+ fn foo();
+ }
+ impl const SomeTrait for () {
+ fn foo() {}
+ }
+ // non-const impl
+ impl SomeTrait for i32 {
+ fn foo() {}
+ }
+
+ // FIXME(effects): This should be a `const` bound instead of a `~const` one.
+ pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
+
+ impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
+ fn drop(&mut self) {
+ T::foo();
+ }
+ }
+
+ pub struct ConstDropWithNonconstBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
+
+ impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> {
+ fn drop(&mut self) {
+ // Note: we DON'T use the `T: SomeTrait` bound
+ }
+ }
+}
+
+use t::*;
+
+implements_const_drop! {
+ 1u8,
+ 2,
+ 3.0,
+ Foo,
+ Bar::A,
+ foo,
+ ConstDrop,
+ HasConstDrop(ConstDrop),
+ TrivialFields(1, 2, 3, 4),
+ &1,
+ &1 as *const i32,
+ ConstDropWithBound::<()>,
+ ConstDropWithNonconstBound::<i32>,
+ Result::<i32, !>::Ok(1),
+}
+
+fn main() {
+ struct HasDropGlue(#[allow(unused_tuple_struct_fields)] Box<u8>);
+ struct HasDropImpl;
+ impl Drop for HasDropImpl {
+ fn drop(&mut self) {
+ println!("not trivial drop");
+ }
+ }
+
+ // These types should pass because ~const in a non-const context should have no effect.
+ a(HasDropGlue(Box::new(0)));
+ a(HasDropImpl);
+
+ assert_eq!(C, 2);
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr
new file mode 100644
index 000000000..daaba08d7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr
@@ -0,0 +1,10 @@
+error: `~const` is not allowed here
+ --> $DIR/const-drop.rs:67:38
+ |
+LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.rs
new file mode 100644
index 000000000..bed4e9fd1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.rs
@@ -0,0 +1,12 @@
+#![feature(const_trait_impl)]
+
+struct Foo;
+
+const impl Foo { //~ ERROR: expected identifier, found keyword
+ fn bar() {}
+}
+
+fn main() {
+ // shouldn't error here because we shouldn't have been able to recover above
+ Foo::bar();
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr
new file mode 100644
index 000000000..efa72463c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found keyword `impl`
+ --> $DIR/const-impl-norecover.rs:5:7
+ |
+LL | const impl Foo {
+ | ^^^^ expected identifier, found keyword
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.rs
new file mode 100644
index 000000000..837124db0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.rs
@@ -0,0 +1,17 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {}
+
+const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword
+
+#[const_trait]
+trait Bar {}
+
+const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword
+
+const fn still_implements<T: Bar>() {}
+
+const _: () = still_implements::<i32>();
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.stderr
new file mode 100644
index 000000000..7217fc855
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-recovery.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `impl`
+ --> $DIR/const-impl-recovery.rs:6:7
+ |
+LL | const impl Foo for i32 {}
+ | ^^^^ expected identifier, found keyword
+ |
+help: you might have meant to write a const trait impl
+ |
+LL - const impl Foo for i32 {}
+LL + impl const Foo for i32 {}
+ |
+
+error: expected identifier, found keyword `impl`
+ --> $DIR/const-impl-recovery.rs:11:7
+ |
+LL | const impl<T: Foo> Bar for T {}
+ | ^^^^ expected identifier, found keyword
+ |
+help: you might have meant to write a const trait impl
+ |
+LL - const impl<T: Foo> Bar for T {}
+LL + impl<T: Foo> const Bar for T {}
+ |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
new file mode 100644
index 000000000..fc3a83876
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -0,0 +1,11 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl, effects)]
+
+pub trait A {}
+// FIXME ~^ HELP: mark `A` as const
+
+impl const A for () {}
+// FIXME ~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
new file mode 100644
index 000000000..f0b6e2b1c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
@@ -0,0 +1,14 @@
+error: const `impl` for trait `A` which is not marked with `#[const_trait]`
+ --> $DIR/const-impl-requires-const-trait.rs:8:12
+ |
+LL | pub trait A {}
+ | - help: mark `A` as const: `#[const_trait]`
+...
+LL | impl const A for () {}
+ | ^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
new file mode 100644
index 000000000..14d306fc3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
@@ -0,0 +1,55 @@
+// known-bug: #110395
+#![allow(incomplete_features)]
+#![feature(
+ associated_type_bounds,
+ const_trait_impl,
+ effects,
+ const_cmp,
+)]
+
+use std::marker::Destruct;
+
+const fn cmp(a: &impl ~const PartialEq) -> bool {
+ a == a
+}
+
+const fn wrap(x: impl ~const PartialEq + ~const Destruct)
+ -> impl ~const PartialEq + ~const Destruct
+{
+ x
+}
+
+#[const_trait]
+trait Foo {
+ fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+}
+
+impl const Foo for () {
+ fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+ 123
+ }
+}
+
+const _: () = {
+ assert!(cmp(&0xDEADBEEFu32));
+ assert!(cmp(&()));
+ assert!(wrap(123) == wrap(123));
+ assert!(wrap(123) != wrap(456));
+ let x = <() as Foo>::huh();
+ assert!(x == x);
+};
+
+#[const_trait]
+trait T {}
+struct S;
+impl const T for S {}
+
+const fn rpit() -> impl ~const T { S }
+
+const fn apit(_: impl ~const T + ~const Destruct) {}
+
+const fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+
+const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
new file mode 100644
index 000000000..ddedf8f1d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
@@ -0,0 +1,28 @@
+error[E0277]: can't compare `impl PartialEq + Destruct + Copy` with `impl PartialEq + Destruct + Copy`
+ --> $DIR/const-impl-trait.rs:28:17
+ |
+LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `impl PartialEq + Destruct + Copy == impl PartialEq + Destruct + Copy`
+ |
+ = help: the trait `~const PartialEq` is not implemented for `impl PartialEq + Destruct + Copy`
+note: required by a bound in `Foo::{opaque#0}`
+ --> $DIR/const-impl-trait.rs:24:22
+ |
+LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+ | ^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
+
+error[E0277]: can't drop `impl PartialEq + Destruct + Copy`
+ --> $DIR/const-impl-trait.rs:28:17
+ |
+LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `impl PartialEq + Destruct + Copy`
+ |
+note: required by a bound in `Foo::{opaque#0}`
+ --> $DIR/const-impl-trait.rs:24:41
+ |
+LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+ | ^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
new file mode 100644
index 000000000..348ca0ab1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
@@ -0,0 +1,4 @@
+#[derive_const(Default)] //~ ERROR use of unstable library feature
+pub struct S;
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
new file mode 100644
index 000000000..2dd96f548
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'derive_const'
+ --> $DIR/derive-const-gate.rs:1:3
+ |
+LL | #[derive_const(Default)]
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(derive_const)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs
new file mode 100644
index 000000000..ce39045d7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs
@@ -0,0 +1,13 @@
+// known-bug: #110395
+#![feature(derive_const, effects)]
+
+pub struct A;
+
+impl Default for A {
+ fn default() -> A { A }
+}
+
+#[derive_const(Default)]
+pub struct S(A);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr
new file mode 100644
index 000000000..dfe8fa79e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr
@@ -0,0 +1,12 @@
+error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-non-const-type.rs:10:16
+ |
+LL | #[derive_const(Default)]
+ | ^^^^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+ = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
new file mode 100644
index 000000000..42d728369
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
@@ -0,0 +1,20 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
+
+pub struct A;
+
+impl const Default for A {
+ fn default() -> A { A }
+}
+
+impl const PartialEq for A {
+ fn eq(&self, _: &A) -> bool { true }
+}
+
+#[derive_const(Default, PartialEq)]
+pub struct S((), A);
+
+const _: () = assert!(S((), A) == S::default());
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
new file mode 100644
index 000000000..c561f8065
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
@@ -0,0 +1,28 @@
+error[E0635]: unknown feature `const_default_impls`
+ --> $DIR/derive-const-use.rs:3:41
+ |
+LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-use.rs:7:12
+ |
+LL | impl const Default for A {
+ | ^^^^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-use.rs:15:16
+ |
+LL | #[derive_const(Default, PartialEq)]
+ | ^^^^^^^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+ = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0635`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
new file mode 100644
index 000000000..b479c967b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(derive_const)]
+#![feature(const_trait_impl, effects)]
+
+#[derive_const(PartialEq)]
+pub struct Reverse<T>(T);
+
+const fn foo(a: Reverse<i32>, b: Reverse<i32>) -> bool {
+ a == b
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs
new file mode 100644
index 000000000..bde8bf20f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs
@@ -0,0 +1,18 @@
+// This tests that `const_trait` default methods can
+// be called from a const context when used across crates.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+
+// aux-build: cross-crate.rs
+extern crate cross_crate;
+
+use cross_crate::*;
+
+const _: () = {
+ Const.func();
+ Const.defaulted_func();
+};
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
new file mode 100644
index 000000000..f0ac953fd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
+ --> $DIR/cross-crate.rs:17:14
+ |
+LL | NonConst.func();
+ | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+ |
+ = help: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs
new file mode 100644
index 000000000..95edbdc0e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs
@@ -0,0 +1,25 @@
+// revisions: stock gated stocknc gatednc
+// [gated] check-pass
+#![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))]
+
+// aux-build: cross-crate.rs
+extern crate cross_crate;
+
+use cross_crate::*;
+
+fn non_const_context() {
+ NonConst.func();
+ Const.func();
+}
+
+const fn const_context() {
+ #[cfg(any(stocknc, gatednc))]
+ NonConst.func();
+ //[stocknc]~^ ERROR: cannot call
+ //[gatednc]~^^ ERROR: the trait bound
+ Const.func();
+ //[stock]~^ ERROR: cannot call
+ //[stocknc]~^^ ERROR: cannot call
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr
new file mode 100644
index 000000000..ab039397e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr
@@ -0,0 +1,12 @@
+error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
+ --> $DIR/cross-crate.rs:20:11
+ |
+LL | Const.func();
+ | ^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
new file mode 100644
index 000000000..ebbe9aa22
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -0,0 +1,21 @@
+error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
+ --> $DIR/cross-crate.rs:17:14
+ |
+LL | NonConst.func();
+ | ^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
+ --> $DIR/cross-crate.rs:20:11
+ |
+LL | Const.func();
+ | ^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
new file mode 100644
index 000000000..f5644c888
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
@@ -0,0 +1,20 @@
+// known-bug: #110395
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {}
+impl Tr for () {}
+
+const fn foo<T>() where T: ~const Tr {}
+
+#[const_trait]
+pub trait Foo {
+ fn foo() {
+ foo::<()>();
+ //FIXME ~^ ERROR the trait bound `(): Tr` is not satisfied
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
new file mode 100644
index 000000000..da2772400
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
@@ -0,0 +1,15 @@
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+pub trait Tr {
+ fn a(&self) {}
+
+ fn b(&self) {
+ ().a()
+ //~^ ERROR the trait bound
+ }
+}
+
+impl Tr for () {}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
new file mode 100644
index 000000000..29db6109a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied
+ --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
+ |
+LL | ().a()
+ | ^ the trait `~const Tr` is not implemented for `()`
+ |
+ = help: the trait `Tr` is implemented for `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs
new file mode 100644
index 000000000..13881e042
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+// This was an ICE, because the compiler ensures the
+// function to be const when performing const checking,
+// but functions marked with the attribute are not const
+// *and* subject to const checking.
+
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![stable(feature = "foo", since = "3.3.3")]
+
+#[const_trait]
+trait Tr {
+ fn a() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs
new file mode 100644
index 000000000..5a0db816a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check-override.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![feature(const_trait_impl, rustc_attrs, effects)]
+
+#[const_trait]
+trait Foo {
+ #[rustc_do_not_const_check]
+ fn into_iter(&self) { println!("FEAR ME!") }
+}
+
+
+impl const Foo for () {
+ fn into_iter(&self) {
+ // ^_^
+ }
+}
+
+const _: () = Foo::into_iter(&());
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check.rs
new file mode 100644
index 000000000..3c39c53de
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/do-not-const-check.rs
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(const_trait_impl, rustc_attrs)]
+
+#[const_trait]
+trait IntoIter {
+ fn into_iter(self);
+}
+
+#[const_trait]
+trait Hmm: Sized {
+ #[rustc_do_not_const_check]
+ fn chain<U>(self, other: U) where U: IntoIter,
+ {
+ other.into_iter()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs
new file mode 100644
index 000000000..a74c50cc8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/auxiliary/cross-crate.rs
@@ -0,0 +1,12 @@
+#![feature(const_trait_impl, effects)]
+
+pub const fn foo() {}
+
+#[const_trait]
+pub trait Bar {
+ fn bar();
+}
+
+impl Bar for () {
+ fn bar() {}
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs
new file mode 100644
index 000000000..6598d1da0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs
@@ -0,0 +1,15 @@
+#![feature(const_closures, const_trait_impl, effects)]
+#![allow(incomplete_features)]
+
+trait Foo {
+ fn foo(&self);
+}
+
+impl Foo for () {
+ fn foo(&self) {}
+}
+
+fn main() {
+ (const || { (()).foo() })();
+ //~^ ERROR: cannot call non-const fn
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr
new file mode 100644
index 000000000..413e21702
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions
+ --> $DIR/const_closure-const_trait_impl-ice-113381.rs:13:22
+ |
+LL | (const || { (()).foo() })();
+ | ^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs
new file mode 100644
index 000000000..e216f6879
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs
@@ -0,0 +1,15 @@
+// Ensure that we don't get a mismatch error when inserting the host param
+// at the end of generic args when the generics have defaulted params.
+//
+// check-pass
+
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+pub trait Foo<Rhs: ?Sized = Self> {
+ /* stuff */
+}
+
+impl const Foo for () {}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs
new file mode 100644
index 000000000..da2778f61
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(effects)]
+
+pub const fn owo() {}
+
+fn main() {
+ // make sure falling back ty/int vars doesn't cause const fallback to be skipped...
+ // See issue: 115791.
+ let _ = 1;
+ if false {
+ let x = panic!();
+ }
+
+ let _ = owo;
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs
new file mode 100644
index 000000000..17f203e15
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+// gate-test-effects
+// ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test
+
+#![feature(const_trait_impl, effects, core_intrinsics, const_eval_select)]
+
+// ensure we are passing in the correct host effect in always const contexts.
+
+pub const fn hmm<T>() -> usize {
+ // FIXME(const_trait_impl): maybe we should have a way to refer to the (hidden) effect param
+ fn one() -> usize { 1 }
+ const fn zero() -> usize { 0 }
+ unsafe {
+ std::intrinsics::const_eval_select((), zero, one)
+ }
+}
+
+const _: () = {
+ let x = hmm::<()>();
+ assert!(0 == x);
+};
+
+pub const fn uwu(x: [u8; hmm::<()>()]) {
+ let [] = x;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs
new file mode 100644
index 000000000..1954d2942
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+// effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds
+
+#![allow(incomplete_features, unused)]
+#![feature(effects, adt_const_params)]
+
+struct Bar<T>(T);
+
+impl<T> Bar<T> {
+ const fn value() -> usize {
+ 42
+ }
+}
+
+struct Foo<const N: [u8; Bar::<u32>::value()]>;
+
+pub fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs
new file mode 100644
index 000000000..2f474d978
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/infer-fallback.rs
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(const_trait_impl, effects)]
+
+const fn a() {}
+
+fn foo<F: FnOnce()>(a: F) {}
+
+fn main() {
+ let _ = a;
+ foo(a);
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
new file mode 100644
index 000000000..59fb48e79
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
@@ -0,0 +1,527 @@
+// check-pass
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs, staged_api)]
+#![feature(fundamental)]
+#![feature(const_trait_impl, effects, const_mut_refs)]
+#![allow(internal_features)]
+#![no_std]
+#![no_core]
+#![stable(feature = "minicore", since = "1.0.0")]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "add"]
+#[const_trait]
+trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl const Add for i32 {
+ type Output = i32;
+ fn add(self, rhs: i32) -> i32 {
+ loop {}
+ }
+}
+
+fn foo() {
+ let x = 42_i32 + 43_i32;
+}
+
+const fn bar() {
+ let x = 42_i32 + 43_i32;
+}
+
+
+#[lang = "Try"]
+#[const_trait]
+trait Try: FromResidual {
+ type Output;
+ type Residual;
+
+ #[lang = "from_output"]
+ fn from_output(output: Self::Output) -> Self;
+
+ #[lang = "branch"]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+}
+
+// FIXME
+// #[const_trait]
+trait FromResidual<R = <Self as Try>::Residual> {
+ #[lang = "from_residual"]
+ fn from_residual(residual: R) -> Self;
+}
+
+enum ControlFlow<B, C = ()> {
+ #[lang = "Continue"]
+ Continue(C),
+ #[lang = "Break"]
+ Break(B),
+}
+
+#[const_trait]
+#[lang = "fn"]
+#[rustc_paren_sugar]
+trait Fn<Args: Tuple>: ~const FnMut<Args> {
+ extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+#[const_trait]
+#[lang = "fn_mut"]
+#[rustc_paren_sugar]
+trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
+ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[const_trait]
+#[lang = "fn_once"]
+#[rustc_paren_sugar]
+trait FnOnce<Args: Tuple> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+struct ConstFnMutClosure<CapturedData, Function> {
+ data: CapturedData,
+ func: Function,
+}
+
+#[lang = "tuple_trait"]
+trait Tuple {}
+
+macro_rules! impl_fn_mut_tuple {
+ ($($var:ident)*) => {
+ impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
+ FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
+ where
+ Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue,
+ Function: ~const Destruct,
+ {
+ type Output = ClosureReturnValue;
+
+ extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
+ self.call_mut(args)
+ }
+ }
+ impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
+ FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
+ where
+ Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
+ Function: ~const Destruct,
+ {
+ extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
+ #[allow(non_snake_case)]
+ let ($($var),*) = &mut self.data;
+ (self.func)(($($var),*), args)
+ }
+ }
+ };
+}
+//impl_fn_mut_tuple!(A);
+//impl_fn_mut_tuple!(A B);
+//impl_fn_mut_tuple!(A B C);
+//impl_fn_mut_tuple!(A B C D);
+//impl_fn_mut_tuple!(A B C D E);
+
+#[lang = "receiver"]
+trait Receiver {}
+
+impl<T: ?Sized> Receiver for &T {}
+
+impl<T: ?Sized> Receiver for &mut T {}
+
+#[lang = "destruct"]
+#[const_trait]
+trait Destruct {}
+
+#[lang = "freeze"]
+unsafe auto trait Freeze {}
+
+#[lang = "drop"]
+#[const_trait]
+trait Drop {
+ fn drop(&mut self);
+}
+
+/*
+#[const_trait]
+trait Residual<O> {
+ type TryType: ~const Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>;
+}
+*/
+
+const fn size_of<T>() -> usize {
+ 42
+}
+
+impl Copy for u8 {}
+
+impl usize {
+ #[rustc_allow_incoherent_impl]
+ const fn repeat_u8(x: u8) -> usize {
+ usize::from_ne_bytes([x; size_of::<usize>()])
+ }
+ #[rustc_allow_incoherent_impl]
+ const fn from_ne_bytes(bytes: [u8; size_of::<Self>()]) -> Self {
+ loop {}
+ }
+}
+
+#[rustc_do_not_const_check] // hooked by const-eval
+const fn panic_display() {
+ panic_fmt();
+}
+
+fn panic_fmt() {}
+
+#[lang = "index"]
+#[const_trait]
+trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+
+#[const_trait]
+unsafe trait SliceIndex<T: ?Sized> {
+ type Output: ?Sized;
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+impl<T, I> const Index<I> for [T]
+where
+ I: ~const SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ #[inline]
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+/* FIXME
+impl<T, I, const N: usize> const Index<I> for [T; N]
+where
+ [T]: ~const Index<I>,
+{
+ type Output = <[T] as Index<I>>::Output;
+
+ #[inline]
+ // FIXME: make `Self::Output` act like `<Self as ~const Index<I>>::Output`
+ fn index(&self, index: I) -> &<[T] as Index<I>>::Output {
+ Index::index(self as &[T], index)
+ }
+}
+*/
+
+#[lang = "unsize"]
+trait Unsize<T: ?Sized> {
+}
+
+#[lang = "coerce_unsized"]
+trait CoerceUnsized<T: ?Sized> {
+}
+
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+
+
+#[lang = "deref"]
+// #[const_trait] FIXME
+trait Deref {
+ #[lang = "deref_target"]
+ type Target: ?Sized;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+
+impl<T: ?Sized> /* const */ Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ *self
+ }
+}
+
+impl<T: ?Sized> /* const */ Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ *self
+ }
+}
+
+enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+}
+
+impl<T> Option<T> {
+ const fn as_ref(&self) -> Option<&T> {
+ match *self {
+ Some(ref x) => Some(x),
+ None => None,
+ }
+ }
+
+ const fn as_mut(&mut self) -> Option<&mut T> {
+ match *self {
+ Some(ref mut x) => Some(x),
+ None => None,
+ }
+ }
+}
+
+use Option::*;
+
+/*
+const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target>
+where
+ T: ~const Deref,
+{
+ match opt {
+ Option::Some(t) => Option::Some(t.deref()),
+ Option::None => Option::None,
+ }
+}
+*/
+
+#[const_trait]
+trait Into<T>: Sized {
+ fn into(self) -> T;
+}
+
+#[const_trait]
+trait From<T>: Sized {
+ fn from(value: T) -> Self;
+}
+
+impl<T, U> const Into<U> for T
+where
+ U: ~const From<T>,
+{
+ fn into(self) -> U {
+ U::from(self)
+ }
+}
+
+impl<T> const From<T> for T {
+ fn from(t: T) -> T {
+ t
+ }
+}
+
+enum Result<T, E> {
+ Ok(T),
+ Err(E),
+}
+use Result::*;
+
+fn from_str(s: &str) -> Result<bool, ()> {
+ match s {
+ "true" => Ok(true),
+ "false" => Ok(false),
+ _ => Err(()),
+ }
+}
+
+#[lang = "eq"]
+#[const_trait]
+trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+}
+
+impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A
+where
+ A: ~const PartialEq<B>,
+{
+ fn eq(&self, other: &&B) -> bool {
+ PartialEq::eq(*self, *other)
+ }
+}
+
+impl PartialEq for str {
+ fn eq(&self, other: &str) -> bool {
+ loop {}
+ }
+}
+
+
+#[lang = "not"]
+#[const_trait]
+trait Not {
+ type Output;
+ fn not(self) -> Self::Output;
+}
+
+impl const Not for bool {
+ type Output = bool;
+ fn not(self) -> bool {
+ !self
+ }
+}
+
+impl Copy for bool {}
+impl<'a> Copy for &'a str {}
+
+#[lang = "pin"]
+#[fundamental]
+#[repr(transparent)]
+struct Pin<P> {
+ pointer: P,
+}
+
+impl<P> Pin<P> {
+ #[lang = "new_unchecked"]
+ const unsafe fn new_unchecked(pointer: P) -> Pin<P> {
+ Pin { pointer }
+ }
+}
+
+impl<'a, T: ?Sized> Pin<&'a T> {
+ const fn get_ref(self) -> &'a T {
+ self.pointer
+ }
+}
+
+
+impl<P: Deref> Pin<P> {
+ /* const */ fn as_ref(&self) -> Pin<&P::Target>
+ where
+ P: /* ~const */ Deref,
+ {
+ unsafe { Pin::new_unchecked(&*self.pointer) }
+ }
+}
+
+
+impl<'a, T: ?Sized> Pin<&'a mut T> {
+ const unsafe fn get_unchecked_mut(self) -> &'a mut T {
+ self.pointer
+ }
+}
+/* FIXME lol
+impl<T> Option<T> {
+ const fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
+ match Pin::get_ref(self).as_ref() {
+ Some(x) => unsafe { Some(Pin::new_unchecked(x)) },
+ None => None,
+ }
+ }
+
+ const fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
+ unsafe {
+ match Pin::get_unchecked_mut(self).as_mut() {
+ Some(x) => Some(Pin::new_unchecked(x)),
+ None => None,
+ }
+ }
+ }
+}
+*/
+
+impl<P: /* ~const */ Deref> /* const */ Deref for Pin<P> {
+ type Target = P::Target;
+ fn deref(&self) -> &P::Target {
+ Pin::get_ref(Pin::as_ref(self))
+ }
+}
+
+impl<T> /* const */ Deref for Option<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ loop {}
+ }
+}
+
+impl<P: Receiver> Receiver for Pin<P> {}
+
+impl<T: Clone> Clone for RefCell<T> {
+ fn clone(&self) -> RefCell<T> {
+ RefCell::new(self.borrow().clone())
+ }
+}
+
+struct RefCell<T: ?Sized> {
+ borrow: UnsafeCell<()>,
+ value: UnsafeCell<T>,
+}
+impl<T> RefCell<T> {
+ const fn new(value: T) -> RefCell<T> {
+ loop {}
+ }
+}
+impl<T: ?Sized> RefCell<T> {
+ fn borrow(&self) -> Ref<'_, T> {
+ loop {}
+ }
+}
+
+#[lang = "unsafe_cell"]
+#[repr(transparent)]
+struct UnsafeCell<T: ?Sized> {
+ value: T,
+}
+
+struct Ref<'b, T: ?Sized + 'b> {
+ value: *const T,
+ borrow: &'b UnsafeCell<()>,
+}
+
+impl<T: ?Sized> Deref for Ref<'_, T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ loop {}
+ }
+}
+
+#[lang = "clone"]
+#[rustc_trivial_field_reads]
+#[const_trait]
+trait Clone: Sized {
+ fn clone(&self) -> Self;
+ fn clone_from(&mut self, source: &Self)
+ where
+ Self: ~const Destruct,
+ {
+ *self = source.clone()
+ }
+}
+
+#[lang = "structural_peq"]
+trait StructuralPartialEq {}
+
+#[lang = "structural_teq"]
+trait StructuralEq {}
+
+const fn drop<T: ~const Destruct>(_: T) {}
+
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_eval_select", since = "1.0.0")]
+ fn const_eval_select<ARG: Tuple, F, G, RET>(
+ arg: ARG,
+ called_in_const: F,
+ called_at_rt: G,
+ ) -> RET
+ /* where clauses enforced by built-in method confirmation:
+ where
+ F: const FnOnce<Arg, Output = RET>,
+ G: FnOnce<Arg, Output = RET>,
+ */;
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.rs
new file mode 100644
index 000000000..8e4850197
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.rs
@@ -0,0 +1,18 @@
+// aux-build: cross-crate.rs
+extern crate cross_crate;
+
+use cross_crate::{Bar, foo};
+
+fn main() {
+ foo::<true>();
+ //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
+ <() as Bar<true>>::bar();
+ //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
+}
+
+const FOO: () = {
+ foo::<false>();
+ //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
+ <() as Bar<false>>::bar();
+ //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
+};
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr
new file mode 100644
index 000000000..cc870ad33
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params-cross-crate.stderr
@@ -0,0 +1,59 @@
+error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params-cross-crate.rs:14:5
+ |
+LL | foo::<false>();
+ | ^^^--------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: function defined here, with 0 generic parameters
+ --> $DIR/auxiliary/cross-crate.rs:3:14
+ |
+LL | pub const fn foo() {}
+ | ^^^
+
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params-cross-crate.rs:16:12
+ |
+LL | <() as Bar<false>>::bar();
+ | ^^^------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/auxiliary/cross-crate.rs:6:11
+ |
+LL | pub trait Bar {
+ | ^^^
+
+error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params-cross-crate.rs:7:5
+ |
+LL | foo::<true>();
+ | ^^^-------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: function defined here, with 0 generic parameters
+ --> $DIR/auxiliary/cross-crate.rs:3:14
+ |
+LL | pub const fn foo() {}
+ | ^^^
+
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params-cross-crate.rs:9:12
+ |
+LL | <() as Bar<true>>::bar();
+ | ^^^------ help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/auxiliary/cross-crate.rs:6:11
+ |
+LL | pub trait Bar {
+ | ^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs
new file mode 100644
index 000000000..929da1ca8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.rs
@@ -0,0 +1,27 @@
+#![feature(const_trait_impl, effects)]
+
+const fn foo() {}
+
+#[const_trait]
+trait Bar {
+ fn bar();
+}
+
+impl Bar for () {
+ fn bar() {}
+}
+
+fn main() {
+ foo::<true>();
+ //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
+ <() as Bar<true>>::bar();
+ //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
+}
+
+const FOO: () = {
+ foo::<false>();
+ //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
+ <() as Bar<false>>::bar();
+ //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
+ //~| ERROR: mismatched types
+};
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr
new file mode 100644
index 000000000..0745d0304
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/no-explicit-const-params.stderr
@@ -0,0 +1,69 @@
+error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params.rs:22:5
+ |
+LL | foo::<false>();
+ | ^^^--------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: function defined here, with 0 generic parameters
+ --> $DIR/no-explicit-const-params.rs:3:10
+ |
+LL | const fn foo() {}
+ | ^^^
+
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params.rs:24:12
+ |
+LL | <() as Bar<false>>::bar();
+ | ^^^------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/no-explicit-const-params.rs:6:7
+ |
+LL | trait Bar {
+ | ^^^
+
+error[E0308]: mismatched types
+ --> $DIR/no-explicit-const-params.rs:24:5
+ |
+LL | <() as Bar<false>>::bar();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `false`, found `true`
+ |
+ = note: expected constant `false`
+ found constant `true`
+
+error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params.rs:15:5
+ |
+LL | foo::<true>();
+ | ^^^-------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: function defined here, with 0 generic parameters
+ --> $DIR/no-explicit-const-params.rs:3:10
+ |
+LL | const fn foo() {}
+ | ^^^
+
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/no-explicit-const-params.rs:17:12
+ |
+LL | <() as Bar<true>>::bar();
+ | ^^^------ help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/no-explicit-const-params.rs:6:7
+ |
+LL | trait Bar {
+ | ^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0107, E0308.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs
new file mode 100644
index 000000000..b30d7743e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(const_trait_impl, effects)]
+
+pub trait Owo<X = <Self as Uwu>::T> {}
+
+#[const_trait]
+pub trait Uwu: Owo {
+ type T;
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr
new file mode 100644
index 000000000..663cdd1fe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+ --> $DIR/feature-gate.rs:14:1
+ |
+LL | fn main() {}
+ | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs
new file mode 100644
index 000000000..0b409fbaa
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs
@@ -0,0 +1,14 @@
+// revisions: stock gated
+// gate-test-const_trait_impl
+
+#![cfg_attr(gated, feature(const_trait_impl))]
+#![feature(rustc_attrs)]
+
+struct S;
+#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder
+trait T {}
+impl const T for S {}
+//[stock]~^ ERROR const trait impls are experimental
+
+#[rustc_error]
+fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr
new file mode 100644
index 000000000..0e938c1c5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr
@@ -0,0 +1,21 @@
+error[E0658]: const trait impls are experimental
+ --> $DIR/feature-gate.rs:10:6
+ |
+LL | impl const T for S {}
+ | ^^^^^
+ |
+ = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
+ --> $DIR/feature-gate.rs:8:1
+ |
+LL | #[const_trait]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs
new file mode 100644
index 000000000..60790e297
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs
@@ -0,0 +1,15 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait Test {}
+
+impl Test for () {}
+
+pub const fn test<T: ~const Test>() {}
+
+pub const fn min_by_i32() -> fn() {
+ test::<()>
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/gate.rs
new file mode 100644
index 000000000..d1c93ab9f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/gate.rs
@@ -0,0 +1,13 @@
+// gate-test-const_closures
+
+fn main() {
+ (const || {})();
+ //~^ ERROR: const closures are experimental
+}
+
+macro_rules! e {
+ ($e:expr) => {}
+}
+
+e!((const || {}));
+//~^ ERROR const closures are experimental
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/gate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/gate.stderr
new file mode 100644
index 000000000..11cc2cd56
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/gate.stderr
@@ -0,0 +1,21 @@
+error[E0658]: const closures are experimental
+ --> $DIR/gate.rs:4:6
+ |
+LL | (const || {})();
+ | ^^^^^
+ |
+ = note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information
+ = help: add `#![feature(const_closures)]` to the crate attributes to enable
+
+error[E0658]: const closures are experimental
+ --> $DIR/gate.rs:12:5
+ |
+LL | e!((const || {}));
+ | ^^^^^
+ |
+ = note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information
+ = help: add `#![feature(const_closures)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.rs
new file mode 100644
index 000000000..d665c4479
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.rs
@@ -0,0 +1,30 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+use std::marker::PhantomData;
+
+struct S<T>(PhantomData<T>);
+
+impl<T> Copy for S<T> {}
+impl<T> Clone for S<T> {
+ fn clone(&self) -> Self {
+ S(PhantomData)
+ }
+}
+
+impl<T> const std::ops::Add for S<T> {
+ type Output = Self;
+
+ fn add(self, _: Self) -> Self {
+ S(std::marker::PhantomData)
+ }
+}
+
+const fn twice<T: std::ops::Add>(arg: S<T>) -> S<T> {
+ arg + arg
+}
+
+fn main() {
+ let _ = twice(S(PhantomData::<i32>));
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr
new file mode 100644
index 000000000..1e8a70ffd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr
@@ -0,0 +1,16 @@
+error[E0015]: cannot call non-const operator in constant functions
+ --> $DIR/generic-bound.rs:25:5
+ |
+LL | arg + arg
+ | ^^^^^^^^^
+ |
+note: impl defined here, but it is not `const`
+ --> $DIR/generic-bound.rs:16:1
+ |
+LL | impl<T> const std::ops::Add for S<T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs
new file mode 100644
index 000000000..426534deb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.rs
@@ -0,0 +1,17 @@
+// Regression test for #69615.
+
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+pub trait MyTrait {
+ fn method(&self) -> Option<()>;
+}
+
+impl const MyTrait for () {
+ fn method(&self) -> Option<()> {
+ Some(())?; //~ ERROR `?` is not allowed in a `const fn`
+ None
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr
new file mode 100644
index 000000000..90f30ea63
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `?` is not allowed in a `const fn`
+ --> $DIR/hir-const-check.rs:12:9
+ |
+LL | Some(())?;
+ | ^^^^^^^^^
+ |
+ = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
+ = help: add `#![feature(const_try)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs
new file mode 100644
index 000000000..05b26465c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+struct S;
+trait T {}
+
+impl ~const T for S {}
+//~^ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr
new file mode 100644
index 000000000..4695728f8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+ --> $DIR/impl-tilde-const-trait.rs:6:6
+ |
+LL | impl ~const T for S {}
+ | ^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
new file mode 100644
index 000000000..6df9696f2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
@@ -0,0 +1,17 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+ fn req(&self);
+
+ fn default() {}
+}
+
+struct S;
+
+impl const Tr for u16 {
+ fn default() {}
+} //~^^ ERROR not all trait items implemented
+
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
new file mode 100644
index 000000000..36c8163f1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `req`
+ --> $DIR/impl-with-default-fn-fail.rs:12:1
+ |
+LL | fn req(&self);
+ | -------------- `req` from trait
+...
+LL | impl const Tr for u16 {
+ | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
new file mode 100644
index 000000000..ae81421e9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+ fn req(&self);
+
+ fn default() {}
+}
+
+impl const Tr for u8 {
+ fn req(&self) {}
+}
+
+macro_rules! impl_tr {
+ ($ty: ty) => {
+ impl const Tr for $ty {
+ fn req(&self) {}
+ }
+ }
+}
+
+impl_tr!(u64);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
new file mode 100644
index 000000000..f8ac793e4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
@@ -0,0 +1,22 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+struct S;
+
+#[const_trait]
+trait A {}
+#[const_trait]
+trait B {}
+
+impl const A for S {}
+impl const B for S {}
+
+impl S {
+ const fn a<T: ~const A>() where T: ~const B {
+
+ }
+}
+
+const _: () = S::a::<S>();
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.rs
new file mode 100644
index 000000000..afd0d137b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.rs
@@ -0,0 +1,13 @@
+#![feature(const_trait_impl)]
+#![allow(bare_trait_objects)]
+
+struct S;
+trait T {}
+
+impl const S {}
+//~^ ERROR inherent impls cannot be `const`
+
+impl const T {}
+//~^ ERROR inherent impls cannot be `const`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.stderr
new file mode 100644
index 000000000..8c5562703
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/inherent-impl.stderr
@@ -0,0 +1,22 @@
+error: inherent impls cannot be `const`
+ --> $DIR/inherent-impl.rs:7:12
+ |
+LL | impl const S {}
+ | ----- ^ inherent impl for this type
+ | |
+ | `const` because of this
+ |
+ = note: only trait implementations may be annotated with `const`
+
+error: inherent impls cannot be `const`
+ --> $DIR/inherent-impl.rs:10:12
+ |
+LL | impl const T {}
+ | ----- ^ inherent impl for this type
+ | |
+ | `const` because of this
+ |
+ = note: only trait implementations may be annotated with `const`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs
new file mode 100644
index 000000000..9f3f38ad4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs
@@ -0,0 +1,39 @@
+// revisions: nn ny yn yy
+// check-pass
+#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)]
+
+#[cfg_attr(any(yn, yy), const_trait)]
+pub trait Index {
+ type Output;
+}
+
+#[cfg_attr(any(ny, yy), const_trait)]
+pub trait IndexMut where Self: Index {
+ const C: <Self as Index>::Output;
+ type Assoc = <Self as Index>::Output;
+ fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output;
+}
+
+impl Index for () { type Output = (); }
+
+#[cfg(not(any(nn, yn)))]
+impl const IndexMut for <() as Index>::Output {
+ const C: <Self as Index>::Output = ();
+ type Assoc = <Self as Index>::Output;
+ fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+ where <Self as Index>::Output:,
+ {}
+}
+
+#[cfg(any(nn, yn))]
+impl IndexMut for <() as Index>::Output {
+ const C: <Self as Index>::Output = ();
+ type Assoc = <Self as Index>::Output;
+ fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+ where <Self as Index>::Output:,
+ {}
+}
+
+const C: <() as Index>::Output = ();
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.rs
new file mode 100644
index 000000000..fe4e91081
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.rs
@@ -0,0 +1,15 @@
+#![feature(allocator_api)]
+#![feature(const_trait_impl)]
+
+use core::convert::{From, TryFrom};
+//~^ ERROR
+//~| ERROR
+
+use std::pin::Pin;
+use std::alloc::Allocator;
+impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>>
+where
+ A: 'static,
+{}
+
+pub fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr
new file mode 100644
index 000000000..c331236a4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -0,0 +1,23 @@
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+ --> $DIR/issue-102156.rs:4:5
+ |
+LL | use core::convert::{From, TryFrom};
+ | ^^^^
+ | |
+ | maybe a missing crate `core`?
+ | help: try using `std` instead of `core`: `std`
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+ --> $DIR/issue-102156.rs:4:5
+ |
+LL | use core::convert::{From, TryFrom};
+ | ^^^^
+ | |
+ | maybe a missing crate `core`?
+ | help: try using `std` instead of `core`: `std`
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs
new file mode 100644
index 000000000..df242721b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs
@@ -0,0 +1,13 @@
+// known-bug: #110395
+#![feature(const_trait_impl)]
+
+struct Bug {
+ inner: [(); match || 1 {
+ n => n(),
+ //FIXME ~^ ERROR the trait bound
+ //FIXME ~| ERROR the trait bound
+ //FIXME ~| ERROR cannot call non-const closure in constants
+ }],
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr
new file mode 100644
index 000000000..077f6c7b2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const closure in constants
+ --> $DIR/issue-102985.rs:6:14
+ |
+LL | n => n(),
+ | ^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-103677.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-103677.rs
new file mode 100644
index 000000000..d81724a36
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-103677.rs
@@ -0,0 +1,5 @@
+// check-pass
+
+const _: fn(&String) = |s| { &*s as &str; };
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs
new file mode 100644
index 000000000..b604c65d7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs
@@ -0,0 +1,20 @@
+#![feature(const_fmt_arguments_new)]
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Tr {
+ fn req(&self);
+
+ fn prov(&self) {
+ println!("lul"); //~ ERROR: cannot call non-const fn `_print` in constant functions
+ self.req();
+ }
+}
+
+struct S;
+
+impl const Tr for S {
+ fn req(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr
new file mode 100644
index 000000000..85996c212
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr
@@ -0,0 +1,12 @@
+error[E0015]: cannot call non-const fn `_print` in constant functions
+ --> $DIR/issue-79450.rs:9:9
+ |
+LL | println!("lul");
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs
new file mode 100644
index 000000000..5127ec069
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs
@@ -0,0 +1,15 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+pub trait A {
+ fn assoc() -> bool;
+}
+
+pub const fn foo<T: A>() -> bool {
+ T::assoc()
+ //FIXME ~^ ERROR the trait bound
+ //FIXME ~| ERROR cannot call non-const fn
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr
new file mode 100644
index 000000000..157b54214
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
+ --> $DIR/issue-88155.rs:10:5
+ |
+LL | T::assoc()
+ | ^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs
new file mode 100644
index 000000000..fdb422201
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs
@@ -0,0 +1,24 @@
+// Regression test for #92111.
+//
+// known-bug: #110395
+// FIXME check-pass
+
+#![feature(const_trait_impl)]
+
+use std::marker::Destruct;
+
+pub trait Tr {}
+
+#[allow(drop_bounds)]
+impl<T: Drop> Tr for T {}
+
+#[derive(Debug)]
+pub struct S(i32);
+
+impl Tr for S {}
+
+const fn a<T: ~const Destruct>(t: T) {}
+
+fn main() {
+ a(S(0));
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr
new file mode 100644
index 000000000..2edaca606
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr
@@ -0,0 +1,11 @@
+error[E0493]: destructor of `T` cannot be evaluated at compile-time
+ --> $DIR/issue-92111.rs:20:32
+ |
+LL | const fn a<T: ~const Destruct>(t: T) {}
+ | ^ - value is dropped here
+ | |
+ | the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
new file mode 100644
index 000000000..4d3469653
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
@@ -0,0 +1,15 @@
+// Regression test for #92230.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+pub trait Super {}
+#[const_trait]
+pub trait Sub: Super {}
+
+impl<A> const Super for &A where A: ~const Super {}
+impl<A> const Sub for &A where A: ~const Sub {}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr
new file mode 100644
index 000000000..89e59e5db
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr
@@ -0,0 +1,12 @@
+error[E0015]: cannot match on `str` in constant functions
+ --> $DIR/match-non-const-eq.rs:7:9
+ |
+LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts
+ | ^^^
+ |
+ = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs
new file mode 100644
index 000000000..d06d0d6dd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs
@@ -0,0 +1,13 @@
+// known-bug: #110395
+// revisions: stock gated
+#![cfg_attr(gated, feature(const_trait_impl))]
+
+const fn foo(input: &'static str) {
+ match input {
+ "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts
+ //FIXME ~^ ERROR cannot match on `str` in constant functions
+ _ => (),
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr
new file mode 100644
index 000000000..5431116a1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr
@@ -0,0 +1,13 @@
+error[E0015]: cannot match on `str` in constant functions
+ --> $DIR/match-non-const-eq.rs:7:9
+ |
+LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts
+ | ^^^
+ |
+ = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs
new file mode 100644
index 000000000..0b423b340
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(const_trait_impl, lazy_cell)]
+
+use std::sync::LazyLock;
+
+static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| {
+ let x = || String::new();
+ x()
+});
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs
new file mode 100644
index 000000000..cd8bb5963
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs
@@ -0,0 +1,15 @@
+#![feature(const_closures, const_trait_impl)]
+#![allow(incomplete_features)]
+
+trait Foo {
+ fn foo(&self);
+}
+
+impl Foo for () {
+ fn foo(&self) {}
+}
+
+fn main() {
+ (const || { (()).foo() })();
+ //~^ ERROR: cannot call non-const fn
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr
new file mode 100644
index 000000000..97ad83130
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions
+ --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:22
+ |
+LL | (const || { (()).foo() })();
+ | ^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
new file mode 100644
index 000000000..dff8a2444
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
@@ -0,0 +1,18 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Convert<T> {
+ fn to(self) -> T;
+}
+
+impl<A, B> const Convert<B> for A where B: ~const From<A> {
+ fn to(self) -> B {
+ B::from(self)
+ }
+}
+
+const FOO: fn() -> String = || "foo".to();
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr
new file mode 100644
index 000000000..b2e09d82a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/non-const-op-in-closure-in-const.rs:10:51
+ |
+LL | impl<A, B> const Convert<B> for A where B: ~const From<A> {
+ | ^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs
new file mode 100644
index 000000000..234b0dd00
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs
@@ -0,0 +1,56 @@
+// Tests that trait bounds on specializing trait impls must be `~const` if the
+// same bound is present on the default impl and is `~const` there.
+// check-pass
+// FIXME(effects) ^ should error
+
+#![feature(const_trait_impl)]
+#![feature(rustc_attrs)]
+#![feature(min_specialization)]
+
+#[rustc_specialization_trait]
+trait Specialize {}
+
+#[const_trait]
+trait Foo {}
+
+#[const_trait]
+trait Bar {
+ fn bar();
+}
+
+impl<T> const Bar for T
+where
+ T: ~const Foo,
+{
+ default fn bar() {}
+}
+
+impl<T> Bar for T
+where
+ T: Foo, //FIXME ~ ERROR missing `~const` qualifier
+ T: Specialize,
+{
+ fn bar() {}
+}
+
+#[const_trait]
+trait Baz {
+ fn baz();
+}
+
+impl<T> const Baz for T
+where
+ T: ~const Foo,
+{
+ default fn baz() {}
+}
+
+impl<T> const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz`
+where
+ T: Foo,
+ T: Specialize,
+{
+ fn baz() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs
new file mode 100644
index 000000000..b6cb24d15
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs
@@ -0,0 +1,39 @@
+// Tests that a const default trait impl can be specialized by another const
+// trait impl and that the specializing impl will be used during const-eval.
+
+// run-pass
+
+#![feature(const_trait_impl, effects)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Value {
+ fn value() -> u32;
+}
+
+const fn get_value<T: ~const Value>() -> u32 {
+ T::value()
+}
+
+impl<T> const Value for T {
+ default fn value() -> u32 {
+ 0
+ }
+}
+
+struct FortyTwo;
+
+impl const Value for FortyTwo {
+ fn value() -> u32 {
+ 42
+ }
+}
+
+const ZERO: u32 = get_value::<()>();
+
+const FORTY_TWO: u32 = get_value::<FortyTwo>();
+
+fn main() {
+ assert_eq!(ZERO, 0);
+ assert_eq!(FORTY_TWO, 42);
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs
new file mode 100644
index 000000000..9a93d01ed
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs
@@ -0,0 +1,26 @@
+// Tests that specializing trait impls must be at least as const as the default impl.
+
+#![feature(const_trait_impl, effects)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Value {
+ fn value() -> u32;
+}
+
+impl<T> const Value for T {
+ default fn value() -> u32 {
+ 0
+ }
+}
+
+struct FortyTwo;
+
+impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl
+ fn value() -> u32 {
+ println!("You can't do that (constly)");
+ 42
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr
new file mode 100644
index 000000000..e356621ba
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on const impl with non-const impl
+ --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1
+ |
+LL | impl Value for FortyTwo {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs
new file mode 100644
index 000000000..2aac0a2b4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Foo {
+ fn foo();
+}
+
+impl const Foo for u32 {
+ default fn foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs
new file mode 100644
index 000000000..92d8be6bb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs
@@ -0,0 +1,49 @@
+// Tests that `~const` trait bounds can be used to specialize const trait impls.
+
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(rustc_attrs)]
+#![feature(min_specialization)]
+
+#[const_trait]
+#[rustc_specialization_trait]
+trait Specialize {}
+
+#[const_trait]
+trait Foo {
+ fn foo();
+}
+
+impl<T> const Foo for T {
+ default fn foo() {}
+}
+
+impl<T> const Foo for T
+where
+ T: ~const Specialize,
+{
+ fn foo() {}
+}
+
+#[const_trait]
+trait Bar {
+ fn bar() {}
+}
+
+impl<T> const Bar for T
+where
+ T: ~const Foo,
+{
+ default fn bar() {}
+}
+
+impl<T> const Bar for T
+where
+ T: ~const Foo,
+ T: ~const Specialize,
+{
+ fn bar() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs
new file mode 100644
index 000000000..51bfaf73b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs
@@ -0,0 +1,57 @@
+// Tests that `T: ~const Foo` in a specializing impl is treated as equivalent to
+// `T: Foo` in the default impl for the purposes of specialization (i.e., it
+// does not think that the user is attempting to specialize on trait `Foo`).
+
+// check-pass
+
+#![feature(rustc_attrs)]
+#![feature(min_specialization)]
+#![feature(const_trait_impl)]
+
+#[rustc_specialization_trait]
+trait Specialize {}
+
+#[const_trait]
+trait Foo {}
+
+#[const_trait]
+trait Bar {
+ fn bar();
+}
+
+impl<T> Bar for T
+where
+ T: Foo,
+{
+ default fn bar() {}
+}
+
+impl<T> const Bar for T
+where
+ T: ~const Foo,
+ T: Specialize,
+{
+ fn bar() {}
+}
+
+#[const_trait]
+trait Baz {
+ fn baz();
+}
+
+impl<T> const Baz for T
+where
+ T: Foo,
+{
+ default fn baz() {}
+}
+
+impl<T> const Baz for T
+where
+ T: ~const Foo,
+ T: Specialize,
+{
+ fn baz() {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs
new file mode 100644
index 000000000..84c7926f4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs
@@ -0,0 +1,39 @@
+// Tests that a non-const default impl can be specialized by a const trait impl,
+// but that the default impl cannot be used in a const context.
+// known-bug: #110395
+// FIXME run-pass
+
+#![feature(const_trait_impl, effects)]
+#![feature(min_specialization)]
+
+#[const_trait]
+trait Value {
+ fn value() -> u32;
+}
+
+const fn get_value<T: ~const Value>() -> u32 {
+ T::value()
+}
+
+impl<T> Value for T {
+ default fn value() -> u32 {
+ println!("You can't do that (constly)");
+ 0
+ }
+}
+
+struct FortyTwo;
+
+impl const Value for FortyTwo {
+ fn value() -> u32 {
+ 42
+ }
+}
+
+fn main() {
+ let zero = get_value::<()>();
+ assert_eq!(zero, 0);
+
+ const FORTY_TWO: u32 = get_value::<FortyTwo>();
+ assert_eq!(FORTY_TWO, 42);
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr
new file mode 100644
index 000000000..68eac990a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
+ --> $DIR/non-const-default-const-specialized.rs:27:1
+ |
+LL | impl<T> Value for T {
+ | ------------------- first implementation here
+...
+LL | impl const Value for FortyTwo {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs
new file mode 100644
index 000000000..ada475909
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs
@@ -0,0 +1,31 @@
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+// known-bug: #110395
+#[rustc_specialization_trait]
+#[const_trait]
+pub trait Sup {}
+
+impl const Sup for () {}
+
+#[const_trait]
+pub trait A {
+ fn a() -> u32;
+}
+
+impl<T: Default> A for T {
+ default fn a() -> u32 {
+ 2
+ }
+}
+
+impl<T: Default + ~const Sup> const A for T {
+ fn a() -> u32 {
+ 3
+ }
+}
+
+const fn generic<T: Default>() {
+ <T as A>::a();
+ //FIXME ~^ ERROR: the trait bound `T: ~const Sup` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr
new file mode 100644
index 000000000..0b35feddc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
+ --> $DIR/specializing-constness-2.rs:27:5
+ |
+LL | <T as A>::a();
+ | ^^^^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs
new file mode 100644
index 000000000..7206a89e5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs
@@ -0,0 +1,31 @@
+#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub trait Sup {}
+
+impl const Sup for () {}
+
+#[const_trait]
+pub trait A {
+ fn a() -> u32;
+}
+
+#[const_trait]
+pub trait Spec {}
+
+impl<T: ~const Spec> const A for T {
+ default fn a() -> u32 {
+ 2
+ }
+}
+
+impl<T: Spec + Sup> A for T {
+//~^ ERROR: cannot specialize
+//FIXME(effects) ~| ERROR: missing `~const` qualifier
+ fn a() -> u32 {
+ 3
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr
new file mode 100644
index 000000000..21e21c2cb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on const impl with non-const impl
+ --> $DIR/specializing-constness.rs:23:1
+ |
+LL | impl<T: Spec + Sup> A for T {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.rs
new file mode 100644
index 000000000..fc0d82727
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.rs
@@ -0,0 +1,16 @@
+// aux-build: staged-api.rs
+extern crate staged_api;
+
+use staged_api::*;
+
+// Const stability has no impact on usage in non-const contexts.
+fn non_const_context() {
+ Unstable::func();
+}
+
+const fn stable_const_context() {
+ Unstable::func();
+ //~^ ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr
new file mode 100644
index 000000000..1346c4c4a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr
@@ -0,0 +1,12 @@
+error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
+ --> $DIR/staged-api-user-crate.rs:12:5
+ |
+LL | Unstable::func();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs
new file mode 100644
index 000000000..b3977e6ce
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs
@@ -0,0 +1,63 @@
+// revisions: stable unstable
+
+#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file.
+#![feature(const_trait_impl, effects)]
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// aux-build: staged-api.rs
+extern crate staged_api;
+
+use staged_api::*;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Foo;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
+#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))]
+impl const MyTrait for Foo {
+ //[stable]~^ ERROR trait implementations cannot be const stable yet
+ fn func() {}
+}
+
+// Const stability has no impact on usage in non-const contexts.
+fn non_const_context() {
+ Unstable::func();
+ Foo::func();
+}
+
+#[unstable(feature = "none", issue = "none")]
+const fn const_context() {
+ Unstable::func();
+ // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+ // not const-stable.
+ Foo::func();
+ //[unstable]~^ ERROR not yet stable as a const fn
+ // ^ fails, because the `foo` feature is not active
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
+pub const fn const_context_not_const_stable() {
+ //[stable]~^ ERROR function has missing const stability attribute
+ Unstable::func();
+ // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+ // not const-stable.
+ Foo::func();
+ //[unstable]~^ ERROR not yet stable as a const fn
+ // ^ fails, because the `foo` feature is not active
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "cheese", since = "1.0.0")]
+const fn stable_const_context() {
+ Unstable::func();
+ //[unstable]~^ ERROR not yet stable as a const fn
+ Foo::func();
+ //[unstable]~^ ERROR not yet stable as a const fn
+ const_context_not_const_stable()
+ //[unstable]~^ ERROR not yet stable as a const fn
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr
new file mode 100644
index 000000000..a1aca762e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr
@@ -0,0 +1,25 @@
+error: trait implementations cannot be const stable yet
+ --> $DIR/staged-api.rs:19:1
+ |
+LL | / impl const MyTrait for Foo {
+LL | |
+LL | | fn func() {}
+LL | | }
+ | |_^
+ |
+ = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+
+error: function has missing const stability attribute
+ --> $DIR/staged-api.rs:42:1
+ |
+LL | / pub const fn const_context_not_const_stable() {
+LL | |
+LL | | Unstable::func();
+LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is
+... |
+LL | | // ^ fails, because the `foo` feature is not active
+LL | | }
+ | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr
new file mode 100644
index 000000000..c38d1a81a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr
@@ -0,0 +1,42 @@
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+ --> $DIR/staged-api.rs:35:5
+ |
+LL | Foo::func();
+ | ^^^^^^^^^^^
+ |
+ = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+ --> $DIR/staged-api.rs:47:5
+ |
+LL | Foo::func();
+ | ^^^^^^^^^^^
+ |
+ = help: add `#![feature(foo)]` to the crate attributes to enable
+
+error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
+ --> $DIR/staged-api.rs:55:5
+ |
+LL | Unstable::func();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: const-stable functions can only call other const-stable functions
+
+error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
+ --> $DIR/staged-api.rs:57:5
+ |
+LL | Foo::func();
+ | ^^^^^^^^^^^
+ |
+ = help: const-stable functions can only call other const-stable functions
+
+error: `const_context_not_const_stable` is not yet stable as a const fn
+ --> $DIR/staged-api.rs:59:5
+ |
+LL | const_context_not_const_stable()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: const-stable functions can only call other const-stable functions
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/static-const-trait-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/static-const-trait-bound.rs
new file mode 100644
index 000000000..4520a3696
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/static-const-trait-bound.rs
@@ -0,0 +1,18 @@
+// check-pass
+pub struct S<T, F: FnOnce() -> T = fn() -> T> {
+ f: F,
+ x: Option<T>,
+}
+
+impl<T, F: FnOnce() -> T> S<T, F> {
+ pub const fn new(f: F) -> Self {
+ Self { f, x: None }
+ }
+}
+
+#[derive(Default)]
+pub struct Foo;
+
+static LOCKED_CALLSITES: S<Foo> = S::new(Default::default);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr
new file mode 100644
index 000000000..bf53b995b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr
@@ -0,0 +1,9 @@
+error[E0635]: unknown feature `const_default_impls`
+ --> $DIR/std-impl-gate.rs:6:46
+ |
+LL | #![cfg_attr(gated, feature(const_trait_impl, const_default_impls))]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0635`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.rs
new file mode 100644
index 000000000..e9e5e0235
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.rs
@@ -0,0 +1,21 @@
+// This tests feature gates for const impls in the standard library.
+
+// revisions: stock gated
+//[gated] known-bug: #110395
+
+#![cfg_attr(gated, feature(const_trait_impl, const_default_impls))]
+
+fn non_const_context() -> Vec<usize> {
+ Default::default()
+}
+
+const fn const_context() -> Vec<usize> {
+ Default::default()
+ //[stock]~^ ERROR cannot call non-const fn
+}
+
+fn main() {
+ const VAL: Vec<usize> = const_context();
+
+ assert_eq!(VAL, non_const_context());
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr
new file mode 100644
index 000000000..6d624def2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr
@@ -0,0 +1,12 @@
+error[E0015]: cannot call non-const fn `<Vec<usize> as Default>::default` in constant functions
+ --> $DIR/std-impl-gate.rs:13:5
+ |
+LL | Default::default()
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
new file mode 100644
index 000000000..12bcdb034
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
@@ -0,0 +1,28 @@
+error: `~const` is not allowed here
+ --> $DIR/super-traits-fail-2.rs:11:12
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^
+ |
+note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
+ --> $DIR/super-traits-fail-2.rs:11:1
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-2.rs:11:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-2.rs:11:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
new file mode 100644
index 000000000..b60399c57
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
@@ -0,0 +1,16 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-2.rs:11:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-2.rs:11:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs
new file mode 100644
index 000000000..93fd96f8f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs
@@ -0,0 +1,20 @@
+#![feature(const_trait_impl)]
+// known-bug: #110395
+// revisions: yy yn ny nn
+
+#[cfg_attr(any(yy, yn), const_trait)]
+trait Foo {
+ fn a(&self);
+}
+
+#[cfg_attr(any(yy, ny), const_trait)]
+trait Bar: ~const Foo {}
+// FIXME [ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+// FIXME [ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]`
+
+const fn foo<T: Bar>(x: &T) {
+ x.a();
+ // FIXME [yn,yy]~^ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
new file mode 100644
index 000000000..e465ebaff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+ --> $DIR/super-traits-fail-2.rs:11:12
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^
+ |
+note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
+ --> $DIR/super-traits-fail-2.rs:11:1
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
new file mode 100644
index 000000000..1faa5b4dd
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
+ --> $DIR/super-traits-fail-2.rs:16:7
+ |
+LL | x.a();
+ | ^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
new file mode 100644
index 000000000..e10c51ef4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -0,0 +1,34 @@
+error: `~const` is not allowed here
+ --> $DIR/super-traits-fail-3.rs:13:12
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^
+ |
+note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
+ --> $DIR/super-traits-fail-3.rs:13:1
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:13:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:13:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:18:24
+ |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+ | ^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
new file mode 100644
index 000000000..cd0ee7327
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
@@ -0,0 +1,16 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:13:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:13:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs
new file mode 100644
index 000000000..5994057b2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs
@@ -0,0 +1,23 @@
+#![feature(const_trait_impl)]
+
+// revisions: yy yn ny nn
+//[yy] known-bug: #110395
+//FIXME [yy] check-pass
+
+#[cfg_attr(any(yy, yn), const_trait)]
+trait Foo {
+ fn a(&self);
+}
+
+#[cfg_attr(any(yy, ny), const_trait)]
+trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]`
+//[yn,nn]~^^^ ERROR: `~const` is not allowed here
+
+const fn foo<T: ~const Bar>(x: &T) {
+ //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+ x.a();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
new file mode 100644
index 000000000..34f6515b5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
@@ -0,0 +1,20 @@
+error: `~const` is not allowed here
+ --> $DIR/super-traits-fail-3.rs:13:12
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^
+ |
+note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
+ --> $DIR/super-traits-fail-3.rs:13:1
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:18:24
+ |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+ | ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr
new file mode 100644
index 000000000..5cccc0251
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
+ --> $DIR/super-traits-fail-3.rs:20:7
+ |
+LL | x.a();
+ | ^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs
new file mode 100644
index 000000000..b3853def7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs
@@ -0,0 +1,21 @@
+// check-pass
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+ fn a(&self);
+}
+#[const_trait]
+trait Bar: ~const Foo {}
+
+struct S;
+impl Foo for S {
+ fn a(&self) {}
+}
+
+impl const Bar for S {}
+//FIXME ~^ ERROR the trait bound
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs
new file mode 100644
index 000000000..92becf7c4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs
@@ -0,0 +1,25 @@
+// check-pass
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Foo {
+ fn a(&self);
+}
+
+#[const_trait]
+trait Bar: ~const Foo {}
+
+struct S;
+impl const Foo for S {
+ fn a(&self) {}
+}
+
+impl const Bar for S {}
+
+const fn foo<T: ~const Bar>(t: &T) {
+ t.a();
+}
+
+const _: () = foo(&S);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/syntax.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/syntax.rs
new file mode 100644
index 000000000..7ac2458e3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/syntax.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_bound_opt_out)]
+#![feature(const_trait_impl)]
+
+// For now, this parses since an error does not occur until AST lowering.
+impl ~const T {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
new file mode 100644
index 000000000..4b720b534
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
@@ -0,0 +1,37 @@
+#![feature(const_trait_impl, effects)]
+#![feature(generic_arg_infer)]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+ fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+ //~^ ERROR `~const` is not allowed here
+ //~| ERROR mismatched types
+ Foo
+ }
+}
+
+#[const_trait]
+trait Add42 {
+ fn add(a: usize) -> usize;
+}
+
+impl const Add42 for () {
+ fn add(a: usize) -> usize {
+ a + 42
+ }
+}
+
+fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ //~^ ERROR `~const` is not allowed here
+ //~| ERROR mismatched types
+ Foo
+}
+
+fn main() {
+ let foo = Foo::<0>;
+ let foo = bar::<(), _>(foo);
+ let _foo = bar::<(), _>(foo);
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
new file mode 100644
index 000000000..b47979381
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
@@ -0,0 +1,45 @@
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-and-const-params.rs:9:15
+ |
+LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-and-const-params.rs:9:8
+ |
+LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+ | ^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-and-const-params.rs:27:11
+ |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-and-const-params.rs:27:4
+ |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ | ^^^
+
+error[E0308]: mismatched types
+ --> $DIR/tilde-const-and-const-params.rs:27:61
+ |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ | ^^^^^^^^^ expected `false`, found `true`
+ |
+ = note: expected constant `false`
+ found constant `true`
+
+error[E0308]: mismatched types
+ --> $DIR/tilde-const-and-const-params.rs:9:44
+ |
+LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+ | ^^^^^^^^^ expected `false`, found `true`
+ |
+ = note: expected constant `false`
+ found constant `true`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
new file mode 100644
index 000000000..5ecb75094
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
@@ -0,0 +1,58 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Trait {}
+
+// Regression test for issue #90052.
+fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed
+
+struct Struct<T: ~const Trait> { field: T } //~ ERROR `~const` is not allowed here
+struct TupleStruct<T: ~const Trait>(T); //~ ERROR `~const` is not allowed here
+struct UnitStruct<T: ~const Trait>; //~ ERROR `~const` is not allowed here
+
+enum Enum<T: ~const Trait> { Variant(T) } //~ ERROR `~const` is not allowed here
+
+union Union<T: ~const Trait> { field: T } //~ ERROR `~const` is not allowed here
+
+type Type<T: ~const Trait> = T; //~ ERROR `~const` is not allowed here
+
+const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed here
+//~^ ERROR generic const items are experimental
+
+trait NonConstTrait {
+ type Type<T: ~const Trait>: ~const Trait;
+ //~^ ERROR `~const` is not allowed
+ //~| ERROR `~const` is not allowed
+ fn non_const_function<T: ~const Trait>(); //~ ERROR `~const` is not allowed
+ const CONSTANT<T: ~const Trait>: (); //~ ERROR `~const` is not allowed
+ //~^ ERROR generic const items are experimental
+}
+
+impl NonConstTrait for () {
+ type Type<T: ~const Trait> = (); //~ ERROR `~const` is not allowed
+ fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed
+ const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed
+ //~^ ERROR generic const items are experimental
+}
+
+struct Implementor;
+
+impl Implementor {
+ type Type<T: ~const Trait> = (); //~ ERROR `~const` is not allowed
+ //~^ ERROR inherent associated types are unstable
+ fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed
+ const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed
+ //~^ ERROR generic const items are experimental
+}
+
+// non-const traits
+trait Child0: ~const Trait {} //~ ERROR `~const` is not allowed
+trait Child1 where Self: ~const Trait {} //~ ERROR `~const` is not allowed
+
+// non-const impl
+impl<T: ~const Trait> Trait for T {} //~ ERROR `~const` is not allowed
+
+// inherent impl (regression test for issue #117004)
+impl<T: ~const Trait> Struct<T> {} //~ ERROR `~const` is not allowed
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
new file mode 100644
index 000000000..497ec5bcf
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -0,0 +1,256 @@
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:7:26
+ |
+LL | fn non_const_function<T: ~const Trait>() {}
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:7:4
+ |
+LL | fn non_const_function<T: ~const Trait>() {}
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:9:18
+ |
+LL | struct Struct<T: ~const Trait> { field: T }
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:10:23
+ |
+LL | struct TupleStruct<T: ~const Trait>(T);
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:11:22
+ |
+LL | struct UnitStruct<T: ~const Trait>;
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:13:14
+ |
+LL | enum Enum<T: ~const Trait> { Variant(T) }
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:15:16
+ |
+LL | union Union<T: ~const Trait> { field: T }
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:17:14
+ |
+LL | type Type<T: ~const Trait> = T;
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:19:19
+ |
+LL | const CONSTANT<T: ~const Trait>: () = ();
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:23:18
+ |
+LL | type Type<T: ~const Trait>: ~const Trait;
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:23:33
+ |
+LL | type Type<T: ~const Trait>: ~const Trait;
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:26:30
+ |
+LL | fn non_const_function<T: ~const Trait>();
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:26:8
+ |
+LL | fn non_const_function<T: ~const Trait>();
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:27:23
+ |
+LL | const CONSTANT<T: ~const Trait>: ();
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:32:18
+ |
+LL | type Type<T: ~const Trait> = ();
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:33:30
+ |
+LL | fn non_const_function<T: ~const Trait>() {}
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:33:8
+ |
+LL | fn non_const_function<T: ~const Trait>() {}
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:34:23
+ |
+LL | const CONSTANT<T: ~const Trait>: () = ();
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:41:18
+ |
+LL | type Type<T: ~const Trait> = ();
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:43:30
+ |
+LL | fn non_const_function<T: ~const Trait>() {}
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:43:8
+ |
+LL | fn non_const_function<T: ~const Trait>() {}
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:44:23
+ |
+LL | const CONSTANT<T: ~const Trait>: () = ();
+ | ^^^^^^
+ |
+ = note: this item cannot have `~const` trait bounds
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:49:15
+ |
+LL | trait Child0: ~const Trait {}
+ | ^^^^^^
+ |
+note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:49:1
+ |
+LL | trait Child0: ~const Trait {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:50:26
+ |
+LL | trait Child1 where Self: ~const Trait {}
+ | ^^^^^^
+ |
+note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:50:1
+ |
+LL | trait Child1 where Self: ~const Trait {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:53:9
+ |
+LL | impl<T: ~const Trait> Trait for T {}
+ | ^^^^^^
+ |
+note: this impl is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:53:1
+ |
+LL | impl<T: ~const Trait> Trait for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-invalid-places.rs:56:9
+ |
+LL | impl<T: ~const Trait> Struct<T> {}
+ | ^^^^^^
+ |
+note: inherent impls cannot have `~const` trait bounds
+ --> $DIR/tilde-const-invalid-places.rs:56:1
+ |
+LL | impl<T: ~const Trait> Struct<T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0658]: generic const items are experimental
+ --> $DIR/tilde-const-invalid-places.rs:19:15
+ |
+LL | const CONSTANT<T: ~const Trait>: () = ();
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+ = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+ --> $DIR/tilde-const-invalid-places.rs:27:19
+ |
+LL | const CONSTANT<T: ~const Trait>: ();
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+ = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+ --> $DIR/tilde-const-invalid-places.rs:34:19
+ |
+LL | const CONSTANT<T: ~const Trait>: () = ();
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+ = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: generic const items are experimental
+ --> $DIR/tilde-const-invalid-places.rs:44:19
+ |
+LL | const CONSTANT<T: ~const Trait>: () = ();
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+ = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
+
+error[E0658]: inherent associated types are unstable
+ --> $DIR/tilde-const-invalid-places.rs:41:5
+ |
+LL | type Type<T: ~const Trait> = ();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+ = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
+
+error: aborting due to 27 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs
new file mode 100644
index 000000000..ed911d965
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs
@@ -0,0 +1,6 @@
+#![feature(const_trait_impl)]
+
+const fn tilde_question<T: ~const ?Sized>() {}
+//~^ ERROR `~const` and `?` are mutually exclusive
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr
new file mode 100644
index 000000000..5850ab41c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr
@@ -0,0 +1,8 @@
+error: `~const` and `?` are mutually exclusive
+ --> $DIR/tilde-const-maybe-trait.rs:3:28
+ |
+LL | const fn tilde_question<T: ~const ?Sized>() {}
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs
new file mode 100644
index 000000000..9b3c2cf2a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_impl)]
+
+struct S<
+ T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add,
+ T: ~const ?for<'a: 'b> m::Trait<'a>,
+>;
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.rs
new file mode 100644
index 000000000..06e4ede8b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+
+struct S<T: ~const ~const Tr>;
+//~^ ERROR expected identifier, found `~`
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr
new file mode 100644
index 000000000..a809736a4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `~`
+ --> $DIR/tilde-twice.rs:5:20
+ |
+LL | struct S<T: ~const ~const Tr>;
+ | ^ expected identifier
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
new file mode 100644
index 000000000..bfd9fe42e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
@@ -0,0 +1,17 @@
+// check-pass
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Foo {
+ fn foo(&self) {}
+}
+
+struct Bar<T>(T);
+
+impl<T> Bar<T> {
+ const fn foo(&self) where T: ~const Foo {
+ self.0.foo()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs
new file mode 100644
index 000000000..8d56295e7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.rs
@@ -0,0 +1,50 @@
+// known-bug: #110395
+
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![feature(const_t_try)]
+#![feature(const_try)]
+#![feature(try_trait_v2)]
+
+#![stable(feature = "foo", since = "1.0")]
+
+use std::ops::{ControlFlow, FromResidual, Try};
+
+#[stable(feature = "foo", since = "1.0")]
+pub struct T;
+
+#[stable(feature = "foo", since = "1.0")]
+#[rustc_const_unstable(feature = "const_t_try", issue = "none")]
+impl const Try for T {
+ type Output = T;
+ type Residual = T;
+
+ fn from_output(t: T) -> T {
+ t
+ }
+
+ fn branch(self) -> ControlFlow<T, T> {
+ ControlFlow::Continue(self)
+ }
+}
+
+#[stable(feature = "foo", since = "1.0")]
+#[rustc_const_unstable(feature = "const_t_try", issue = "none")]
+impl const FromResidual for T {
+ fn from_residual(t: T) -> T {
+ t
+ }
+}
+
+#[stable(feature = "foo", since = "1.0")]
+#[const_trait]
+pub trait Tr {
+ #[stable(feature = "foo", since = "1.0")]
+ fn bar() -> T {
+ T?
+ // Should be allowed.
+ // Must enable unstable features to call this trait fn in const contexts.
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr
new file mode 100644
index 000000000..deed05ae1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr
@@ -0,0 +1,29 @@
+error[E0015]: `?` cannot determine the branch of `T` in constant functions
+ --> $DIR/trait-default-body-stability.rs:44:9
+ |
+LL | T?
+ | ^^
+ |
+note: impl defined here, but it is not `const`
+ --> $DIR/trait-default-body-stability.rs:18:1
+ |
+LL | impl const Try for T {
+ | ^^^^^^^^^^^^^^^^^^^^
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error[E0015]: `?` cannot convert from residual of `T` in constant functions
+ --> $DIR/trait-default-body-stability.rs:44:9
+ |
+LL | T?
+ | ^^
+ |
+note: impl defined here, but it is not `const`
+ --> $DIR/trait-default-body-stability.rs:33:1
+ |
+LL | impl const FromResidual for T {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-method-ptr-in-consts-ice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-method-ptr-in-consts-ice.rs
new file mode 100644
index 000000000..7d7cb967c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-method-ptr-in-consts-ice.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+struct LazyLock<T> {
+ data: (Option<T>, fn() -> T),
+}
+
+impl<T> LazyLock<T> {
+ pub const fn new(f: fn() -> T) -> LazyLock<T> {
+ LazyLock { data: (None, f) }
+ }
+}
+
+struct A<T = i32>(Option<T>);
+
+impl<T> Default for A<T> {
+ fn default() -> Self {
+ A(None)
+ }
+}
+
+static EMPTY_SET: LazyLock<A<i32>> = LazyLock::new(A::default);
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs
new file mode 100644
index 000000000..94be3ff46
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs
@@ -0,0 +1,33 @@
+// Like trait-where-clause.rs, but we are calling from a const context.
+// Checking the validity of traits' where clauses happen at a later stage.
+// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a
+// test is not enough.
+// known-bug: #110395
+// FIXME check-pass
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Bar {}
+
+#[const_trait]
+trait Foo {
+ fn a();
+ fn b() where Self: ~const Bar;
+ fn c<T: ~const Bar>();
+}
+
+const fn test1<T: ~const Foo + Bar>() {
+ T::a();
+ T::b();
+ //FIXME ~^ ERROR the trait bound
+ T::c::<T>();
+ //FIXME ~^ ERROR the trait bound
+}
+
+const fn test2<T: ~const Foo + ~const Bar>() {
+ T::a();
+ T::b();
+ T::c::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
new file mode 100644
index 000000000..2a9647da7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/trait-where-clause-const.rs:21:5
+ |
+LL | T::b();
+ | ^^^^^^ expected `host`, found `true`
+ |
+ = note: expected constant `host`
+ found constant `true`
+
+error[E0308]: mismatched types
+ --> $DIR/trait-where-clause-const.rs:23:5
+ |
+LL | T::c::<T>();
+ | ^^^^^^^^^^^ expected `host`, found `true`
+ |
+ = note: expected constant `host`
+ found constant `true`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs
new file mode 100644
index 000000000..5439f859a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs
@@ -0,0 +1,41 @@
+// run-pass
+
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Bar {
+ fn bar() -> u8;
+}
+
+#[const_trait]
+trait Foo {
+ fn foo() -> u8 where Self: ~const Bar {
+ <Self as Bar>::bar() * 6
+ }
+}
+
+struct NonConst;
+struct Const;
+
+impl Bar for NonConst {
+ fn bar() -> u8 {
+ 3
+ }
+}
+
+impl Foo for NonConst {}
+
+impl const Bar for Const {
+ fn bar() -> u8 {
+ 4
+ }
+}
+
+impl const Foo for Const {}
+
+fn main() {
+ const ANS1: u8 = Const::foo();
+ let ans2 = NonConst::foo();
+
+ assert_eq!(ANS1 + ans2, 42);
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
new file mode 100644
index 000000000..c578813b8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Foo {
+ fn bar() where Self: ~const Foo;
+}
+
+struct S;
+
+impl Foo for S {
+ fn bar() {}
+}
+
+fn baz<T: Foo>() {
+ T::bar();
+}
+
+const fn qux<T: ~const Foo>() {
+ T::bar();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs
new file mode 100644
index 000000000..11f353f3f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -0,0 +1,28 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+trait Foo {
+ fn a();
+ fn b() where Self: ~const Bar;
+ //~^ ERROR `~const` is not allowed here
+ fn c<T: ~const Bar>();
+ //~^ ERROR `~const` is not allowed here
+}
+
+fn test1<T: Foo>() {
+ T::a();
+ T::b();
+ //~^ ERROR the trait bound
+ T::c::<T>();
+ //~^ ERROR the trait bound
+}
+
+fn test2<T: Foo + Bar>() {
+ T::a();
+ T::b();
+ T::c::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr
new file mode 100644
index 000000000..abe24b662
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -0,0 +1,59 @@
+error: `~const` is not allowed here
+ --> $DIR/trait-where-clause.rs:8:24
+ |
+LL | fn b() where Self: ~const Bar;
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/trait-where-clause.rs:8:8
+ |
+LL | fn b() where Self: ~const Bar;
+ | ^
+
+error: `~const` is not allowed here
+ --> $DIR/trait-where-clause.rs:10:13
+ |
+LL | fn c<T: ~const Bar>();
+ | ^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/trait-where-clause.rs:10:8
+ |
+LL | fn c<T: ~const Bar>();
+ | ^
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+ --> $DIR/trait-where-clause.rs:16:5
+ |
+LL | T::b();
+ | ^ the trait `Bar` is not implemented for `T`
+ |
+note: required by a bound in `Foo::b`
+ --> $DIR/trait-where-clause.rs:8:24
+ |
+LL | fn b() where Self: ~const Bar;
+ | ^^^^^^^^^^ required by this bound in `Foo::b`
+help: consider further restricting this bound
+ |
+LL | fn test1<T: Foo + Bar>() {
+ | +++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+ --> $DIR/trait-where-clause.rs:18:12
+ |
+LL | T::c::<T>();
+ | ^ the trait `Bar` is not implemented for `T`
+ |
+note: required by a bound in `Foo::c`
+ --> $DIR/trait-where-clause.rs:10:13
+ |
+LL | fn c<T: ~const Bar>();
+ | ^^^^^^^^^^ required by this bound in `Foo::c`
+help: consider further restricting this bound
+ |
+LL | fn test1<T: Foo + Bar>() {
+ | +++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs
new file mode 100644
index 000000000..d63381b5f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+
+struct S<T: const Tr>;
+//~^ ERROR const bounds must start with `~`
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr
new file mode 100644
index 000000000..646cdfc78
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr
@@ -0,0 +1,10 @@
+error: const bounds must start with `~`
+ --> $DIR/without-tilde.rs:5:13
+ |
+LL | struct S<T: const Tr>;
+ | -^^^^
+ | |
+ | help: add `~`: `~`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs
new file mode 100644
index 000000000..0907061d6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs
@@ -0,0 +1,14 @@
+// force-host
+// edition: 2018
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use std::str::FromStr;
+
+#[proc_macro]
+pub fn number_of_tokens(_: TokenStream) -> TokenStream {
+ TokenStream::from_str("c\"\"").unwrap().into_iter().count().to_string().parse().unwrap()
+}
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs
index 3fc5fd481..503739600 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs
@@ -1,5 +1,4 @@
-// FIXME(c_str_literals): This should be `run-pass`
-// known-bug: #113333
+// run-pass
// edition: 2021
#![feature(c_str_literals)]
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr
deleted file mode 100644
index 571c319d8..000000000
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error: prefix `c` is unknown
- --> $DIR/basic.rs:8:27
- |
-LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul());
- | ^ unknown prefix
- |
- = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
- |
-LL | assert_eq!(b"test\0", c "test".to_bytes_with_nul());
- | +
-
-error: no rules expected the token `"test"`
- --> $DIR/basic.rs:8:28
- |
-LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul());
- | -^^^^^
- | |
- | no rules expected this token in macro call
- | help: missing comma here
- |
- = note: while trying to match sequence start
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs
new file mode 100644
index 000000000..b3557c71b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs
@@ -0,0 +1,16 @@
+// even if this crate is edition 2021, proc macros compiled using older
+// editions should still be able to observe the pre-2021 token behavior
+//
+// adapted from tests/ui/rust-2021/reserved-prefixes-via-macro.rs
+
+// edition: 2021
+// check-pass
+
+// aux-build: count.rs
+extern crate count;
+
+const _: () = {
+ assert!(count::number_of_tokens!() == 2);
+};
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr
index 8de36ca4a..ea666e433 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr
@@ -1,32 +1,21 @@
-error: prefix `c` is unknown
+error[E0658]: `c".."` literals are experimental
--> $DIR/gate.rs:10:5
|
LL | c"foo";
- | ^ unknown prefix
+ | ^^^^^^
|
- = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
- |
-LL | c "foo";
- | +
+ = note: see issue #105723 <https://github.com/rust-lang/rust/issues/105723> for more information
+ = help: add `#![feature(c_str_literals)]` to the crate attributes to enable
-error: prefix `c` is unknown
+error[E0658]: `c".."` literals are experimental
--> $DIR/gate.rs:13:8
|
LL | m!(c"test");
- | ^ unknown prefix
- |
- = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
+ | ^^^^^^^
|
-LL | m!(c "test");
- | +
-
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"foo"`
- --> $DIR/gate.rs:10:6
- |
-LL | c"foo";
- | ^^^^^ expected one of 8 possible tokens
+ = note: see issue #105723 <https://github.com/rust-lang/rust/issues/105723> for more information
+ = help: add `#![feature(c_str_literals)]` to the crate attributes to enable
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
index 96945f125..dc1bf8045 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
Binary files differ
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr
index 2226c7aa6..82d9f9cb3 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr
Binary files differ
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs
index 066505c23..380445d7a 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs
@@ -1,5 +1,4 @@
-// FIXME(c_str_literals): This should be `run-pass`
-// known-bug: #113333
+// run-pass
// edition: 2021
#![feature(c_str_literals)]
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr
deleted file mode 100644
index 47361fb61..000000000
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error: prefix `c` is unknown
- --> $DIR/non-ascii.rs:9:9
- |
-LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
- | ^ unknown prefix
- |
- = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
- |
-LL | c "\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
- | +
-
-error: out of range hex escape
- --> $DIR/non-ascii.rs:9:11
- |
-LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
- | ^^^^ must be a character in the range [\x00-\x7f]
-
-error: out of range hex escape
- --> $DIR/non-ascii.rs:9:15
- |
-LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
- | ^^^^ must be a character in the range [\x00-\x7f]
-
-error: no rules expected the token `"\xEF\x80🦀\u{1F980}"`
- --> $DIR/non-ascii.rs:9:10
- |
-LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
- | -^^^^^^^^^^^^^^^^^^^^
- | |
- | no rules expected this token in macro call
- | help: missing comma here
- |
-note: while trying to match `,`
- --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-
-error: aborting due to 4 previous errors
-