summaryrefslogtreecommitdiffstats
path: root/tests/ui/rfcs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfcs')
-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.rs135
-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.rs40
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr16
-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)0
-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.rs22
-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.stderr59
-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.rs211
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr217
-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.rs66
-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.stderr19
-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.stderr36
-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.stderr48
-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/feature-gate.rs96
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr431
-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/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.stderr14
-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-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-1.rs3
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs6
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.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.stderr20
-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/chains-without-let.rs20
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.stderr33
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs480
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr1911
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs55
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr147
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs62
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr120
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs45
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr38
-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-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.rs43
-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.rs19
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr5
-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.rs14
-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.stderr8
-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.stderr15
-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.stderr20
-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-in-impl.stderr8
-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-chain.stderr23
-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-dup-bound.stderr23
-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.stderr28
-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.stderr15
-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-generic-method-pass.stderr17
-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.stderr20
-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.rs10
-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.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs30
-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.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.rs25
-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.rs43
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr50
-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.stderr58
-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.stderr58
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs113
-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.rs9
-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.stderr39
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs5
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr21
-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.rs19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr53
-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/const_derives/derive-const-with-params.stderr20
-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.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs24
-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.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr15
-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.stderr15
-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/helloworld.rs29
-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.stderr11
-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.stderr19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr41
-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.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr24
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs23
-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.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs12
-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.rs58
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr18
-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/specializing-constness-2.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr21
-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.stderr14
-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.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr14
-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.stderr19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr19
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs18
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr20
-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.rs34
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs7
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.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.stderr20
-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.rs31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr35
-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.rs26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr35
-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
543 files changed, 16490 insertions, 83 deletions
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..f08ba522a
--- /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 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..012ccab17
--- /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 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..623fd585a
--- /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 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..2b3fbd2a4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
@@ -0,0 +1,135 @@
+// 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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/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..46600e7b2
--- /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 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..567685950
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs
@@ -0,0 +1,40 @@
+// 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;
+
+struct B(Fn);
+
+fn main() {
+ let s = B(my_fn);
+ match s {
+ B(TEST) => println!("matched"),
+ //~^ WARN pointers in patterns 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..d6afc0255
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
@@ -0,0 +1,16 @@
+warning: function pointers and unsized pointers 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:35: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: 1 warning 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..1c4fb9146
--- /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 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..6adebada0
--- /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 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..f5b10f062
--- /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 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..d183eaaa6 100644
--- a/tests/ui/rfcs/rfc1623-2.stderr
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
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..d4410e147
--- /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 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..a6fec9c4e
--- /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 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..bee639bf2
--- /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 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..aca839d80
--- /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 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..409dede1a
--- /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 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..f72b3ab02
--- /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 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..8b01941b4
--- /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 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..ca5fa6df2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs
@@ -0,0 +1,22 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
+#![feature(return_position_impl_trait_in_trait)]
+#![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/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..5ee6d127e
--- /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 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..7f6749fc9
--- /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 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..53779d365
--- /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 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..bc8fd92ce
--- /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 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..cb329548d
--- /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 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..a19750cc7
--- /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 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..b7c0b0bb6
--- /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 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..fc06de90a
--- /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 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..07991af6e
--- /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 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..e1e1bf7f6
--- /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 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..181f57899
--- /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 `&&str`
+ found reference `&'static str`
+
+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..c672acee0
--- /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 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..5b51dc5ac
--- /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 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..ad84ebe3a
--- /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 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..a61dcf839
--- /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 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..872cb9b8b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr
@@ -0,0 +1,59 @@
+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`, which is marked as non-exhaustive
+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`, which is marked as non-exhaustive
+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..de1bf8be8
--- /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:5:5
+ |
+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:14:5
+ |
+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.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
new file mode 100644
index 000000000..3482af747
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
@@ -0,0 +1,211 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
+
+#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)]
+
+// 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 unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
+use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct};
+
+#[non_exhaustive]
+#[derive(Default)]
+pub struct Foo {
+ a: u8,
+ b: usize,
+ c: String,
+}
+
+#[non_exhaustive]
+pub enum Bar {
+ A,
+ B,
+ C,
+}
+
+fn main() {
+ let enumeration = Bar::A;
+
+ // Ok: this is a crate local non_exhaustive enum
+ match enumeration {
+ Bar::A => {}
+ Bar::B => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ let non_enum = NonExhaustiveEnum::Unit;
+
+ // Ok: without the attribute
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ match non_enum {
+ NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ let x = 5;
+ match non_enum {
+ NonExhaustiveEnum::Unit if x > 10 => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: all covered and not `unreachable-patterns`
+ #[deny(unreachable_patterns)]
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NestedNonExhaustive::B {
+ NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
+ NestedNonExhaustive::A(_) => {}
+ NestedNonExhaustive::B => {}
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+ //~^^^^^ some variants are not matched explicitly
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ match VariantNonExhaustive::Baz(1, 2) {
+ VariantNonExhaustive::Baz(_, _) => {}
+ VariantNonExhaustive::Bar { x, .. } => {}
+ }
+ //~^^ some fields are not explicitly listed
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ //~^ some fields are not explicitly listed
+
+ // Ok: this is local
+ #[warn(non_exhaustive_omitted_patterns)]
+ let Foo { a, b, .. } = Foo::default();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ 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
+ #[warn(non_exhaustive_omitted_patterns)]
+ let MixedVisFields { a, b, .. } = MixedVisFields::default();
+
+ // Ok: because this only has 1 variant
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NonExhaustiveSingleVariant::A(true) {
+ NonExhaustiveSingleVariant::A(true) => {}
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NonExhaustiveSingleVariant::A(true) {
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: we don't lint on `if let` expressions
+ #[deny(non_exhaustive_omitted_patterns)]
+ if let NonExhaustiveEnum::Tuple(_) = non_enum {}
+
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: the feature is on and all variants are matched
+ #[deny(non_exhaustive_omitted_patterns)]
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ UnstableEnum::Unstable => {}
+ _ => {}
+ }
+
+ // Ok: the feature is on and both variants are matched
+ #[deny(non_exhaustive_omitted_patterns)]
+ match OnlyUnstableEnum::Unstable {
+ OnlyUnstableEnum::Unstable => {}
+ OnlyUnstableEnum::Unstable2 => {}
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match OnlyUnstableEnum::Unstable {
+ OnlyUnstableEnum::Unstable => {}
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable fields are matched with feature on
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable and stable fields are matched with feature on
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
+
+ // Ok: local bindings are allowed
+ #[deny(non_exhaustive_omitted_patterns)]
+ let local = NonExhaustiveEnum::Unit;
+
+ // Ok: missing patterns will be blocked by the pattern being refutable
+ #[deny(non_exhaustive_omitted_patterns)]
+ let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
+ //~^ refutable pattern in local binding
+
+ // Check that matching on a reference results in a correctly spanned diagnostic
+ #[deny(non_exhaustive_omitted_patterns)]
+ match &non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+}
+
+#[deny(non_exhaustive_omitted_patterns)]
+// Ok: Pattern in a param is always wildcard
+pub fn takes_non_exhaustive(_: NonExhaustiveEnum) {
+ let _closure = |_: NonExhaustiveEnum| {};
+}
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..923394474
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -0,0 +1,217 @@
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:102: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:99:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:107: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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:106:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:115: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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:114:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:115: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
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:173: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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:172:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:181: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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:180:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:58:9
+ |
+LL | _ => {}
+ | ^ 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.rs:57:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:65:9
+ |
+LL | _ => {}
+ | ^ 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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:64:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:75:9
+ |
+LL | _ => {}
+ | ^ pattern `NonExhaustiveEnum::Unit` 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.rs:74:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:92:32
+ |
+LL | NestedNonExhaustive::A(_) => {}
+ | ^ 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` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:89:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:94:9
+ |
+LL | _ => {}
+ | ^ pattern `NestedNonExhaustive::C` 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:132:9
+ |
+LL | _ => {}
+ | ^ pattern `NonExhaustiveSingleVariant::A(_)` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:130:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:144:9
+ |
+LL | _ => {}
+ | ^ 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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:143:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:168:9
+ |
+LL | _ => {}
+ | ^ 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
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:165:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/omitted-patterns.rs:194: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:202:9
+ |
+LL | _ => {}
+ | ^ 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.rs:198:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors; 6 warnings emitted
+
+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..82ee68687
--- /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::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
+
+fn main() {
+ // OK: this matches all the stable variants
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // 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..f38368590
--- /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:23:9
+ |
+LL | _ => {}
+ | ^ 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:22:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 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..f39e6ee29
--- /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 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..a9c54af04
--- /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:17:23
+ |
+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..ec2a2f6f0
--- /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:16:23
+ |
+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..b6b777ec5
--- /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:17:23
+ |
+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..721890db4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
@@ -0,0 +1,66 @@
+// Check that we can manually implement an object-unsafe trait for its trait object.
+
+// 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..e7ddf8df4
--- /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 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..6d6562dae
--- /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 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..0cab47170
--- /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` 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..454c98ff9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr
@@ -0,0 +1,10 @@
+error: `start` 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` is not allowed to be `#[track_caller]`
+
+error: aborting due to 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..b36597bde
--- /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 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..670c423a7
--- /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(generator_trait)]
+#![feature(generators)]
+
+use std::ops::{Generator, GeneratorState};
+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_generator<F: Generator<String, Yield = (&'static str, String, Loc), Return = ()>>(
+ val: Pin<&mut F>
+) -> (&'static str, String, Loc) {
+ match val.resume("Mono".to_string()) {
+ GeneratorState::Yielded(val) => val,
+ _ => unreachable!()
+ }
+}
+
+#[track_caller]
+fn dyn_generator(
+ val: Pin<&mut dyn Generator<String, Yield = (&'static str, String, Loc), Return = ()>>
+) -> (&'static str, String, Loc) {
+ match val.resume("Dyn".to_string()) {
+ GeneratorState::Yielded(val) => val,
+ _ => unreachable!()
+ }
+}
+
+fn test_generator() {
+ let generator = #[track_caller] |arg: String| {
+ yield ("first", arg.clone(), Location::caller());
+ yield ("second", arg.clone(), Location::caller());
+ };
+
+ let mut pinned = Box::pin(generator);
+ let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut());
+ assert_eq!(dyn_ret, "first");
+ assert_eq!(dyn_arg, "Dyn".to_string());
+ // The `Generator` 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_generator(pinned.as_mut());
+ let mono_line = line!() - 1;
+ assert_eq!(mono_ret, "second");
+ // The generator 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_generator = || { yield Location::caller(); };
+ let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller
+ let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) {
+ GeneratorState::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_generator();
+}
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..76300cce5
--- /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 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..0c388f5fe
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -0,0 +1,19 @@
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/dont-infer-static.rs:6:10
+ |
+LL | bar: Bar<U>
+ | ^^^^^^ ...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 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..595a5c280
--- /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 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..3059f95ae
--- /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 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..589e95899
--- /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 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..9912e36b2
--- /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 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..16b64bdc2
--- /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 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..4350e6e8b
--- /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 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..c08add7ed
--- /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 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..769555234
--- /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 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..a785c63ce
--- /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 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..d9342013f
--- /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 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..508114357
--- /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 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..2c660b285
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -0,0 +1,36 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-enum-not-wf.rs:17:18
+ |
+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 | 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 | 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..5dff4c8ff
--- /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 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..975776cdd
--- /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 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..be05ecec0
--- /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 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..4ba1778d6
--- /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 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..34ff1362c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
@@ -0,0 +1,48 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/regions-struct-not-wf.rs:13:16
+ |
+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 | 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..9c836b190
--- /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 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..2b4625f77
--- /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 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..c39a70f66
--- /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 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..818915721
--- /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 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..7df4f06d1
--- /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 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..bd6778cf3
--- /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 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..122e8fd35
--- /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 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/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
new file mode 100644
index 000000000..3beb20f0a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -0,0 +1,96 @@
+// 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 `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+
+ () if (((let 0 = 1))) => {}
+ //~^ ERROR `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+
+ () 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 `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+
+ () if true && (let 0 = 1) => {}
+ //~^ ERROR `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+
+ () if (let 0 = 1) && (let 0 = 1) => {}
+ //~^ 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 `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+
+ () 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 `let` expressions in this position are unstable
+ //~| 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
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+
+
+ () 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 `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+ use_expr!((let 0 = 1));
+ //~^ ERROR `let` expressions in this position are unstable
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR `let` expressions are not supported here
+ 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..dc182ce46
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
@@ -0,0 +1,431 @@
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:10:16
+ |
+LL | () if (let 0 = 1) => {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:15:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:28:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:33:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:38:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:38:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:46: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:46:55
+ |
+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:46:68
+ |
+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:78:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:82:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^
+
+error: no rules expected the token `let`
+ --> $DIR/feature-gate.rs:92: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:71:10
+ |
+LL | ($e:expr) => {
+ | ^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $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: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:15: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:15:18
+ |
+LL | () if (((let 0 = 1))) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:28: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:28:16
+ |
+LL | () if (let 0 = 1) && true => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:33: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:33:24
+ |
+LL | () if true && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:38: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:38:16
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:38: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:38:31
+ |
+LL | () if (let 0 = 1) && (let 0 = 1) => {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:46: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:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:46: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:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:46: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:46:42
+ |
+LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:78:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^
+ |
+ = 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:78:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/feature-gate.rs:82:16
+ |
+LL | use_expr!((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:82:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^^^^^^^
+
+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:20: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:24: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:46: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:61: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:88: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:10:16
+ |
+LL | () if (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:15:18
+ |
+LL | () if (((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: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:24: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:28:16
+ |
+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:33:24
+ |
+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:38:16
+ |
+LL | () if (let 0 = 1) && (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:38:31
+ |
+LL | () if (let 0 = 1) && (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:46: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:46: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:46:42
+ |
+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:46:55
+ |
+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:46:68
+ |
+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:61: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[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:78:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^
+ |
+ = 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:82:16
+ |
+LL | use_expr!((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: aborting due to 45 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
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/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..a20a6062c
--- /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] Unit = Unit
+[$DIR/dbg-macro-expected-behavior.rs:23] a = Unit
+[$DIR/dbg-macro-expected-behavior.rs:29] Point { x: 42, y: 24 } = Point {
+ x: 42,
+ y: 24,
+}
+[$DIR/dbg-macro-expected-behavior.rs:30] b = Point {
+ x: 42,
+ y: 24,
+}
+[$DIR/dbg-macro-expected-behavior.rs:38]
+[$DIR/dbg-macro-expected-behavior.rs:42] &a = NoCopy(
+ 1337,
+)
+[$DIR/dbg-macro-expected-behavior.rs:42] dbg!(& a) = NoCopy(
+ 1337,
+)
+[$DIR/dbg-macro-expected-behavior.rs:47] f(&42) = 42
+before
+[$DIR/dbg-macro-expected-behavior.rs:52] { foo += 1; eprintln!("before"); 7331 } = 7331
+[$DIR/dbg-macro-expected-behavior.rs:60] ("Yeah",) = (
+ "Yeah",
+)
+[$DIR/dbg-macro-expected-behavior.rs:63] 1 = 1
+[$DIR/dbg-macro-expected-behavior.rs:63] 2 = 2
+[$DIR/dbg-macro-expected-behavior.rs:67] 1u8 = 1
+[$DIR/dbg-macro-expected-behavior.rs:67] 2u32 = 2
+[$DIR/dbg-macro-expected-behavior.rs:67] "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..e97fdcce1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `a`
+ --> $DIR/dbg-macro-move-semantics.rs:9:18
+ |
+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
+ |
+
+error: aborting due to 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..ce165e646
--- /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 previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..a3e559054
--- /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 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..1597e5be4
--- /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 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-1.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.rs
new file mode 100644
index 000000000..c07ba54af
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.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-1.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr
new file mode 100644
index 000000000..a8f3abe59
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr
@@ -0,0 +1,8 @@
+error: cannot load a crate with a non-ascii name `ьаг`
+ --> $DIR/crate_name_nonascii_forbidden-1.rs:1:1
+ |
+LL | extern crate ьаг;
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs
new file mode 100644
index 000000000..f8e033937
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs
@@ -0,0 +1,6 @@
+// compile-flags:--extern му_сгате
+// edition:2018
+
+use му_сгате::baz; //~ 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-2.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr
new file mode 100644
index 000000000..05fc4fb22
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr
@@ -0,0 +1,8 @@
+error: cannot load a crate with a non-ascii name `му_сгате`
+ --> $DIR/crate_name_nonascii_forbidden-2.rs:4:5
+ |
+LL | use му_сгате::baz;
+ | ^^^^^^^^
+
+error: aborting due to 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..7639ae9f6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.stderr
@@ -0,0 +1,20 @@
+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"
+
+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..e6dee2a1d
--- /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 `let` expressions are not supported here
+ _ => {}
+ }
+}
+
+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..26850998c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr
@@ -0,0 +1,21 @@
+error: `let` expressions are not supported here
+ --> $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/chains-without-let.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.rs
new file mode 100644
index 000000000..e0dded152
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.rs
@@ -0,0 +1,20 @@
+fn and_chain() {
+ let z;
+ if true && { z = 3; true} && z == 3 {}
+ //~^ ERROR E0381
+}
+
+fn and_chain_2() {
+ let z;
+ true && { z = 3; true} && z == 3;
+ //~^ ERROR E0381
+}
+
+fn or_chain() {
+ let z;
+ if false || { z = 3; false} || z == 3 {}
+ //~^ ERROR E0381
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.stderr
new file mode 100644
index 000000000..30d5a6779
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/chains-without-let.stderr
@@ -0,0 +1,33 @@
+error[E0381]: used binding `z` is possibly-uninitialized
+ --> $DIR/chains-without-let.rs:3:34
+ |
+LL | let z;
+ | - binding declared here but left uninitialized
+LL | if true && { z = 3; true} && z == 3 {}
+ | ----- ^ `z` used here but it is possibly-uninitialized
+ | |
+ | binding initialized here in some conditions
+
+error[E0381]: used binding `z` is possibly-uninitialized
+ --> $DIR/chains-without-let.rs:9:31
+ |
+LL | let z;
+ | - binding declared here but left uninitialized
+LL | true && { z = 3; true} && z == 3;
+ | ----- ^ `z` used here but it is possibly-uninitialized
+ | |
+ | binding initialized here in some conditions
+
+error[E0381]: used binding `z` is possibly-uninitialized
+ --> $DIR/chains-without-let.rs:15:36
+ |
+LL | let z;
+ | - binding declared here but left uninitialized
+LL | if false || { z = 3; false} || z == 3 {}
+ | ----- ^ `z` used here but it is possibly-uninitialized
+ | |
+ | binding initialized here in some conditions
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
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..2a9a5472b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -0,0 +1,480 @@
+// 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 `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ if (((let 0 = 1))) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ if (let 0 = 1) && true {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ if true && (let 0 = 1) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ if (let 0 = 1) && (let 0 = 1) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ while (((let 0 = 1))) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ while (let 0 = 1) && true {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ while true && (let 0 = 1) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ while (let 0 = 1) && (let 0 = 1) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ use_expr!((let 0 = 1));
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+}
+
+fn nested_within_if_expr() {
+ if &let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ if !let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ if *let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR type `bool` cannot be dereferenced
+ //~| ERROR expected expression, found `let` statement
+ if -let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR cannot apply unary operator `-` to type `bool`
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR the `?` operator can only be applied to values that implement `Try`
+ //~| ERROR the `?` operator can only be used in a function that returns `Result`
+ //~| ERROR expected expression, found `let` statement
+
+ if true || let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ if (true || let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ if true && (true || let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ if true || (true && let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ if x = let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ if true..(let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+ if ..(let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+ if (let 0 = 0).. {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ // Binds as `(let ... = true)..true &&/|| false`.
+ if let Range { start: _, end: _ } = true..true && false {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ if let Range { start: _, end: _ } = true..true || false {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: true, end } = t)..(&&false)`.
+ let t = &&true;
+ if let Range { start: true, end } = t..&&false {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+
+ if let true = let true = true {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+}
+
+fn nested_within_while_expr() {
+ while &let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ while !let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ while *let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR type `bool` cannot be dereferenced
+ //~| ERROR expected expression, found `let` statement
+ while -let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR cannot apply unary operator `-` to type `bool`
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR the `?` operator can only be applied to values that implement `Try`
+ //~| ERROR the `?` operator can only be used in a function that returns `Result`
+ //~| ERROR expected expression, found `let` statement
+
+ while true || let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ while (true || let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ while true && (true || let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ while true || (true && let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ while x = let 0 = 0 {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ while true..(let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+ while ..(let 0 = 0) {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+ while (let 0 = 0).. {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ // Binds as `(let ... = true)..true &&/|| false`.
+ while let Range { start: _, end: _ } = true..true && false {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ while let Range { start: _, end: _ } = true..true || false {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+
+ // Binds as `(let Range { start: true, end } = t)..(&&false)`.
+ let t = &&true;
+ while let Range { start: true, end } = t..&&false {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+
+ while let true = let true = true {}
+ //~^ ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ !let 0 = 0;
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ *let 0 = 0;
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR type `bool` cannot be dereferenced
+ //~| ERROR expected expression, found `let` statement
+ -let 0 = 0;
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR cannot apply unary operator `-` to type `bool`
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR the `?` operator can only be used in a function that returns `Result`
+ //~| ERROR the `?` operator can only be applied to values that implement `Try`
+ //~| ERROR expected expression, found `let` statement
+
+ true || let 0 = 0;
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ (true || let 0 = 0);
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ true && (true || let 0 = 0);
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ let mut x = true;
+ x = let 0 = 0;
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ true..(let 0 = 0);
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ ..(let 0 = 0);
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ (let 0 = 0)..;
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+
+ (let Range { start: _, end: _ } = true..true || false);
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| ERROR expected expression, found `let` statement
+
+ (let true = let true = true);
+ //~^ ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR mismatched types
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ }>::O = 5 {}
+
+ while let A::<{
+ true && let 1 = 1
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ }>::O = 5 {}
+
+ if A::<{
+ true && let 1 = 1
+ //~^ ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ }
+
+ if (let Some(a) = opt) && true {
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt) && (let Some(b) = a) {
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| 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 `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt && (let Some(b) = a)) && true {
+ //~^ ERROR `let` expressions are not supported here
+ //~| ERROR `let` expressions are not supported here
+ //~| ERROR expected expression, found `let` statement
+ //~| ERROR expected expression, found `let` statement
+ }
+ if (let Some(a) = opt && (true)) && true {
+ //~^ ERROR `let` expressions are not supported here
+ //~| 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..81933173c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -0,0 +1,1911 @@
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:29:9
+ |
+LL | if (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:33:11
+ |
+LL | if (((let 0 = 1))) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:37:9
+ |
+LL | if (let 0 = 1) && true {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:41:17
+ |
+LL | if true && (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:45:9
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:45:24
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:51: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:51:48
+ |
+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:51:61
+ |
+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:61:12
+ |
+LL | while (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:65:14
+ |
+LL | while (((let 0 = 1))) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:69:12
+ |
+LL | while (let 0 = 1) && true {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:73:20
+ |
+LL | while true && (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:77:12
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:77:27
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:83: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:83:51
+ |
+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:83:64
+ |
+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:110:9
+ |
+LL | if &let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:115:9
+ |
+LL | if !let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:118:9
+ |
+LL | if *let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:122:9
+ |
+LL | if -let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:132:9
+ |
+LL | if (let 0 = 0)? {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:138:16
+ |
+LL | if true || let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:141:17
+ |
+LL | if (true || let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:144:25
+ |
+LL | if true && (true || let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:147:25
+ |
+LL | if true || (true && let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:152:12
+ |
+LL | if x = let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:157:15
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:161:11
+ |
+LL | if ..(let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:165:9
+ |
+LL | if (let 0 = 0).. {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:196:19
+ |
+LL | if let true = let true = true {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:202:12
+ |
+LL | while &let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:207:12
+ |
+LL | while !let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:210:12
+ |
+LL | while *let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:214:12
+ |
+LL | while -let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:224:12
+ |
+LL | while (let 0 = 0)? {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:230:19
+ |
+LL | while true || let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:233:20
+ |
+LL | while (true || let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:236:28
+ |
+LL | while true && (true || let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:239:28
+ |
+LL | while true || (true && let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:244:15
+ |
+LL | while x = let 0 = 0 {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:249:18
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:253:14
+ |
+LL | while ..(let 0 = 0) {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:257:12
+ |
+LL | while (let 0 = 0).. {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:288:22
+ |
+LL | while let true = let true = true {}
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:304:6
+ |
+LL | &let 0 = 0;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:308:6
+ |
+LL | !let 0 = 0;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:311:6
+ |
+LL | *let 0 = 0;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:315:6
+ |
+LL | -let 0 = 0;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:325:6
+ |
+LL | (let 0 = 0)?;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:331:13
+ |
+LL | true || let 0 = 0;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:334:14
+ |
+LL | (true || let 0 = 0);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:337:22
+ |
+LL | true && (true || let 0 = 0);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:342:9
+ |
+LL | x = let 0 = 0;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:346:12
+ |
+LL | true..(let 0 = 0);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:349:8
+ |
+LL | ..(let 0 = 0);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:352:6
+ |
+LL | (let 0 = 0)..;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:356:6
+ |
+LL | (let Range { start: _, end: _ } = true..true || false);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:361:6
+ |
+LL | (let true = let true = true);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:361:17
+ |
+LL | (let true = let true = true);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:368:25
+ |
+LL | let x = true && let y = 1;
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:374:19
+ |
+LL | [1, 2, 3][let _ = ()]
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:379:6
+ |
+LL | &let 0 = 0
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:391:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:397:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:403:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:415:17
+ |
+LL | true && let 1 = 1
+ | ^^^
+
+error: expressions must be enclosed in braces to be used as const generic arguments
+ --> $DIR/disallowed-positions.rs:415: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:425:9
+ |
+LL | if (let Some(a) = opt && true) {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:430:9
+ |
+LL | if (let Some(a) = opt) && true {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:434:9
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:434:32
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:443:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:443:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:449:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:449:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:455:9
+ |
+LL | if (let Some(a) = opt && (true)) && true {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:472:22
+ |
+LL | let x = (true && let y = 1);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:477:20
+ |
+LL | ([1, 2, 3][let _ = ()])
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:99:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/disallowed-positions.rs:103:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^
+
+error: `let` expressions are not supported here
+ --> $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: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:33: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:33:11
+ |
+LL | if (((let 0 = 1))) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:37: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:37:9
+ |
+LL | if (let 0 = 1) && true {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:41: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:41:17
+ |
+LL | if true && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:45: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:45:9
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:45: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:45:24
+ |
+LL | if (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:51: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:51:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:51: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:51:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:51: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:51:35
+ |
+LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:61: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:61:12
+ |
+LL | while (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:65: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:65:14
+ |
+LL | while (((let 0 = 1))) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:69: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:69:12
+ |
+LL | while (let 0 = 1) && true {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:73: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:73:20
+ |
+LL | while true && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:77: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:77:12
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:77: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:77:27
+ |
+LL | while (let 0 = 1) && (let 0 = 1) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:83: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:83:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:83: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:83:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:83: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:83:38
+ |
+LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:99:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^
+ |
+ = 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:99:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:99:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^
+ |
+ = 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:99:16
+ |
+LL | use_expr!((let 0 = 1 && 0 == 0));
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:103:16
+ |
+LL | use_expr!((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:103:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:103:16
+ |
+LL | use_expr!((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:103:16
+ |
+LL | use_expr!((let 0 = 1));
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:110:9
+ |
+LL | if &let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:115:9
+ |
+LL | if !let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:118:9
+ |
+LL | if *let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:122:9
+ |
+LL | if -let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:132:9
+ |
+LL | if (let 0 = 0)? {}
+ | ^^^^^^^^^
+ |
+ = 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:132:9
+ |
+LL | if (let 0 = 0)? {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:138: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:138:13
+ |
+LL | if true || let 0 = 0 {}
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:141:17
+ |
+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:141:14
+ |
+LL | if (true || let 0 = 0) {}
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:144:25
+ |
+LL | if true && (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:144:22
+ |
+LL | if true && (true || let 0 = 0) {}
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:147:25
+ |
+LL | if true || (true && let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = 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:147:17
+ |
+LL | if true || (true && let 0 = 0) {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:152:12
+ |
+LL | if x = let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:157:15
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = 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:157:15
+ |
+LL | if true..(let 0 = 0) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:161:11
+ |
+LL | if ..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = 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:161:11
+ |
+LL | if ..(let 0 = 0) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:165:9
+ |
+LL | if (let 0 = 0).. {}
+ | ^^^^^^^^^
+ |
+ = 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:165:9
+ |
+LL | if (let 0 = 0).. {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:171:8
+ |
+LL | if let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:175:8
+ |
+LL | if let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:182:8
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:190:8
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:196:19
+ |
+LL | if let true = let true = true {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:202:12
+ |
+LL | while &let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:207:12
+ |
+LL | while !let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:210:12
+ |
+LL | while *let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:214:12
+ |
+LL | while -let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:224:12
+ |
+LL | while (let 0 = 0)? {}
+ | ^^^^^^^^^
+ |
+ = 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:224:12
+ |
+LL | while (let 0 = 0)? {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:230: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:230:16
+ |
+LL | while true || let 0 = 0 {}
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:233:20
+ |
+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:233:17
+ |
+LL | while (true || let 0 = 0) {}
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:236:28
+ |
+LL | while true && (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:236:25
+ |
+LL | while true && (true || let 0 = 0) {}
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:239:28
+ |
+LL | while true || (true && let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = 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:239:20
+ |
+LL | while true || (true && let 0 = 0) {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:244:15
+ |
+LL | while x = let 0 = 0 {}
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:249:18
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = 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:249:18
+ |
+LL | while true..(let 0 = 0) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:253:14
+ |
+LL | while ..(let 0 = 0) {}
+ | ^^^^^^^^^
+ |
+ = 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:253:14
+ |
+LL | while ..(let 0 = 0) {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:257:12
+ |
+LL | while (let 0 = 0).. {}
+ | ^^^^^^^^^
+ |
+ = 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:257:12
+ |
+LL | while (let 0 = 0).. {}
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:263:11
+ |
+LL | while let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:267:11
+ |
+LL | while let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:274:11
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:282:11
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:288:22
+ |
+LL | while let true = let true = true {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:304:6
+ |
+LL | &let 0 = 0;
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:308:6
+ |
+LL | !let 0 = 0;
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:311:6
+ |
+LL | *let 0 = 0;
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:315:6
+ |
+LL | -let 0 = 0;
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:325:6
+ |
+LL | (let 0 = 0)?;
+ | ^^^^^^^^^
+ |
+ = 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:325:6
+ |
+LL | (let 0 = 0)?;
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:331:13
+ |
+LL | 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:331:10
+ |
+LL | true || let 0 = 0;
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:334:14
+ |
+LL | (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:334:11
+ |
+LL | (true || let 0 = 0);
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:337:22
+ |
+LL | true && (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:337:19
+ |
+LL | true && (true || let 0 = 0);
+ | ^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:342:9
+ |
+LL | x = let 0 = 0;
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:346:12
+ |
+LL | true..(let 0 = 0);
+ | ^^^^^^^^^
+ |
+ = 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:346:12
+ |
+LL | true..(let 0 = 0);
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:349:8
+ |
+LL | ..(let 0 = 0);
+ | ^^^^^^^^^
+ |
+ = 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:349:8
+ |
+LL | ..(let 0 = 0);
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:352:6
+ |
+LL | (let 0 = 0)..;
+ | ^^^^^^^^^
+ |
+ = 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:352:6
+ |
+LL | (let 0 = 0)..;
+ | ^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:356:6
+ |
+LL | (let Range { start: _, end: _ } = true..true || false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:361:6
+ |
+LL | (let true = let 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:361:6
+ |
+LL | (let true = let true = true);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:379:6
+ |
+LL | &let 0 = 0
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:391:17
+ |
+LL | true && let 1 = 1
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:397:17
+ |
+LL | true && let 1 = 1
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:403:17
+ |
+LL | true && let 1 = 1
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:415:17
+ |
+LL | true && let 1 = 1
+ | ^^^^^^^^^
+ |
+ = note: only supported directly in conditions of `if` and `while` expressions
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:425: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:425:9
+ |
+LL | if (let Some(a) = opt && true) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:430: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:430:9
+ |
+LL | if (let Some(a) = opt) && true {
+ | ^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:434: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:434:9
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:434: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:434:32
+ |
+LL | if (let Some(a) = opt) && (let Some(b) = a) {
+ | ^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:443: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:443:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:443: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:443:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
+ | ^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:449: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:449:9
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:449: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:449:31
+ |
+LL | if (let Some(a) = opt && (let Some(b) = a)) && true {
+ | ^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/disallowed-positions.rs:455: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:455:9
+ |
+LL | if (let Some(a) = opt && (true)) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:110:8
+ |
+LL | if &let 0 = 0 {}
+ | ^^^^^^^^^^ expected `bool`, found `&bool`
+ |
+help: consider removing the borrow
+ |
+LL - if &let 0 = 0 {}
+LL + if let 0 = 0 {}
+ |
+
+error[E0614]: type `bool` cannot be dereferenced
+ --> $DIR/disallowed-positions.rs:118:8
+ |
+LL | if *let 0 = 0 {}
+ | ^^^^^^^^^^
+
+error[E0600]: cannot apply unary operator `-` to type `bool`
+ --> $DIR/disallowed-positions.rs:122:8
+ |
+LL | if -let 0 = 0 {}
+ | ^^^^^^^^^^ cannot apply unary operator `-`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:132:8
+ |
+LL | if (let 0 = 0)? {}
+ | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
+ |
+ = help: the trait `Try` is not implemented for `bool`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/disallowed-positions.rs:132:19
+ |
+LL | fn nested_within_if_expr() {
+ | -------------------------- this function should return `Result` or `Option` to accept `?`
+...
+LL | if (let 0 = 0)? {}
+ | ^ cannot use the `?` operator in a function that returns `()`
+ |
+ = help: the trait `FromResidual<_>` is not implemented for `()`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:152:8
+ |
+LL | if x = let 0 = 0 {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: you might have meant to compare for equality
+ |
+LL | if x == let 0 = 0 {}
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:157: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:161:8
+ |
+LL | if ..(let 0 = 0) {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeTo<bool>`
+ |
+ = note: expected type `bool`
+ found struct `RangeTo<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:165:8
+ |
+LL | if (let 0 = 0).. {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeFrom<bool>`
+ |
+ = note: expected type `bool`
+ found struct `RangeFrom<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:171: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:171:8
+ |
+LL | if let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:175: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:175:8
+ |
+LL | if let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:182: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:182:41
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^ expected `bool`, found closure
+ |
+ = note: expected type `bool`
+ found closure `[closure@$DIR/disallowed-positions.rs:182:41: 182:43]`
+help: use parentheses to call this closure
+ |
+LL | if let Range { start: F, end } = F..(|| true)() {}
+ | + +++
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:182:8
+ |
+LL | if let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:190: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[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:190:44
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^ expected `bool`, found `&&bool`
+ |
+help: consider removing the `&&`
+ |
+LL - if let Range { start: true, end } = t..&&false {}
+LL + if let Range { start: true, end } = t..false {}
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:190:8
+ |
+LL | if let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:128: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:202:11
+ |
+LL | while &let 0 = 0 {}
+ | ^^^^^^^^^^ expected `bool`, found `&bool`
+ |
+help: consider removing the borrow
+ |
+LL - while &let 0 = 0 {}
+LL + while let 0 = 0 {}
+ |
+
+error[E0614]: type `bool` cannot be dereferenced
+ --> $DIR/disallowed-positions.rs:210:11
+ |
+LL | while *let 0 = 0 {}
+ | ^^^^^^^^^^
+
+error[E0600]: cannot apply unary operator `-` to type `bool`
+ --> $DIR/disallowed-positions.rs:214:11
+ |
+LL | while -let 0 = 0 {}
+ | ^^^^^^^^^^ cannot apply unary operator `-`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:224:11
+ |
+LL | while (let 0 = 0)? {}
+ | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
+ |
+ = help: the trait `Try` is not implemented for `bool`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/disallowed-positions.rs:224:22
+ |
+LL | fn nested_within_while_expr() {
+ | ----------------------------- this function should return `Result` or `Option` to accept `?`
+...
+LL | while (let 0 = 0)? {}
+ | ^ cannot use the `?` operator in a function that returns `()`
+ |
+ = help: the trait `FromResidual<_>` is not implemented for `()`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:244:11
+ |
+LL | while x = let 0 = 0 {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: you might have meant to compare for equality
+ |
+LL | while x == let 0 = 0 {}
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:249: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:253:11
+ |
+LL | while ..(let 0 = 0) {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeTo<bool>`
+ |
+ = note: expected type `bool`
+ found struct `RangeTo<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:257:11
+ |
+LL | while (let 0 = 0).. {}
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeFrom<bool>`
+ |
+ = note: expected type `bool`
+ found struct `RangeFrom<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:263: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:263:11
+ |
+LL | while let Range { start: _, end: _ } = true..true && false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:267: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:267:11
+ |
+LL | while let Range { start: _, end: _ } = true..true || false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:274: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:274:44
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^ expected `bool`, found closure
+ |
+ = note: expected type `bool`
+ found closure `[closure@$DIR/disallowed-positions.rs:274:44: 274:46]`
+help: use parentheses to call this closure
+ |
+LL | while let Range { start: F, end } = F..(|| true)() {}
+ | + +++
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:274:11
+ |
+LL | while let Range { start: F, end } = F..|| true {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:282: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[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:282:47
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^ expected `bool`, found `&&bool`
+ |
+help: consider removing the `&&`
+ |
+LL - while let Range { start: true, end } = t..&&false {}
+LL + while let Range { start: true, end } = t..false {}
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:282:11
+ |
+LL | while let Range { start: true, end } = t..&&false {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<bool>`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:220:23
+ |
+LL | while let 0 = 0? {}
+ | ^^ the `?` operator cannot be applied to type `{integer}`
+ |
+ = help: the trait `Try` is not implemented for `{integer}`
+
+error[E0614]: type `bool` cannot be dereferenced
+ --> $DIR/disallowed-positions.rs:311:5
+ |
+LL | *let 0 = 0;
+ | ^^^^^^^^^^
+
+error[E0600]: cannot apply unary operator `-` to type `bool`
+ --> $DIR/disallowed-positions.rs:315:5
+ |
+LL | -let 0 = 0;
+ | ^^^^^^^^^^ cannot apply unary operator `-`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:325:5
+ |
+LL | (let 0 = 0)?;
+ | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
+ |
+ = help: the trait `Try` is not implemented for `bool`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+ --> $DIR/disallowed-positions.rs:325:16
+ |
+LL | fn outside_if_and_while_expr() {
+ | ------------------------------ this function should return `Result` or `Option` to accept `?`
+...
+LL | (let 0 = 0)?;
+ | ^ cannot use the `?` operator in a function that returns `()`
+ |
+ = help: the trait `FromResidual<_>` is not implemented for `()`
+
+error[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:356: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[E0308]: mismatched types
+ --> $DIR/disallowed-positions.rs:379:5
+ |
+LL | fn outside_if_and_while_expr() {
+ | - help: try adding a return type: `-> &bool`
+...
+LL | &let 0 = 0
+ | ^^^^^^^^^^ expected `()`, found `&bool`
+
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+ --> $DIR/disallowed-positions.rs:321: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 215 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0600, E0614.
+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..2a6c14435
--- /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,55 @@
+#![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 `let` expressions are not supported here
+ //~| 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..9bc3e7541
--- /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,147 @@
+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 {
+ | ^^^
+
+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:24: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:24: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:28: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:28: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:32: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:32: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:38: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:44: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:50: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: `let` expressions are not supported here
+ --> $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[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 14 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..2b407ef51
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
@@ -0,0 +1,62 @@
+// 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 `let` expressions in this position are unstable [E0658]
+ //~| ERROR expected expression, found `let` statement
+
+ macro_rules! use_expr {
+ ($e:expr) => {
+ if $e {}
+ while $e {}
+ }
+ }
+ #[cfg(FALSE)] (let 0 = 1);
+ //~^ ERROR `let` expressions in this position are unstable [E0658]
+ //~| 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..7a43b71fc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
@@ -0,0 +1,120 @@
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:55:20
+ |
+LL | #[cfg(FALSE)] (let 0 = 1);
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/feature-gate.rs:45:17
+ |
+LL | noop_expr!((let 0 = 1));
+ | ^^^
+
+error: no rules expected the token `let`
+ --> $DIR/feature-gate.rs:58: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:50: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[E0658]: `let` expressions in this position are unstable
+ --> $DIR/feature-gate.rs:55:20
+ |
+LL | #[cfg(FALSE)] (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:45:17
+ |
+LL | noop_expr!((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: aborting due to 13 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..a942d1f4c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
@@ -0,0 +1,45 @@
+#![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
+ 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
+ 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..d1ce83c72
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr
@@ -0,0 +1,38 @@
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:8:19
+ |
+LL | let _ = &&let Some(x) = Some(42);
+ | ^^^
+
+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 {
+ | ^^^
+
+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 {
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:23:23
+ |
+LL | [1, 2, 3][let _ = ()];
+ | ^^^
+
+error: expected expression, found `let` statement
+ --> $DIR/invalid-let-in-a-valid-let-context.rs:32:47
+ |
+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:40:21
+ |
+LL | let x = let y = 1;
+ | ^^^
+
+error: aborting due to 6 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-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..82c4120b4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs
@@ -0,0 +1,43 @@
+// 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..593821bf9
--- /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 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..d7a418959
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
@@ -0,0 +1,19 @@
+// 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"
+#[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..020ac6a2b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr
@@ -0,0 +1,5 @@
+error: Dlltool could not create import library:
+ $DLLTOOL: Syntax error in def file $DEF_FILE:1
+
+error: aborting due to 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..fb70b987f
--- /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 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..953306189
--- /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 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..2bce9758e
--- /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 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..b56449299
--- /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 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..3ae901e0d
--- /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 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..510108405
--- /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 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..b635a09af
--- /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 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..f8265ae69
--- /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 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..780a510c5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
@@ -0,0 +1,14 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[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.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..0cffae1da
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -0,0 +1,8 @@
+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 previous error
+
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..e73082c11
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
@@ -0,0 +1,23 @@
+#![feature(const_trait_impl)]
+
+#[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..589e3f024
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
@@ -0,0 +1,19 @@
+#![feature(const_trait_impl)]
+#![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..dd9933974
--- /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)]
+
+#[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..7350909ba
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
+ --> $DIR/call-const-trait-method-fail.rs:25:7
+ |
+LL | a.plus(b)
+ | ^^^^ the trait `~const Plus` is not implemented for `u32`
+ |
+note: the trait `Plus` is implemented for `u32`, but that implementation is not `const`
+ --> $DIR/call-const-trait-method-fail.rs:25:7
+ |
+LL | a.plus(b)
+ | ^^^^
+
+error: aborting due to 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..ff53eea11
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-pass.stderr
@@ -0,0 +1,20 @@
+error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
+ --> $DIR/call-const-trait-method-pass.rs:7:12
+ |
+LL | impl const std::ops::Add for Int {
+ | ^^^^^^^^^^^^^
+ |
+ = 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 `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/call-const-trait-method-pass.rs:15:12
+ |
+LL | impl const PartialEq for Int {
+ | ^^^^^^^^^
+ |
+ = 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 2 previous errors
+
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..5120e6bfb
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs
@@ -0,0 +1,15 @@
+// known-bug: #110395
+#![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-in-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr
new file mode 100644
index 000000000..02d53cc78
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/call-generic-in-impl.rs:9:16
+ |
+LL | impl<T: ~const PartialEq> const MyPartialEq for T {
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
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..3febb328a
--- /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`.
+
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+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-chain.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr
new file mode 100644
index 000000000..529a472e0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr
@@ -0,0 +1,23 @@
+error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/call-generic-method-chain.rs:9:12
+ |
+LL | impl const PartialEq for S {
+ | ^^^^^^^^^
+ |
+ = 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/call-generic-method-chain.rs:18:32
+ |
+LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/call-generic-method-chain.rs:22:40
+ |
+LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
+ | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
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..e618160d3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
@@ -0,0 +1,31 @@
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+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-dup-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr
new file mode 100644
index 000000000..bdc6ccc8a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr
@@ -0,0 +1,23 @@
+error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/call-generic-method-dup-bound.rs:7:12
+ |
+LL | impl const PartialEq for S {
+ | ^^^^^^^^^
+ |
+ = 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/call-generic-method-dup-bound.rs:18:44
+ |
+LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/call-generic-method-dup-bound.rs:25:37
+ |
+LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+ | ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
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..fe1abbf42
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs
@@ -0,0 +1,9 @@
+// known-bug: #110395
+#![feature(const_trait_impl)]
+
+pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
+ *t == *t
+ // (remove this) ~^ ERROR can't compare
+}
+
+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..3963f64ad
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -0,0 +1,28 @@
+error[E0277]: can't compare `T` with `T` in const contexts
+ --> $DIR/call-generic-method-fail.rs:5:5
+ |
+LL | *t == *t
+ | ^^^^^^^^ no implementation for `T == T`
+ |
+note: the trait `PartialEq` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/call-generic-method-fail.rs:5:5
+ |
+LL | *t == *t
+ | ^^^^^^^^
+
+error[E0015]: cannot call non-const operator in constant functions
+ --> $DIR/call-generic-method-fail.rs:5:5
+ |
+LL | *t == *t
+ | ^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+help: consider further restricting this bound
+ |
+LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
+ | ++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
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..414a8c87d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -0,0 +1,26 @@
+#![feature(const_trait_impl)]
+
+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
+
+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..a28d6ce05
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+ --> $DIR/call-generic-method-nonconst.rs:23:22
+ |
+LL | pub const EQ: bool = equals_self(&S);
+ | ^^^^^^^^^^^^^^^ the trait `~const Foo` is not implemented for `S`
+ |
+note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
+ --> $DIR/call-generic-method-nonconst.rs:23:22
+ |
+LL | pub const EQ: bool = equals_self(&S);
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 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..09f35a277
--- /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`.
+
+// known-bug: #110395
+
+#![feature(const_trait_impl)]
+
+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-generic-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr
new file mode 100644
index 000000000..7fbe89dba
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr
@@ -0,0 +1,17 @@
+error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/call-generic-method-pass.rs:9:12
+ |
+LL | impl const PartialEq for S {
+ | ^^^^^^^^^
+ |
+ = 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/call-generic-method-pass.rs:18:32
+ |
+LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+ | ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
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..4f858d61e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
@@ -0,0 +1,20 @@
+error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
+ --> $DIR/const-and-non-const-impl.rs:7:12
+ |
+LL | impl const std::ops::Add for i32 {
+ | ^^^^^^^^^^^^^
+ |
+ = 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 `Add` which is not marked with `#[const_trait]`
+ --> $DIR/const-and-non-const-impl.rs:23:12
+ |
+LL | impl const std::ops::Add for Int {
+ | ^^^^^^^^^^^^^
+ |
+ = 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 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..52984fb6b
--- /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)]
+
+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..c8783de4c
--- /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 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..2c99d8bf1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
@@ -0,0 +1,10 @@
+// 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-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..112416a35
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied in `fn(()) -> i32 {<() as Tr>::a}`
+ --> $DIR/const-closure-trait-method-fail.rs:18:23
+ |
+LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()`
+ |
+note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
+ --> $DIR/const-closure-trait-method-fail.rs:18:23
+ |
+LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it appears within the type `fn(()) -> i32 {<() as Tr>::a}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..3e6d19088
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs
@@ -0,0 +1,19 @@
+// 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-closures.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs
new file mode 100644
index 000000000..7c55b51c8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs
@@ -0,0 +1,30 @@
+// 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-default-method-bodies.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs
new file mode 100644
index 000000000..140a06a73
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.rs
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl)]
+
+#[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..f9d0d1f78
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -0,0 +1,15 @@
+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`
+ |
+note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
+ --> $DIR/const-default-method-bodies.rs:24:5
+ |
+LL | NonConstImpl.a();
+ | ^^^^^^^^^^^^
+
+error: aborting due to 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..948f0efbc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.rs
@@ -0,0 +1,25 @@
+// 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-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..3de9d37d4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs
@@ -0,0 +1,43 @@
+// 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 {}
+
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ fn drop(&mut self) {
+ T::a();
+ }
+}
+
+const fn check<T: ~const Destruct>(_: T) {}
+
+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..375f5d2c5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr
@@ -0,0 +1,50 @@
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+ --> $DIR/const-drop-fail-2.rs:31:23
+ |
+LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+ |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail-2.rs:31:23
+ |
+LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail-2.rs:21:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+ --> $DIR/const-drop-fail-2.rs:32:5
+ |
+LL | ConstDropImplWithBounds(PhantomData)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+ |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail-2.rs:32:5
+ |
+LL | ConstDropImplWithBounds(PhantomData)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail-2.rs:21:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+ --> $DIR/const-drop-fail-2.rs:37:9
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+ | ^^^^^^^^
+ |
+note: the implementor must specify the same requirement
+ --> $DIR/const-drop-fail-2.rs:35:1
+ |
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
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..e745cbd24
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -0,0 +1,58 @@
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+ |
+note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+ = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+ |
+note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+note: required because it appears within the type `ConstImplWithDropGlue`
+ --> $DIR/const-drop-fail.rs:18:8
+ |
+LL | struct ConstImplWithDropGlue(NonTrivialDrop);
+ | ^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/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..e745cbd24
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -0,0 +1,58 @@
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+ |
+note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+ = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: can't drop `NonTrivialDrop` in const contexts
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+ |
+note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:28:23
+ |
+LL | const _: () = check($exp);
+ | ^^^^^^^^^^^
+...
+LL | / check_all! {
+LL | | NonTrivialDrop,
+LL | | ConstImplWithDropGlue(NonTrivialDrop),
+LL | | }
+ | |_- in this macro invocation
+note: required because it appears within the type `ConstImplWithDropGlue`
+ --> $DIR/const-drop-fail.rs:18:8
+ |
+LL | struct ConstImplWithDropGlue(NonTrivialDrop);
+ | ^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/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..b0fc3adf9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs
@@ -0,0 +1,113 @@
+// run-pass
+// 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) {}
+
+const fn b() -> u8 {
+ let mut c = 0;
+ let _ = S(&mut c);
+ 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() {}
+ }
+
+ 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-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..603f6b7d2
--- /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 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..2b4963991
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+pub trait A {}
+//~^ HELP: mark `A` as const
+
+impl const A for () {}
+//~^ 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..478adcf3e
--- /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:6: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 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..f396deff4
--- /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,
+ const_cmp,
+ return_position_impl_trait_in_trait,
+)]
+
+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..f9078e227
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
@@ -0,0 +1,39 @@
+error[E0635]: unknown feature `const_cmp`
+ --> $DIR/const-impl-trait.rs:6:5
+ |
+LL | const_cmp,
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-impl-trait.rs:12:30
+ |
+LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-impl-trait.rs:16:30
+ |
+LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-impl-trait.rs:17:20
+ |
+LL | -> impl ~const PartialEq + ~const Destruct
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-impl-trait.rs:24:29
+ |
+LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+ | ^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/const-impl-trait.rs:28:29
+ |
+LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+ | ^^^^^^^^^
+
+error: aborting due to 6 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-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
new file mode 100644
index 000000000..dba3ad7f8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
@@ -0,0 +1,5 @@
+#[derive_const(Default)] //~ ERROR use of unstable library feature
+//~^ ERROR not marked with `#[const_trait]`
+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..6a81f96d8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
@@ -0,0 +1,21 @@
+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: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-gate.rs:1: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 2 previous errors
+
+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..b575ea8da
--- /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)]
+
+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..1c69ad431
--- /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 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..69098542b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
@@ -0,0 +1,19 @@
+// known-bug: #110395
+#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+
+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..88054096e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
@@ -0,0 +1,53 @@
+error[E0635]: unknown feature `const_cmp`
+ --> $DIR/derive-const-use.rs:2:30
+ |
+LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+ | ^^^^^^^^^
+
+error[E0635]: unknown feature `const_default_impls`
+ --> $DIR/derive-const-use.rs:2:41
+ |
+LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-use.rs:6: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 `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-use.rs:10:12
+ |
+LL | impl const PartialEq 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:14: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: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-use.rs:14:25
+ |
+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 `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 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..2a5d0176b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
@@ -0,0 +1,13 @@
+// known-bug: #110395
+
+#![feature(derive_const)]
+#![feature(const_trait_impl)]
+
+#[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/const_derives/derive-const-with-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr
new file mode 100644
index 000000000..fa7832658
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr
@@ -0,0 +1,20 @@
+error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
+ --> $DIR/derive-const-with-params.rs:6:16
+ |
+LL | #[derive_const(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 `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/derive-const-with-params.rs:6:16
+ |
+LL | #[derive_const(PartialEq)]
+ | ^^^^^^^^^
+ |
+ = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
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..633b7cc25
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -0,0 +1,15 @@
+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`
+ |
+note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
+ --> $DIR/cross-crate.rs:17:5
+ |
+LL | NonConst.func();
+ | ^^^^^^^^
+
+error: aborting due to 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..6df47022c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.rs
@@ -0,0 +1,24 @@
+// revisions: stock gated stocknc gatednc
+// [gated] check-pass
+#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))]
+
+// 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: the trait bound
+ //[gatednc]~^^ ERROR: the trait bound
+ Const.func();
+ //[stock]~^ 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..22f13a741
--- /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 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..9e97d3f11
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `cross_crate::NonConst: 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`
+ |
+note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
+ --> $DIR/cross-crate.rs:17:5
+ |
+LL | NonConst.func();
+ | ^^^^^^^^
+
+error: aborting due to 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-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..96acdc300
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
@@ -0,0 +1,17 @@
+#![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::<()>();
+ //~^ ERROR the trait bound `(): ~const Tr` is not satisfied
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
new file mode 100644
index 000000000..26644f72c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): ~const Tr` is not satisfied
+ --> $DIR/default-method-body-is-const-body-checking.rs:12:9
+ |
+LL | foo::<()>();
+ | ^^^^^^^^^^^ the trait `~const Tr` is not implemented for `()`
+ |
+note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
+ --> $DIR/default-method-body-is-const-body-checking.rs:12:9
+ |
+LL | foo::<()>();
+ | ^^^^^^^^^^^
+
+error: aborting due to 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-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..f70ecbc37
--- /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)]
+
+#[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..21ecddaff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -0,0 +1,15 @@
+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 `()`
+ |
+note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
+ --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+ |
+LL | ().a()
+ | ^^
+
+error: aborting due to 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..1b45cd9aa
--- /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(since = "1", feature = "foo")]
+
+#[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..730e268c0
--- /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)]
+
+#[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/helloworld.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs
new file mode 100644
index 000000000..49457354c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs
@@ -0,0 +1,29 @@
+// 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, rustc_attrs)]
+
+// ensure we are passing in the correct host effect in always const contexts.
+
+pub const fn hmm</* T, */ #[rustc_host] const host: bool = true>() -> usize {
+ if host {
+ 1
+ } else {
+ 0
+ }
+}
+
+const _: () = {
+ let x = hmm();
+ assert!(0 == x);
+};
+
+/* FIXME(effects)
+pub const fn uwu(x: [u8; hmm::<()>()]) {
+ let [] = x;
+}
+*/
+
+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..4c630d33c
--- /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 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..1b21d7c0e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr
@@ -0,0 +1,11 @@
+error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
+ --> $DIR/generic-bound.rs:16:15
+ |
+LL | impl<T> const std::ops::Add for S<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 previous error
+
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..337c73340
--- /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)]
+
+#[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..6d2be1daa
--- /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 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..0a91719e1
--- /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 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..6c6ca9f5d
--- /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 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..8bf00eaff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -0,0 +1,19 @@
+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: consider adding `extern crate core` to use the `core` crate
+
+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: consider adding `extern crate core` to use the `core` 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-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..07d3f51ed
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs
@@ -0,0 +1,12 @@
+#![feature(const_trait_impl)]
+
+struct Bug {
+ inner: [(); match || 1 {
+ n => n(),
+ //~^ ERROR the trait bound
+ //~| ERROR the trait bound
+ //~| 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..b98ccbe5d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr
@@ -0,0 +1,41 @@
+error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+ |
+ = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const`
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^
+ = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+ |
+ = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const`
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^
+ = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0015]: cannot call non-const closure in constants
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^
+ |
+ = note: closures need an RFC before allowed to be called in constants
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an 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..082c0333f
--- /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 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..b132c395a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs
@@ -0,0 +1,13 @@
+#![feature(const_trait_impl)]
+
+pub trait A {
+ fn assoc() -> bool;
+}
+
+pub const fn foo<T: A>() -> bool {
+ T::assoc()
+ //~^ ERROR the trait bound
+ //~| 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..955923505
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: ~const A` is not satisfied
+ --> $DIR/issue-88155.rs:8:5
+ |
+LL | T::assoc()
+ | ^^^^^^^^^^ the trait `~const A` is not implemented for `T`
+ |
+note: the trait `A` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/issue-88155.rs:8:5
+ |
+LL | T::assoc()
+ | ^^^^^^^^^^
+
+error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
+ --> $DIR/issue-88155.rs:8:5
+ |
+LL | T::assoc()
+ | ^^^^^^^^^^
+ |
+ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs
new file mode 100644
index 000000000..21ddf4ab4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+fn foo<T>() where T: ~const Bar {}
+//~^ ERROR `~const` is not allowed
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr
new file mode 100644
index 000000000..b2a936537
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+ --> $DIR/issue-90052.rs:6:22
+ |
+LL | fn foo<T>() where T: ~const Bar {}
+ | ^^^^^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/issue-90052.rs:6:4
+ |
+LL | fn foo<T>() where T: ~const Bar {}
+ | ^^^
+
+error: aborting due to previous error
+
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..96a3e386e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs
@@ -0,0 +1,23 @@
+// Regression test for #92111.
+//
+// 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-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..bd0dd126c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr
@@ -0,0 +1,26 @@
+error[E0277]: can't compare `str` with `str` in const contexts
+ --> $DIR/match-non-const-eq.rs:6:9
+ |
+LL | "a" => (),
+ | ^^^ no implementation for `str == str`
+ |
+ = help: the trait `~const PartialEq` is not implemented for `str`
+note: the trait `PartialEq` is implemented for `str`, but that implementation is not `const`
+ --> $DIR/match-non-const-eq.rs:6:9
+ |
+LL | "a" => (),
+ | ^^^
+
+error[E0015]: cannot match on `str` in constant functions
+ --> $DIR/match-non-const-eq.rs:6:9
+ |
+LL | "a" => (),
+ | ^^^
+ |
+ = 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 2 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an 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..0d04101a3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs
@@ -0,0 +1,12 @@
+// revisions: stock gated
+#![cfg_attr(gated, feature(const_trait_impl))]
+
+const fn foo(input: &'static str) {
+ match input {
+ "a" => (), //[gated]~ ERROR can't compare `str` with `str` in const contexts
+ //~^ 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..dcb9b49ea
--- /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:6:9
+ |
+LL | "a" => (),
+ | ^^^
+ |
+ = 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 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..979d7febb
--- /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 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..cfdda4713
--- /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 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..f31123f16
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs
@@ -0,0 +1,58 @@
+// 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.
+
+#![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();
+}
+
+// bgr360: I was only able to exercise the code path that raises the
+// "missing ~const qualifier" error by making this base impl non-const, even
+// though that doesn't really make sense to do. As seen below, if the base impl
+// is made const, rustc fails earlier with an overlapping impl failure.
+impl<T> Bar for T
+where
+ T: ~const Foo,
+{
+ default fn bar() {}
+}
+
+impl<T> Bar for T
+where
+ T: Foo, //~ 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 //~ 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-bound-non-const-specialized-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
new file mode 100644
index 000000000..057cf4aea
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
@@ -0,0 +1,18 @@
+error: missing `~const` qualifier for specialization
+ --> $DIR/const-default-bound-non-const-specialized-bound.rs:32:8
+ |
+LL | T: Foo,
+ | ^^^
+
+error[E0119]: conflicting implementations of trait `Baz`
+ --> $DIR/const-default-bound-non-const-specialized-bound.rs:50:1
+ |
+LL | impl<T> const Baz for T
+ | ----------------------- first implementation here
+...
+LL | impl<T> const Baz for T
+ | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
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..9ddea427c
--- /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)]
+#![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..a3bb9b3f9
--- /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)]
+#![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..247668047
--- /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 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..35aa52fbd
--- /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.
+
+// run-pass
+
+#![feature(const_trait_impl)]
+#![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/specializing-constness-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.rs
new file mode 100644
index 000000000..633543700
--- /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)]
+
+#[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();
+ //~^ 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..8923416f4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `T: ~const Sup` is not satisfied
+ --> $DIR/specializing-constness-2.rs:27:5
+ |
+LL | <T as A>::a();
+ | ^^^^^^^^^^^^^ the trait `~const Sup` is not implemented for `T`
+ |
+note: required for `T` to implement `~const A`
+ --> $DIR/specializing-constness-2.rs:20:37
+ |
+LL | impl<T: Default + ~const Sup> const A for T {
+ | ---------- ^ ^
+ | |
+ | unsatisfied trait bound introduced here
+help: consider further restricting this bound
+ |
+LL | const fn generic<T: Default + ~const Sup>() {
+ | ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..5c2a3f801
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs
@@ -0,0 +1,31 @@
+#![feature(const_trait_impl, 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
+//~| 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..1ffdc50e5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr
@@ -0,0 +1,14 @@
+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: missing `~const` qualifier for specialization
+ --> $DIR/specializing-constness.rs:23:9
+ |
+LL | impl<T: Spec + Sup> A for T {
+ | ^^^^
+
+error: aborting due to 2 previous errors
+
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..d7aa0d95c
--- /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 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..1d79f5adf
--- /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)]
+#![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..78aab9469
--- /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 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..6a3396401
--- /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 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..97f346e8c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
@@ -0,0 +1,14 @@
+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 {}
+ | ^^^
+
+error: aborting due to 2 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..97f346e8c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
@@ -0,0 +1,14 @@
+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 {}
+ | ^^^
+
+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..ecb06271c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs
@@ -0,0 +1,20 @@
+#![feature(const_trait_impl)]
+
+// 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 {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]`
+
+const fn foo<T: Bar>(x: &T) {
+ x.a();
+ //[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..c9fa19554
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail-2.rs:16:7
+ |
+LL | x.a();
+ | ^ the trait `~const Foo` is not implemented for `T`
+ |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/super-traits-fail-2.rs:16:5
+ |
+LL | x.a();
+ | ^
+help: consider further restricting this bound
+ |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+ | ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..c9fa19554
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail-2.rs:16:7
+ |
+LL | x.a();
+ | ^ the trait `~const Foo` is not implemented for `T`
+ |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/super-traits-fail-2.rs:16:5
+ |
+LL | x.a();
+ | ^
+help: consider further restricting this bound
+ |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+ | ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..fdc6b8058
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -0,0 +1,20 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:12:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:12:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:16:24
+ |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+ | ^^^
+
+error: aborting due to 3 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..7375b8c81
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
@@ -0,0 +1,14 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:12:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:12:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+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..8cf64944a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs
@@ -0,0 +1,21 @@
+#![feature(const_trait_impl)]
+
+// revisions: yy yn ny nn
+//[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]`
+
+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..7a152914b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:16:24
+ |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+ | ^^^
+
+error: aborting due to previous error
+
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..3e2b81368
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs
@@ -0,0 +1,18 @@
+#![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 {}
+//~^ ERROR the trait bound
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr
new file mode 100644
index 000000000..bf12ef1ca
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail.rs:15:20
+ |
+LL | impl const Bar for S {}
+ | ^ the trait `~const Foo` is not implemented for `S`
+ |
+note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
+ --> $DIR/super-traits-fail.rs:15:20
+ |
+LL | impl const Bar for S {}
+ | ^
+note: required by a bound in `Bar`
+ --> $DIR/super-traits-fail.rs:8:12
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^^^^^^^^ required by this bound in `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..df96f6fb4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs
@@ -0,0 +1,25 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[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..78a64b901
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
@@ -0,0 +1,34 @@
+#![feature(const_trait_impl)]
+#![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) }> {
+ 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
+ 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..aae72f36e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-and-const-params.rs:25: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:25:4
+ |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ | ^^^
+
+error: aborting due to previous error
+
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..95f7aaba0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
@@ -0,0 +1,7 @@
+#![feature(const_trait_impl)]
+#![feature(associated_type_bounds)]
+
+struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+//~^ ERROR `~const` and `?` are mutually exclusive
+
+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..d20f146df
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -0,0 +1,8 @@
+error: `~const` and `?` are mutually exclusive
+ --> $DIR/tilde-const-invalid-places.rs:4:25
+ |
+LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 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..928d23e8a
--- /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 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..285cef571
--- /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)]
+
+#[const_trait]
+trait Foo {
+ fn foo(&self) {}
+}
+
+struct Bar<T>(T);
+
+impl<T: ~const Foo> Bar<T> {
+ const fn foo(&self) {
+ 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..35dc1ca12
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-default-body-stability.stderr
@@ -0,0 +1,20 @@
+error: const `impl` for trait `Try` which is not marked with `#[const_trait]`
+ --> $DIR/trait-default-body-stability.rs:18:12
+ |
+LL | impl const Try for 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 `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
+ --> $DIR/trait-default-body-stability.rs:33:12
+ |
+LL | impl const FromResidual for 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 2 previous errors
+
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..bfe98b98c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs
@@ -0,0 +1,31 @@
+// 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.
+#![feature(const_trait_impl)]
+
+#[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();
+ //~^ ERROR the trait bound
+ T::c::<T>();
+ //~^ 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..f2846b6a6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+ --> $DIR/trait-where-clause-const.rs:19:5
+ |
+LL | T::b();
+ | ^^^^^^ the trait `~const Bar` is not implemented for `T`
+ |
+note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/trait-where-clause-const.rs:19:5
+ |
+LL | T::b();
+ | ^^^^^^
+help: consider further restricting this bound
+ |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+ | ++++++++++++
+
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+ --> $DIR/trait-where-clause-const.rs:21:5
+ |
+LL | T::c::<T>();
+ | ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
+ |
+note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/trait-where-clause-const.rs:21:5
+ |
+LL | T::c::<T>();
+ | ^^^^^^^^^^^
+help: consider further restricting this bound
+ |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+ | ++++++++++++
+
+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/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..4b8b00406
--- /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)]
+
+#[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..3b028ac48
--- /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)]
+
+#[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..85ca5fc90
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -0,0 +1,26 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+trait Foo {
+ fn a();
+ fn b() where Self: ~const Bar;
+ fn c<T: ~const Bar>();
+}
+
+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..11f0c4016
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `T: Bar` is not satisfied
+ --> $DIR/trait-where-clause.rs:14: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:16: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:9: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 2 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..31300354a
--- /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 previous error
+