summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
commita4b7ed7a42c716ab9f05e351f003d589124fd55d (patch)
treeb620cd3f223850b28716e474e80c58059dca5dd4 /tests/ui/traits
parentAdding upstream version 1.67.1+dfsg1. (diff)
downloadrustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.tar.xz
rustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.zip
Adding upstream version 1.68.2+dfsg1.upstream/1.68.2+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/traits')
-rw-r--r--tests/ui/traits/alias/ambiguous.rs24
-rw-r--r--tests/ui/traits/alias/ambiguous.stderr28
-rw-r--r--tests/ui/traits/alias/auxiliary/greeter.rs13
-rw-r--r--tests/ui/traits/alias/auxiliary/send_sync.rs3
-rw-r--r--tests/ui/traits/alias/basic.rs8
-rw-r--r--tests/ui/traits/alias/bounds.rs57
-rw-r--r--tests/ui/traits/alias/cross-crate.rs17
-rw-r--r--tests/ui/traits/alias/cross-crate.stderr31
-rw-r--r--tests/ui/traits/alias/generic-default-in-dyn.rs10
-rw-r--r--tests/ui/traits/alias/generic-default-in-dyn.stderr35
-rw-r--r--tests/ui/traits/alias/impl.rs7
-rw-r--r--tests/ui/traits/alias/impl.stderr9
-rw-r--r--tests/ui/traits/alias/import-cross-crate.rs14
-rw-r--r--tests/ui/traits/alias/import.rs40
-rw-r--r--tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs19
-rw-r--r--tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs14
-rw-r--r--tests/ui/traits/alias/issue-75983.rs17
-rw-r--r--tests/ui/traits/alias/issue-83613.rs12
-rw-r--r--tests/ui/traits/alias/issue-83613.stderr11
-rw-r--r--tests/ui/traits/alias/maybe-bound.rs29
-rw-r--r--tests/ui/traits/alias/no-duplicates.rs126
-rw-r--r--tests/ui/traits/alias/no-duplicates.stderr527
-rw-r--r--tests/ui/traits/alias/no-extra-traits.rs121
-rw-r--r--tests/ui/traits/alias/no-extra-traits.stderr579
-rw-r--r--tests/ui/traits/alias/object-fail.rs11
-rw-r--r--tests/ui/traits/alias/object-fail.stderr21
-rw-r--r--tests/ui/traits/alias/object-wf.rs85
-rw-r--r--tests/ui/traits/alias/object.rs18
-rw-r--r--tests/ui/traits/alias/only-maybe-bound.rs22
-rw-r--r--tests/ui/traits/alias/only-maybe-bound.stderr21
-rw-r--r--tests/ui/traits/alias/self-in-const-generics.rs12
-rw-r--r--tests/ui/traits/alias/self-in-const-generics.stderr11
-rw-r--r--tests/ui/traits/alias/self-in-generics.rs15
-rw-r--r--tests/ui/traits/alias/self-in-generics.stderr11
-rw-r--r--tests/ui/traits/alias/style_lint.rs8
-rw-r--r--tests/ui/traits/alias/style_lint.stderr10
-rw-r--r--tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed13
-rw-r--r--tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs13
-rw-r--r--tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr14
-rw-r--r--tests/ui/traits/alias/syntax-fail.rs10
-rw-r--r--tests/ui/traits/alias/syntax-fail.stderr26
-rw-r--r--tests/ui/traits/alias/syntax.rs24
-rw-r--r--tests/ui/traits/alias/wf.rs7
-rw-r--r--tests/ui/traits/alias/wf.stderr19
-rw-r--r--tests/ui/traits/alignment-gep-tup-like-1.rs37
-rw-r--r--tests/ui/traits/anon-static-method.rs15
-rw-r--r--tests/ui/traits/anon_trait_static_method_exe.rs12
-rw-r--r--tests/ui/traits/as-struct-constructor.rs6
-rw-r--r--tests/ui/traits/as-struct-constructor.stderr9
-rw-r--r--tests/ui/traits/assignability-trait.rs47
-rw-r--r--tests/ui/traits/assoc-type-in-superbad.rs16
-rw-r--r--tests/ui/traits/assoc-type-in-superbad.stderr15
-rw-r--r--tests/ui/traits/assoc-type-in-supertrait.rs23
-rw-r--r--tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs23
-rw-r--r--tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr91
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs14
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr16
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs15
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs15
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr16
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs20
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr15
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs17
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr16
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs27
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr22
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs24
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr22
-rw-r--r--tests/ui/traits/associated_type_bound/issue-51446.rs34
-rw-r--r--tests/ui/traits/astconv-cycle-between-and-type.rs29
-rw-r--r--tests/ui/traits/augmented-assignments-trait.rs12
-rw-r--r--tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs9
-rw-r--r--tests/ui/traits/auxiliary/go_trait.rs43
-rw-r--r--tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs60
-rw-r--r--tests/ui/traits/auxiliary/trait_safety_lib.rs9
-rw-r--r--tests/ui/traits/auxiliary/traitimpl.rs7
-rw-r--r--tests/ui/traits/bad-method-typaram-kind.rs14
-rw-r--r--tests/ui/traits/bad-method-typaram-kind.stderr19
-rw-r--r--tests/ui/traits/bad-sized.rs9
-rw-r--r--tests/ui/traits/bad-sized.stderr45
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs11
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr20
-rw-r--r--tests/ui/traits/bound/auxiliary/crate_a1.rs9
-rw-r--r--tests/ui/traits/bound/auxiliary/crate_a2.rs13
-rw-r--r--tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs13
-rw-r--r--tests/ui/traits/bound/basic.rs25
-rw-r--r--tests/ui/traits/bound/generic_trait.rs30
-rw-r--r--tests/ui/traits/bound/impl-comparison-duplicates.rs16
-rw-r--r--tests/ui/traits/bound/in-arc.rs108
-rw-r--r--tests/ui/traits/bound/multiple.rs9
-rw-r--r--tests/ui/traits/bound/not-on-bare-trait.rs13
-rw-r--r--tests/ui/traits/bound/not-on-bare-trait.stderr34
-rw-r--r--tests/ui/traits/bound/not-on-struct.rs38
-rw-r--r--tests/ui/traits/bound/not-on-struct.stderr175
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-in-fns.rs20
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr27
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-in-impls.rs25
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr15
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-locals.rs17
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-locals.stderr27
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-rpass.rs21
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-static.rs15
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-static.stderr15
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-xc.rs14
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-xc.stderr27
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-xc1.rs15
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-xc1.stderr27
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums.rs43
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums.stderr99
-rw-r--r--tests/ui/traits/bound/recursion.rs20
-rw-r--r--tests/ui/traits/bound/same-crate-name.rs55
-rw-r--r--tests/ui/traits/bound/same-crate-name.stderr75
-rw-r--r--tests/ui/traits/bound/sugar.rs19
-rw-r--r--tests/ui/traits/bound/sugar.stderr19
-rw-r--r--tests/ui/traits/bug-7183-generics.rs36
-rw-r--r--tests/ui/traits/bug-7295.rs14
-rw-r--r--tests/ui/traits/cache-issue-18209.rs20
-rw-r--r--tests/ui/traits/cache-reached-depth-ice.rs45
-rw-r--r--tests/ui/traits/cache-reached-depth-ice.stderr11
-rw-r--r--tests/ui/traits/coercion-generic-bad.rs19
-rw-r--r--tests/ui/traits/coercion-generic-bad.stderr12
-rw-r--r--tests/ui/traits/coercion-generic-regions.rs19
-rw-r--r--tests/ui/traits/coercion-generic-regions.stderr15
-rw-r--r--tests/ui/traits/coercion-generic.rs25
-rw-r--r--tests/ui/traits/coercion.rs35
-rw-r--r--tests/ui/traits/composition-trivial.rs12
-rw-r--r--tests/ui/traits/conditional-dispatch.rs34
-rw-r--r--tests/ui/traits/conditional-model-fn.rs53
-rw-r--r--tests/ui/traits/conservative_impl_trait.rs8
-rw-r--r--tests/ui/traits/copy-guessing.rs38
-rw-r--r--tests/ui/traits/copy-impl-cannot-normalize.rs25
-rw-r--r--tests/ui/traits/copy-impl-cannot-normalize.stderr24
-rw-r--r--tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr22
-rw-r--r--tests/ui/traits/copy-is-not-modulo-regions.rs19
-rw-r--r--tests/ui/traits/copy-requires-self-wf.rs14
-rw-r--r--tests/ui/traits/cycle-cache-err-60010.rs74
-rw-r--r--tests/ui/traits/cycle-cache-err-60010.stderr39
-rw-r--r--tests/ui/traits/cycle-generic-bound.rs11
-rw-r--r--tests/ui/traits/cycle-type-trait.rs25
-rw-r--r--tests/ui/traits/default-method/auxiliary/xc.rs40
-rw-r--r--tests/ui/traits/default-method/auxiliary/xc_2.rs17
-rw-r--r--tests/ui/traits/default-method/bound-subst.rs18
-rw-r--r--tests/ui/traits/default-method/bound-subst2.rs16
-rw-r--r--tests/ui/traits/default-method/bound-subst3.rs17
-rw-r--r--tests/ui/traits/default-method/bound-subst4.rs19
-rw-r--r--tests/ui/traits/default-method/bound.rs16
-rw-r--r--tests/ui/traits/default-method/macro.rs20
-rw-r--r--tests/ui/traits/default-method/mut.rs11
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of.rs44
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of.stderr15
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs19
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr34
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs13
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr11
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs46
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr100
-rw-r--r--tests/ui/traits/default-method/self.rs18
-rw-r--r--tests/ui/traits/default-method/supervtable.rs28
-rw-r--r--tests/ui/traits/default-method/trivial.rs21
-rw-r--r--tests/ui/traits/default-method/xc-2.rs26
-rw-r--r--tests/ui/traits/default-method/xc.rs81
-rw-r--r--tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs20
-rw-r--r--tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr34
-rw-r--r--tests/ui/traits/duplicate-methods.rs6
-rw-r--r--tests/ui/traits/duplicate-methods.stderr13
-rw-r--r--tests/ui/traits/dyn-trait.rs17
-rw-r--r--tests/ui/traits/early-vtbl-resolution.rs19
-rw-r--r--tests/ui/traits/elaborate-type-region.rs49
-rw-r--r--tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs16
-rw-r--r--tests/ui/traits/fmt-pointer-trait.rs24
-rw-r--r--tests/ui/traits/fn-trait-cast-diagnostic.rs26
-rw-r--r--tests/ui/traits/fn-trait-cast-diagnostic.stderr43
-rw-r--r--tests/ui/traits/generic.rs45
-rw-r--r--tests/ui/traits/ignore-err-impls.rs9
-rw-r--r--tests/ui/traits/ignore-err-impls.stderr14
-rw-r--r--tests/ui/traits/impl-1.rs16
-rw-r--r--tests/ui/traits/impl-1.stderr9
-rw-r--r--tests/ui/traits/impl-2.rs19
-rw-r--r--tests/ui/traits/impl-bounds-checking.rs14
-rw-r--r--tests/ui/traits/impl-bounds-checking.stderr15
-rw-r--r--tests/ui/traits/impl-can-not-have-untraitful-items.rs9
-rw-r--r--tests/ui/traits/impl-can-not-have-untraitful-items.stderr22
-rw-r--r--tests/ui/traits/impl-different-num-params.rs12
-rw-r--r--tests/ui/traits/impl-different-num-params.stderr12
-rw-r--r--tests/ui/traits/impl-evaluation-order.rs39
-rw-r--r--tests/ui/traits/impl-for-module.rs11
-rw-r--r--tests/ui/traits/impl-for-module.stderr12
-rw-r--r--tests/ui/traits/impl-implicit-trait.rs26
-rw-r--r--tests/ui/traits/impl-inherent-prefer-over-trait.rs30
-rw-r--r--tests/ui/traits/impl-method-mismatch.rs13
-rw-r--r--tests/ui/traits/impl-method-mismatch.stderr17
-rw-r--r--tests/ui/traits/impl-object-overlap-issue-23853.rs18
-rw-r--r--tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs31
-rw-r--r--tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr27
-rw-r--r--tests/ui/traits/impl.rs41
-rw-r--r--tests/ui/traits/impl_trait_as_trait_return_position.rs17
-rw-r--r--tests/ui/traits/inductive-overflow/lifetime.rs33
-rw-r--r--tests/ui/traits/inductive-overflow/lifetime.stderr24
-rw-r--r--tests/ui/traits/inductive-overflow/simultaneous.rs20
-rw-r--r--tests/ui/traits/inductive-overflow/simultaneous.stderr22
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs18
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr35
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait.rs15
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait.stderr22
-rw-r--r--tests/ui/traits/inductive-overflow/two-traits.rs22
-rw-r--r--tests/ui/traits/inductive-overflow/two-traits.stderr32
-rw-r--r--tests/ui/traits/infer-from-object-issue-26952.rs26
-rw-r--r--tests/ui/traits/inherent-method-order.rs25
-rw-r--r--tests/ui/traits/inheritance/auto-xc-2.rs23
-rw-r--r--tests/ui/traits/inheritance/auto-xc.rs25
-rw-r--r--tests/ui/traits/inheritance/auto.rs29
-rw-r--r--tests/ui/traits/inheritance/auxiliary/auto_xc.rs7
-rw-r--r--tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs9
-rw-r--r--tests/ui/traits/inheritance/auxiliary/overloading_xc.rs38
-rw-r--r--tests/ui/traits/inheritance/auxiliary/xc_call.rs11
-rw-r--r--tests/ui/traits/inheritance/basic.rs26
-rw-r--r--tests/ui/traits/inheritance/call-bound-inherited.rs20
-rw-r--r--tests/ui/traits/inheritance/call-bound-inherited2.rs23
-rw-r--r--tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs33
-rw-r--r--tests/ui/traits/inheritance/cast.rs33
-rw-r--r--tests/ui/traits/inheritance/cross-trait-call-xc.rs20
-rw-r--r--tests/ui/traits/inheritance/cross-trait-call.rs19
-rw-r--r--tests/ui/traits/inheritance/diamond.rs28
-rw-r--r--tests/ui/traits/inheritance/multiple-inheritors.rs23
-rw-r--r--tests/ui/traits/inheritance/multiple-params.rs26
-rw-r--r--tests/ui/traits/inheritance/num.rs13
-rw-r--r--tests/ui/traits/inheritance/num0.rs24
-rw-r--r--tests/ui/traits/inheritance/num1.rs15
-rw-r--r--tests/ui/traits/inheritance/num2.rs86
-rw-r--r--tests/ui/traits/inheritance/num3.rs19
-rw-r--r--tests/ui/traits/inheritance/num5.rs26
-rw-r--r--tests/ui/traits/inheritance/overloading-simple.rs27
-rw-r--r--tests/ui/traits/inheritance/overloading-xc-exe.rs20
-rw-r--r--tests/ui/traits/inheritance/overloading.rs47
-rw-r--r--tests/ui/traits/inheritance/repeated-supertrait-ambig.rs43
-rw-r--r--tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr65
-rw-r--r--tests/ui/traits/inheritance/repeated-supertrait.rs48
-rw-r--r--tests/ui/traits/inheritance/self-in-supertype.rs62
-rw-r--r--tests/ui/traits/inheritance/self.rs29
-rw-r--r--tests/ui/traits/inheritance/simple.rs24
-rw-r--r--tests/ui/traits/inheritance/static.rs26
-rw-r--r--tests/ui/traits/inheritance/static2.rs29
-rw-r--r--tests/ui/traits/inheritance/subst.rs27
-rw-r--r--tests/ui/traits/inheritance/subst2.rs37
-rw-r--r--tests/ui/traits/inheritance/visibility.rs20
-rw-r--r--tests/ui/traits/invalid_operator_trait.rs23
-rw-r--r--tests/ui/traits/invalid_operator_trait.stderr8
-rw-r--r--tests/ui/traits/issue-102989.rs14
-rw-r--r--tests/ui/traits/issue-102989.stderr34
-rw-r--r--tests/ui/traits/issue-104322.rs80
-rw-r--r--tests/ui/traits/issue-106072.rs5
-rw-r--r--tests/ui/traits/issue-106072.stderr30
-rw-r--r--tests/ui/traits/issue-18400.rs26
-rw-r--r--tests/ui/traits/issue-18400.stderr20
-rw-r--r--tests/ui/traits/issue-18412.rs26
-rw-r--r--tests/ui/traits/issue-20692.rs11
-rw-r--r--tests/ui/traits/issue-20692.stderr35
-rw-r--r--tests/ui/traits/issue-22019.rs34
-rw-r--r--tests/ui/traits/issue-22110.rs27
-rw-r--r--tests/ui/traits/issue-22655.rs23
-rw-r--r--tests/ui/traits/issue-23003-overflow.rs29
-rw-r--r--tests/ui/traits/issue-23003.rs32
-rw-r--r--tests/ui/traits/issue-23825.rs21
-rw-r--r--tests/ui/traits/issue-24010.rs14
-rw-r--r--tests/ui/traits/issue-26339.rs31
-rw-r--r--tests/ui/traits/issue-28576.rs12
-rw-r--r--tests/ui/traits/issue-28576.stderr20
-rw-r--r--tests/ui/traits/issue-32963.rs11
-rw-r--r--tests/ui/traits/issue-32963.stderr27
-rw-r--r--tests/ui/traits/issue-33140-hack-boundaries.rs70
-rw-r--r--tests/ui/traits/issue-33140-hack-boundaries.stderr85
-rw-r--r--tests/ui/traits/issue-33140.rs47
-rw-r--r--tests/ui/traits/issue-33140.stderr31
-rw-r--r--tests/ui/traits/issue-35869.rs21
-rw-r--r--tests/ui/traits/issue-35869.stderr71
-rw-r--r--tests/ui/traits/issue-3683.rs18
-rw-r--r--tests/ui/traits/issue-38033.rs79
-rw-r--r--tests/ui/traits/issue-38404.rs6
-rw-r--r--tests/ui/traits/issue-38404.stderr17
-rw-r--r--tests/ui/traits/issue-38604.rs16
-rw-r--r--tests/ui/traits/issue-38604.stderr33
-rw-r--r--tests/ui/traits/issue-3973.rs25
-rw-r--r--tests/ui/traits/issue-3973.stderr22
-rw-r--r--tests/ui/traits/issue-4107.rs26
-rw-r--r--tests/ui/traits/issue-43132.rs65
-rw-r--r--tests/ui/traits/issue-43784-supertrait.rs10
-rw-r--r--tests/ui/traits/issue-43784-supertrait.stderr24
-rw-r--r--tests/ui/traits/issue-50480.rs15
-rw-r--r--tests/ui/traits/issue-50480.stderr92
-rw-r--r--tests/ui/traits/issue-52893.rs57
-rw-r--r--tests/ui/traits/issue-52893.stderr29
-rw-r--r--tests/ui/traits/issue-56202.rs17
-rw-r--r--tests/ui/traits/issue-56488.rs13
-rw-r--r--tests/ui/traits/issue-59029-1.rs9
-rw-r--r--tests/ui/traits/issue-59029-1.stderr15
-rw-r--r--tests/ui/traits/issue-59029-2.rs8
-rw-r--r--tests/ui/traits/issue-6128.rs22
-rw-r--r--tests/ui/traits/issue-6334.rs46
-rw-r--r--tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs11
-rw-r--r--tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr17
-rw-r--r--tests/ui/traits/issue-65673.rs12
-rw-r--r--tests/ui/traits/issue-65673.stderr12
-rw-r--r--tests/ui/traits/issue-68295.rs47
-rw-r--r--tests/ui/traits/issue-68295.stderr17
-rw-r--r--tests/ui/traits/issue-7013.rs26
-rw-r--r--tests/ui/traits/issue-7013.stderr18
-rw-r--r--tests/ui/traits/issue-70944.rs23
-rw-r--r--tests/ui/traits/issue-71036.rs17
-rw-r--r--tests/ui/traits/issue-71036.stderr12
-rw-r--r--tests/ui/traits/issue-71136.rs8
-rw-r--r--tests/ui/traits/issue-71136.stderr19
-rw-r--r--tests/ui/traits/issue-72410.rs18
-rw-r--r--tests/ui/traits/issue-72410.stderr25
-rw-r--r--tests/ui/traits/issue-72455.rs27
-rw-r--r--tests/ui/traits/issue-75627.rs6
-rw-r--r--tests/ui/traits/issue-75627.stderr14
-rw-r--r--tests/ui/traits/issue-77982.rs41
-rw-r--r--tests/ui/traits/issue-77982.stderr98
-rw-r--r--tests/ui/traits/issue-78372.rs13
-rw-r--r--tests/ui/traits/issue-78372.stderr65
-rw-r--r--tests/ui/traits/issue-78632.rs59
-rw-r--r--tests/ui/traits/issue-79458.rs10
-rw-r--r--tests/ui/traits/issue-79458.stderr16
-rw-r--r--tests/ui/traits/issue-8153.rs16
-rw-r--r--tests/ui/traits/issue-8153.stderr14
-rw-r--r--tests/ui/traits/issue-82830.rs18
-rw-r--r--tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs66
-rw-r--r--tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr38
-rw-r--r--tests/ui/traits/issue-84399-bad-fresh-caching.rs55
-rw-r--r--tests/ui/traits/issue-85360-eval-obligation-ice.rs143
-rw-r--r--tests/ui/traits/issue-85360-eval-obligation-ice.stderr38
-rw-r--r--tests/ui/traits/issue-85735.rs13
-rw-r--r--tests/ui/traits/issue-85735.stderr18
-rw-r--r--tests/ui/traits/issue-87558.rs9
-rw-r--r--tests/ui/traits/issue-87558.stderr24
-rw-r--r--tests/ui/traits/issue-89119.rs11
-rw-r--r--tests/ui/traits/issue-90195-2.rs20
-rw-r--r--tests/ui/traits/issue-90195.rs21
-rw-r--r--tests/ui/traits/issue-90662-projection-caching.rs34
-rw-r--r--tests/ui/traits/issue-91594.rs17
-rw-r--r--tests/ui/traits/issue-91594.stderr18
-rw-r--r--tests/ui/traits/issue-91949-hangs-on-recursion.rs32
-rw-r--r--tests/ui/traits/issue-91949-hangs-on-recursion.stderr25
-rw-r--r--tests/ui/traits/issue-92292.rs32
-rw-r--r--tests/ui/traits/issue-9394-inherited-calls.rs62
-rw-r--r--tests/ui/traits/issue-95311.rs19
-rw-r--r--tests/ui/traits/issue-95898.rs9
-rw-r--r--tests/ui/traits/issue-95898.stderr17
-rw-r--r--tests/ui/traits/issue-96664.rs16
-rw-r--r--tests/ui/traits/issue-96665.rs16
-rw-r--r--tests/ui/traits/issue-97576.rs13
-rw-r--r--tests/ui/traits/issue-97576.stderr11
-rw-r--r--tests/ui/traits/issue-97695-double-trivial-bound.rs24
-rw-r--r--tests/ui/traits/issue-99875.rs16
-rw-r--r--tests/ui/traits/issue-99875.stderr36
-rw-r--r--tests/ui/traits/item-inside-macro.rs30
-rw-r--r--tests/ui/traits/item-privacy.rs134
-rw-r--r--tests/ui/traits/item-privacy.stderr188
-rw-r--r--tests/ui/traits/kindck-owned-contains-1.rs21
-rw-r--r--tests/ui/traits/map-types.rs19
-rw-r--r--tests/ui/traits/map-types.stderr12
-rw-r--r--tests/ui/traits/matching-lifetimes.rs20
-rw-r--r--tests/ui/traits/matching-lifetimes.stderr41
-rw-r--r--tests/ui/traits/method-private.rs20
-rw-r--r--tests/ui/traits/method-private.stderr18
-rw-r--r--tests/ui/traits/monad.rs48
-rw-r--r--tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs32
-rw-r--r--tests/ui/traits/multidispatch-bad.rs22
-rw-r--r--tests/ui/traits/multidispatch-bad.stderr21
-rw-r--r--tests/ui/traits/multidispatch-conditional-impl-not-considered.rs24
-rw-r--r--tests/ui/traits/multidispatch-convert-ambig-dest.rs31
-rw-r--r--tests/ui/traits/multidispatch-convert-ambig-dest.stderr43
-rw-r--r--tests/ui/traits/multidispatch-infer-convert-target.rs36
-rw-r--r--tests/ui/traits/multidispatch1.rs33
-rw-r--r--tests/ui/traits/multidispatch2.rs39
-rw-r--r--tests/ui/traits/mutual-recursion-issue-75860.rs15
-rw-r--r--tests/ui/traits/mutual-recursion-issue-75860.stderr13
-rw-r--r--tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs7
-rw-r--r--tests/ui/traits/negative-impls/eager-mono.rs12
-rw-r--r--tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs53
-rw-r--r--tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr52
-rw-r--r--tests/ui/traits/negative-impls/feature-gate-negative_impls.rs3
-rw-r--r--tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr12
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-error.rs68
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-error.stderr127
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs21
-rw-r--r--tests/ui/traits/negative-impls/negative-default-impls.rs11
-rw-r--r--tests/ui/traits/negative-impls/negative-default-impls.stderr19
-rw-r--r--tests/ui/traits/negative-impls/negative-impls-basic.rs17
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-negative.rs13
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-negative.stderr12
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive-item.rs13
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr22
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive.rs14
-rw-r--r--tests/ui/traits/negative-impls/negative-specializes-positive.stderr21
-rw-r--r--tests/ui/traits/negative-impls/no-items.rs11
-rw-r--r--tests/ui/traits/negative-impls/no-items.stderr9
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs26
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr11
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs33
-rw-r--r--tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr11
-rw-r--r--tests/ui/traits/negative-impls/positive-specializes-negative.rs9
-rw-r--r--tests/ui/traits/negative-impls/positive-specializes-negative.stderr21
-rw-r--r--tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs24
-rw-r--r--tests/ui/traits/new-solver/fn-trait-closure.rs15
-rw-r--r--tests/ui/traits/new-solver/fn-trait.rs13
-rw-r--r--tests/ui/traits/new-solver/pointer-sized.rs12
-rw-r--r--tests/ui/traits/new-solver/pointer-sized.stderr24
-rw-r--r--tests/ui/traits/no-fallback-multiple-impls.rs16
-rw-r--r--tests/ui/traits/no-fallback-multiple-impls.stderr9
-rw-r--r--tests/ui/traits/no_send-struct.rs17
-rw-r--r--tests/ui/traits/no_send-struct.stderr18
-rw-r--r--tests/ui/traits/normalize-supertrait.rs37
-rw-r--r--tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs24
-rw-r--r--tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr41
-rw-r--r--tests/ui/traits/object-does-not-impl-trait.rs8
-rw-r--r--tests/ui/traits/object-does-not-impl-trait.stderr17
-rw-r--r--tests/ui/traits/object-one-type-two-traits.rs31
-rw-r--r--tests/ui/traits/object/auto-dedup-in-impl.rs19
-rw-r--r--tests/ui/traits/object/auto-dedup-in-impl.stderr12
-rw-r--r--tests/ui/traits/object/auto-dedup.rs46
-rw-r--r--tests/ui/traits/object/bounds-cycle-1.rs24
-rw-r--r--tests/ui/traits/object/bounds-cycle-2.rs28
-rw-r--r--tests/ui/traits/object/bounds-cycle-3.rs25
-rw-r--r--tests/ui/traits/object/bounds-cycle-4.rs25
-rw-r--r--tests/ui/traits/object/enforce-supertrait-projection.rs24
-rw-r--r--tests/ui/traits/object/enforce-supertrait-projection.stderr26
-rw-r--r--tests/ui/traits/object/exclusion.rs19
-rw-r--r--tests/ui/traits/object/generics.rs41
-rw-r--r--tests/ui/traits/object/issue-33140-traitobject-crate.rs108
-rw-r--r--tests/ui/traits/object/issue-33140-traitobject-crate.stderr95
-rw-r--r--tests/ui/traits/object/issue-44454-1.rs22
-rw-r--r--tests/ui/traits/object/issue-44454-1.stderr10
-rw-r--r--tests/ui/traits/object/issue-44454-2.rs22
-rw-r--r--tests/ui/traits/object/issue-44454-2.stderr17
-rw-r--r--tests/ui/traits/object/issue-44454-3.rs33
-rw-r--r--tests/ui/traits/object/issue-44454-3.stderr11
-rw-r--r--tests/ui/traits/object/lifetime-first.rs13
-rw-r--r--tests/ui/traits/object/macro-matcher.rs12
-rw-r--r--tests/ui/traits/object/macro-matcher.stderr19
-rw-r--r--tests/ui/traits/object/safety.rs17
-rw-r--r--tests/ui/traits/object/safety.stderr49
-rw-r--r--tests/ui/traits/object/supertrait-lifetime-bound.rs14
-rw-r--r--tests/ui/traits/object/supertrait-lifetime-bound.stderr11
-rw-r--r--tests/ui/traits/object/vs-lifetime-2.rs11
-rw-r--r--tests/ui/traits/object/vs-lifetime-2.stderr9
-rw-r--r--tests/ui/traits/object/vs-lifetime.rs17
-rw-r--r--tests/ui/traits/object/vs-lifetime.stderr52
-rw-r--r--tests/ui/traits/object/with-lifetime-bound.rs34
-rw-r--r--tests/ui/traits/object/with-self-in-projection-output-bad.rs50
-rw-r--r--tests/ui/traits/object/with-self-in-projection-output-bad.stderr21
-rw-r--r--tests/ui/traits/object/with-self-in-projection-output-good.rs28
-rw-r--r--tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs51
-rw-r--r--tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs30
-rw-r--r--tests/ui/traits/operator-overloading-issue-52025.rs57
-rw-r--r--tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs10
-rw-r--r--tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr11
-rw-r--r--tests/ui/traits/overlap-permitted-for-marker-traits.rs28
-rw-r--r--tests/ui/traits/param-without-lifetime-constraint.rs20
-rw-r--r--tests/ui/traits/param-without-lifetime-constraint.stderr19
-rw-r--r--tests/ui/traits/parameterized-with-bounds.rs21
-rw-r--r--tests/ui/traits/pointee-deduction.rs22
-rw-r--r--tests/ui/traits/pointee-tail-is-generic-errors.rs22
-rw-r--r--tests/ui/traits/pointee-tail-is-generic-errors.stderr40
-rw-r--r--tests/ui/traits/pointee-tail-is-generic.rs29
-rw-r--r--tests/ui/traits/principal-less-objects.rs42
-rw-r--r--tests/ui/traits/privacy.rs24
-rw-r--r--tests/ui/traits/project-modulo-regions.rs55
-rw-r--r--tests/ui/traits/project-modulo-regions.with_clause.stderr11
-rw-r--r--tests/ui/traits/project-modulo-regions.without_clause.stderr11
-rw-r--r--tests/ui/traits/region-pointer-simple.rs21
-rw-r--r--tests/ui/traits/reservation-impl/coherence-conflict.rs14
-rw-r--r--tests/ui/traits/reservation-impl/coherence-conflict.stderr13
-rw-r--r--tests/ui/traits/reservation-impl/no-use.rs12
-rw-r--r--tests/ui/traits/reservation-impl/no-use.stderr13
-rw-r--r--tests/ui/traits/reservation-impl/non-lattice-ok.rs59
-rw-r--r--tests/ui/traits/reservation-impl/ok.rs28
-rw-r--r--tests/ui/traits/resolution-in-overloaded-op.rs11
-rw-r--r--tests/ui/traits/resolution-in-overloaded-op.stderr16
-rw-r--r--tests/ui/traits/safety-fn-body.mir.stderr11
-rw-r--r--tests/ui/traits/safety-fn-body.rs19
-rw-r--r--tests/ui/traits/safety-fn-body.thir.stderr11
-rw-r--r--tests/ui/traits/safety-inherent-impl.rs9
-rw-r--r--tests/ui/traits/safety-inherent-impl.stderr11
-rw-r--r--tests/ui/traits/safety-ok-cc.rs24
-rw-r--r--tests/ui/traits/safety-ok.rs18
-rw-r--r--tests/ui/traits/safety-trait-impl-cc.rs15
-rw-r--r--tests/ui/traits/safety-trait-impl-cc.stderr15
-rw-r--r--tests/ui/traits/safety-trait-impl.rs18
-rw-r--r--tests/ui/traits/safety-trait-impl.stderr28
-rw-r--r--tests/ui/traits/self-without-lifetime-constraint.rs53
-rw-r--r--tests/ui/traits/self-without-lifetime-constraint.stderr19
-rw-r--r--tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs69
-rw-r--r--tests/ui/traits/static-method-generic-inference.rs28
-rw-r--r--tests/ui/traits/static-method-generic-inference.stderr17
-rw-r--r--tests/ui/traits/static-method-overwriting.rs34
-rw-r--r--tests/ui/traits/static-outlives-a-where-clause.rs23
-rw-r--r--tests/ui/traits/staticness-mismatch.rs11
-rw-r--r--tests/ui/traits/staticness-mismatch.stderr12
-rw-r--r--tests/ui/traits/suggest-deferences/issue-39029.fixed18
-rw-r--r--tests/ui/traits/suggest-deferences/issue-39029.rs18
-rw-r--r--tests/ui/traits/suggest-deferences/issue-39029.stderr19
-rw-r--r--tests/ui/traits/suggest-deferences/issue-62530.fixed15
-rw-r--r--tests/ui/traits/suggest-deferences/issue-62530.rs15
-rw-r--r--tests/ui/traits/suggest-deferences/issue-62530.stderr21
-rw-r--r--tests/ui/traits/suggest-deferences/multiple-0.fixed36
-rw-r--r--tests/ui/traits/suggest-deferences/multiple-0.rs36
-rw-r--r--tests/ui/traits/suggest-deferences/multiple-0.stderr21
-rw-r--r--tests/ui/traits/suggest-deferences/multiple-1.rs54
-rw-r--r--tests/ui/traits/suggest-deferences/multiple-1.stderr18
-rw-r--r--tests/ui/traits/suggest-deferences/root-obligation.fixed13
-rw-r--r--tests/ui/traits/suggest-deferences/root-obligation.rs13
-rw-r--r--tests/ui/traits/suggest-deferences/root-obligation.stderr21
-rw-r--r--tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed14
-rw-r--r--tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs14
-rw-r--r--tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr15
-rw-r--r--tests/ui/traits/suggest-fully-qualified-closure.rs24
-rw-r--r--tests/ui/traits/suggest-fully-qualified-closure.stderr34
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs60
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr186
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs64
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr224
-rw-r--r--tests/ui/traits/suggest-where-clause.rs36
-rw-r--r--tests/ui/traits/suggest-where-clause.stderr90
-rw-r--r--tests/ui/traits/superdefault-generics.rs39
-rw-r--r--tests/ui/traits/syntax-polarity.rs21
-rw-r--r--tests/ui/traits/syntax-trait-polarity.rs25
-rw-r--r--tests/ui/traits/syntax-trait-polarity.stderr37
-rw-r--r--tests/ui/traits/test-2.rs17
-rw-r--r--tests/ui/traits/test-2.stderr85
-rw-r--r--tests/ui/traits/test.rs6
-rw-r--r--tests/ui/traits/test.stderr9
-rw-r--r--tests/ui/traits/to-str.rs36
-rw-r--r--tests/ui/traits/track-obligations.rs88
-rw-r--r--tests/ui/traits/track-obligations.stderr76
-rw-r--r--tests/ui/traits/trait-or-new-type-instead.rs6
-rw-r--r--tests/ui/traits/trait-or-new-type-instead.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/basic.rs86
-rw-r--r--tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs38
-rw-r--r--tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs13
-rw-r--r--tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr21
-rw-r--r--tests/ui/traits/trait-upcasting/diamond.rs114
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.rs86
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.stderr168
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs12
-rw-r--r--tests/ui/traits/trait-upcasting/lifetime.rs94
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.rs27
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr19
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs21
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/replace-vptr.rs48
-rw-r--r--tests/ui/traits/trait-upcasting/struct.rs173
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.rs69
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.stderr68
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs26
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.stderr23
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs31
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr42
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr18
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.rs20
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.stderr18
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr52
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.rs48
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr52
-rw-r--r--tests/ui/traits/typeclasses-eq-example-static.rs68
-rw-r--r--tests/ui/traits/typeclasses-eq-example.rs64
-rw-r--r--tests/ui/traits/ufcs-object.rs17
-rw-r--r--tests/ui/traits/unspecified-self-in-trait-ref.rs30
-rw-r--r--tests/ui/traits/unspecified-self-in-trait-ref.stderr105
-rw-r--r--tests/ui/traits/use-before-def.rs10
-rw-r--r--tests/ui/traits/vtable-res-trait-param.rs23
-rw-r--r--tests/ui/traits/vtable-res-trait-param.stderr17
-rw-r--r--tests/ui/traits/vtable/issue-91807.rs17
-rw-r--r--tests/ui/traits/vtable/issue-97381.rs30
-rw-r--r--tests/ui/traits/vtable/issue-97381.stderr15
-rw-r--r--tests/ui/traits/vtable/vtable-diamond.rs44
-rw-r--r--tests/ui/traits/vtable/vtable-diamond.stderr29
-rw-r--r--tests/ui/traits/vtable/vtable-multi-level.rs143
-rw-r--r--tests/ui/traits/vtable/vtable-multi-level.stderr203
-rw-r--r--tests/ui/traits/vtable/vtable-multiple.rs33
-rw-r--r--tests/ui/traits/vtable/vtable-multiple.stderr27
-rw-r--r--tests/ui/traits/vtable/vtable-non-object-safe.rs18
-rw-r--r--tests/ui/traits/vtable/vtable-non-object-safe.stderr16
-rw-r--r--tests/ui/traits/vtable/vtable-vacant.rs31
-rw-r--r--tests/ui/traits/vtable/vtable-vacant.stderr16
-rw-r--r--tests/ui/traits/wf-object/maybe-bound.rs18
-rw-r--r--tests/ui/traits/wf-object/maybe-bound.stderr32
-rw-r--r--tests/ui/traits/wf-object/no-duplicates.rs33
-rw-r--r--tests/ui/traits/wf-object/no-duplicates.stderr58
-rw-r--r--tests/ui/traits/wf-object/only-maybe-bound.rs7
-rw-r--r--tests/ui/traits/wf-object/only-maybe-bound.stderr15
-rw-r--r--tests/ui/traits/wf-object/reverse-order.rs15
-rw-r--r--tests/ui/traits/where-clause-vs-impl.rs45
-rw-r--r--tests/ui/traits/with-bounds-default.rs32
-rw-r--r--tests/ui/traits/with-dst.rs22
595 files changed, 18631 insertions, 0 deletions
diff --git a/tests/ui/traits/alias/ambiguous.rs b/tests/ui/traits/alias/ambiguous.rs
new file mode 100644
index 000000000..28409e0c6
--- /dev/null
+++ b/tests/ui/traits/alias/ambiguous.rs
@@ -0,0 +1,24 @@
+#![feature(trait_alias)]
+
+mod inner {
+ pub trait A { fn foo(&self); }
+ pub trait B { fn foo(&self); }
+
+ impl A for u8 {
+ fn foo(&self) {}
+ }
+ impl B for u8 {
+ fn foo(&self) {}
+ }
+
+ pub trait C = A + B;
+}
+
+use inner::C;
+
+fn main() {
+ let t = 1u8;
+ t.foo(); //~ ERROR E0034
+
+ inner::A::foo(&t); // ok
+}
diff --git a/tests/ui/traits/alias/ambiguous.stderr b/tests/ui/traits/alias/ambiguous.stderr
new file mode 100644
index 000000000..0fe1a7967
--- /dev/null
+++ b/tests/ui/traits/alias/ambiguous.stderr
@@ -0,0 +1,28 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/ambiguous.rs:21:7
+ |
+LL | t.foo();
+ | ^^^ multiple `foo` found
+ |
+note: candidate #1 is defined in an impl of the trait `A` for the type `u8`
+ --> $DIR/ambiguous.rs:8:9
+ |
+LL | fn foo(&self) {}
+ | ^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `B` for the type `u8`
+ --> $DIR/ambiguous.rs:11:9
+ |
+LL | fn foo(&self) {}
+ | ^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | A::foo(&t);
+ | ~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | B::foo(&t);
+ | ~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/traits/alias/auxiliary/greeter.rs b/tests/ui/traits/alias/auxiliary/greeter.rs
new file mode 100644
index 000000000..9e4122155
--- /dev/null
+++ b/tests/ui/traits/alias/auxiliary/greeter.rs
@@ -0,0 +1,13 @@
+#![feature(trait_alias)]
+
+pub trait Hello {
+ fn hello(&self);
+}
+
+pub struct Hi;
+
+impl Hello for Hi {
+ fn hello(&self) {}
+}
+
+pub trait Greet = Hello;
diff --git a/tests/ui/traits/alias/auxiliary/send_sync.rs b/tests/ui/traits/alias/auxiliary/send_sync.rs
new file mode 100644
index 000000000..9e56b87e0
--- /dev/null
+++ b/tests/ui/traits/alias/auxiliary/send_sync.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SendSync = Send + Sync;
diff --git a/tests/ui/traits/alias/basic.rs b/tests/ui/traits/alias/basic.rs
new file mode 100644
index 000000000..d8168f299
--- /dev/null
+++ b/tests/ui/traits/alias/basic.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+pub trait Foo {}
+pub trait FooAlias = Foo;
+
+fn main() {}
diff --git a/tests/ui/traits/alias/bounds.rs b/tests/ui/traits/alias/bounds.rs
new file mode 100644
index 000000000..b97eb38c5
--- /dev/null
+++ b/tests/ui/traits/alias/bounds.rs
@@ -0,0 +1,57 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+use std::marker::PhantomData;
+
+trait Empty {}
+trait EmptyAlias = Empty;
+trait CloneDefault = Clone + Default;
+trait SendSyncAlias = Send + Sync;
+trait WhereSendAlias = where Self: Send;
+trait SendEqAlias<T> = Send where T: PartialEq<Self>;
+trait I32Iterator = Iterator<Item = i32>;
+
+#[allow(dead_code)]
+struct Foo<T: SendSyncAlias>(PhantomData<T>);
+#[allow(dead_code)]
+struct Bar<T>(PhantomData<T>) where T: SendSyncAlias;
+
+impl dyn EmptyAlias {}
+
+impl<T: SendSyncAlias> Empty for T {}
+
+fn a<T: CloneDefault>() -> (T, T) {
+ let one = T::default();
+ let two = one.clone();
+ (one, two)
+}
+
+fn b(x: &impl SendEqAlias<i32>) -> bool {
+ 22_i32 == *x
+}
+
+fn c<T: I32Iterator>(x: &mut T) -> Option<i32> {
+ x.next()
+}
+
+fn d<T: SendSyncAlias>() {
+ is_send_and_sync::<T>();
+}
+
+fn is_send_and_sync<T: Send + Sync>() {}
+
+fn main() {
+ let both = a::<i32>();
+ assert_eq!(both.0, 0);
+ assert_eq!(both.1, 0);
+ let both: (i32, i32) = a();
+ assert_eq!(both.0, 0);
+ assert_eq!(both.1, 0);
+
+ assert!(b(&22));
+
+ assert_eq!(c(&mut vec![22].into_iter()), Some(22));
+
+ d::<i32>();
+}
diff --git a/tests/ui/traits/alias/cross-crate.rs b/tests/ui/traits/alias/cross-crate.rs
new file mode 100644
index 000000000..8919c6434
--- /dev/null
+++ b/tests/ui/traits/alias/cross-crate.rs
@@ -0,0 +1,17 @@
+// aux-build:send_sync.rs
+
+#![feature(trait_alias)]
+
+extern crate send_sync;
+
+use std::rc::Rc;
+use send_sync::SendSync;
+
+fn use_alias<T: SendSync>() {}
+
+fn main() {
+ use_alias::<u32>();
+ use_alias::<Rc<u32>>();
+ //~^ ERROR `Rc<u32>` cannot be sent between threads safely [E0277]
+ //~^^ ERROR `Rc<u32>` cannot be shared between threads safely [E0277]
+}
diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr
new file mode 100644
index 000000000..ae9d7d0a9
--- /dev/null
+++ b/tests/ui/traits/alias/cross-crate.stderr
@@ -0,0 +1,31 @@
+error[E0277]: `Rc<u32>` cannot be sent between threads safely
+ --> $DIR/cross-crate.rs:14:17
+ |
+LL | use_alias::<Rc<u32>>();
+ | ^^^^^^^ `Rc<u32>` cannot be sent between threads safely
+ |
+ = help: the trait `Send` is not implemented for `Rc<u32>`
+ = note: required for `Rc<u32>` to implement `SendSync`
+note: required by a bound in `use_alias`
+ --> $DIR/cross-crate.rs:10:17
+ |
+LL | fn use_alias<T: SendSync>() {}
+ | ^^^^^^^^ required by this bound in `use_alias`
+
+error[E0277]: `Rc<u32>` cannot be shared between threads safely
+ --> $DIR/cross-crate.rs:14:17
+ |
+LL | use_alias::<Rc<u32>>();
+ | ^^^^^^^ `Rc<u32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Rc<u32>`
+ = note: required for `Rc<u32>` to implement `SendSync`
+note: required by a bound in `use_alias`
+ --> $DIR/cross-crate.rs:10:17
+ |
+LL | fn use_alias<T: SendSync>() {}
+ | ^^^^^^^^ required by this bound in `use_alias`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alias/generic-default-in-dyn.rs b/tests/ui/traits/alias/generic-default-in-dyn.rs
new file mode 100644
index 000000000..d44e1c2a9
--- /dev/null
+++ b/tests/ui/traits/alias/generic-default-in-dyn.rs
@@ -0,0 +1,10 @@
+trait SendEqAlias<T> = PartialEq;
+//~^ ERROR trait aliases are experimental
+
+struct Foo<T>(dyn SendEqAlias<T>);
+//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393]
+
+struct Bar<T>(dyn SendEqAlias<T>, T);
+//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393]
+
+fn main() {}
diff --git a/tests/ui/traits/alias/generic-default-in-dyn.stderr b/tests/ui/traits/alias/generic-default-in-dyn.stderr
new file mode 100644
index 000000000..0d3f794aa
--- /dev/null
+++ b/tests/ui/traits/alias/generic-default-in-dyn.stderr
@@ -0,0 +1,35 @@
+error[E0658]: trait aliases are experimental
+ --> $DIR/generic-default-in-dyn.rs:1:1
+ |
+LL | trait SendEqAlias<T> = PartialEq;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #41517 <https://github.com/rust-lang/rust/issues/41517> for more information
+ = help: add `#![feature(trait_alias)]` to the crate attributes to enable
+
+error[E0393]: the type parameter `Rhs` must be explicitly specified
+ --> $DIR/generic-default-in-dyn.rs:4:19
+ |
+LL | struct Foo<T>(dyn SendEqAlias<T>);
+ | ^^^^^^^^^^^^^^ missing reference to `Rhs`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ |
+ = note: type parameter `Rhs` must be specified for this
+ |
+ = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error[E0393]: the type parameter `Rhs` must be explicitly specified
+ --> $DIR/generic-default-in-dyn.rs:7:19
+ |
+LL | struct Bar<T>(dyn SendEqAlias<T>, T);
+ | ^^^^^^^^^^^^^^ missing reference to `Rhs`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ |
+ = note: type parameter `Rhs` must be specified for this
+ |
+ = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0393, E0658.
+For more information about an error, try `rustc --explain E0393`.
diff --git a/tests/ui/traits/alias/impl.rs b/tests/ui/traits/alias/impl.rs
new file mode 100644
index 000000000..6e35793a0
--- /dev/null
+++ b/tests/ui/traits/alias/impl.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias)]
+
+trait DefaultAlias = Default;
+
+impl DefaultAlias for () {} //~ ERROR expected trait, found trait alias
+
+fn main() {}
diff --git a/tests/ui/traits/alias/impl.stderr b/tests/ui/traits/alias/impl.stderr
new file mode 100644
index 000000000..cedcd1021
--- /dev/null
+++ b/tests/ui/traits/alias/impl.stderr
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found trait alias `DefaultAlias`
+ --> $DIR/impl.rs:5:6
+ |
+LL | impl DefaultAlias for () {}
+ | ^^^^^^^^^^^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/traits/alias/import-cross-crate.rs b/tests/ui/traits/alias/import-cross-crate.rs
new file mode 100644
index 000000000..868585cd0
--- /dev/null
+++ b/tests/ui/traits/alias/import-cross-crate.rs
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:greeter.rs
+
+#![feature(trait_alias)]
+
+extern crate greeter;
+
+// Import only the alias, not the real trait.
+use greeter::{Greet, Hi};
+
+fn main() {
+ let hi = Hi;
+ hi.hello(); // From `Hello`, via `Greet` alias.
+}
diff --git a/tests/ui/traits/alias/import.rs b/tests/ui/traits/alias/import.rs
new file mode 100644
index 000000000..802a8f156
--- /dev/null
+++ b/tests/ui/traits/alias/import.rs
@@ -0,0 +1,40 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod inner {
+ pub trait Foo {
+ fn foo(&self);
+ }
+
+ pub struct Qux;
+
+ impl Foo for Qux {
+ fn foo(&self) {}
+ }
+
+ pub trait Bar = Foo;
+}
+
+mod two {
+ pub trait A {
+ fn foo();
+ }
+
+ impl A for u8 {
+ fn foo() {}
+ }
+}
+
+// Import only the alias, not the `Foo` trait.
+use inner::{Bar, Qux};
+
+// Declaring an alias also brings in aliased methods.
+trait Two = two::A;
+
+fn main() {
+ let q = Qux;
+ q.foo(); // From Bar.
+
+ u8::foo(); // From A.
+}
diff --git a/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs b/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs
new file mode 100644
index 000000000..5e27ed3c6
--- /dev/null
+++ b/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+trait SomeTrait {
+ fn map(&self) {}
+}
+
+impl<T> SomeTrait for Option<T> {}
+
+trait SomeAlias = SomeTrait;
+
+fn main() {
+ let x = Some(123);
+ // This should resolve to the trait impl for Option
+ Option::map(x, |z| z);
+ // This should resolve to the trait impl for SomeTrait
+ SomeTrait::map(&x);
+}
diff --git a/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs b/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs
new file mode 100644
index 000000000..e49125d10
--- /dev/null
+++ b/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+trait Bounded { const MAX: Self; }
+
+impl Bounded for u32 {
+ // This should correctly resolve to the associated const in the inherent impl of u32.
+ const MAX: Self = u32::MAX;
+}
+
+trait Num = Bounded + Copy;
+
+fn main() {}
diff --git a/tests/ui/traits/alias/issue-75983.rs b/tests/ui/traits/alias/issue-75983.rs
new file mode 100644
index 000000000..f9a7f36de
--- /dev/null
+++ b/tests/ui/traits/alias/issue-75983.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+struct Bar;
+trait Foo {}
+impl Foo for Bar {}
+
+trait Baz = Foo where Bar: Foo;
+
+fn new() -> impl Baz {
+ Bar
+}
+
+fn main() {
+ let _ = new();
+}
diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs
new file mode 100644
index 000000000..2462e703a
--- /dev/null
+++ b/tests/ui/traits/alias/issue-83613.rs
@@ -0,0 +1,12 @@
+#![feature(type_alias_impl_trait)]
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
+type OpaqueType = impl OpaqueTrait;
+fn mk_opaque() -> OpaqueType {
+ || 0
+}
+trait AnotherTrait {}
+impl<T: Send> AnotherTrait for T {}
+impl AnotherTrait for OpaqueType {}
+//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+fn main() {}
diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr
new file mode 100644
index 000000000..a78294da6
--- /dev/null
+++ b/tests/ui/traits/alias/issue-83613.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+ --> $DIR/issue-83613.rs:10:1
+ |
+LL | impl<T: Send> AnotherTrait for T {}
+ | -------------------------------- first implementation here
+LL | impl AnotherTrait for OpaqueType {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/alias/maybe-bound.rs b/tests/ui/traits/alias/maybe-bound.rs
new file mode 100644
index 000000000..284baa481
--- /dev/null
+++ b/tests/ui/traits/alias/maybe-bound.rs
@@ -0,0 +1,29 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay.
+
+#![feature(trait_alias)]
+
+trait Foo {}
+
+trait S = ?Sized;
+
+// Nest a couple of levels deep:
+trait _0 = S;
+trait _1 = _0;
+
+// Straight list expansion:
+type _T0 = dyn _1 + Foo;
+
+// In second position:
+type _T1 = dyn Foo + _1;
+
+// ... and with an auto trait:
+type _T2 = dyn Foo + Send + _1;
+
+// Twice:
+trait _2 = _1 + _1;
+
+type _T3 = dyn _2 + Foo;
+
+fn main() {}
diff --git a/tests/ui/traits/alias/no-duplicates.rs b/tests/ui/traits/alias/no-duplicates.rs
new file mode 100644
index 000000000..88feb8917
--- /dev/null
+++ b/tests/ui/traits/alias/no-duplicates.rs
@@ -0,0 +1,126 @@
+// The purpose of this test is to demonstrate that duplicating object safe traits
+// that are not auto traits is rejected with trait aliases even though one could
+// reasonably accept this.
+
+#![feature(trait_alias)]
+
+use std::marker::Unpin;
+
+// Some arbitrary object-safe trait:
+trait Obj {}
+
+// Nest a few levels deep:
+trait _0 = Obj;
+trait _1 = _0;
+
+type _T00 = dyn _0 + _0;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T01 = dyn _1 + _0;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T02 = dyn _1 + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T03 = dyn Obj + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T04 = dyn _1 + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Nest some more and in weird ways:
+
+trait _2 = _0 + _1;
+trait _3 = Obj;
+trait _4 = _3;
+
+type _T10 = dyn _2 + _3;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T11 = dyn _3 + _2;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T12 = dyn Obj + _2;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T13 = dyn _2 + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T14 = dyn _1 + _3;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T15 = dyn _3 + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T16 = dyn _1 + _4;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T17 = dyn _4 + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Include auto traits:
+
+trait _5 = Obj + Send;
+
+type _T20 = dyn _5 + _5;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T21 = dyn Obj + _5;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T22 = dyn _5 + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T23 = dyn _5 + Send + Sync + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Also nest:
+
+trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send
+
+type _T30 = dyn _6;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T31 = dyn _6 + Send;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T32 = dyn Send + _6;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Nest some more:
+
+trait _7 = _5 + Sync;
+trait _8 = Unpin + _7;
+
+type _T40 = dyn _8 + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T41 = dyn Obj + _8;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T42 = dyn _8 + _4;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T43 = dyn _4 + _8;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T44 = dyn _4 + Send + Sync + _8;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Take higher ranked types into account.
+
+// Note that `'a` and `'b` are intentionally different to make sure we consider
+// them semantically the same.
+trait ObjL<'l> {}
+trait _9 = for<'a> ObjL<'a>;
+trait _10 = for<'b> ObjL<'b>;
+type _T50 = dyn _9 + _10;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+trait ObjT<T> {}
+trait _11 = ObjT<for<'a> fn(&'a u8)>;
+trait _12 = ObjT<for<'b> fn(&'b u8)>;
+type _T60 = dyn _11 + _12;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+fn main() {}
diff --git a/tests/ui/traits/alias/no-duplicates.stderr b/tests/ui/traits/alias/no-duplicates.stderr
new file mode 100644
index 000000000..bf244b97e
--- /dev/null
+++ b/tests/ui/traits/alias/no-duplicates.stderr
@@ -0,0 +1,527 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:16:22
+ |
+LL | trait _0 = Obj;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+...
+LL | type _T00 = dyn _0 + _0;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:19:22
+ |
+LL | trait _0 = Obj;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | type _T01 = dyn _1 + _0;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:22:22
+ |
+LL | trait _0 = Obj;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _1 = _0;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+...
+LL | type _T02 = dyn _1 + _1;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:25:23
+ |
+LL | trait _0 = Obj;
+ | --- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | type _T03 = dyn Obj + _1;
+ | --- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:28:22
+ |
+LL | trait _0 = Obj;
+ | --- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | type _T04 = dyn _1 + Obj;
+ | -- ^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:37:17
+ |
+LL | trait _0 = Obj;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _2 = _0 + _1;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T10 = dyn _2 + _3;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:40:22
+ |
+LL | trait _0 = Obj;
+ | --- additional non-auto trait
+...
+LL | trait _2 = _0 + _1;
+ | -- referenced here (additional use)
+LL | trait _3 = Obj;
+ | --- first non-auto trait
+...
+LL | type _T11 = dyn _3 + _2;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:43:23
+ |
+LL | trait _0 = Obj;
+ | --- additional non-auto trait
+...
+LL | trait _2 = _0 + _1;
+ | -- referenced here (additional use)
+...
+LL | type _T12 = dyn Obj + _2;
+ | --- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:46:17
+ |
+LL | trait _0 = Obj;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _2 = _0 + _1;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T13 = dyn _2 + Obj;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:49:22
+ |
+LL | trait _0 = Obj;
+ | --- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _3 = Obj;
+ | --- additional non-auto trait
+...
+LL | type _T14 = dyn _1 + _3;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:52:22
+ |
+LL | trait _0 = Obj;
+ | --- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _3 = Obj;
+ | --- first non-auto trait
+...
+LL | type _T15 = dyn _3 + _1;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:55:22
+ |
+LL | trait _0 = Obj;
+ | --- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _3 = Obj;
+ | --- additional non-auto trait
+LL | trait _4 = _3;
+ | -- referenced here (additional use)
+...
+LL | type _T16 = dyn _1 + _4;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:58:22
+ |
+LL | trait _0 = Obj;
+ | --- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _3 = Obj;
+ | --- first non-auto trait
+LL | trait _4 = _3;
+ | -- referenced here (first use)
+...
+LL | type _T17 = dyn _4 + _1;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:65:22
+ |
+LL | trait _5 = Obj + Send;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL |
+LL | type _T20 = dyn _5 + _5;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:68:23
+ |
+LL | trait _5 = Obj + Send;
+ | --- additional non-auto trait
+...
+LL | type _T21 = dyn Obj + _5;
+ | --- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:71:22
+ |
+LL | trait _5 = Obj + Send;
+ | --- first non-auto trait
+...
+LL | type _T22 = dyn _5 + Obj;
+ | -- ^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:74:36
+ |
+LL | trait _5 = Obj + Send;
+ | --- first non-auto trait
+...
+LL | type _T23 = dyn _5 + Send + Sync + Obj;
+ | -- ^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:81:17
+ |
+LL | trait _5 = Obj + Send;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+...
+LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+LL |
+LL | type _T30 = dyn _6;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:84:17
+ |
+LL | trait _5 = Obj + Send;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+...
+LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T31 = dyn _6 + Send;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:87:24
+ |
+LL | trait _5 = Obj + Send;
+ | ---
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+...
+LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T32 = dyn Send + _6;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:95:22
+ |
+LL | trait _5 = Obj + Send;
+ | --- first non-auto trait
+...
+LL | trait _7 = _5 + Sync;
+ | -- referenced here (first use)
+LL | trait _8 = Unpin + _7;
+ | -- referenced here (first use)
+LL |
+LL | type _T40 = dyn _8 + Obj;
+ | -- ^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:98:23
+ |
+LL | trait _5 = Obj + Send;
+ | --- additional non-auto trait
+...
+LL | trait _7 = _5 + Sync;
+ | -- referenced here (additional use)
+LL | trait _8 = Unpin + _7;
+ | -- referenced here (additional use)
+...
+LL | type _T41 = dyn Obj + _8;
+ | --- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:101:22
+ |
+LL | trait _3 = Obj;
+ | --- additional non-auto trait
+LL | trait _4 = _3;
+ | -- referenced here (additional use)
+...
+LL | trait _5 = Obj + Send;
+ | --- first non-auto trait
+...
+LL | trait _7 = _5 + Sync;
+ | -- referenced here (first use)
+LL | trait _8 = Unpin + _7;
+ | -- referenced here (first use)
+...
+LL | type _T42 = dyn _8 + _4;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:104:22
+ |
+LL | trait _3 = Obj;
+ | --- first non-auto trait
+LL | trait _4 = _3;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Obj + Send;
+ | --- additional non-auto trait
+...
+LL | trait _7 = _5 + Sync;
+ | -- referenced here (additional use)
+LL | trait _8 = Unpin + _7;
+ | -- referenced here (additional use)
+...
+LL | type _T43 = dyn _4 + _8;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:107:36
+ |
+LL | trait _3 = Obj;
+ | --- first non-auto trait
+LL | trait _4 = _3;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Obj + Send;
+ | --- additional non-auto trait
+...
+LL | trait _7 = _5 + Sync;
+ | -- referenced here (additional use)
+LL | trait _8 = Unpin + _7;
+ | -- referenced here (additional use)
+...
+LL | type _T44 = dyn _4 + Send + Sync + _8;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:117:22
+ |
+LL | trait _9 = for<'a> ObjL<'a>;
+ | ---------------- first non-auto trait
+LL | trait _10 = for<'b> ObjL<'b>;
+ | ---------------- additional non-auto trait
+LL | type _T50 = dyn _9 + _10;
+ | -- ^^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:123:23
+ |
+LL | trait _11 = ObjT<for<'a> fn(&'a u8)>;
+ | ------------------------ first non-auto trait
+LL | trait _12 = ObjT<for<'b> fn(&'b u8)>;
+ | ------------------------ additional non-auto trait
+LL | type _T60 = dyn _11 + _12;
+ | --- ^^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error: aborting due to 27 previous errors
+
+For more information about this error, try `rustc --explain E0225`.
diff --git a/tests/ui/traits/alias/no-extra-traits.rs b/tests/ui/traits/alias/no-extra-traits.rs
new file mode 100644
index 000000000..4dad8c0f8
--- /dev/null
+++ b/tests/ui/traits/alias/no-extra-traits.rs
@@ -0,0 +1,121 @@
+// The purpose of this test is to demonstrate that trait alias expansion
+// preserves the rule that `dyn Trait` may only reference one non-auto trait.
+
+#![feature(trait_alias)]
+
+use std::marker::Unpin;
+
+// Some arbitrary object-safe traits:
+trait ObjA {}
+trait ObjB {}
+
+// Nest a few levels deep:
+trait _0 = ObjA;
+trait _1 = _0;
+
+type _T00 = dyn _0 + ObjB;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T01 = dyn ObjB + _0;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T02 = dyn ObjB + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T03 = dyn _1 + ObjB;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Nest some more and in weird ways:
+
+trait _2 = ObjB;
+trait _3 = _2;
+trait _4 = _3;
+
+type _T10 = dyn _2 + _3;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T11 = dyn _3 + _2;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T12 = dyn _2 + _4;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T13 = dyn _4 + _2;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Include auto traits:
+
+trait _5 = Sync + ObjB + Send;
+
+type _T20 = dyn _5 + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T21 = dyn _1 + _5;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T22 = dyn _5 + ObjA;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T23 = dyn ObjA + _5;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T24 = dyn Send + _5 + _1 + Sync;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T25 = dyn _1 + Sync + _5 + Send;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T26 = dyn Sync + Send + _5 + ObjA;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T27 = dyn Send + Sync + ObjA + _5;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Also nest:
+
+trait _6 = _1 + _5;
+trait _7 = _6;
+trait _8 = _7;
+
+type _T30 = dyn _6;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T31 = dyn _6 + Send;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T32 = dyn Send + _6;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T33 = dyn _8;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T34 = dyn _8 + Send;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T35 = dyn Send + _8;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Nest some more:
+
+trait _9 = _5 + Sync;
+trait _10 = Unpin + _9;
+
+type _T40 = dyn _10 + ObjA;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T41 = dyn ObjA + _10;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T42 = dyn _10 + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T43 = dyn Send + _10 + Sync + ObjA;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T44 = dyn ObjA + _10 + Send + Sync;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _T45 = dyn Sync + Send + _10 + _1;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+fn main() {}
diff --git a/tests/ui/traits/alias/no-extra-traits.stderr b/tests/ui/traits/alias/no-extra-traits.stderr
new file mode 100644
index 000000000..4b1ddf684
--- /dev/null
+++ b/tests/ui/traits/alias/no-extra-traits.stderr
@@ -0,0 +1,579 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:16:22
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+...
+LL | type _T00 = dyn _0 + ObjB;
+ | -- ^^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:19:24
+ |
+LL | trait _0 = ObjA;
+ | ---- additional non-auto trait
+...
+LL | type _T01 = dyn ObjB + _0;
+ | ---- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:22:24
+ |
+LL | trait _0 = ObjA;
+ | ---- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | type _T02 = dyn ObjB + _1;
+ | ---- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:25:22
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | type _T03 = dyn _1 + ObjB;
+ | -- ^^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:34:22
+ |
+LL | trait _2 = ObjB;
+ | ----
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _3 = _2;
+ | -- referenced here (additional use)
+...
+LL | type _T10 = dyn _2 + _3;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:37:22
+ |
+LL | trait _2 = ObjB;
+ | ----
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _3 = _2;
+ | -- referenced here (first use)
+...
+LL | type _T11 = dyn _3 + _2;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:40:22
+ |
+LL | trait _2 = ObjB;
+ | ----
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _3 = _2;
+ | -- referenced here (additional use)
+LL | trait _4 = _3;
+ | -- referenced here (additional use)
+...
+LL | type _T12 = dyn _2 + _4;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:43:22
+ |
+LL | trait _2 = ObjB;
+ | ----
+ | |
+ | additional non-auto trait
+ | first non-auto trait
+LL | trait _3 = _2;
+ | -- referenced here (first use)
+LL | trait _4 = _3;
+ | -- referenced here (first use)
+...
+LL | type _T13 = dyn _4 + _2;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:50:22
+ |
+LL | trait _0 = ObjA;
+ | ---- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+LL |
+LL | type _T20 = dyn _5 + _1;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:53:22
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | type _T21 = dyn _1 + _5;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:56:22
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | type _T22 = dyn _5 + ObjA;
+ | -- ^^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:59:24
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | type _T23 = dyn ObjA + _5;
+ | ---- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:62:29
+ |
+LL | trait _0 = ObjA;
+ | ---- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | type _T24 = dyn Send + _5 + _1 + Sync;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:65:29
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | type _T25 = dyn _1 + Sync + _5 + Send;
+ | -- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:68:36
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | type _T26 = dyn Sync + Send + _5 + ObjA;
+ | -- ^^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:71:38
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | type _T27 = dyn Send + Sync + ObjA + _5;
+ | ---- ^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:80:17
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _6 = _1 + _5;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T30 = dyn _6;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:83:17
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _6 = _1 + _5;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T31 = dyn _6 + Send;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:86:24
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _6 = _1 + _5;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+...
+LL | type _T32 = dyn Send + _6;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:89:17
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _6 = _1 + _5;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+LL | trait _7 = _6;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+LL | trait _8 = _7;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+...
+LL | type _T33 = dyn _8;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:92:17
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _6 = _1 + _5;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+LL | trait _7 = _6;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+LL | trait _8 = _7;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+...
+LL | type _T34 = dyn _8 + Send;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:95:24
+ |
+LL | trait _0 = ObjA;
+ | ---- first non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (first use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _6 = _1 + _5;
+ | -- -- referenced here (additional use)
+ | |
+ | referenced here (first use)
+LL | trait _7 = _6;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+LL | trait _8 = _7;
+ | --
+ | |
+ | referenced here (additional use)
+ | referenced here (first use)
+...
+LL | type _T35 = dyn Send + _8;
+ | ^^
+ | |
+ | trait alias used in trait object type (additional use)
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:103:23
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | trait _9 = _5 + Sync;
+ | -- referenced here (first use)
+LL | trait _10 = Unpin + _9;
+ | -- referenced here (first use)
+LL |
+LL | type _T40 = dyn _10 + ObjA;
+ | --- ^^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:106:24
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _9 = _5 + Sync;
+ | -- referenced here (additional use)
+LL | trait _10 = Unpin + _9;
+ | -- referenced here (additional use)
+...
+LL | type _T41 = dyn ObjA + _10;
+ | ---- ^^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:109:23
+ |
+LL | trait _0 = ObjA;
+ | ---- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | trait _9 = _5 + Sync;
+ | -- referenced here (first use)
+LL | trait _10 = Unpin + _9;
+ | -- referenced here (first use)
+...
+LL | type _T42 = dyn _10 + _1;
+ | --- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:112:37
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | trait _9 = _5 + Sync;
+ | -- referenced here (first use)
+LL | trait _10 = Unpin + _9;
+ | -- referenced here (first use)
+...
+LL | type _T43 = dyn Send + _10 + Sync + ObjA;
+ | --- ^^^^ additional non-auto trait
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:115:24
+ |
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- additional non-auto trait
+...
+LL | trait _9 = _5 + Sync;
+ | -- referenced here (additional use)
+LL | trait _10 = Unpin + _9;
+ | -- referenced here (additional use)
+...
+LL | type _T44 = dyn ObjA + _10 + Send + Sync;
+ | ---- ^^^ trait alias used in trait object type (additional use)
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-extra-traits.rs:118:37
+ |
+LL | trait _0 = ObjA;
+ | ---- additional non-auto trait
+LL | trait _1 = _0;
+ | -- referenced here (additional use)
+...
+LL | trait _5 = Sync + ObjB + Send;
+ | ---- first non-auto trait
+...
+LL | trait _9 = _5 + Sync;
+ | -- referenced here (first use)
+LL | trait _10 = Unpin + _9;
+ | -- referenced here (first use)
+...
+LL | type _T45 = dyn Sync + Send + _10 + _1;
+ | --- ^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error: aborting due to 28 previous errors
+
+For more information about this error, try `rustc --explain E0225`.
diff --git a/tests/ui/traits/alias/object-fail.rs b/tests/ui/traits/alias/object-fail.rs
new file mode 100644
index 000000000..5c753ff20
--- /dev/null
+++ b/tests/ui/traits/alias/object-fail.rs
@@ -0,0 +1,11 @@
+#![feature(trait_alias)]
+
+trait EqAlias = Eq;
+trait IteratorAlias = Iterator;
+
+fn main() {
+ let _: &dyn EqAlias = &123;
+ //~^ ERROR the trait `Eq` cannot be made into an object [E0038]
+ let _: &dyn IteratorAlias = &vec![123].into_iter();
+ //~^ ERROR must be specified
+}
diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr
new file mode 100644
index 000000000..048a150df
--- /dev/null
+++ b/tests/ui/traits/alias/object-fail.stderr
@@ -0,0 +1,21 @@
+error[E0038]: the trait `Eq` cannot be made into an object
+ --> $DIR/object-fail.rs:7:13
+ |
+LL | let _: &dyn EqAlias = &123;
+ | ^^^^^^^^^^^ `Eq` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ |
+ = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+
+error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
+ --> $DIR/object-fail.rs:9:17
+ |
+LL | let _: &dyn IteratorAlias = &vec![123].into_iter();
+ | ^^^^^^^^^^^^^ help: specify the associated type: `IteratorAlias<Item = Type>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0038, E0191.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/alias/object-wf.rs b/tests/ui/traits/alias/object-wf.rs
new file mode 100644
index 000000000..1440f02df
--- /dev/null
+++ b/tests/ui/traits/alias/object-wf.rs
@@ -0,0 +1,85 @@
+// check-pass
+
+// This test checks that trait objects involving trait aliases are well-formed.
+
+#![feature(trait_alias)]
+
+trait Obj {}
+
+trait _0 = Send + Sync;
+
+// Just auto traits:
+
+trait _1 = _0 + Send + Sync;
+
+use std::marker::Unpin;
+
+fn _f0() {
+ let _: Box<dyn _0>;
+ let _: Box<dyn _1>;
+ let _: Box<dyn Unpin + _1 + Send + Sync>;
+}
+
+// Include object safe traits:
+
+fn _f1() {
+ let _: Box<dyn Obj + _0>;
+ let _: Box<dyn Obj + _1>;
+ let _: Box<dyn Obj + _1 + _0>;
+}
+
+// And when the object safe trait is in a trait alias:
+
+trait _2 = Obj;
+
+fn _f2() {
+ let _: Box<dyn _2 + _0>;
+ let _: Box<dyn _2 + _1>;
+ let _: Box<dyn _2 + _1 + _0>;
+}
+
+// And it should also work when that trait is has auto traits to the right of it.
+
+trait _3 = Obj + Unpin;
+
+fn _f3() {
+ let _: Box<dyn _3 + _0>;
+ let _: Box<dyn _3 + _1>;
+ let _: Box<dyn _3 + _1 + _0>;
+}
+
+// Nest the trait deeply:
+
+trait _4 = _3;
+trait _5 = _4 + Sync + _0 + Send;
+trait _6 = _5 + Send + _1 + Sync;
+
+fn _f4() {
+ let _: Box<dyn _6 + _0>;
+ let _: Box<dyn _6 + _1>;
+ let _: Box<dyn _6 + _1 + _0>;
+}
+
+// Just nest the trait alone:
+
+trait _7 = _2;
+trait _8 = _7;
+trait _9 = _8;
+
+fn _f5() {
+ let _: Box<dyn _9>;
+}
+
+// First bound is auto trait:
+
+trait _10 = Send + Obj;
+trait _11 = Obj + Send;
+trait _12 = Sync + _11;
+trait _13 = Send + _12;
+
+fn f6() {
+ let _: Box<dyn _10>;
+ let _: Box<dyn _13>;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/alias/object.rs b/tests/ui/traits/alias/object.rs
new file mode 100644
index 000000000..12177cd82
--- /dev/null
+++ b/tests/ui/traits/alias/object.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+trait Foo = PartialEq<i32> + Send;
+trait Bar = Foo + Sync;
+
+trait I32Iterator = Iterator<Item = i32>;
+
+pub fn main() {
+ let a: &dyn Bar = &123;
+ assert!(*a == 123);
+ let b = Box::new(456) as Box<dyn Foo>;
+ assert!(*b == 456);
+
+ let c: &mut dyn I32Iterator = &mut vec![123].into_iter();
+ assert_eq!(c.next(), Some(123));
+}
diff --git a/tests/ui/traits/alias/only-maybe-bound.rs b/tests/ui/traits/alias/only-maybe-bound.rs
new file mode 100644
index 000000000..e4abf314e
--- /dev/null
+++ b/tests/ui/traits/alias/only-maybe-bound.rs
@@ -0,0 +1,22 @@
+// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just
+// `?Sized` results from trait alias expansion.
+
+#![feature(trait_alias)]
+
+trait S = ?Sized;
+
+// Nest a couple of levels deep:
+trait _0 = S;
+trait _1 = _0;
+
+// Straight list expansion:
+type _T0 = dyn _1;
+//~^ ERROR at least one trait is required for an object type [E0224]
+
+// Twice:
+trait _2 = _1 + _1;
+
+type _T1 = dyn _2;
+//~^ ERROR at least one trait is required for an object type [E0224]
+
+fn main() {}
diff --git a/tests/ui/traits/alias/only-maybe-bound.stderr b/tests/ui/traits/alias/only-maybe-bound.stderr
new file mode 100644
index 000000000..175ec8120
--- /dev/null
+++ b/tests/ui/traits/alias/only-maybe-bound.stderr
@@ -0,0 +1,21 @@
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/only-maybe-bound.rs:13:12
+ |
+LL | trait _1 = _0;
+ | -------- this alias does not contain a trait
+...
+LL | type _T0 = dyn _1;
+ | ^^^^^^
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/only-maybe-bound.rs:19:12
+ |
+LL | trait _2 = _1 + _1;
+ | -------- this alias does not contain a trait
+LL |
+LL | type _T1 = dyn _2;
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/traits/alias/self-in-const-generics.rs b/tests/ui/traits/alias/self-in-const-generics.rs
new file mode 100644
index 000000000..b0de8ccd6
--- /dev/null
+++ b/tests/ui/traits/alias/self-in-const-generics.rs
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+#![feature(trait_alias)]
+
+trait Bar<const N: usize> {}
+
+trait BB = Bar<{ 2 + 1 }>;
+
+fn foo(x: &dyn BB) {}
+//~^ ERROR the trait alias `BB` cannot be made into an object [E0038]
+
+fn main() {}
diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr
new file mode 100644
index 000000000..61cc217cf
--- /dev/null
+++ b/tests/ui/traits/alias/self-in-const-generics.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait alias `BB` cannot be made into an object
+ --> $DIR/self-in-const-generics.rs:9:16
+ |
+LL | fn foo(x: &dyn BB) {}
+ | ^^
+ |
+ = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/alias/self-in-generics.rs b/tests/ui/traits/alias/self-in-generics.rs
new file mode 100644
index 000000000..0bb6335f9
--- /dev/null
+++ b/tests/ui/traits/alias/self-in-generics.rs
@@ -0,0 +1,15 @@
+// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
+// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
+// Using `save-analysis` triggers type-checking `f` that would be normally skipped
+// as `type_of` emitted an error.
+//
+// compile-flags: -Zsave-analysis
+
+#![feature(trait_alias)]
+
+pub trait SelfInput = Fn(&mut Self);
+
+pub fn f(_f: &dyn SelfInput) {}
+//~^ ERROR the trait alias `SelfInput` cannot be made into an object [E0038]
+
+fn main() {}
diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr
new file mode 100644
index 000000000..110d60e6e
--- /dev/null
+++ b/tests/ui/traits/alias/self-in-generics.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait alias `SelfInput` cannot be made into an object
+ --> $DIR/self-in-generics.rs:12:19
+ |
+LL | pub fn f(_f: &dyn SelfInput) {}
+ | ^^^^^^^^^
+ |
+ = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/alias/style_lint.rs b/tests/ui/traits/alias/style_lint.rs
new file mode 100644
index 000000000..33be20054
--- /dev/null
+++ b/tests/ui/traits/alias/style_lint.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+trait Foo = std::fmt::Display + std::fmt::Debug;
+trait bar = std::fmt::Display + std::fmt::Debug; //~WARN trait alias `bar` should have an upper camel case name
+
+fn main() {}
diff --git a/tests/ui/traits/alias/style_lint.stderr b/tests/ui/traits/alias/style_lint.stderr
new file mode 100644
index 000000000..91e2ea90e
--- /dev/null
+++ b/tests/ui/traits/alias/style_lint.stderr
@@ -0,0 +1,10 @@
+warning: trait alias `bar` should have an upper camel case name
+ --> $DIR/style_lint.rs:6:7
+ |
+LL | trait bar = std::fmt::Display + std::fmt::Debug;
+ | ^^^ help: convert the identifier to upper camel case: `Bar`
+ |
+ = note: `#[warn(non_camel_case_types)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed
new file mode 100644
index 000000000..8a94abaeb
--- /dev/null
+++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed
@@ -0,0 +1,13 @@
+// Regression test of #43913.
+
+// run-rustfix
+
+#![feature(trait_alias)]
+#![allow(bare_trait_objects, dead_code)]
+
+trait Strings = Iterator<Item=String>;
+
+struct Struct<S: Strings>(S);
+//~^ ERROR: expected trait, found type alias `Strings`
+
+fn main() {}
diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs
new file mode 100644
index 000000000..40c678c28
--- /dev/null
+++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs
@@ -0,0 +1,13 @@
+// Regression test of #43913.
+
+// run-rustfix
+
+#![feature(trait_alias)]
+#![allow(bare_trait_objects, dead_code)]
+
+type Strings = Iterator<Item=String>;
+
+struct Struct<S: Strings>(S);
+//~^ ERROR: expected trait, found type alias `Strings`
+
+fn main() {}
diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr
new file mode 100644
index 000000000..6e03eeada
--- /dev/null
+++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr
@@ -0,0 +1,14 @@
+error[E0404]: expected trait, found type alias `Strings`
+ --> $DIR/suggest-trait-alias-instead-of-type.rs:10:18
+ |
+LL | struct Struct<S: Strings>(S);
+ | ^^^^^^^ type aliases cannot be used as traits
+ |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+ |
+LL | trait Strings = Iterator<Item=String>;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/traits/alias/syntax-fail.rs b/tests/ui/traits/alias/syntax-fail.rs
new file mode 100644
index 000000000..039bbce8c
--- /dev/null
+++ b/tests/ui/traits/alias/syntax-fail.rs
@@ -0,0 +1,10 @@
+#![feature(trait_alias)]
+
+trait Foo {}
+auto trait A = Foo; //~ ERROR trait aliases cannot be `auto`
+unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe`
+
+trait C: Ord = Eq; //~ ERROR bounds are not allowed on trait aliases
+trait D: = Eq; //~ ERROR bounds are not allowed on trait aliases
+
+fn main() {}
diff --git a/tests/ui/traits/alias/syntax-fail.stderr b/tests/ui/traits/alias/syntax-fail.stderr
new file mode 100644
index 000000000..748b92056
--- /dev/null
+++ b/tests/ui/traits/alias/syntax-fail.stderr
@@ -0,0 +1,26 @@
+error: trait aliases cannot be `auto`
+ --> $DIR/syntax-fail.rs:4:1
+ |
+LL | auto trait A = Foo;
+ | ^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
+
+error: trait aliases cannot be `unsafe`
+ --> $DIR/syntax-fail.rs:5:1
+ |
+LL | unsafe trait B = Foo;
+ | ^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
+
+error: bounds are not allowed on trait aliases
+ --> $DIR/syntax-fail.rs:7:8
+ |
+LL | trait C: Ord = Eq;
+ | ^^^^^
+
+error: bounds are not allowed on trait aliases
+ --> $DIR/syntax-fail.rs:8:8
+ |
+LL | trait D: = Eq;
+ | ^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/traits/alias/syntax.rs b/tests/ui/traits/alias/syntax.rs
new file mode 100644
index 000000000..17557a51a
--- /dev/null
+++ b/tests/ui/traits/alias/syntax.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+trait SimpleAlias = Default;
+trait GenericAlias<T> = Iterator<Item = T>;
+trait Partial<T> = IntoIterator<Item = T>;
+trait SpecificAlias = GenericAlias<i32>;
+trait PartialEqRef<'a, T: 'a> = PartialEq<&'a T>;
+trait StaticAlias = 'static;
+
+trait Things<T> {}
+trait Romeo {}
+#[allow(dead_code)]
+struct The<T>(T);
+#[allow(dead_code)]
+struct Fore<T>(T);
+impl<T, U> Things<T> for The<U> {}
+impl<T> Romeo for Fore<T> {}
+
+trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo;
+trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>;
+
+fn main() {}
diff --git a/tests/ui/traits/alias/wf.rs b/tests/ui/traits/alias/wf.rs
new file mode 100644
index 000000000..d10e2abb0
--- /dev/null
+++ b/tests/ui/traits/alias/wf.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias)]
+
+trait Foo {}
+trait A<T: Foo> {}
+trait B<T> = A<T>; //~ ERROR `T: Foo` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr
new file mode 100644
index 000000000..7172008d3
--- /dev/null
+++ b/tests/ui/traits/alias/wf.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: Foo` is not satisfied
+ --> $DIR/wf.rs:5:14
+ |
+LL | trait B<T> = A<T>;
+ | ^^^^ the trait `Foo` is not implemented for `T`
+ |
+note: required by a bound in `A`
+ --> $DIR/wf.rs:4:12
+ |
+LL | trait A<T: Foo> {}
+ | ^^^ required by this bound in `A`
+help: consider restricting type parameter `T`
+ |
+LL | trait B<T: Foo> = A<T>;
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alignment-gep-tup-like-1.rs b/tests/ui/traits/alignment-gep-tup-like-1.rs
new file mode 100644
index 000000000..eb503dcf3
--- /dev/null
+++ b/tests/ui/traits/alignment-gep-tup-like-1.rs
@@ -0,0 +1,37 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+
+struct pair<A,B> {
+ a: A, b: B
+}
+
+trait Invokable<A> {
+ fn f(&self) -> (A, u16);
+}
+
+struct Invoker<A> {
+ a: A,
+ b: u16,
+}
+
+impl<A:Clone> Invokable<A> for Invoker<A> {
+ fn f(&self) -> (A, u16) {
+ (self.a.clone(), self.b)
+ }
+}
+
+fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
+ Box::new(Invoker {
+ a: a,
+ b: b,
+ }) as Box<dyn Invokable<A>+'static>
+}
+
+pub fn main() {
+ let (a, b) = f(22_u64, 44u16).f();
+ println!("a={} b={}", a, b);
+ assert_eq!(a, 22u64);
+ assert_eq!(b, 44u16);
+}
diff --git a/tests/ui/traits/anon-static-method.rs b/tests/ui/traits/anon-static-method.rs
new file mode 100644
index 000000000..ede01afae
--- /dev/null
+++ b/tests/ui/traits/anon-static-method.rs
@@ -0,0 +1,15 @@
+// run-pass
+struct Foo {
+ x: isize
+}
+
+impl Foo {
+ pub fn new() -> Foo {
+ Foo { x: 3 }
+ }
+}
+
+pub fn main() {
+ let x = Foo::new();
+ println!("{}", x.x);
+}
diff --git a/tests/ui/traits/anon_trait_static_method_exe.rs b/tests/ui/traits/anon_trait_static_method_exe.rs
new file mode 100644
index 000000000..b49302954
--- /dev/null
+++ b/tests/ui/traits/anon_trait_static_method_exe.rs
@@ -0,0 +1,12 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// aux-build:anon_trait_static_method_lib.rs
+
+extern crate anon_trait_static_method_lib;
+use anon_trait_static_method_lib::Foo;
+
+pub fn main() {
+ let x = Foo::new();
+ println!("{}", x.x);
+}
diff --git a/tests/ui/traits/as-struct-constructor.rs b/tests/ui/traits/as-struct-constructor.rs
new file mode 100644
index 000000000..13ebf9d8d
--- /dev/null
+++ b/tests/ui/traits/as-struct-constructor.rs
@@ -0,0 +1,6 @@
+trait TraitNotAStruct {}
+
+fn main() {
+ TraitNotAStruct{ value: 0 };
+ //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct`
+}
diff --git a/tests/ui/traits/as-struct-constructor.stderr b/tests/ui/traits/as-struct-constructor.stderr
new file mode 100644
index 000000000..d06e85f3a
--- /dev/null
+++ b/tests/ui/traits/as-struct-constructor.stderr
@@ -0,0 +1,9 @@
+error[E0574]: expected struct, variant or union type, found trait `TraitNotAStruct`
+ --> $DIR/as-struct-constructor.rs:4:5
+ |
+LL | TraitNotAStruct{ value: 0 };
+ | ^^^^^^^^^^^^^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/tests/ui/traits/assignability-trait.rs b/tests/ui/traits/assignability-trait.rs
new file mode 100644
index 000000000..a8547c1d2
--- /dev/null
+++ b/tests/ui/traits/assignability-trait.rs
@@ -0,0 +1,47 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// Tests that type assignability is used to search for instances when
+// making method calls, but only if there aren't any matches without
+// it.
+
+trait iterable<A> {
+ fn iterate<F>(&self, blk: F) -> bool where F: FnMut(&A) -> bool;
+}
+
+impl<'a,A> iterable<A> for &'a [A] {
+ fn iterate<F>(&self, f: F) -> bool where F: FnMut(&A) -> bool {
+ self.iter().all(f)
+ }
+}
+
+impl<A> iterable<A> for Vec<A> {
+ fn iterate<F>(&self, f: F) -> bool where F: FnMut(&A) -> bool {
+ self.iter().all(f)
+ }
+}
+
+fn length<A, T: iterable<A>>(x: T) -> usize {
+ let mut len = 0;
+ x.iterate(|_y| {
+ len += 1;
+ true
+ });
+ return len;
+}
+
+pub fn main() {
+ let x: Vec<isize> = vec![0,1,2,3];
+ // Call a method
+ x.iterate(|y| { assert_eq!(x[*y as usize], *y); true });
+ // Call a parameterized function
+ assert_eq!(length(x.clone()), x.len());
+ // Call a parameterized function, with type arguments that require
+ // a borrow
+ assert_eq!(length::<isize, &[isize]>(&*x), x.len());
+
+ // Now try it with a type that *needs* to be borrowed
+ let z = [0,1,2,3];
+ // Call a parameterized function
+ assert_eq!(length::<isize, &[isize]>(&z), z.len());
+}
diff --git a/tests/ui/traits/assoc-type-in-superbad.rs b/tests/ui/traits/assoc-type-in-superbad.rs
new file mode 100644
index 000000000..65340b2a2
--- /dev/null
+++ b/tests/ui/traits/assoc-type-in-superbad.rs
@@ -0,0 +1,16 @@
+// Test case where an associated type is referenced from within the
+// supertrait definition, and the impl makes the wrong
+// associations. Issue #20220.
+
+use std::vec::IntoIter;
+
+pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
+ type Key;
+}
+
+impl Foo for IntoIter<i32> {
+ type Key = u32;
+ //~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/assoc-type-in-superbad.stderr b/tests/ui/traits/assoc-type-in-superbad.stderr
new file mode 100644
index 000000000..7fa1d2c2e
--- /dev/null
+++ b/tests/ui/traits/assoc-type-in-superbad.stderr
@@ -0,0 +1,15 @@
+error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+ --> $DIR/assoc-type-in-superbad.rs:12:16
+ |
+LL | type Key = u32;
+ | ^^^ expected `u32`, found `i32`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/assoc-type-in-superbad.rs:7:25
+ |
+LL | pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/assoc-type-in-supertrait.rs b/tests/ui/traits/assoc-type-in-supertrait.rs
new file mode 100644
index 000000000..7d6a754cc
--- /dev/null
+++ b/tests/ui/traits/assoc-type-in-supertrait.rs
@@ -0,0 +1,23 @@
+// run-pass
+// Test case where an associated type is referenced from within the
+// supertrait definition. Issue #20220.
+
+
+use std::vec::IntoIter;
+
+pub trait Foo: Iterator<Item=<Self as Foo>::Key> {
+ type Key;
+}
+
+impl Foo for IntoIter<i32> {
+ type Key = i32;
+}
+
+fn sum_foo<F:Foo<Key=i32>>(f: F) -> i32 {
+ f.fold(0, |a,b| a + b)
+}
+
+fn main() {
+ let x = sum_foo(vec![11, 10, 1].into_iter());
+ assert_eq!(x, 22);
+}
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
new file mode 100644
index 000000000..471a6b836
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
@@ -0,0 +1,23 @@
+trait Bar {
+ type Baz;
+}
+
+struct Foo<T> where T: Bar, <T as Bar>::Baz: String { //~ ERROR expected trait, found struct
+ t: T,
+}
+
+struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found struct
+ t: &'a T,
+}
+
+fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, found struct
+}
+
+fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found
+}
+
+fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+//~^ ERROR expected trait, found struct
+//~| ERROR use of undeclared type `Unresolved`
+
+fn main() {}
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
new file mode 100644
index 000000000..5be334986
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -0,0 +1,91 @@
+error[E0433]: failed to resolve: use of undeclared type `Unresolved`
+ --> $DIR/assoc_type_bound_with_struct.rs:19:31
+ |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+ | ^^^^^^^^^^ use of undeclared type `Unresolved`
+
+error[E0404]: expected trait, found struct `String`
+ --> $DIR/assoc_type_bound_with_struct.rs:5:46
+ |
+LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
+ | ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
+ |
+ = note: similarly named trait `ToString` defined here
+ |
+help: constrain the associated type to `String`
+ |
+LL | struct Foo<T> where T: Bar, T: Bar<Baz = String> {
+ | ~~~~~~~~~~~~~~~~~~~~
+help: a trait with a similar name exists
+ |
+LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: ToString {
+ | ~~~~~~~~
+
+error[E0404]: expected trait, found struct `String`
+ --> $DIR/assoc_type_bound_with_struct.rs:9:54
+ |
+LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
+ | ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
+ |
+ = note: similarly named trait `ToString` defined here
+ |
+help: constrain the associated type to `String`
+ |
+LL | struct Qux<'a, T> where T: Bar, &'a T: Bar<Baz = String> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+help: a trait with a similar name exists
+ |
+LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: ToString {
+ | ~~~~~~~~
+
+error[E0404]: expected trait, found struct `String`
+ --> $DIR/assoc_type_bound_with_struct.rs:13:45
+ |
+LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
+ | ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
+ |
+ = note: similarly named trait `ToString` defined here
+ |
+help: constrain the associated type to `String`
+ |
+LL | fn foo<T: Bar>(_: T) where T: Bar<Baz = String> {
+ | ~~~~~~~~~~~~~~~~~~~~
+help: a trait with a similar name exists
+ |
+LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: ToString {
+ | ~~~~~~~~
+
+error[E0404]: expected trait, found struct `String`
+ --> $DIR/assoc_type_bound_with_struct.rs:16:57
+ |
+LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
+ | ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
+ |
+ = note: similarly named trait `ToString` defined here
+ |
+help: constrain the associated type to `String`
+ |
+LL | fn qux<'a, T: Bar>(_: &'a T) where &'a T: Bar<Baz = String> {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+help: a trait with a similar name exists
+ |
+LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
+ | ~~~~~~~~
+
+error[E0404]: expected trait, found struct `String`
+ --> $DIR/assoc_type_bound_with_struct.rs:19:51
+ |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+ | ^^^^^^ help: a trait with a similar name exists: `ToString`
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
+ |
+ = note: similarly named trait `ToString` defined here
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0404, E0433.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs
new file mode 100644
index 000000000..b1f124c7e
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs
@@ -0,0 +1,14 @@
+// Check that we validate associated type bounds for trait objects
+
+trait X {
+ type Y: Clone;
+}
+
+fn f<T: X + ?Sized>() {
+ None::<T::Y>.clone();
+}
+
+fn main() {
+ f::<dyn X<Y = str>>();
+ //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
new file mode 100644
index 000000000..fa7a8a2a0
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `str: Clone` is not satisfied
+ --> $DIR/check-trait-object-bounds-1.rs:12:9
+ |
+LL | f::<dyn X<Y = str>>();
+ | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+ |
+ = help: the trait `Clone` is implemented for `String`
+note: required by a bound in `f`
+ --> $DIR/check-trait-object-bounds-1.rs:7:9
+ |
+LL | fn f<T: X + ?Sized>() {
+ | ^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs
new file mode 100644
index 000000000..1422dda27
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs
@@ -0,0 +1,15 @@
+// Make sure that we're handling bound lifetimes correctly when validating trait
+// bounds.
+// run-pass
+
+trait X<'a> {
+ type F: FnOnce(&i32) -> &'a i32;
+}
+
+fn f<T: for<'r> X<'r> + ?Sized>() {
+ None::<T::F>.map(|f| f(&0));
+}
+
+fn main() {
+ f::<dyn for<'x> X<'x, F = fn(&i32) -> &'x i32>>();
+}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs
new file mode 100644
index 000000000..eb2fb6e84
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs
@@ -0,0 +1,15 @@
+// Check that we validate associated type bounds for trait objects when they
+// have bound lifetimes
+
+trait X<'a> {
+ type F: FnOnce(&i32) -> &'a i32;
+}
+
+fn f<T: for<'r> X<'r> + ?Sized>() {
+ None::<T::F>.map(|f| f(&0));
+}
+
+fn main() {
+ f::<dyn for<'x> X<'x, F = i32>>();
+ //~^ expected a `FnOnce<(&i32,)>` closure, found `i32`
+}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
new file mode 100644
index 000000000..10e82c54e
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32`
+ --> $DIR/check-trait-object-bounds-2.rs:13:9
+ |
+LL | f::<dyn for<'x> X<'x, F = i32>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
+ |
+ = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32`
+note: required by a bound in `f`
+ --> $DIR/check-trait-object-bounds-2.rs:8:9
+ |
+LL | fn f<T: for<'r> X<'r> + ?Sized>() {
+ | ^^^^^^^^^^^^^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs
new file mode 100644
index 000000000..ba04fd93a
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs
@@ -0,0 +1,20 @@
+// Check that we validate associated type bounds for trait objects
+
+trait X<'a> {
+ type Y: Into<&'static str> + From<&'a str>;
+}
+
+fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str {
+ T::Y::from(s).into()
+}
+
+pub fn main() {
+ let z;
+ {
+ let s = String::from("abcdef");
+ z = f::<dyn X<Y = &str>>(&s);
+ //~^ ERROR `s` does not live long enough
+ }
+
+ println!("{}", z)
+}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr
new file mode 100644
index 000000000..ade552c4b
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `s` does not live long enough
+ --> $DIR/check-trait-object-bounds-3.rs:15:34
+ |
+LL | z = f::<dyn X<Y = &str>>(&s);
+ | ---------------------^^-
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `s` is borrowed for `'static`
+LL |
+LL | }
+ | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs
new file mode 100644
index 000000000..e9ca1563f
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs
@@ -0,0 +1,17 @@
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Super {
+ type Y: Clone;
+}
+
+trait X: Super {}
+
+fn f<T: X + ?Sized>() {
+ None::<T::Y>.clone();
+}
+
+fn main() {
+ f::<dyn X<Y = str>>();
+ //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
new file mode 100644
index 000000000..4891ee9c2
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `str: Clone` is not satisfied
+ --> $DIR/check-trait-object-bounds-4.rs:15:9
+ |
+LL | f::<dyn X<Y = str>>();
+ | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+ |
+ = help: the trait `Clone` is implemented for `String`
+note: required by a bound in `f`
+ --> $DIR/check-trait-object-bounds-4.rs:10:9
+ |
+LL | fn f<T: X + ?Sized>() {
+ | ^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs
new file mode 100644
index 000000000..7d733ad26
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs
@@ -0,0 +1,27 @@
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Super {
+ type V;
+}
+
+trait Obj: Super {
+ type U: Is<T = Self::V>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i64>) {
+ is_obj(x)
+ //~^ type mismatch resolving `<i32 as Is>::T == i64`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr
new file mode 100644
index 000000000..00fdb3753
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr
@@ -0,0 +1,22 @@
+error[E0271]: type mismatch resolving `<i32 as Is>::T == i64`
+ --> $DIR/check-trait-object-bounds-5.rs:23:12
+ |
+LL | is_obj(x)
+ | ------ ^ type mismatch resolving `<i32 as Is>::T == i64`
+ | |
+ | required by a bound introduced by this call
+ |
+note: expected this to be `i64`
+ --> $DIR/check-trait-object-bounds-5.rs:9:14
+ |
+LL | type T = U;
+ | ^
+note: required by a bound in `is_obj`
+ --> $DIR/check-trait-object-bounds-5.rs:20:23
+ |
+LL | fn is_obj<T: ?Sized + Obj>(_: &T) {}
+ | ^^^ required by this bound in `is_obj`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs
new file mode 100644
index 000000000..cb196d67f
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs
@@ -0,0 +1,24 @@
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj {
+ type U: Is<T = Self::V>;
+ type V;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i64>) {
+ is_obj(x)
+ //~^ ERROR type mismatch resolving `<i32 as Is>::T == i64`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr
new file mode 100644
index 000000000..9b0975e5e
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr
@@ -0,0 +1,22 @@
+error[E0271]: type mismatch resolving `<i32 as Is>::T == i64`
+ --> $DIR/check-trait-object-bounds-6.rs:20:12
+ |
+LL | is_obj(x)
+ | ------ ^ type mismatch resolving `<i32 as Is>::T == i64`
+ | |
+ | required by a bound introduced by this call
+ |
+note: expected this to be `i64`
+ --> $DIR/check-trait-object-bounds-6.rs:9:14
+ |
+LL | type T = U;
+ | ^
+note: required by a bound in `is_obj`
+ --> $DIR/check-trait-object-bounds-6.rs:17:23
+ |
+LL | fn is_obj<T: ?Sized + Obj>(_: &T) {}
+ | ^^^ required by this bound in `is_obj`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/associated_type_bound/issue-51446.rs b/tests/ui/traits/associated_type_bound/issue-51446.rs
new file mode 100644
index 000000000..7dd95de73
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/issue-51446.rs
@@ -0,0 +1,34 @@
+// Regression test for #51446.
+// check-pass
+
+trait Foo {
+ type Item;
+ fn get(&self) -> Self::Item;
+}
+
+fn blah<T, F>(x: T, f: F) -> B<T::Item, impl Fn(T::Item)>
+where
+ T: Foo,
+ F: Fn(T::Item),
+{
+ B { x: x.get(), f }
+}
+
+pub struct B<T, F>
+where
+ F: Fn(T),
+{
+ pub x: T,
+ pub f: F,
+}
+
+impl Foo for i32 {
+ type Item = i32;
+ fn get(&self) -> i32 {
+ *self
+ }
+}
+
+fn main() {
+ let _ = blah(0, |_| ());
+}
diff --git a/tests/ui/traits/astconv-cycle-between-and-type.rs b/tests/ui/traits/astconv-cycle-between-and-type.rs
new file mode 100644
index 000000000..cc8f9dc51
--- /dev/null
+++ b/tests/ui/traits/astconv-cycle-between-and-type.rs
@@ -0,0 +1,29 @@
+// run-pass
+// Test that we are able to successfully compile a setup where a trait
+// (`Trait1`) references a struct (`SomeType<u32>`) which in turn
+// carries a predicate that references the trait (`u32 : Trait1`,
+// substituted).
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+trait Trait1 : Trait2<SomeType<u32>> {
+ fn dumb(&self) { }
+}
+
+trait Trait2<A> {
+ fn dumber(&self, _: A) { }
+}
+
+struct SomeType<A>
+ where A : Trait1
+{
+ a: A
+}
+
+impl Trait1 for u32 { }
+
+impl Trait2<SomeType<u32>> for u32 { }
+
+fn main() { }
diff --git a/tests/ui/traits/augmented-assignments-trait.rs b/tests/ui/traits/augmented-assignments-trait.rs
new file mode 100644
index 000000000..747a5393f
--- /dev/null
+++ b/tests/ui/traits/augmented-assignments-trait.rs
@@ -0,0 +1,12 @@
+// run-pass
+use std::ops::AddAssign;
+
+struct Int(#[allow(unused_tuple_struct_fields)] i32);
+
+impl AddAssign for Int {
+ fn add_assign(&mut self, _: Int) {
+ unimplemented!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs b/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs
new file mode 100644
index 000000000..dceec7e3e
--- /dev/null
+++ b/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs
@@ -0,0 +1,9 @@
+pub struct Foo {
+ pub x: isize
+}
+
+impl Foo {
+ pub fn new() -> Foo {
+ Foo { x: 3 }
+ }
+}
diff --git a/tests/ui/traits/auxiliary/go_trait.rs b/tests/ui/traits/auxiliary/go_trait.rs
new file mode 100644
index 000000000..aa0ec2289
--- /dev/null
+++ b/tests/ui/traits/auxiliary/go_trait.rs
@@ -0,0 +1,43 @@
+#![feature(specialization)]
+
+// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy.
+
+pub trait Go {
+ fn go(&self, arg: isize);
+}
+
+pub fn go<G:Go>(this: &G, arg: isize) {
+ this.go(arg)
+}
+
+pub trait GoMut {
+ fn go_mut(&mut self, arg: isize);
+}
+
+pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) {
+ this.go_mut(arg)
+}
+
+pub trait GoOnce {
+ fn go_once(self, arg: isize);
+}
+
+pub fn go_once<G:GoOnce>(this: G, arg: isize) {
+ this.go_once(arg)
+}
+
+impl<G> GoMut for G
+ where G : Go
+{
+ default fn go_mut(&mut self, arg: isize) {
+ go(&*self, arg)
+ }
+}
+
+impl<G> GoOnce for G
+ where G : GoMut
+{
+ default fn go_once(mut self, arg: isize) {
+ go_mut(&mut self, arg)
+ }
+}
diff --git a/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs b/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs
new file mode 100644
index 000000000..769e89731
--- /dev/null
+++ b/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs
@@ -0,0 +1,60 @@
+// This is the auxiliary crate for the regression test for issue #89119, minimized
+// from `zvariant-2.8.0`.
+
+use std::convert::TryFrom;
+use std::borrow::Cow;
+
+pub struct Str<'a>(Cow<'a, str>);
+impl<'a> Str<'a> {
+ pub fn to_owned(&self) -> Str<'static> {
+ todo!()
+ }
+}
+
+pub enum Value<'a> {
+ Str(Str<'a>),
+ Value(Box<Value<'a>>),
+}
+impl<'a> Value<'a> {
+ pub fn to_owned(&self) -> Value<'static> {
+ match self {
+ Value::Str(v) => Value::Str(v.to_owned()),
+ Value::Value(v) => {
+ let o = OwnedValue::from(&**v);
+ Value::Value(Box::new(o.into_inner()))
+ }
+ }
+ }
+}
+
+struct OwnedValue(Value<'static>);
+impl OwnedValue {
+ pub(crate) fn into_inner(self) -> Value<'static> {
+ todo!()
+ }
+}
+impl<'a, T> TryFrom<OwnedValue> for Vec<T>
+where
+ T: TryFrom<Value<'a>, Error = ()>,
+{
+ type Error = ();
+ fn try_from(_: OwnedValue) -> Result<Self, Self::Error> {
+ todo!()
+ }
+}
+impl TryFrom<OwnedValue> for Vec<OwnedValue> {
+ type Error = ();
+ fn try_from(_: OwnedValue) -> Result<Self, Self::Error> {
+ todo!()
+ }
+}
+impl<'a> From<Value<'a>> for OwnedValue {
+ fn from(_: Value<'a>) -> Self {
+ todo!()
+ }
+}
+impl<'a> From<&Value<'a>> for OwnedValue {
+ fn from(_: &Value<'a>) -> Self {
+ todo!()
+ }
+}
diff --git a/tests/ui/traits/auxiliary/trait_safety_lib.rs b/tests/ui/traits/auxiliary/trait_safety_lib.rs
new file mode 100644
index 000000000..6fc432ed4
--- /dev/null
+++ b/tests/ui/traits/auxiliary/trait_safety_lib.rs
@@ -0,0 +1,9 @@
+// Simple smoke test that unsafe traits can be compiled etc.
+
+pub unsafe trait Foo {
+ fn foo(&self) -> isize;
+}
+
+unsafe impl Foo for isize {
+ fn foo(&self) -> isize { *self }
+}
diff --git a/tests/ui/traits/auxiliary/traitimpl.rs b/tests/ui/traits/auxiliary/traitimpl.rs
new file mode 100644
index 000000000..fda5314cd
--- /dev/null
+++ b/tests/ui/traits/auxiliary/traitimpl.rs
@@ -0,0 +1,7 @@
+// Test inherent trait impls work cross-crait.
+
+pub trait Bar<'a> : 'a {}
+
+impl<'a> Bar<'a> {
+ pub fn bar(&self) {}
+}
diff --git a/tests/ui/traits/bad-method-typaram-kind.rs b/tests/ui/traits/bad-method-typaram-kind.rs
new file mode 100644
index 000000000..b088eae1c
--- /dev/null
+++ b/tests/ui/traits/bad-method-typaram-kind.rs
@@ -0,0 +1,14 @@
+fn foo<T:'static>() {
+ 1.bar::<T>(); //~ ERROR `T` cannot be sent between threads safely
+}
+
+trait Bar {
+ fn bar<T:Send>(&self);
+}
+
+impl Bar for usize {
+ fn bar<T:Send>(&self) {
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr
new file mode 100644
index 000000000..56acfbe80
--- /dev/null
+++ b/tests/ui/traits/bad-method-typaram-kind.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `T` cannot be sent between threads safely
+ --> $DIR/bad-method-typaram-kind.rs:2:13
+ |
+LL | 1.bar::<T>();
+ | ^ `T` cannot be sent between threads safely
+ |
+note: required by a bound in `Bar::bar`
+ --> $DIR/bad-method-typaram-kind.rs:6:14
+ |
+LL | fn bar<T:Send>(&self);
+ | ^^^^ required by this bound in `Bar::bar`
+help: consider further restricting this bound
+ |
+LL | fn foo<T:'static + std::marker::Send>() {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bad-sized.rs b/tests/ui/traits/bad-sized.rs
new file mode 100644
index 000000000..a15219679
--- /dev/null
+++ b/tests/ui/traits/bad-sized.rs
@@ -0,0 +1,9 @@
+trait Trait {}
+
+pub fn main() {
+ let x: Vec<dyn Trait + Sized> = Vec::new();
+ //~^ ERROR only auto traits can be used as additional traits in a trait object
+ //~| ERROR the size for values of type
+ //~| ERROR the size for values of type
+ //~| ERROR the size for values of type
+}
diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr
new file mode 100644
index 000000000..fb9900bc5
--- /dev/null
+++ b/tests/ui/traits/bad-sized.stderr
@@ -0,0 +1,45 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/bad-sized.rs:4:28
+ |
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ----- ^^^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Trait + Sized {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+ --> $DIR/bad-sized.rs:4:12
+ |
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `dyn Trait`
+note: required by a bound in `Vec`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+ --> $DIR/bad-sized.rs:4:37
+ |
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `dyn Trait`
+note: required by a bound in `Vec::<T>::new`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+ --> $DIR/bad-sized.rs:4:37
+ |
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `dyn Trait`
+note: required by a bound in `Vec`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0225, E0277.
+For more information about an error, try `rustc --explain E0225`.
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
new file mode 100644
index 000000000..f9a934764
--- /dev/null
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
@@ -0,0 +1,11 @@
+fn strip_lf(s: &str) -> &str {
+ s.strip_suffix(b'\n').unwrap_or(s)
+ //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8`
+ //~| NOTE expected an `FnMut<(char,)>` closure, found `u8`
+ //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8`
+ //~| HELP the following other types implement trait `Pattern<'a>`:
+ //~| NOTE required for `u8` to implement `Pattern<'_>`
+
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
new file mode 100644
index 000000000..ce9ab2d81
--- /dev/null
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
@@ -0,0 +1,20 @@
+error[E0277]: expected a `FnMut<(char,)>` closure, found `u8`
+ --> $DIR/assoc-fn-bound-root-obligation.rs:2:7
+ |
+LL | s.strip_suffix(b'\n').unwrap_or(s)
+ | ^^^^^^^^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
+ |
+ = help: the trait `FnMut<(char,)>` is not implemented for `u8`
+ = help: the following other types implement trait `Pattern<'a>`:
+ &'b String
+ &'b [char; N]
+ &'b [char]
+ &'b str
+ &'c &'b str
+ [char; N]
+ char
+ = note: required for `u8` to implement `Pattern<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/auxiliary/crate_a1.rs b/tests/ui/traits/bound/auxiliary/crate_a1.rs
new file mode 100644
index 000000000..6aa010258
--- /dev/null
+++ b/tests/ui/traits/bound/auxiliary/crate_a1.rs
@@ -0,0 +1,9 @@
+pub trait Bar {}
+
+pub fn try_foo(x: impl Bar) {}
+
+pub struct ImplementsTraitForUsize<T> {
+ _marker: std::marker::PhantomData<T>,
+}
+
+impl Bar for ImplementsTraitForUsize<usize> {}
diff --git a/tests/ui/traits/bound/auxiliary/crate_a2.rs b/tests/ui/traits/bound/auxiliary/crate_a2.rs
new file mode 100644
index 000000000..d6057db5e
--- /dev/null
+++ b/tests/ui/traits/bound/auxiliary/crate_a2.rs
@@ -0,0 +1,13 @@
+pub struct Foo;
+
+pub trait Bar {}
+
+impl Bar for Foo {}
+
+pub struct DoesNotImplementTrait;
+
+pub struct ImplementsWrongTraitConditionally<T> {
+ _marker: std::marker::PhantomData<T>,
+}
+
+impl Bar for ImplementsWrongTraitConditionally<isize> {}
diff --git a/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs b/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs
new file mode 100644
index 000000000..7e9592eee
--- /dev/null
+++ b/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs
@@ -0,0 +1,13 @@
+pub trait Trait {
+ fn dummy(&self) { }
+}
+
+pub struct Foo<T:Trait> {
+ pub x: T,
+}
+
+pub enum Bar<T:Trait> {
+ ABar(isize),
+ BBar(T),
+ CBar(usize),
+}
diff --git a/tests/ui/traits/bound/basic.rs b/tests/ui/traits/bound/basic.rs
new file mode 100644
index 000000000..8c8a7eb7d
--- /dev/null
+++ b/tests/ui/traits/bound/basic.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unconditional_recursion)]
+
+// pretty-expanded FIXME #23616
+
+trait Foo {
+}
+
+fn b(_x: Box<dyn Foo+Send>) {
+}
+
+fn c(x: Box<dyn Foo+Sync+Send>) {
+ e(x);
+}
+
+fn d(x: Box<dyn Foo+Send>) {
+ e(x);
+}
+
+fn e(x: Box<dyn Foo>) {
+ e(x);
+}
+
+pub fn main() { }
diff --git a/tests/ui/traits/bound/generic_trait.rs b/tests/ui/traits/bound/generic_trait.rs
new file mode 100644
index 000000000..18382bb59
--- /dev/null
+++ b/tests/ui/traits/bound/generic_trait.rs
@@ -0,0 +1,30 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+
+trait connection {
+ fn read(&self) -> isize;
+}
+
+trait connection_factory<C:connection> {
+ fn create(&self) -> C;
+}
+
+type my_connection = ();
+type my_connection_factory = ();
+
+impl connection for () {
+ fn read(&self) -> isize { 43 }
+}
+
+impl connection_factory<my_connection> for my_connection_factory {
+ fn create(&self) -> my_connection { () }
+}
+
+pub fn main() {
+ let factory = ();
+ let connection = factory.create();
+ let result = connection.read();
+ assert_eq!(result, 43);
+}
diff --git a/tests/ui/traits/bound/impl-comparison-duplicates.rs b/tests/ui/traits/bound/impl-comparison-duplicates.rs
new file mode 100644
index 000000000..de6c2afa2
--- /dev/null
+++ b/tests/ui/traits/bound/impl-comparison-duplicates.rs
@@ -0,0 +1,16 @@
+// run-pass
+// Tests that type parameter bounds on an implementation need not match the
+// trait exactly, as long as the implementation doesn't demand *more* bounds
+// than the trait.
+
+// pretty-expanded FIXME #23616
+
+trait A {
+ fn foo<T: Eq + Ord>(&self);
+}
+
+impl A for isize {
+ fn foo<T: Ord>(&self) {} // Ord implies Eq, so this is ok.
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bound/in-arc.rs b/tests/ui/traits/bound/in-arc.rs
new file mode 100644
index 000000000..a1492c0b9
--- /dev/null
+++ b/tests/ui/traits/bound/in-arc.rs
@@ -0,0 +1,108 @@
+// run-pass
+#![allow(unused_must_use)]
+// Tests that a heterogeneous list of existential `dyn` types can be put inside an Arc
+// and shared between threads as long as all types fulfill Send.
+
+// ignore-emscripten no threads support
+
+use std::sync::Arc;
+use std::sync::mpsc::channel;
+use std::thread;
+
+trait Pet {
+ fn name(&self, blk: Box<dyn FnMut(&str)>);
+ fn num_legs(&self) -> usize;
+ fn of_good_pedigree(&self) -> bool;
+}
+
+struct Catte {
+ num_whiskers: usize,
+ name: String,
+}
+
+struct Dogge {
+ bark_decibels: usize,
+ tricks_known: usize,
+ name: String,
+}
+
+struct Goldfyshe {
+ swim_speed: usize,
+ name: String,
+}
+
+impl Pet for Catte {
+ fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) }
+ fn num_legs(&self) -> usize { 4 }
+ fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 }
+}
+impl Pet for Dogge {
+ fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) }
+ fn num_legs(&self) -> usize { 4 }
+ fn of_good_pedigree(&self) -> bool {
+ self.bark_decibels < 70 || self.tricks_known > 20
+ }
+}
+impl Pet for Goldfyshe {
+ fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) }
+ fn num_legs(&self) -> usize { 0 }
+ fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 }
+}
+
+pub fn main() {
+ let catte = Catte { num_whiskers: 7, name: "alonzo_church".to_string() };
+ let dogge1 = Dogge {
+ bark_decibels: 100,
+ tricks_known: 42,
+ name: "alan_turing".to_string(),
+ };
+ let dogge2 = Dogge {
+ bark_decibels: 55,
+ tricks_known: 11,
+ name: "albert_einstein".to_string(),
+ };
+ let fishe = Goldfyshe {
+ swim_speed: 998,
+ name: "alec_guinness".to_string(),
+ };
+ let arc = Arc::new(vec![
+ Box::new(catte) as Box<dyn Pet+Sync+Send>,
+ Box::new(dogge1) as Box<dyn Pet+Sync+Send>,
+ Box::new(fishe) as Box<dyn Pet+Sync+Send>,
+ Box::new(dogge2) as Box<dyn Pet+Sync+Send>]);
+ let (tx1, rx1) = channel();
+ let arc1 = arc.clone();
+ let t1 = thread::spawn(move|| { check_legs(arc1); tx1.send(()); });
+ let (tx2, rx2) = channel();
+ let arc2 = arc.clone();
+ let t2 = thread::spawn(move|| { check_names(arc2); tx2.send(()); });
+ let (tx3, rx3) = channel();
+ let arc3 = arc.clone();
+ let t3 = thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); });
+ rx1.recv();
+ rx2.recv();
+ rx3.recv();
+ t1.join();
+ t2.join();
+ t3.join();
+}
+
+fn check_legs(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) {
+ let mut legs = 0;
+ for pet in arc.iter() {
+ legs += pet.num_legs();
+ }
+ assert!(legs == 12);
+}
+fn check_names(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) {
+ for pet in arc.iter() {
+ pet.name(Box::new(|name| {
+ assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
+ }))
+ }
+}
+fn check_pedigree(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) {
+ for pet in arc.iter() {
+ assert!(pet.of_good_pedigree());
+ }
+}
diff --git a/tests/ui/traits/bound/multiple.rs b/tests/ui/traits/bound/multiple.rs
new file mode 100644
index 000000000..868b33407
--- /dev/null
+++ b/tests/ui/traits/bound/multiple.rs
@@ -0,0 +1,9 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+fn f<T:PartialEq + PartialOrd>(_: T) {
+}
+
+pub fn main() {
+ f(3);
+}
diff --git a/tests/ui/traits/bound/not-on-bare-trait.rs b/tests/ui/traits/bound/not-on-bare-trait.rs
new file mode 100644
index 000000000..daf18c670
--- /dev/null
+++ b/tests/ui/traits/bound/not-on-bare-trait.rs
@@ -0,0 +1,13 @@
+trait Foo {
+ fn dummy(&self) {}
+}
+
+// This should emit the less confusing error, not the more confusing one.
+
+fn foo(_x: Foo + Send) {
+ //~^ ERROR the size for values of type
+ //~| WARN trait objects without an explicit `dyn` are deprecated
+ //~| WARN this is accepted in the current edition
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr
new file mode 100644
index 000000000..36b08a7d3
--- /dev/null
+++ b/tests/ui/traits/bound/not-on-bare-trait.stderr
@@ -0,0 +1,34 @@
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/not-on-bare-trait.rs:7:12
+ |
+LL | fn foo(_x: Foo + Send) {
+ | ^^^^^^^^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
+help: use `dyn`
+ |
+LL | fn foo(_x: dyn Foo + Send) {
+ | +++
+
+error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
+ --> $DIR/not-on-bare-trait.rs:7:8
+ |
+LL | fn foo(_x: Foo + Send) {
+ | ^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
+ = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | fn foo(_x: impl Foo + Send) {
+ | ++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn foo(_x: &Foo + Send) {
+ | +
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/not-on-struct.rs b/tests/ui/traits/bound/not-on-struct.rs
new file mode 100644
index 000000000..8633e9d7a
--- /dev/null
+++ b/tests/ui/traits/bound/not-on-struct.rs
@@ -0,0 +1,38 @@
+// We don't need those errors. Ideally we would silence them, but to do so we need to move the
+// lint from being an early-lint during parsing to a late-lint, because it needs to be aware of
+// the types involved.
+#![allow(bare_trait_objects)]
+
+struct Foo;
+
+fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo`
+
+type TypeAlias<T> = Box<dyn Vec<T>>; //~ ERROR expected trait, found struct `Vec`
+
+struct A;
+fn a() -> A + 'static { //~ ERROR expected trait, found
+ A
+}
+fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) { //~ ERROR expected trait, found
+ panic!()
+}
+fn c() -> 'static + A { //~ ERROR expected trait, found
+ A
+}
+fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) { //~ ERROR expected trait, found
+ panic!()
+}
+fn e() -> 'static + A + 'static { //~ ERROR expected trait, found
+//~^ ERROR only a single explicit lifetime bound is permitted
+ A
+}
+fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { //~ ERROR expected trait, found
+//~^ ERROR only a single explicit lifetime bound is permitted
+ panic!()
+}
+struct Traitor;
+trait Trait {}
+fn g() -> Traitor + 'static { //~ ERROR expected trait, found struct `Traitor`
+ A
+}
+fn main() {}
diff --git a/tests/ui/traits/bound/not-on-struct.stderr b/tests/ui/traits/bound/not-on-struct.stderr
new file mode 100644
index 000000000..2de35dc7f
--- /dev/null
+++ b/tests/ui/traits/bound/not-on-struct.stderr
@@ -0,0 +1,175 @@
+error[E0226]: only a single explicit lifetime bound is permitted
+ --> $DIR/not-on-struct.rs:25:25
+ |
+LL | fn e() -> 'static + A + 'static {
+ | ^^^^^^^
+
+error[E0226]: only a single explicit lifetime bound is permitted
+ --> $DIR/not-on-struct.rs:29:53
+ |
+LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
+ | ^^
+
+error[E0404]: expected trait, found struct `Foo`
+ --> $DIR/not-on-struct.rs:8:16
+ |
+LL | fn foo(_x: Box<Foo + Send>) { }
+ | ^^^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:8:22
+ |
+LL | fn foo(_x: Box<Foo + Send>) { }
+ | --- ^^^^ ...because of this bound
+ | |
+ | expected this type to be a trait...
+
+error[E0404]: expected trait, found struct `Vec`
+ --> $DIR/not-on-struct.rs:10:29
+ |
+LL | type TypeAlias<T> = Box<dyn Vec<T>>;
+ | ^^^^^^ not a trait
+
+error[E0404]: expected trait, found struct `A`
+ --> $DIR/not-on-struct.rs:13:11
+ |
+LL | fn a() -> A + 'static {
+ | ^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:13:15
+ |
+LL | fn a() -> A + 'static {
+ | - ^^^^^^^ ...because of this bound
+ | |
+ | expected this type to be a trait...
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn a() -> A + 'static {
+LL + fn a() -> A {
+ |
+
+error[E0404]: expected trait, found enum `Result`
+ --> $DIR/not-on-struct.rs:16:34
+ |
+LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) {
+ | ^^^^^^^^^^^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:16:48
+ |
+LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) {
+ | ----------- ^^ ...because of this bound
+ | |
+ | expected this type to be a trait...
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) {
+LL + fn b<'a,T,E>(iter: Iterator<Item=Result<T,E>>) {
+ |
+
+error[E0404]: expected trait, found struct `A`
+ --> $DIR/not-on-struct.rs:19:21
+ |
+LL | fn c() -> 'static + A {
+ | ^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:19:11
+ |
+LL | fn c() -> 'static + A {
+ | ^^^^^^^ - expected this type to be a trait...
+ | |
+ | ...because of this bound
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn c() -> 'static + A {
+LL + fn c() -> A {
+ |
+
+error[E0404]: expected trait, found enum `Result`
+ --> $DIR/not-on-struct.rs:22:39
+ |
+LL | fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) {
+ | ^^^^^^^^^^^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:22:34
+ |
+LL | fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) {
+ | ^^ ----------- expected this type to be a trait...
+ | |
+ | ...because of this bound
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) {
+LL + fn d<'a,T,E>(iter: Iterator<Item=Result<T,E>>) {
+ |
+
+error[E0404]: expected trait, found struct `A`
+ --> $DIR/not-on-struct.rs:25:21
+ |
+LL | fn e() -> 'static + A + 'static {
+ | ^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:25:11
+ |
+LL | fn e() -> 'static + A + 'static {
+ | ^^^^^^^ - ^^^^^^^ ...because of these bounds
+ | |
+ | expected this type to be a trait...
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn e() -> 'static + A + 'static {
+LL + fn e() -> A {
+ |
+
+error[E0404]: expected trait, found enum `Result`
+ --> $DIR/not-on-struct.rs:29:39
+ |
+LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
+ | ^^^^^^^^^^^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:29:34
+ |
+LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
+ | ^^ ----------- ^^ ...because of these bounds
+ | |
+ | expected this type to be a trait...
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
+LL + fn f<'a,T,E>(iter: Iterator<Item=Result<T,E>>) {
+ |
+
+error[E0404]: expected trait, found struct `Traitor`
+ --> $DIR/not-on-struct.rs:35:11
+ |
+LL | trait Trait {}
+ | ----------- similarly named trait `Trait` defined here
+LL | fn g() -> Traitor + 'static {
+ | ^^^^^^^ not a trait
+ |
+help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
+ --> $DIR/not-on-struct.rs:35:21
+ |
+LL | fn g() -> Traitor + 'static {
+ | ------- ^^^^^^^ ...because of this bound
+ | |
+ | expected this type to be a trait...
+help: if you meant to use a type and not a trait here, remove the bounds
+ |
+LL - fn g() -> Traitor + 'static {
+LL + fn g() -> Traitor {
+ |
+help: a trait with a similar name exists
+ |
+LL | fn g() -> Trait + 'static {
+ | ~~~~~
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0226, E0404.
+For more information about an error, try `rustc --explain E0226`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs b/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs
new file mode 100644
index 000000000..6a6fcf530
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs
@@ -0,0 +1,20 @@
+trait Trait {}
+
+struct Foo<T:Trait> {
+ x: T,
+}
+
+enum Bar<T:Trait> {
+ ABar(isize),
+ BBar(T),
+ CBar(usize),
+}
+
+fn explode(x: Foo<u32>) {}
+//~^ ERROR E0277
+
+fn kaboom(y: Bar<f32>) {}
+//~^ ERROR E0277
+
+fn main() {
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr
new file mode 100644
index 000000000..61237a63e
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `u32: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-in-fns.rs:13:15
+ |
+LL | fn explode(x: Foo<u32>) {}
+ | ^^^^^^^^ the trait `Trait` is not implemented for `u32`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums-in-fns.rs:3:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `f32: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-in-fns.rs:16:14
+ |
+LL | fn kaboom(y: Bar<f32>) {}
+ | ^^^^^^^^ the trait `Trait` is not implemented for `f32`
+ |
+note: required by a bound in `Bar`
+ --> $DIR/on-structs-and-enums-in-fns.rs:7:12
+ |
+LL | enum Bar<T:Trait> {
+ | ^^^^^ required by this bound in `Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs b/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs
new file mode 100644
index 000000000..d37949952
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs
@@ -0,0 +1,25 @@
+trait Trait {}
+
+struct Foo<T:Trait> {
+ x: T,
+}
+
+enum Bar<T:Trait> {
+ ABar(isize),
+ BBar(T),
+ CBar(usize),
+}
+
+trait PolyTrait<T>
+{
+ fn whatever(&self, t: T) {}
+}
+
+struct Struct;
+
+impl PolyTrait<Foo<u16>> for Struct {
+//~^ ERROR E0277
+}
+
+fn main() {
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr
new file mode 100644
index 000000000..8a4374226
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `u16: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-in-impls.rs:20:6
+ |
+LL | impl PolyTrait<Foo<u16>> for Struct {
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums-in-impls.rs:3:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.rs b/tests/ui/traits/bound/on-structs-and-enums-locals.rs
new file mode 100644
index 000000000..60ba343bb
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-locals.rs
@@ -0,0 +1,17 @@
+trait Trait {
+ fn dummy(&self) { }
+}
+
+struct Foo<T:Trait> {
+ x: T,
+}
+
+fn main() {
+ let foo = Foo {
+ x: 3
+ //~^ ERROR E0277
+ };
+
+ let baz: Foo<usize> = loop { };
+ //~^ ERROR E0277
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr
new file mode 100644
index 000000000..20bbe69c0
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-locals.rs:15:14
+ |
+LL | let baz: Foo<usize> = loop { };
+ | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums-locals.rs:5:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `{integer}: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-locals.rs:11:12
+ |
+LL | x: 3
+ | ^ the trait `Trait` is not implemented for `{integer}`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums-locals.rs:5:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-rpass.rs b/tests/ui/traits/bound/on-structs-and-enums-rpass.rs
new file mode 100644
index 000000000..4dc4fecc9
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-rpass.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// pretty-expanded FIXME #23616
+
+trait U {}
+trait T<X: U> { fn get(self) -> X; }
+
+trait S2<Y: U> {
+ fn m(x: Box<dyn T<Y>+'static>) {}
+}
+
+struct St<X: U> {
+ f: Box<dyn T<X>+'static>,
+}
+
+impl<X: U> St<X> {
+ fn blah() {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.rs b/tests/ui/traits/bound/on-structs-and-enums-static.rs
new file mode 100644
index 000000000..df3f8b8a5
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.rs
@@ -0,0 +1,15 @@
+trait Trait {
+ fn dummy(&self) { }
+}
+
+struct Foo<T:Trait> {
+ x: T,
+}
+
+static X: Foo<usize> = Foo {
+//~^ ERROR E0277
+ x: 1,
+};
+
+fn main() {
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
new file mode 100644
index 000000000..fda734e85
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-static.rs:9:11
+ |
+LL | static X: Foo<usize> = Foo {
+ | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums-static.rs:5:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc.rs b/tests/ui/traits/bound/on-structs-and-enums-xc.rs
new file mode 100644
index 000000000..94316d240
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-xc.rs
@@ -0,0 +1,14 @@
+// aux-build:on_structs_and_enums_xc.rs
+
+extern crate on_structs_and_enums_xc;
+
+use on_structs_and_enums_xc::{Bar, Foo, Trait};
+
+fn explode(x: Foo<usize>) {}
+//~^ ERROR E0277
+
+fn kaboom(y: Bar<f32>) {}
+//~^ ERROR E0277
+
+fn main() {
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc.stderr
new file mode 100644
index 000000000..5064b60bf
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-xc.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-xc.rs:7:15
+ |
+LL | fn explode(x: Foo<usize>) {}
+ | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18
+ |
+LL | pub struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `f32: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-xc.rs:10:14
+ |
+LL | fn kaboom(y: Bar<f32>) {}
+ | ^^^^^^^^ the trait `Trait` is not implemented for `f32`
+ |
+note: required by a bound in `Bar`
+ --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16
+ |
+LL | pub enum Bar<T:Trait> {
+ | ^^^^^ required by this bound in `Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc1.rs b/tests/ui/traits/bound/on-structs-and-enums-xc1.rs
new file mode 100644
index 000000000..5ef35b513
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.rs
@@ -0,0 +1,15 @@
+// aux-build:on_structs_and_enums_xc.rs
+
+extern crate on_structs_and_enums_xc;
+
+use on_structs_and_enums_xc::{Bar, Foo, Trait};
+
+fn main() {
+ let foo = Foo {
+ x: 3
+ //~^ ERROR E0277
+ };
+ let bar: Bar<f64> = return;
+ //~^ ERROR E0277
+ let _ = bar;
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr
new file mode 100644
index 000000000..3fb5decb7
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `f64: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-xc1.rs:12:14
+ |
+LL | let bar: Bar<f64> = return;
+ | ^^^^^^^^ the trait `Trait` is not implemented for `f64`
+ |
+note: required by a bound in `Bar`
+ --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16
+ |
+LL | pub enum Bar<T:Trait> {
+ | ^^^^^ required by this bound in `Bar`
+
+error[E0277]: the trait bound `{integer}: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums-xc1.rs:9:12
+ |
+LL | x: 3
+ | ^ the trait `Trait` is not implemented for `{integer}`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18
+ |
+LL | pub struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums.rs b/tests/ui/traits/bound/on-structs-and-enums.rs
new file mode 100644
index 000000000..024084fa7
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums.rs
@@ -0,0 +1,43 @@
+trait Trait {}
+
+struct Foo<T:Trait> {
+ x: T,
+}
+
+enum Bar<T:Trait> {
+ ABar(isize),
+ BBar(T),
+ CBar(usize),
+}
+
+impl<T> Foo<T> {
+//~^ ERROR `T: Trait` is not satisfied
+ fn uhoh() {}
+}
+
+struct Baz {
+ a: Foo<isize>, //~ ERROR E0277
+}
+
+enum Boo {
+ Quux(Bar<usize>), //~ ERROR E0277
+}
+
+struct Badness<U> {
+ b: Foo<U>, //~ ERROR E0277
+}
+
+enum MoreBadness<V> {
+ EvenMoreBadness(Bar<V>), //~ ERROR E0277
+}
+
+struct TupleLike(
+ Foo<i32>, //~ ERROR E0277
+);
+
+enum Enum {
+ DictionaryLike { field: Bar<u8> }, //~ ERROR E0277
+}
+
+fn main() {
+}
diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr
new file mode 100644
index 000000000..fe05b8634
--- /dev/null
+++ b/tests/ui/traits/bound/on-structs-and-enums.stderr
@@ -0,0 +1,99 @@
+error[E0277]: the trait bound `T: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:13:9
+ |
+LL | impl<T> Foo<T> {
+ | ^^^^^^ the trait `Trait` is not implemented for `T`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums.rs:3:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+help: consider restricting type parameter `T`
+ |
+LL | impl<T: Trait> Foo<T> {
+ | +++++++
+
+error[E0277]: the trait bound `isize: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:19:8
+ |
+LL | a: Foo<isize>,
+ | ^^^^^^^^^^ the trait `Trait` is not implemented for `isize`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums.rs:3:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:23:10
+ |
+LL | Quux(Bar<usize>),
+ | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+ |
+note: required by a bound in `Bar`
+ --> $DIR/on-structs-and-enums.rs:7:12
+ |
+LL | enum Bar<T:Trait> {
+ | ^^^^^ required by this bound in `Bar`
+
+error[E0277]: the trait bound `U: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:27:8
+ |
+LL | b: Foo<U>,
+ | ^^^^^^ the trait `Trait` is not implemented for `U`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums.rs:3:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+help: consider restricting type parameter `U`
+ |
+LL | struct Badness<U: Trait> {
+ | +++++++
+
+error[E0277]: the trait bound `V: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:31:21
+ |
+LL | EvenMoreBadness(Bar<V>),
+ | ^^^^^^ the trait `Trait` is not implemented for `V`
+ |
+note: required by a bound in `Bar`
+ --> $DIR/on-structs-and-enums.rs:7:12
+ |
+LL | enum Bar<T:Trait> {
+ | ^^^^^ required by this bound in `Bar`
+help: consider restricting type parameter `V`
+ |
+LL | enum MoreBadness<V: Trait> {
+ | +++++++
+
+error[E0277]: the trait bound `i32: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:35:5
+ |
+LL | Foo<i32>,
+ | ^^^^^^^^ the trait `Trait` is not implemented for `i32`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/on-structs-and-enums.rs:3:14
+ |
+LL | struct Foo<T:Trait> {
+ | ^^^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `u8: Trait` is not satisfied
+ --> $DIR/on-structs-and-enums.rs:39:29
+ |
+LL | DictionaryLike { field: Bar<u8> },
+ | ^^^^^^^ the trait `Trait` is not implemented for `u8`
+ |
+note: required by a bound in `Bar`
+ --> $DIR/on-structs-and-enums.rs:7:12
+ |
+LL | enum Bar<T:Trait> {
+ | ^^^^^ required by this bound in `Bar`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/recursion.rs b/tests/ui/traits/bound/recursion.rs
new file mode 100644
index 000000000..0023ff654
--- /dev/null
+++ b/tests/ui/traits/bound/recursion.rs
@@ -0,0 +1,20 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+trait I { fn i(&self) -> Self; }
+
+trait A<T:I> {
+ fn id(x:T) -> T { x.i() }
+}
+
+trait J<T> { fn j(&self) -> T; }
+
+trait B<T:J<T>> {
+ fn id(x:T) -> T { x.j() }
+}
+
+trait C {
+ fn id<T:J<T>>(x:T) -> T { x.j() }
+}
+
+pub fn main() { }
diff --git a/tests/ui/traits/bound/same-crate-name.rs b/tests/ui/traits/bound/same-crate-name.rs
new file mode 100644
index 000000000..8d646a414
--- /dev/null
+++ b/tests/ui/traits/bound/same-crate-name.rs
@@ -0,0 +1,55 @@
+// aux-build:crate_a1.rs
+// aux-build:crate_a2.rs
+
+// Issue 22750
+// This tests the extra help message reported when a trait bound
+// is not met but the struct implements a trait with the same path.
+
+fn main() {
+ let foo = {
+ extern crate crate_a2 as a;
+ a::Foo
+ };
+
+ let implements_no_traits = {
+ extern crate crate_a2 as a;
+ a::DoesNotImplementTrait
+ };
+
+ let other_variant_implements_mismatched_trait = {
+ extern crate crate_a2 as a;
+ a::ImplementsWrongTraitConditionally { _marker: std::marker::PhantomData::<isize> }
+ };
+
+ let other_variant_implements_correct_trait = {
+ extern crate crate_a1 as a;
+ a::ImplementsTraitForUsize { _marker: std::marker::PhantomData::<isize> }
+ };
+
+ {
+ extern crate crate_a1 as a;
+ a::try_foo(foo);
+ //~^ ERROR E0277
+ //~| trait impl with same name found
+ //~| perhaps two different versions of crate `crate_a2`
+
+ // We don't want to see the "version mismatch" help message here
+ // because `implements_no_traits` has no impl for `Foo`
+ a::try_foo(implements_no_traits);
+ //~^ ERROR E0277
+
+ // We don't want to see the "version mismatch" help message here
+ // because `other_variant_implements_mismatched_trait`
+ // does not have an impl for its `<isize>` variant,
+ // only for its `<usize>` variant.
+ a::try_foo(other_variant_implements_mismatched_trait);
+ //~^ ERROR E0277
+
+ // We don't want to see the "version mismatch" help message here
+ // because `ImplementsTraitForUsize` only has
+ // impls for the correct trait where the path is not misleading.
+ a::try_foo(other_variant_implements_correct_trait);
+ //~^ ERROR E0277
+ //~| the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
+ }
+}
diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr
new file mode 100644
index 000000000..f66cad77f
--- /dev/null
+++ b/tests/ui/traits/bound/same-crate-name.stderr
@@ -0,0 +1,75 @@
+error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied
+ --> $DIR/same-crate-name.rs:31:20
+ |
+LL | a::try_foo(foo);
+ | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+help: trait impl with same name found
+ --> $DIR/auxiliary/crate_a2.rs:5:1
+ |
+LL | impl Bar for Foo {}
+ | ^^^^^^^^^^^^^^^^
+ = note: perhaps two different versions of crate `crate_a2` are being used?
+ = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
+note: required by a bound in `try_foo`
+ --> $DIR/auxiliary/crate_a1.rs:3:24
+ |
+LL | pub fn try_foo(x: impl Bar) {}
+ | ^^^ required by this bound in `try_foo`
+
+error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satisfied
+ --> $DIR/same-crate-name.rs:38:20
+ |
+LL | a::try_foo(implements_no_traits);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
+note: required by a bound in `try_foo`
+ --> $DIR/auxiliary/crate_a1.rs:3:24
+ |
+LL | pub fn try_foo(x: impl Bar) {}
+ | ^^^ required by this bound in `try_foo`
+
+error[E0277]: the trait bound `ImplementsWrongTraitConditionally<isize>: main::a::Bar` is not satisfied
+ --> $DIR/same-crate-name.rs:45:20
+ |
+LL | a::try_foo(other_variant_implements_mismatched_trait);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+ | |
+ | required by a bound introduced by this call
+ |
+help: trait impl with same name found
+ --> $DIR/auxiliary/crate_a2.rs:13:1
+ |
+LL | impl Bar for ImplementsWrongTraitConditionally<isize> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: perhaps two different versions of crate `crate_a2` are being used?
+ = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
+note: required by a bound in `try_foo`
+ --> $DIR/auxiliary/crate_a1.rs:3:24
+ |
+LL | pub fn try_foo(x: impl Bar) {}
+ | ^^^ required by this bound in `try_foo`
+
+error[E0277]: the trait bound `ImplementsTraitForUsize<isize>: main::a::Bar` is not satisfied
+ --> $DIR/same-crate-name.rs:51:20
+ |
+LL | a::try_foo(other_variant_implements_correct_trait);
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
+note: required by a bound in `try_foo`
+ --> $DIR/auxiliary/crate_a1.rs:3:24
+ |
+LL | pub fn try_foo(x: impl Bar) {}
+ | ^^^ required by this bound in `try_foo`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/sugar.rs b/tests/ui/traits/bound/sugar.rs
new file mode 100644
index 000000000..65b6f6faa
--- /dev/null
+++ b/tests/ui/traits/bound/sugar.rs
@@ -0,0 +1,19 @@
+// Tests for "default" bounds inferred for traits with no bounds list.
+
+trait Foo {}
+
+fn a(_x: Box<dyn Foo + Send>) {
+}
+
+fn b(_x: &'static (dyn Foo + 'static)) {
+}
+
+fn c(x: Box<dyn Foo + Sync>) {
+ a(x); //~ ERROR mismatched types
+}
+
+fn d(x: &'static (dyn Foo + Sync)) {
+ b(x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bound/sugar.stderr b/tests/ui/traits/bound/sugar.stderr
new file mode 100644
index 000000000..b67648c7b
--- /dev/null
+++ b/tests/ui/traits/bound/sugar.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/sugar.rs:12:7
+ |
+LL | a(x);
+ | - ^ expected trait `Foo + Send`, found trait `Foo + Sync`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected struct `Box<(dyn Foo + Send + 'static)>`
+ found struct `Box<(dyn Foo + Sync + 'static)>`
+note: function defined here
+ --> $DIR/sugar.rs:5:4
+ |
+LL | fn a(_x: Box<dyn Foo + Send>) {
+ | ^ -----------------------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/bug-7183-generics.rs b/tests/ui/traits/bug-7183-generics.rs
new file mode 100644
index 000000000..f53a17361
--- /dev/null
+++ b/tests/ui/traits/bug-7183-generics.rs
@@ -0,0 +1,36 @@
+// run-pass
+
+trait Speak : Sized {
+ fn say(&self, s:&str) -> String;
+ fn hi(&self) -> String { hello(self) }
+}
+
+fn hello<S:Speak>(s:&S) -> String{
+ s.say("hello")
+}
+
+impl Speak for isize {
+ fn say(&self, s:&str) -> String {
+ format!("{}: {}", s, *self)
+ }
+}
+
+impl<T: Speak> Speak for Option<T> {
+ fn say(&self, s:&str) -> String {
+ match *self {
+ None => format!("{} - none", s),
+ Some(ref x) => { format!("something!{}", x.say(s)) }
+ }
+ }
+}
+
+
+pub fn main() {
+ assert_eq!(3.hi(), "hello: 3".to_string());
+ assert_eq!(Some(Some(3)).hi(),
+ "something!something!hello: 3".to_string());
+ assert_eq!(None::<isize>.hi(), "hello - none".to_string());
+
+ assert_eq!(Some(None::<isize>).hi(), "something!hello - none".to_string());
+ assert_eq!(Some(3).hi(), "something!hello: 3".to_string());
+}
diff --git a/tests/ui/traits/bug-7295.rs b/tests/ui/traits/bug-7295.rs
new file mode 100644
index 000000000..156ff2ee8
--- /dev/null
+++ b/tests/ui/traits/bug-7295.rs
@@ -0,0 +1,14 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub trait Foo<T> {
+ fn func1<U>(&self, t: U, w: T);
+
+ fn func2<U>(&self, t: U, w: T) {
+ self.func1(t, w);
+ }
+}
+
+pub fn main() {
+
+}
diff --git a/tests/ui/traits/cache-issue-18209.rs b/tests/ui/traits/cache-issue-18209.rs
new file mode 100644
index 000000000..15676e455
--- /dev/null
+++ b/tests/ui/traits/cache-issue-18209.rs
@@ -0,0 +1,20 @@
+// run-pass
+// Test that the cache results from the default method do not pollute
+// the cache for the later call in `load()`.
+//
+// See issue #18209.
+
+// pretty-expanded FIXME #23616
+
+pub trait Foo {
+ fn load_from() -> Box<Self>;
+ fn load() -> Box<Self> {
+ Foo::load_from()
+ }
+}
+
+pub fn load<M: Foo>() -> Box<M> {
+ Foo::load()
+}
+
+fn main() { }
diff --git a/tests/ui/traits/cache-reached-depth-ice.rs b/tests/ui/traits/cache-reached-depth-ice.rs
new file mode 100644
index 000000000..c36ac0857
--- /dev/null
+++ b/tests/ui/traits/cache-reached-depth-ice.rs
@@ -0,0 +1,45 @@
+#![feature(rustc_attrs)]
+
+// Test for a particular corner case where the evaluation
+// cache can get out of date. The problem here is that
+// when we cache C, we have observed that it reaches
+// to depth 2 (the node for B), but we later realize
+// that B itself depends on A (reached depth 0). We
+// failed to update the depth for C transitively, which
+// resulted in an assertion failure when it was referenced
+// from D.
+//
+// A (reached depth 0)
+// E
+// B // depth 2 -- reached depth = 0
+// C // depth 3 -- reached depth = 2 (should be 0)
+// B
+// A // depth 0
+// D (depth 1)
+// C (cache -- reached depth = 2)
+
+struct A {
+ e: E,
+ d: C,
+}
+
+struct E {
+ b: B,
+}
+
+struct B {
+ a: Option<Box<A>>,
+ c: C,
+}
+
+struct C {
+ b: Option<Box<B>>,
+}
+
+#[rustc_evaluate_where_clauses]
+fn test<X: ?Sized + Send>() {}
+
+fn main() {
+ test::<A>();
+ //~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+}
diff --git a/tests/ui/traits/cache-reached-depth-ice.stderr b/tests/ui/traits/cache-reached-depth-ice.stderr
new file mode 100644
index 000000000..082aa0f5c
--- /dev/null
+++ b/tests/ui/traits/cache-reached-depth-ice.stderr
@@ -0,0 +1,11 @@
+error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ --> $DIR/cache-reached-depth-ice.rs:43:5
+ |
+LL | fn test<X: ?Sized + Send>() {}
+ | ---- predicate
+...
+LL | test::<A>();
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/coercion-generic-bad.rs b/tests/ui/traits/coercion-generic-bad.rs
new file mode 100644
index 000000000..2e115c732
--- /dev/null
+++ b/tests/ui/traits/coercion-generic-bad.rs
@@ -0,0 +1,19 @@
+struct Struct {
+ person: &'static str
+}
+
+trait Trait<T> {
+ fn f(&self, x: T);
+}
+
+impl Trait<&'static str> for Struct {
+ fn f(&self, x: &'static str) {
+ println!("Hello, {}!", x);
+ }
+}
+
+fn main() {
+ let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
+ //~^ ERROR `Struct: Trait<isize>` is not satisfied
+ s.f(1);
+}
diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr
new file mode 100644
index 000000000..93d6770eb
--- /dev/null
+++ b/tests/ui/traits/coercion-generic-bad.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `Struct: Trait<isize>` is not satisfied
+ --> $DIR/coercion-generic-bad.rs:16:36
+ |
+LL | let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
+ |
+ = help: the trait `Trait<&'static str>` is implemented for `Struct`
+ = note: required for the cast from `Struct` to the object type `dyn Trait<isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/coercion-generic-regions.rs b/tests/ui/traits/coercion-generic-regions.rs
new file mode 100644
index 000000000..af478df6d
--- /dev/null
+++ b/tests/ui/traits/coercion-generic-regions.rs
@@ -0,0 +1,19 @@
+struct Struct {
+ person: &'static str
+}
+
+trait Trait<T> {
+ fn f(&self, x: T);
+}
+
+impl Trait<&'static str> for Struct {
+ fn f(&self, x: &'static str) {
+ println!("Hello, {}!", x);
+ }
+}
+
+fn main() {
+ let person = "Fred".to_string();
+ let person: &str = &person; //~ ERROR `person` does not live long enough
+ let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person });
+}
diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr
new file mode 100644
index 000000000..5cfb64901
--- /dev/null
+++ b/tests/ui/traits/coercion-generic-regions.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `person` does not live long enough
+ --> $DIR/coercion-generic-regions.rs:17:24
+ |
+LL | let person: &str = &person;
+ | ^^^^^^^
+ | |
+ | borrowed value does not live long enough
+ | assignment requires that `person` is borrowed for `'static`
+LL | let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person });
+LL | }
+ | - `person` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/traits/coercion-generic.rs b/tests/ui/traits/coercion-generic.rs
new file mode 100644
index 000000000..bf4dda495
--- /dev/null
+++ b/tests/ui/traits/coercion-generic.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(dead_code)]
+trait Trait<T> {
+ fn f(&self, x: T);
+}
+
+#[derive(Copy, Clone)]
+struct Struct {
+ x: isize,
+ y: isize,
+}
+
+impl Trait<&'static str> for Struct {
+ fn f(&self, x: &'static str) {
+ println!("Hi, {}!", x);
+ }
+}
+
+pub fn main() {
+ let a = Struct { x: 1, y: 2 };
+ let b: Box<dyn Trait<&'static str>> = Box::new(a);
+ b.f("Mary");
+ let c: &dyn Trait<&'static str> = &a;
+ c.f("Joe");
+}
diff --git a/tests/ui/traits/coercion.rs b/tests/ui/traits/coercion.rs
new file mode 100644
index 000000000..e62742bac
--- /dev/null
+++ b/tests/ui/traits/coercion.rs
@@ -0,0 +1,35 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_mut)]
+#![allow(unused_variables)]
+
+use std::io::{self, Write};
+
+trait Trait {
+ fn f(&self);
+}
+
+#[derive(Copy, Clone)]
+struct Struct {
+ x: isize,
+ y: isize,
+}
+
+impl Trait for Struct {
+ fn f(&self) {
+ println!("Hi!");
+ }
+}
+
+fn foo(mut a: Box<dyn Write>) {}
+
+pub fn main() {
+ let a = Struct { x: 1, y: 2 };
+ let b: Box<dyn Trait> = Box::new(a);
+ b.f();
+ let c: &dyn Trait = &a;
+ c.f();
+
+ let out = io::stdout();
+ foo(Box::new(out));
+}
diff --git a/tests/ui/traits/composition-trivial.rs b/tests/ui/traits/composition-trivial.rs
new file mode 100644
index 000000000..90e5dcd68
--- /dev/null
+++ b/tests/ui/traits/composition-trivial.rs
@@ -0,0 +1,12 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+trait Foo {
+ fn foo(&self);
+}
+
+trait Bar : Foo {
+ fn bar(&self);
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/conditional-dispatch.rs b/tests/ui/traits/conditional-dispatch.rs
new file mode 100644
index 000000000..dd882dce6
--- /dev/null
+++ b/tests/ui/traits/conditional-dispatch.rs
@@ -0,0 +1,34 @@
+// run-pass
+// Test that we are able to resolve conditional dispatch. Here, the
+// blanket impl for T:Copy coexists with an impl for Box<T>, because
+// Box does not impl Copy.
+
+
+trait Get {
+ fn get(&self) -> Self;
+}
+
+trait MyCopy { fn copy(&self) -> Self; }
+impl MyCopy for u16 { fn copy(&self) -> Self { *self } }
+impl MyCopy for u32 { fn copy(&self) -> Self { *self } }
+impl MyCopy for i32 { fn copy(&self) -> Self { *self } }
+impl<T:Copy> MyCopy for Option<T> { fn copy(&self) -> Self { *self } }
+
+impl<T:MyCopy> Get for T {
+ fn get(&self) -> T { self.copy() }
+}
+
+impl Get for Box<i32> {
+ fn get(&self) -> Box<i32> { Box::new(get_it(&**self)) }
+}
+
+fn get_it<T:Get>(t: &T) -> T {
+ (*t).get()
+}
+
+fn main() {
+ assert_eq!(get_it(&1_u32), 1_u32);
+ assert_eq!(get_it(&1_u16), 1_u16);
+ assert_eq!(get_it(&Some(1_u16)), Some(1_u16));
+ assert_eq!(get_it(&Box::new(1)), Box::new(1));
+}
diff --git a/tests/ui/traits/conditional-model-fn.rs b/tests/ui/traits/conditional-model-fn.rs
new file mode 100644
index 000000000..ba8867003
--- /dev/null
+++ b/tests/ui/traits/conditional-model-fn.rs
@@ -0,0 +1,53 @@
+// run-pass
+#![allow(unused_imports)]
+// A model for how the `Fn` traits could work. You can implement at
+// most one of `Go`, `GoMut`, or `GoOnce`, and then the others follow
+// automatically.
+
+// aux-build:go_trait.rs
+
+extern crate go_trait;
+
+use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once};
+
+use std::rc::Rc;
+use std::cell::Cell;
+
+struct SomeGoableThing {
+ counter: Rc<Cell<isize>>
+}
+
+impl Go for SomeGoableThing {
+ fn go(&self, arg: isize) {
+ self.counter.set(self.counter.get() + arg);
+ }
+}
+
+struct SomeGoOnceableThing {
+ counter: Rc<Cell<isize>>
+}
+
+impl GoOnce for SomeGoOnceableThing {
+ fn go_once(self, arg: isize) {
+ self.counter.set(self.counter.get() + arg);
+ }
+}
+
+fn main() {
+ let counter = Rc::new(Cell::new(0));
+ let mut x = SomeGoableThing { counter: counter.clone() };
+
+ go(&x, 10);
+ assert_eq!(counter.get(), 10);
+
+ go_mut(&mut x, 100);
+ assert_eq!(counter.get(), 110);
+
+ go_once(x, 1_000);
+ assert_eq!(counter.get(), 1_110);
+
+ let x = SomeGoOnceableThing { counter: counter.clone() };
+
+ go_once(x, 10_000);
+ assert_eq!(counter.get(), 11_110);
+}
diff --git a/tests/ui/traits/conservative_impl_trait.rs b/tests/ui/traits/conservative_impl_trait.rs
new file mode 100644
index 000000000..4f25e57be
--- /dev/null
+++ b/tests/ui/traits/conservative_impl_trait.rs
@@ -0,0 +1,8 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// #39665
+
+fn batches(n: &u32) -> impl Iterator<Item=&u32> {
+ std::iter::once(n)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs
new file mode 100644
index 000000000..f031dd9ca
--- /dev/null
+++ b/tests/ui/traits/copy-guessing.rs
@@ -0,0 +1,38 @@
+// run-pass
+#![allow(dead_code)]
+// "guessing" in trait selection can affect `copy_or_move`. Check that this
+// is correctly handled. I am not sure what is the "correct" behaviour,
+// but we should at least not ICE.
+
+use std::mem;
+
+struct U([u8; 1337]);
+
+struct S<'a,T:'a>(&'a T);
+impl<'a, T> Clone for S<'a, T> { fn clone(&self) -> Self { S(self.0) } }
+/// This impl triggers inference "guessing" - S<_>: Copy => _ = U
+impl<'a> Copy for S<'a, Option<U>> {}
+
+fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
+
+fn main() {
+ let n = None;
+ let e = S(&n);
+ let f = || {
+ // S being copy is critical for this to work
+ drop(e);
+ mem::size_of_val(e.0)
+ };
+ assert_impls_fn(&f);
+ assert_eq!(f(), 1337+1);
+
+ assert_eq!((|| {
+ // S being Copy is not critical here, but
+ // we check it anyway.
+ let n = None;
+ let e = S(&n);
+ let ret = mem::size_of_val(e.0);
+ drop(e);
+ ret
+ })(), 1337+1);
+}
diff --git a/tests/ui/traits/copy-impl-cannot-normalize.rs b/tests/ui/traits/copy-impl-cannot-normalize.rs
new file mode 100644
index 000000000..a78ff046e
--- /dev/null
+++ b/tests/ui/traits/copy-impl-cannot-normalize.rs
@@ -0,0 +1,25 @@
+trait TraitFoo {
+ type Bar;
+}
+
+struct Foo<T>
+where
+ T: TraitFoo,
+{
+ inner: T::Bar,
+}
+
+impl<T> Clone for Foo<T>
+where
+ T: TraitFoo,
+ T::Bar: Clone,
+{
+ fn clone(&self) -> Self {
+ Self { inner: self.inner.clone() }
+ }
+}
+
+impl<T> Copy for Foo<T> {}
+//~^ ERROR the trait bound `T: TraitFoo` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr
new file mode 100644
index 000000000..86c511c08
--- /dev/null
+++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: TraitFoo` is not satisfied
+ --> $DIR/copy-impl-cannot-normalize.rs:22:18
+ |
+LL | impl<T> Copy for Foo<T> {}
+ | ^^^^^^ the trait `TraitFoo` is not implemented for `T`
+ |
+note: required for `Foo<T>` to implement `Clone`
+ --> $DIR/copy-impl-cannot-normalize.rs:12:9
+ |
+LL | impl<T> Clone for Foo<T>
+ | ^^^^^ ^^^^^^
+LL | where
+LL | T: TraitFoo,
+ | -------- unsatisfied trait bound introduced here
+note: required by a bound in `Copy`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+help: consider restricting type parameter `T`
+ |
+LL | impl<T: TraitFoo> Copy for Foo<T> {}
+ | ++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr
new file mode 100644
index 000000000..edd94d201
--- /dev/null
+++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr
@@ -0,0 +1,22 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/copy-is-not-modulo-regions.rs:13:21
+ |
+LL | struct Bar<'lt>(Foo<'lt>);
+ | -------- this field does not implement `Copy`
+...
+LL | impl<'any> Copy for Bar<'any> {}
+ | ^^^^^^^^^
+ |
+note: the `Copy` impl for `Foo<'any>` requires that `'any: 'static`
+ --> $DIR/copy-is-not-modulo-regions.rs:10:17
+ |
+LL | struct Bar<'lt>(Foo<'lt>);
+ | ^^^^^^^^
+help: consider restricting type parameter `'any`
+ |
+LL | impl<'any: 'static> Copy for Bar<'any> {}
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/traits/copy-is-not-modulo-regions.rs b/tests/ui/traits/copy-is-not-modulo-regions.rs
new file mode 100644
index 000000000..adb870237
--- /dev/null
+++ b/tests/ui/traits/copy-is-not-modulo-regions.rs
@@ -0,0 +1,19 @@
+// revisions: not_static yes_static
+//[yes_static] check-pass
+
+#[derive(Clone)]
+struct Foo<'lt>(&'lt ());
+
+impl Copy for Foo<'static> {}
+
+#[derive(Clone)]
+struct Bar<'lt>(Foo<'lt>);
+
+#[cfg(not_static)]
+impl<'any> Copy for Bar<'any> {}
+//[not_static]~^ the trait `Copy` may not be implemented for this type
+
+#[cfg(yes_static)]
+impl<'any> Copy for Bar<'static> {}
+
+fn main() {}
diff --git a/tests/ui/traits/copy-requires-self-wf.rs b/tests/ui/traits/copy-requires-self-wf.rs
new file mode 100644
index 000000000..9abfdfab9
--- /dev/null
+++ b/tests/ui/traits/copy-requires-self-wf.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#[derive(Clone)]
+struct A<'a, T>(&'a T);
+
+impl<'a, T: Copy + 'a> Copy for A<'a, T> {}
+
+#[derive(Clone)]
+struct B<'a, T>(A<'a, T>);
+
+// `T: '_` should be implied by `WF(B<'_, T>)`.
+impl<T: Copy> Copy for B<'_, T> {}
+
+fn main() {}
diff --git a/tests/ui/traits/cycle-cache-err-60010.rs b/tests/ui/traits/cycle-cache-err-60010.rs
new file mode 100644
index 000000000..94e718317
--- /dev/null
+++ b/tests/ui/traits/cycle-cache-err-60010.rs
@@ -0,0 +1,74 @@
+// Test that we properly detect the cycle amongst the traits
+// here and report an error.
+
+use std::panic::RefUnwindSafe;
+
+trait Database {
+ type Storage;
+}
+trait HasQueryGroup {}
+trait Query<DB> {
+ type Data;
+}
+trait SourceDatabase {
+ fn parse(&self) {
+ loop {}
+ }
+}
+
+struct ParseQuery;
+struct RootDatabase {
+ _runtime: Runtime<RootDatabase>,
+}
+struct Runtime<DB: Database> {
+ _storage: Box<DB::Storage>,
+}
+struct SalsaStorage {
+ _parse: <ParseQuery as Query<RootDatabase>>::Data,
+ //~^ ERROR overflow
+}
+
+impl Database for RootDatabase {
+ // This would also be an error if we didn't abort compilation on the error
+ // above.
+ type Storage = SalsaStorage;
+}
+impl HasQueryGroup for RootDatabase {}
+impl<DB> Query<DB> for ParseQuery
+where
+ DB: SourceDatabase,
+ DB: Database,
+{
+ type Data = RootDatabase;
+}
+impl<T> SourceDatabase for T
+where
+ T: RefUnwindSafe,
+ T: HasQueryGroup,
+{
+}
+
+pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 {
+ // This is not satisfied:
+ //
+ // - `RootDatabase: SourceDatabase`
+ // - requires `RootDatabase: RefUnwindSafe` + `RootDatabase: HasQueryGroup`
+ // - `RootDatabase: RefUnwindSafe`
+ // - requires `Runtime<RootDatabase>: RefUnwindSafe`
+ // - `Runtime<RootDatabase>: RefUnwindSafe`
+ // - requires `DB::Storage: RefUnwindSafe` (`SalsaStorage: RefUnwindSafe`)
+ // - `SalsaStorage: RefUnwindSafe`
+ // - requires `<ParseQuery as Query<RootDatabase>>::Data: RefUnwindSafe`,
+ // which means `ParseQuery: Query<RootDatabase>`
+ // - `ParseQuery: Query<RootDatabase>`
+ // - requires `RootDatabase: SourceDatabase`,
+ // - `RootDatabase: SourceDatabase` is already on the stack, so we have a
+ // cycle with non-coinductive participants
+ //
+ // we used to fail to report an error here because we got the
+ // caching wrong.
+ SourceDatabase::parse(db);
+ 22
+}
+
+fn main() {}
diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr
new file mode 100644
index 000000000..eeee99760
--- /dev/null
+++ b/tests/ui/traits/cycle-cache-err-60010.stderr
@@ -0,0 +1,39 @@
+error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
+ --> $DIR/cycle-cache-err-60010.rs:27:13
+ |
+LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: required because it appears within the type `PhantomData<SalsaStorage>`
+ = note: required because it appears within the type `Unique<SalsaStorage>`
+ = note: required because it appears within the type `Box<SalsaStorage>`
+note: required because it appears within the type `Runtime<RootDatabase>`
+ --> $DIR/cycle-cache-err-60010.rs:23:8
+ |
+LL | struct Runtime<DB: Database> {
+ | ^^^^^^^
+note: required because it appears within the type `RootDatabase`
+ --> $DIR/cycle-cache-err-60010.rs:20:8
+ |
+LL | struct RootDatabase {
+ | ^^^^^^^^^^^^
+note: required for `RootDatabase` to implement `SourceDatabase`
+ --> $DIR/cycle-cache-err-60010.rs:44:9
+ |
+LL | impl<T> SourceDatabase for T
+ | ^^^^^^^^^^^^^^ ^
+LL | where
+LL | T: RefUnwindSafe,
+ | ------------- unsatisfied trait bound introduced here
+note: required for `ParseQuery` to implement `Query<RootDatabase>`
+ --> $DIR/cycle-cache-err-60010.rs:37:10
+ |
+LL | impl<DB> Query<DB> for ParseQuery
+ | ^^^^^^^^^ ^^^^^^^^^^
+LL | where
+LL | DB: SourceDatabase,
+ | -------------- unsatisfied trait bound introduced here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/cycle-generic-bound.rs b/tests/ui/traits/cycle-generic-bound.rs
new file mode 100644
index 000000000..9241f3789
--- /dev/null
+++ b/tests/ui/traits/cycle-generic-bound.rs
@@ -0,0 +1,11 @@
+// run-pass
+// Regression test for #15477. This test just needs to compile.
+
+// pretty-expanded FIXME #23616
+
+trait Chromosome<X: Chromosome<i32>> {
+}
+
+impl Chromosome<i32> for i32 { }
+
+fn main() { }
diff --git a/tests/ui/traits/cycle-type-trait.rs b/tests/ui/traits/cycle-type-trait.rs
new file mode 100644
index 000000000..c62d01403
--- /dev/null
+++ b/tests/ui/traits/cycle-type-trait.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(dead_code)]
+// Test a case where a supertrait references a type that references
+// the original trait. This poses no problem at the moment.
+
+// pretty-expanded FIXME #23616
+
+trait Chromosome: Get<Struct<i32>> {
+}
+
+trait Get<A> {
+ fn get(&self) -> A;
+}
+
+struct Struct<C:Chromosome> { c: C }
+
+impl Chromosome for i32 { }
+
+impl Get<Struct<i32>> for i32 {
+ fn get(&self) -> Struct<i32> {
+ Struct { c: *self }
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/default-method/auxiliary/xc.rs b/tests/ui/traits/default-method/auxiliary/xc.rs
new file mode 100644
index 000000000..0fb26af80
--- /dev/null
+++ b/tests/ui/traits/default-method/auxiliary/xc.rs
@@ -0,0 +1,40 @@
+pub struct Something { pub x: isize }
+
+pub trait A {
+ fn f(&self) -> isize;
+ fn g(&self) -> isize { 10 }
+ fn h(&self) -> isize { 11 }
+ fn lurr(x: &Self, y: &Self) -> isize { x.g() + y.h() }
+}
+
+
+impl A for isize {
+ fn f(&self) -> isize { 10 }
+}
+
+impl A for Something {
+ fn f(&self) -> isize { 10 }
+}
+
+pub trait B<T> {
+ fn thing<U>(&self, x: T, y: U) -> (T, U) { (x, y) }
+ fn staticthing<U>(_z: &Self, x: T, y: U) -> (T, U) { (x, y) }
+}
+
+impl<T> B<T> for isize { }
+impl B<f64> for bool { }
+
+
+
+pub trait TestEquality {
+ fn test_eq(&self, rhs: &Self) -> bool;
+ fn test_neq(&self, rhs: &Self) -> bool {
+ !self.test_eq(rhs)
+ }
+}
+
+impl TestEquality for isize {
+ fn test_eq(&self, rhs: &isize) -> bool {
+ *self == *rhs
+ }
+}
diff --git a/tests/ui/traits/default-method/auxiliary/xc_2.rs b/tests/ui/traits/default-method/auxiliary/xc_2.rs
new file mode 100644
index 000000000..979233820
--- /dev/null
+++ b/tests/ui/traits/default-method/auxiliary/xc_2.rs
@@ -0,0 +1,17 @@
+// aux-build:xc.rs
+
+extern crate xc as aux;
+use aux::A;
+
+pub struct a_struct { pub x: isize }
+
+impl A for a_struct {
+ fn f(&self) -> isize { 10 }
+}
+
+// This function will need to get inlined, and badness may result.
+pub fn welp<A>(x: A) -> A {
+ let a = a_struct { x: 0 };
+ a.g();
+ x
+}
diff --git a/tests/ui/traits/default-method/bound-subst.rs b/tests/ui/traits/default-method/bound-subst.rs
new file mode 100644
index 000000000..6a5d5c8ba
--- /dev/null
+++ b/tests/ui/traits/default-method/bound-subst.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+
+trait A<T> {
+ fn g<U>(&self, x: T, y: U) -> (T, U) { (x, y) }
+}
+
+impl A<i32> for i32 { }
+impl<T> A<T> for u32 { }
+
+fn f<T, U, V: A<T>>(i: V, j: T, k: U) -> (T, U) {
+ i.g(j, k)
+}
+
+pub fn main () {
+ assert_eq!(f(0, 1, 2), (1, 2));
+ assert_eq!(f(0, 1, 2), (1, 2));
+}
diff --git a/tests/ui/traits/default-method/bound-subst2.rs b/tests/ui/traits/default-method/bound-subst2.rs
new file mode 100644
index 000000000..78eabba2d
--- /dev/null
+++ b/tests/ui/traits/default-method/bound-subst2.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+
+trait A<T> {
+ fn g(&self, x: T) -> T { x }
+}
+
+impl A<isize> for isize { }
+
+fn f<T, V: A<T>>(i: V, j: T) -> T {
+ i.g(j)
+}
+
+pub fn main () {
+ assert_eq!(f(0, 2), 2);
+}
diff --git a/tests/ui/traits/default-method/bound-subst3.rs b/tests/ui/traits/default-method/bound-subst3.rs
new file mode 100644
index 000000000..dd39dec4b
--- /dev/null
+++ b/tests/ui/traits/default-method/bound-subst3.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+
+trait A {
+ fn g<T>(&self, x: T, y: T) -> (T, T) { (x, y) }
+}
+
+impl A for isize { }
+
+fn f<T, V: A>(i: V, j: T, k: T) -> (T, T) {
+ i.g(j, k)
+}
+
+pub fn main () {
+ assert_eq!(f(0, 1, 2), (1, 2));
+ assert_eq!(f(0, 1u8, 2u8), (1u8, 2u8));
+}
diff --git a/tests/ui/traits/default-method/bound-subst4.rs b/tests/ui/traits/default-method/bound-subst4.rs
new file mode 100644
index 000000000..ef1330645
--- /dev/null
+++ b/tests/ui/traits/default-method/bound-subst4.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(unused_variables)]
+
+
+trait A<T> {
+ fn g(&self, x: usize) -> usize { x }
+ fn h(&self, x: T) { }
+}
+
+impl<T> A<T> for isize { }
+
+fn f<T, V: A<T>>(i: V, j: usize) -> usize {
+ i.g(j)
+}
+
+pub fn main () {
+ assert_eq!(f::<f64, isize>(0, 2), 2);
+ assert_eq!(f::<usize, isize>(0, 2), 2);
+}
diff --git a/tests/ui/traits/default-method/bound.rs b/tests/ui/traits/default-method/bound.rs
new file mode 100644
index 000000000..0855a9db8
--- /dev/null
+++ b/tests/ui/traits/default-method/bound.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+
+trait A {
+ fn g(&self) -> isize { 10 }
+}
+
+impl A for isize { }
+
+fn f<T:A>(i: T) {
+ assert_eq!(i.g(), 10);
+}
+
+pub fn main () {
+ f(0);
+}
diff --git a/tests/ui/traits/default-method/macro.rs b/tests/ui/traits/default-method/macro.rs
new file mode 100644
index 000000000..2b50ee9b4
--- /dev/null
+++ b/tests/ui/traits/default-method/macro.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+
+trait Foo {
+ fn bar(&self) -> String {
+ format!("test")
+ }
+}
+
+enum Baz {
+ Quux
+}
+
+impl Foo for Baz {
+}
+
+pub fn main() {
+ let q = Baz::Quux;
+ assert_eq!(q.bar(), "test".to_string());
+}
diff --git a/tests/ui/traits/default-method/mut.rs b/tests/ui/traits/default-method/mut.rs
new file mode 100644
index 000000000..5f8e983b0
--- /dev/null
+++ b/tests/ui/traits/default-method/mut.rs
@@ -0,0 +1,11 @@
+// run-pass
+#![allow(unused_assignments)]
+// pretty-expanded FIXME #23616
+
+#![allow(unused_variables)]
+
+trait Foo {
+ fn foo(&self, mut v: isize) { v = 1; }
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs
new file mode 100644
index 000000000..5ba2f5ce3
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs
@@ -0,0 +1,44 @@
+#![feature(rustc_attrs)]
+
+#[rustc_must_implement_one_of(eq, neq)]
+trait Equal {
+ fn eq(&self, other: &Self) -> bool {
+ !self.neq(other)
+ }
+
+ fn neq(&self, other: &Self) -> bool {
+ !self.eq(other)
+ }
+}
+
+struct T0;
+struct T1;
+struct T2;
+struct T3;
+
+impl Equal for T0 {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+}
+
+impl Equal for T1 {
+ fn neq(&self, _other: &Self) -> bool {
+ false
+ }
+}
+
+impl Equal for T2 {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+
+ fn neq(&self, _other: &Self) -> bool {
+ false
+ }
+}
+
+impl Equal for T3 {}
+//~^ not all trait items implemented, missing one of: `eq`, `neq`
+
+fn main() {}
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr
new file mode 100644
index 000000000..5a4dd1388
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr
@@ -0,0 +1,15 @@
+error[E0046]: not all trait items implemented, missing one of: `eq`, `neq`
+ --> $DIR/rustc_must_implement_one_of.rs:41:1
+ |
+LL | impl Equal for T3 {}
+ | ^^^^^^^^^^^^^^^^^ missing one of `eq`, `neq` in implementation
+ |
+note: required because of this annotation
+ --> $DIR/rustc_must_implement_one_of.rs:3:1
+ |
+LL | #[rustc_must_implement_one_of(eq, neq)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs
new file mode 100644
index 000000000..8db5fa615
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs
@@ -0,0 +1,19 @@
+#![feature(rustc_attrs)]
+
+#[rustc_must_implement_one_of(a, a)]
+//~^ functions names are duplicated
+trait Trait {
+ fn a() {}
+}
+
+#[rustc_must_implement_one_of(b, a, a, c, b, c)]
+//~^ functions names are duplicated
+//~| functions names are duplicated
+//~| functions names are duplicated
+trait Trait1 {
+ fn a() {}
+ fn b() {}
+ fn c() {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr
new file mode 100644
index 000000000..cd1476a6e
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr
@@ -0,0 +1,34 @@
+error: functions names are duplicated
+ --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31
+ |
+LL | #[rustc_must_implement_one_of(a, a)]
+ | ^ ^
+ |
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
+
+error: functions names are duplicated
+ --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34
+ |
+LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
+ | ^ ^
+ |
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
+
+error: functions names are duplicated
+ --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31
+ |
+LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
+ | ^ ^
+ |
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
+
+error: functions names are duplicated
+ --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40
+ |
+LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
+ | ^ ^
+ |
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs
new file mode 100644
index 000000000..ec2995872
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs
@@ -0,0 +1,13 @@
+#[rustc_must_implement_one_of(eq, neq)]
+//~^ the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std
+trait Equal {
+ fn eq(&self, other: &Self) -> bool {
+ !self.neq(other)
+ }
+
+ fn neq(&self, other: &Self) -> bool {
+ !self.eq(other)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr
new file mode 100644
index 000000000..228bc3e35
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std
+ --> $DIR/rustc_must_implement_one_of_gated.rs:1:1
+ |
+LL | #[rustc_must_implement_one_of(eq, neq)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(rustc_attrs)]` 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/traits/default-method/rustc_must_implement_one_of_misuse.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs
new file mode 100644
index 000000000..b1b91966c
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs
@@ -0,0 +1,46 @@
+#![feature(rustc_attrs)]
+
+#[rustc_must_implement_one_of(a, b)]
+//~^ function not found in this trait
+//~| function not found in this trait
+trait Tr0 {}
+
+#[rustc_must_implement_one_of(a, b)]
+//~^ function not found in this trait
+trait Tr1 {
+ fn a() {}
+}
+
+#[rustc_must_implement_one_of(a)]
+//~^ the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+trait Tr2 {
+ fn a() {}
+}
+
+#[rustc_must_implement_one_of]
+//~^ malformed `rustc_must_implement_one_of` attribute input
+trait Tr3 {}
+
+#[rustc_must_implement_one_of(A, B)]
+trait Tr4 {
+ const A: u8 = 1; //~ not a function
+
+ type B; //~ not a function
+}
+
+#[rustc_must_implement_one_of(a, b)]
+trait Tr5 {
+ fn a(); //~ function doesn't have a default implementation
+
+ fn b(); //~ function doesn't have a default implementation
+}
+
+#[rustc_must_implement_one_of(abc, xyz)]
+//~^ attribute should be applied to a trait
+fn function() {}
+
+#[rustc_must_implement_one_of(abc, xyz)]
+//~^ attribute should be applied to a trait
+struct Struct {}
+
+fn main() {}
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
new file mode 100644
index 000000000..38e692521
--- /dev/null
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
@@ -0,0 +1,100 @@
+error: malformed `rustc_must_implement_one_of` attribute input
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:20:1
+ |
+LL | #[rustc_must_implement_one_of]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]`
+
+error: attribute should be applied to a trait
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:38:1
+ |
+LL | #[rustc_must_implement_one_of(abc, xyz)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn function() {}
+ | ---------------- not a trait
+
+error: attribute should be applied to a trait
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:42:1
+ |
+LL | #[rustc_must_implement_one_of(abc, xyz)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct Struct {}
+ | ---------------- not a trait
+
+error: function not found in this trait
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
+ |
+LL | #[rustc_must_implement_one_of(a, b)]
+ | ^
+
+error: function not found in this trait
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34
+ |
+LL | #[rustc_must_implement_one_of(a, b)]
+ | ^
+
+error: function not found in this trait
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34
+ |
+LL | #[rustc_must_implement_one_of(a, b)]
+ | ^
+
+error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1
+ |
+LL | #[rustc_must_implement_one_of(a)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: not a function
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5
+ |
+LL | const A: u8 = 1;
+ | ^^^^^^^^^^^^^^^^
+ |
+note: required by this annotation
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1
+ |
+LL | #[rustc_must_implement_one_of(A, B)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
+
+error: not a function
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5
+ |
+LL | type B;
+ | ^^^^^^^
+ |
+note: required by this annotation
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1
+ |
+LL | #[rustc_must_implement_one_of(A, B)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
+
+error: function doesn't have a default implementation
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5
+ |
+LL | fn a();
+ | ^^^^^^^
+ |
+note: required by this annotation
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1
+ |
+LL | #[rustc_must_implement_one_of(a, b)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function doesn't have a default implementation
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5
+ |
+LL | fn b();
+ | ^^^^^^^
+ |
+note: required by this annotation
+ --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1
+ |
+LL | #[rustc_must_implement_one_of(a, b)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/traits/default-method/self.rs b/tests/ui/traits/default-method/self.rs
new file mode 100644
index 000000000..cdf4d1e14
--- /dev/null
+++ b/tests/ui/traits/default-method/self.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+
+trait Cat {
+ fn meow(&self) -> bool;
+ fn scratch(&self) -> bool { self.purr() }
+ fn purr(&self) -> bool { true }
+}
+
+impl Cat for isize {
+ fn meow(&self) -> bool {
+ self.scratch()
+ }
+}
+
+pub fn main() {
+ assert!(5.meow());
+}
diff --git a/tests/ui/traits/default-method/supervtable.rs b/tests/ui/traits/default-method/supervtable.rs
new file mode 100644
index 000000000..939ad5135
--- /dev/null
+++ b/tests/ui/traits/default-method/supervtable.rs
@@ -0,0 +1,28 @@
+// run-pass
+
+
+// Tests that we can call a function bounded over a supertrait from
+// a default method
+
+fn require_y<T: Y>(x: T) -> isize { x.y() }
+
+trait Y {
+ fn y(self) -> isize;
+}
+
+
+trait Z: Y + Sized {
+ fn x(self) -> isize {
+ require_y(self)
+ }
+}
+
+impl Y for isize {
+ fn y(self) -> isize { self }
+}
+
+impl Z for isize {}
+
+pub fn main() {
+ assert_eq!(12.x(), 12);
+}
diff --git a/tests/ui/traits/default-method/trivial.rs b/tests/ui/traits/default-method/trivial.rs
new file mode 100644
index 000000000..dc41938ec
--- /dev/null
+++ b/tests/ui/traits/default-method/trivial.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+
+trait Cat {
+ fn meow(&self) -> bool;
+ fn scratch(&self) -> bool;
+ fn purr(&self) -> bool { true }
+}
+
+impl Cat for isize {
+ fn meow(&self) -> bool {
+ self.scratch()
+ }
+ fn scratch(&self) -> bool {
+ self.purr()
+ }
+}
+
+pub fn main() {
+ assert!(5.meow());
+}
diff --git a/tests/ui/traits/default-method/xc-2.rs b/tests/ui/traits/default-method/xc-2.rs
new file mode 100644
index 000000000..1de61dcf8
--- /dev/null
+++ b/tests/ui/traits/default-method/xc-2.rs
@@ -0,0 +1,26 @@
+// run-pass
+// aux-build:xc.rs
+// aux-build:xc_2.rs
+
+
+
+extern crate xc as aux;
+extern crate xc_2 as aux2;
+use aux::A;
+use aux2::{a_struct, welp};
+
+
+pub fn main () {
+
+ let a = a_struct { x: 0 };
+ let b = a_struct { x: 1 };
+
+ assert_eq!(0.g(), 10);
+ assert_eq!(a.g(), 10);
+ assert_eq!(a.h(), 11);
+ assert_eq!(b.g(), 10);
+ assert_eq!(b.h(), 11);
+ assert_eq!(A::lurr(&a, &b), 21);
+
+ welp(&0);
+}
diff --git a/tests/ui/traits/default-method/xc.rs b/tests/ui/traits/default-method/xc.rs
new file mode 100644
index 000000000..76a1573d6
--- /dev/null
+++ b/tests/ui/traits/default-method/xc.rs
@@ -0,0 +1,81 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// aux-build:xc.rs
+
+
+extern crate xc as aux;
+use aux::{A, TestEquality, Something};
+use aux::B;
+
+fn f<T: aux::A>(i: T) {
+ assert_eq!(i.g(), 10);
+}
+
+fn welp<T>(i: isize, _x: &T) -> isize {
+ i.g()
+}
+
+mod stuff {
+ pub struct thing { pub x: isize }
+}
+
+impl A for stuff::thing {
+ fn f(&self) -> isize { 10 }
+}
+
+fn g<T, U, V: B<T>>(i: V, j: T, k: U) -> (T, U) {
+ i.thing(j, k)
+}
+
+fn eq<T: TestEquality>(lhs: &T, rhs: &T) -> bool {
+ lhs.test_eq(rhs)
+}
+fn neq<T: TestEquality>(lhs: &T, rhs: &T) -> bool {
+ lhs.test_neq(rhs)
+}
+
+
+impl TestEquality for stuff::thing {
+ fn test_eq(&self, rhs: &stuff::thing) -> bool {
+ //self.x.test_eq(&rhs.x)
+ eq(&self.x, &rhs.x)
+ }
+}
+
+
+pub fn main() {
+ // Some tests of random things
+ f(0);
+
+ assert_eq!(A::lurr(&0, &1), 21);
+
+ let a = stuff::thing { x: 0 };
+ let b = stuff::thing { x: 1 };
+ let c = Something { x: 1 };
+
+ assert_eq!(0.g(), 10);
+ assert_eq!(a.g(), 10);
+ assert_eq!(a.h(), 11);
+ assert_eq!(c.h(), 11);
+
+ assert_eq!(0.thing(3.14f64, 1), (3.14f64, 1));
+ assert_eq!(B::staticthing(&0, 3.14f64, 1), (3.14f64, 1));
+ assert_eq!(B::<f64>::staticthing::<isize>(&0, 3.14, 1), (3.14, 1));
+
+ assert_eq!(g(0, 3.14f64, 1), (3.14f64, 1));
+ assert_eq!(g(false, 3.14f64, 1), (3.14, 1));
+
+
+ // Trying out a real one
+ assert!(12.test_neq(&10));
+ assert!(!10.test_neq(&10));
+ assert!(a.test_neq(&b));
+ assert!(!a.test_neq(&a));
+
+ assert!(neq(&12, &10));
+ assert!(!neq(&10, &10));
+ assert!(neq(&a, &b));
+ assert!(!neq(&a, &a));
+}
diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs
new file mode 100644
index 000000000..9a444be50
--- /dev/null
+++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs
@@ -0,0 +1,20 @@
+struct Thing<X>(X);
+
+trait Method<T> {
+ fn method(self, _: i32) -> T;
+}
+
+impl<X> Method<i32> for Thing<X> {
+ fn method(self, _: i32) -> i32 { 0 }
+}
+
+impl<X> Method<u32> for Thing<X> {
+ fn method(self, _: i32) -> u32 { 0 }
+}
+
+fn main() {
+ let thing = Thing(true);
+ thing.method(42);
+ //~^ ERROR type annotations needed
+ //~| ERROR type annotations needed
+}
diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr
new file mode 100644
index 000000000..57b2587ae
--- /dev/null
+++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr
@@ -0,0 +1,34 @@
+error[E0282]: type annotations needed
+ --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
+ |
+LL | thing.method(42);
+ | ^^^^^^
+ |
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing<bool> as Method<T>>::method(thing, 42);
+ | +++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
+ |
+LL | thing.method(42);
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing<bool>: Method<_>` found
+ --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1
+ |
+LL | impl<X> Method<i32> for Thing<X> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl<X> Method<u32> for Thing<X> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing<bool> as Method<T>>::method(thing, 42);
+ | +++++++++++++++++++++++++++++++++++ ~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/duplicate-methods.rs b/tests/ui/traits/duplicate-methods.rs
new file mode 100644
index 000000000..1f9bdf56f
--- /dev/null
+++ b/tests/ui/traits/duplicate-methods.rs
@@ -0,0 +1,6 @@
+trait Foo {
+ fn orange(&self);
+ fn orange(&self); //~ ERROR the name `orange` is defined multiple times
+}
+
+fn main() {}
diff --git a/tests/ui/traits/duplicate-methods.stderr b/tests/ui/traits/duplicate-methods.stderr
new file mode 100644
index 000000000..6aa88d0df
--- /dev/null
+++ b/tests/ui/traits/duplicate-methods.stderr
@@ -0,0 +1,13 @@
+error[E0428]: the name `orange` is defined multiple times
+ --> $DIR/duplicate-methods.rs:3:5
+ |
+LL | fn orange(&self);
+ | ----------------- previous definition of the value `orange` here
+LL | fn orange(&self);
+ | ^^^^^^^^^^^^^^^^^ `orange` redefined here
+ |
+ = note: `orange` must be defined only once in the value namespace of this trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/ui/traits/dyn-trait.rs b/tests/ui/traits/dyn-trait.rs
new file mode 100644
index 000000000..e1c1a8de5
--- /dev/null
+++ b/tests/ui/traits/dyn-trait.rs
@@ -0,0 +1,17 @@
+// run-pass
+// ignore-pretty `dyn ::foo` parses differently in the current edition
+
+use std::fmt::Display;
+
+static BYTE: u8 = 33;
+
+fn main() {
+ let x: &(dyn 'static + Display) = &BYTE;
+ let y: Box<dyn Display + 'static> = Box::new(BYTE);
+ let _: &dyn (Display) = &BYTE;
+ let _: &dyn (::std::fmt::Display) = &BYTE;
+ let xstr = format!("{}", x);
+ let ystr = format!("{}", y);
+ assert_eq!(xstr, "33");
+ assert_eq!(ystr, "33");
+}
diff --git a/tests/ui/traits/early-vtbl-resolution.rs b/tests/ui/traits/early-vtbl-resolution.rs
new file mode 100644
index 000000000..f4b69c140
--- /dev/null
+++ b/tests/ui/traits/early-vtbl-resolution.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait thing<A> {
+ fn foo(&self) -> Option<A>;
+}
+impl<A> thing<A> for isize {
+ fn foo(&self) -> Option<A> { None }
+}
+fn foo_func<A, B: thing<A>>(x: B) -> Option<A> { x.foo() }
+
+struct A { a: isize }
+
+pub fn main() {
+ let _x: Option<f64> = foo_func(0);
+}
diff --git a/tests/ui/traits/elaborate-type-region.rs b/tests/ui/traits/elaborate-type-region.rs
new file mode 100644
index 000000000..03aef0184
--- /dev/null
+++ b/tests/ui/traits/elaborate-type-region.rs
@@ -0,0 +1,49 @@
+// run-pass
+#![allow(dead_code)]
+
+// Test that we elaborate `Type: 'region` constraints and infer various important things.
+
+trait Master<'a, T: ?Sized> {
+ fn foo() where T: 'a;
+}
+
+// [U]: 'a => U: 'a
+impl<'a, U> Master<'a, [U]> for () {
+ fn foo() where U: 'a { }
+}
+
+// &'b U: 'a => 'b: 'a, U: 'a
+impl<'a, 'b, U> Master<'a, &'b U> for () {
+ fn foo() where 'b: 'a, U: 'a { }
+}
+
+// &'b [U]: 'a => 'b: 'a, U: 'a
+impl<'a, 'b, U> Master<'a, &'b [U]> for () {
+ fn foo() where 'b: 'a, U: 'a { }
+}
+
+// Foo<'b>: 'a => 'b: 'a
+struct Foo<'a> { x: &'a () }
+impl<'a, 'b> Master<'a, Foo<'b>> for () {
+ fn foo() where 'b: 'a { }
+}
+
+// Bar<'b, T>: 'a => 'b: 'a, T: 'a
+struct Bar<'a, T: 'a> { x: &'a T }
+impl<'a, 'b, T> Master<'a, Bar<'b, T>> for () {
+ fn foo() where 'b: 'a, T: 'a { }
+}
+
+// fn(T): 'a => T: 'a
+impl<'a, T> Master<'a, fn(T)> for () {
+ fn foo() where T: 'a { }
+}
+
+// fn() -> T: 'a => T: 'a
+impl<'a, T> Master<'a, fn() -> T> for () {
+ fn foo() where T: 'a { }
+}
+
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs b/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs
new file mode 100644
index 000000000..3413db6a6
--- /dev/null
+++ b/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs
@@ -0,0 +1,16 @@
+// run-pass
+// Test that we do not error out because of a (False) ambiguity
+// between the builtin rules for Sized and the where clause. Issue
+// #20959.
+
+// pretty-expanded FIXME #23616
+
+fn foo<K>(x: Option<K>)
+ where Option<K> : Sized
+{
+ let _y = x;
+}
+
+fn main() {
+ foo(Some(22));
+}
diff --git a/tests/ui/traits/fmt-pointer-trait.rs b/tests/ui/traits/fmt-pointer-trait.rs
new file mode 100644
index 000000000..b7876b9bd
--- /dev/null
+++ b/tests/ui/traits/fmt-pointer-trait.rs
@@ -0,0 +1,24 @@
+// run-pass
+use std::ptr;
+use std::rc::Rc;
+use std::sync::Arc;
+
+fn main() {
+ let p: *const u8 = ptr::null();
+ let rc = Rc::new(1usize);
+ let arc = Arc::new(1usize);
+ let b = Box::new("hi");
+
+ let _ = format!("{:p}{:p}{:p}",
+ rc, arc, b);
+
+ if cfg!(target_pointer_width = "32") {
+ assert_eq!(format!("{:#p}", p),
+ "0x00000000");
+ } else {
+ assert_eq!(format!("{:#p}", p),
+ "0x0000000000000000");
+ }
+ assert_eq!(format!("{:p}", p),
+ "0x0");
+}
diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.rs b/tests/ui/traits/fn-trait-cast-diagnostic.rs
new file mode 100644
index 000000000..e20aa210e
--- /dev/null
+++ b/tests/ui/traits/fn-trait-cast-diagnostic.rs
@@ -0,0 +1,26 @@
+// There are two different instances to check that even if
+// the trait is implemented for the output of a function,
+// it will still be displayed if the function itself implements a trait.
+trait Foo {}
+
+impl Foo for fn() -> bool {}
+impl Foo for bool {}
+
+fn example() -> bool {
+ true
+}
+
+trait NoOtherFoo {}
+
+impl NoOtherFoo for fn() -> bool {}
+
+fn do_on_foo(v: impl Foo) {}
+fn do_on_single_foo(v: impl NoOtherFoo) {}
+
+fn main() {
+ do_on_foo(example);
+ //~^ ERROR the trait bound
+
+ do_on_single_foo(example);
+ //~^ ERROR the trait bound
+}
diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.stderr b/tests/ui/traits/fn-trait-cast-diagnostic.stderr
new file mode 100644
index 000000000..6851dcdd5
--- /dev/null
+++ b/tests/ui/traits/fn-trait-cast-diagnostic.stderr
@@ -0,0 +1,43 @@
+error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied
+ --> $DIR/fn-trait-cast-diagnostic.rs:21:15
+ |
+LL | do_on_foo(example);
+ | --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `do_on_foo`
+ --> $DIR/fn-trait-cast-diagnostic.rs:17:22
+ |
+LL | fn do_on_foo(v: impl Foo) {}
+ | ^^^ required by this bound in `do_on_foo`
+help: use parentheses to call this function
+ |
+LL | do_on_foo(example());
+ | ++
+help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
+ |
+LL | do_on_foo(example as fn() -> bool);
+ | +++++++++++++++
+
+error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied
+ --> $DIR/fn-trait-cast-diagnostic.rs:24:22
+ |
+LL | do_on_single_foo(example);
+ | ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `do_on_single_foo`
+ --> $DIR/fn-trait-cast-diagnostic.rs:18:29
+ |
+LL | fn do_on_single_foo(v: impl NoOtherFoo) {}
+ | ^^^^^^^^^^ required by this bound in `do_on_single_foo`
+help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
+ |
+LL | do_on_single_foo(example as fn() -> bool);
+ | +++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/generic.rs b/tests/ui/traits/generic.rs
new file mode 100644
index 000000000..80efe1c93
--- /dev/null
+++ b/tests/ui/traits/generic.rs
@@ -0,0 +1,45 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+
+
+trait to_str {
+ fn to_string_(&self) -> String;
+}
+impl to_str for isize {
+ fn to_string_(&self) -> String { self.to_string() }
+}
+impl to_str for String {
+ fn to_string_(&self) -> String { self.clone() }
+}
+impl to_str for () {
+ fn to_string_(&self) -> String { "()".to_string() }
+}
+
+trait map<T> {
+ fn map<U, F>(&self, f: F) -> Vec<U> where F: FnMut(&T) -> U;
+}
+impl<T> map<T> for Vec<T> {
+ fn map<U, F>(&self, mut f: F) -> Vec<U> where F: FnMut(&T) -> U {
+ let mut r = Vec::new();
+ for i in self {
+ r.push(f(i));
+ }
+ r
+ }
+}
+
+fn foo<U, T: map<U>>(x: T) -> Vec<String> {
+ x.map(|_e| "hi".to_string() )
+}
+fn bar<U:to_str,T:map<U>>(x: T) -> Vec<String> {
+ x.map(|_e| _e.to_string_() )
+}
+
+pub fn main() {
+ assert_eq!(foo(vec![1]), ["hi".to_string()]);
+ assert_eq!(bar::<isize, Vec<isize> >(vec![4, 5]), ["4".to_string(), "5".to_string()]);
+ assert_eq!(bar::<String, Vec<String> >(vec!["x".to_string(), "y".to_string()]),
+ ["x".to_string(), "y".to_string()]);
+ assert_eq!(bar::<(), Vec<()>>(vec![()]), ["()".to_string()]);
+}
diff --git a/tests/ui/traits/ignore-err-impls.rs b/tests/ui/traits/ignore-err-impls.rs
new file mode 100644
index 000000000..67e880b00
--- /dev/null
+++ b/tests/ui/traits/ignore-err-impls.rs
@@ -0,0 +1,9 @@
+pub struct S;
+
+trait Generic<T> {}
+
+impl<'a, T> Generic<&'a T> for S {}
+impl Generic<Type> for S {}
+//~^ ERROR cannot find type `Type` in this scope
+
+fn main() {}
diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr
new file mode 100644
index 000000000..45bd533b5
--- /dev/null
+++ b/tests/ui/traits/ignore-err-impls.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `Type` in this scope
+ --> $DIR/ignore-err-impls.rs:6:14
+ |
+LL | impl Generic<Type> for S {}
+ | ^^^^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | impl<Type> Generic<Type> for S {}
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/impl-1.rs b/tests/ui/traits/impl-1.rs
new file mode 100644
index 000000000..d22ac72d1
--- /dev/null
+++ b/tests/ui/traits/impl-1.rs
@@ -0,0 +1,16 @@
+// Test calling methods on an impl for a bare trait. This test checks that the
+// trait impl is only applied to a trait object, not concrete types which implement
+// the trait.
+
+trait T {}
+
+impl<'a> dyn T + 'a {
+ fn foo(&self) {}
+}
+
+impl T for i32 {}
+
+fn main() {
+ let x = &42i32;
+ x.foo(); //~ERROR: no method named `foo` found
+}
diff --git a/tests/ui/traits/impl-1.stderr b/tests/ui/traits/impl-1.stderr
new file mode 100644
index 000000000..7694e3f5c
--- /dev/null
+++ b/tests/ui/traits/impl-1.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no method named `foo` found for reference `&i32` in the current scope
+ --> $DIR/impl-1.rs:15:7
+ |
+LL | x.foo();
+ | ^^^ method not found in `&i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/impl-2.rs b/tests/ui/traits/impl-2.rs
new file mode 100644
index 000000000..804ffec12
--- /dev/null
+++ b/tests/ui/traits/impl-2.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_snake_case)]
+
+// pretty-expanded FIXME #23616
+
+pub mod Foo {
+ pub trait Trait {
+ fn foo(&self);
+ }
+}
+
+mod Bar {
+ impl<'a> dyn (::Foo::Trait) + 'a {
+ fn bar(&self) { self.foo() }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/impl-bounds-checking.rs b/tests/ui/traits/impl-bounds-checking.rs
new file mode 100644
index 000000000..5e65a27bf
--- /dev/null
+++ b/tests/ui/traits/impl-bounds-checking.rs
@@ -0,0 +1,14 @@
+pub trait Clone2 {
+ fn clone(&self) -> Self;
+}
+
+
+trait Getter<T: Clone2> {
+ fn get(&self) -> T;
+}
+
+impl Getter<isize> for isize { //~ ERROR `isize: Clone2` is not satisfied
+ fn get(&self) -> isize { *self }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr
new file mode 100644
index 000000000..1f969efe1
--- /dev/null
+++ b/tests/ui/traits/impl-bounds-checking.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `isize: Clone2` is not satisfied
+ --> $DIR/impl-bounds-checking.rs:10:24
+ |
+LL | impl Getter<isize> for isize {
+ | ^^^^^ the trait `Clone2` is not implemented for `isize`
+ |
+note: required by a bound in `Getter`
+ --> $DIR/impl-bounds-checking.rs:6:17
+ |
+LL | trait Getter<T: Clone2> {
+ | ^^^^^^ required by this bound in `Getter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/impl-can-not-have-untraitful-items.rs b/tests/ui/traits/impl-can-not-have-untraitful-items.rs
new file mode 100644
index 000000000..0c885447b
--- /dev/null
+++ b/tests/ui/traits/impl-can-not-have-untraitful-items.rs
@@ -0,0 +1,9 @@
+trait A { }
+
+impl A for isize {
+ const BAR: () = (); //~ ERROR const `BAR` is not a member of trait `A`
+ type Baz = (); //~ ERROR type `Baz` is not a member of trait `A`
+ fn foo(&self) { } //~ ERROR method `foo` is not a member of trait `A`
+}
+
+fn main() { }
diff --git a/tests/ui/traits/impl-can-not-have-untraitful-items.stderr b/tests/ui/traits/impl-can-not-have-untraitful-items.stderr
new file mode 100644
index 000000000..7f56f34ea
--- /dev/null
+++ b/tests/ui/traits/impl-can-not-have-untraitful-items.stderr
@@ -0,0 +1,22 @@
+error[E0438]: const `BAR` is not a member of trait `A`
+ --> $DIR/impl-can-not-have-untraitful-items.rs:4:5
+ |
+LL | const BAR: () = ();
+ | ^^^^^^^^^^^^^^^^^^^ not a member of trait `A`
+
+error[E0437]: type `Baz` is not a member of trait `A`
+ --> $DIR/impl-can-not-have-untraitful-items.rs:5:5
+ |
+LL | type Baz = ();
+ | ^^^^^^^^^^^^^^ not a member of trait `A`
+
+error[E0407]: method `foo` is not a member of trait `A`
+ --> $DIR/impl-can-not-have-untraitful-items.rs:6:5
+ |
+LL | fn foo(&self) { }
+ | ^^^^^^^^^^^^^^^^^ not a member of trait `A`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0407, E0437, E0438.
+For more information about an error, try `rustc --explain E0407`.
diff --git a/tests/ui/traits/impl-different-num-params.rs b/tests/ui/traits/impl-different-num-params.rs
new file mode 100644
index 000000000..53400622d
--- /dev/null
+++ b/tests/ui/traits/impl-different-num-params.rs
@@ -0,0 +1,12 @@
+trait Foo {
+ fn bar(&self, x: usize) -> Self;
+}
+impl Foo for isize {
+ fn bar(&self) -> isize {
+ //~^ ERROR method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2
+ *self
+ }
+}
+
+fn main() {
+}
diff --git a/tests/ui/traits/impl-different-num-params.stderr b/tests/ui/traits/impl-different-num-params.stderr
new file mode 100644
index 000000000..910ba3510
--- /dev/null
+++ b/tests/ui/traits/impl-different-num-params.stderr
@@ -0,0 +1,12 @@
+error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2
+ --> $DIR/impl-different-num-params.rs:5:12
+ |
+LL | fn bar(&self, x: usize) -> Self;
+ | --------------- trait requires 2 parameters
+...
+LL | fn bar(&self) -> isize {
+ | ^^^^^ expected 2 parameters, found 1
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0050`.
diff --git a/tests/ui/traits/impl-evaluation-order.rs b/tests/ui/traits/impl-evaluation-order.rs
new file mode 100644
index 000000000..57809d89a
--- /dev/null
+++ b/tests/ui/traits/impl-evaluation-order.rs
@@ -0,0 +1,39 @@
+// Regression test for #79902
+
+// Check that evaluation (which is used to determine whether to copy a type in
+// MIR building) evaluates bounds from normalizing an impl after evaluating
+// any bounds on the impl.
+
+// check-pass
+
+trait A {
+ type B;
+}
+trait M {}
+
+struct G<T, U>(*const T, *const U);
+
+impl<T, U> Clone for G<T, U> {
+ fn clone(&self) -> Self {
+ G { ..*self }
+ }
+}
+
+impl<T, U> Copy for G<T, U::B>
+where
+ T: A<B = U>,
+ U: A,
+{
+}
+
+impl A for () {
+ type B = ();
+}
+
+fn is_m<T: M>(_: T) {}
+
+fn main() {
+ let x = G(&(), &());
+ drop(x);
+ drop(x);
+}
diff --git a/tests/ui/traits/impl-for-module.rs b/tests/ui/traits/impl-for-module.rs
new file mode 100644
index 000000000..9004627c5
--- /dev/null
+++ b/tests/ui/traits/impl-for-module.rs
@@ -0,0 +1,11 @@
+mod a {
+}
+
+trait A {
+}
+
+impl A for a { //~ ERROR expected type, found module
+}
+
+fn main() {
+}
diff --git a/tests/ui/traits/impl-for-module.stderr b/tests/ui/traits/impl-for-module.stderr
new file mode 100644
index 000000000..6ec4083b5
--- /dev/null
+++ b/tests/ui/traits/impl-for-module.stderr
@@ -0,0 +1,12 @@
+error[E0573]: expected type, found module `a`
+ --> $DIR/impl-for-module.rs:7:12
+ |
+LL | trait A {
+ | ------- similarly named trait `A` defined here
+...
+LL | impl A for a {
+ | ^ help: a trait with a similar name exists: `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/tests/ui/traits/impl-implicit-trait.rs b/tests/ui/traits/impl-implicit-trait.rs
new file mode 100644
index 000000000..fac2bcce2
--- /dev/null
+++ b/tests/ui/traits/impl-implicit-trait.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+// pretty-expanded FIXME #23616
+
+enum option_<T> {
+ none_,
+ some_(T),
+}
+
+impl<T> option_<T> {
+ pub fn foo(&self) -> bool { true }
+}
+
+enum option__ {
+ none__,
+ some__(isize)
+}
+
+impl option__ {
+ pub fn foo(&self) -> bool { true }
+}
+
+pub fn main() {
+}
diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.rs b/tests/ui/traits/impl-inherent-prefer-over-trait.rs
new file mode 100644
index 000000000..827607888
--- /dev/null
+++ b/tests/ui/traits/impl-inherent-prefer-over-trait.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+struct Foo;
+
+trait Trait {
+ fn bar(&self);
+}
+
+// Inherent impls should be preferred over trait ones.
+impl Foo {
+ fn bar(&self) {}
+}
+
+impl dyn Trait {
+ fn baz(_: &Foo) {}
+}
+
+impl Trait for Foo {
+ fn bar(&self) { panic!("wrong method called!") }
+}
+
+fn main() {
+ Foo.bar();
+ Foo::bar(&Foo);
+ <Foo>::bar(&Foo);
+
+ // Should work even if Trait::baz doesn't exist.
+ // N.B: `<Trait>::bar` would be ambiguous.
+ <dyn Trait>::baz(&Foo);
+}
diff --git a/tests/ui/traits/impl-method-mismatch.rs b/tests/ui/traits/impl-method-mismatch.rs
new file mode 100644
index 000000000..62580755c
--- /dev/null
+++ b/tests/ui/traits/impl-method-mismatch.rs
@@ -0,0 +1,13 @@
+trait Mumbo {
+ fn jumbo(&self, x: &usize) -> usize;
+}
+
+impl Mumbo for usize {
+ // Cannot have a larger effect than the trait:
+ unsafe fn jumbo(&self, x: &usize) { *self + *x; }
+ //~^ ERROR method `jumbo` has an incompatible type for trait
+ //~| expected signature `fn
+ //~| found signature `unsafe fn
+}
+
+fn main() {}
diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr
new file mode 100644
index 000000000..252b5aff9
--- /dev/null
+++ b/tests/ui/traits/impl-method-mismatch.stderr
@@ -0,0 +1,17 @@
+error[E0053]: method `jumbo` has an incompatible type for trait
+ --> $DIR/impl-method-mismatch.rs:7:5
+ |
+LL | unsafe fn jumbo(&self, x: &usize) { *self + *x; }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
+ |
+note: type in trait
+ --> $DIR/impl-method-mismatch.rs:2:5
+ |
+LL | fn jumbo(&self, x: &usize) -> usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected signature `fn(&usize, &usize) -> usize`
+ found signature `unsafe fn(&usize, &usize)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.rs b/tests/ui/traits/impl-object-overlap-issue-23853.rs
new file mode 100644
index 000000000..e490967b6
--- /dev/null
+++ b/tests/ui/traits/impl-object-overlap-issue-23853.rs
@@ -0,0 +1,18 @@
+// run-pass
+// Test that we are able to compile the case where both a blanket impl
+// and the object type itself supply the required trait obligation.
+// In this case, the blanket impl for `Foo` applies to any type,
+// including `Bar`, but the object type `Bar` also implicitly supplies
+// this context.
+
+trait Foo { fn dummy(&self) { } }
+
+trait Bar: Foo { }
+
+impl<T:?Sized> Foo for T { }
+
+fn want_foo<B:?Sized+Foo>() { }
+
+fn main() {
+ want_foo::<dyn Bar>();
+}
diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs
new file mode 100644
index 000000000..05b9db972
--- /dev/null
+++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs
@@ -0,0 +1,31 @@
+// Check that when we test the supertrait we ensure consistent use of
+// lifetime parameters. In this case, implementing T2<'a,'b> requires
+// an impl of T1<'a>, but we have an impl of T1<'b>.
+
+trait T1<'x> {
+ fn x(&self) -> &'x isize;
+}
+
+trait T2<'x, 'y> : T1<'x> {
+ fn y(&self) -> &'y isize;
+}
+
+struct S<'a, 'b> {
+ a: &'a isize,
+ b: &'b isize
+}
+
+impl<'a,'b> T1<'b> for S<'a, 'b> {
+ fn x(&self) -> &'b isize {
+ self.b
+ }
+}
+
+impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { //~ ERROR cannot infer an appropriate lifetime
+ fn y(&self) -> &'b isize {
+ self.b
+ }
+}
+
+pub fn main() {
+}
diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
new file mode 100644
index 000000000..1bace8ab2
--- /dev/null
+++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -0,0 +1,27 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
+ --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28
+ |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+ | ^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
+ --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6
+ |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+ | ^^
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined here...
+ --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9
+ |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28
+ |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+ | ^^^^^^^^^
+ = note: expected `T1<'a>`
+ found `T1<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs
new file mode 100644
index 000000000..f512d91eb
--- /dev/null
+++ b/tests/ui/traits/impl.rs
@@ -0,0 +1,41 @@
+// run-pass
+// Test calling methods on an impl for a bare trait.
+
+// aux-build:traitimpl.rs
+
+extern crate traitimpl;
+use traitimpl::Bar;
+
+static mut COUNT: usize = 1;
+
+trait T {
+ fn t(&self) {}
+}
+
+impl<'a> dyn T+'a {
+ fn foo(&self) {
+ unsafe { COUNT *= 2; }
+ }
+ fn bar() {
+ unsafe { COUNT *= 3; }
+ }
+}
+
+impl T for isize {}
+
+struct Foo;
+impl<'a> Bar<'a> for Foo {}
+
+fn main() {
+ let x: &dyn T = &42;
+
+ x.foo();
+ <dyn T>::foo(x);
+ <dyn T>::bar();
+
+ unsafe { assert_eq!(COUNT, 12); }
+
+ // Cross-crait case
+ let x: &dyn Bar = &Foo;
+ x.bar();
+}
diff --git a/tests/ui/traits/impl_trait_as_trait_return_position.rs b/tests/ui/traits/impl_trait_as_trait_return_position.rs
new file mode 100644
index 000000000..c3325fd80
--- /dev/null
+++ b/tests/ui/traits/impl_trait_as_trait_return_position.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+trait A {
+ type Foo;
+}
+
+impl<T> A for T {
+ type Foo = ();
+}
+
+fn foo() -> impl std::borrow::Borrow<<u8 as A>::Foo> {
+ ()
+}
+
+fn main() {
+ foo();
+}
diff --git a/tests/ui/traits/inductive-overflow/lifetime.rs b/tests/ui/traits/inductive-overflow/lifetime.rs
new file mode 100644
index 000000000..bf536d21c
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/lifetime.rs
@@ -0,0 +1,33 @@
+// Test that we don't hit the recursion limit for short cycles involving lifetimes.
+
+// Shouldn't hit this, we should realize that we're in a cycle sooner.
+#![recursion_limit="20"]
+
+trait NotAuto {}
+trait Y {
+ type P;
+}
+
+impl<'a> Y for C<'a> {
+ type P = Box<X<C<'a>>>;
+}
+
+struct C<'a>(&'a ());
+struct X<T: Y>(T::P);
+
+impl<T: NotAuto> NotAuto for Box<T> {} //~ NOTE: required
+//~^ NOTE unsatisfied trait bound introduced here
+impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
+impl<'a> NotAuto for C<'a> {}
+
+fn is_send<S: NotAuto>() {}
+//~^ NOTE: required
+//~| NOTE: required
+
+fn main() {
+ // Should only be a few notes.
+ is_send::<X<C<'static>>>();
+ //~^ ERROR overflow evaluating
+ //~| 3 redundant requirements hidden
+ //~| required for
+}
diff --git a/tests/ui/traits/inductive-overflow/lifetime.stderr b/tests/ui/traits/inductive-overflow/lifetime.stderr
new file mode 100644
index 000000000..357e59991
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/lifetime.stderr
@@ -0,0 +1,24 @@
+error[E0275]: overflow evaluating the requirement `X<C<'_>>: NotAuto`
+ --> $DIR/lifetime.rs:29:5
+ |
+LL | is_send::<X<C<'static>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: required for `Box<X<C<'_>>>` to implement `NotAuto`
+ --> $DIR/lifetime.rs:18:18
+ |
+LL | impl<T: NotAuto> NotAuto for Box<T> {}
+ | ------- ^^^^^^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 3 redundant requirements hidden
+ = note: required for `X<C<'static>>` to implement `NotAuto`
+note: required by a bound in `is_send`
+ --> $DIR/lifetime.rs:23:15
+ |
+LL | fn is_send<S: NotAuto>() {}
+ | ^^^^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/inductive-overflow/simultaneous.rs b/tests/ui/traits/inductive-overflow/simultaneous.rs
new file mode 100644
index 000000000..40ac92146
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/simultaneous.rs
@@ -0,0 +1,20 @@
+// Regression test for #33344, initial version. This example allowed
+// arbitrary trait bounds to be synthesized.
+
+trait Tweedledum: IntoIterator {}
+trait Tweedledee: IntoIterator {}
+
+impl<T: Tweedledum> Tweedledee for T {}
+impl<T: Tweedledee> Tweedledum for T {}
+
+trait Combo: IntoIterator {}
+impl<T: Tweedledee + Tweedledum> Combo for T {}
+
+fn is_ee<T: Combo>(t: T) {
+ t.into_iter();
+}
+
+fn main() {
+ is_ee(4);
+ //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle
+}
diff --git a/tests/ui/traits/inductive-overflow/simultaneous.stderr b/tests/ui/traits/inductive-overflow/simultaneous.stderr
new file mode 100644
index 000000000..e3b4ec07d
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/simultaneous.stderr
@@ -0,0 +1,22 @@
+error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum`
+ --> $DIR/simultaneous.rs:18:5
+ |
+LL | is_ee(4);
+ | ^^^^^
+ |
+note: required for `{integer}` to implement `Combo`
+ --> $DIR/simultaneous.rs:11:34
+ |
+LL | impl<T: Tweedledee + Tweedledum> Combo for T {}
+ | ---------- ^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `is_ee`
+ --> $DIR/simultaneous.rs:13:13
+ |
+LL | fn is_ee<T: Combo>(t: T) {
+ | ^^^^^ required by this bound in `is_ee`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs
new file mode 100644
index 000000000..5fea47a1b
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs
@@ -0,0 +1,18 @@
+// Auto-trait-based version of #29859, supertrait version. Test that using
+// a simple auto trait `..` impl alone still doesn't allow arbitrary bounds
+// to be synthesized.
+
+#![feature(auto_traits)]
+#![feature(negative_impls)]
+
+auto trait Magic: Copy {} //~ ERROR E0568
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+ let (a, b) = copy(NoClone); //~ ERROR
+ println!("{:?} {:?}", a, b);
+}
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
new file mode 100644
index 000000000..3ec288d13
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -0,0 +1,35 @@
+error[E0568]: auto traits cannot have super traits or lifetime bounds
+ --> $DIR/supertrait-auto-trait.rs:8:17
+ |
+LL | auto trait Magic: Copy {}
+ | -----^^^^^^ help: remove the super traits or lifetime bounds
+ | |
+ | auto trait cannot have super traits or lifetime bounds
+
+error[E0277]: the trait bound `NoClone: Copy` is not satisfied
+ --> $DIR/supertrait-auto-trait.rs:16:23
+ |
+LL | let (a, b) = copy(NoClone);
+ | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `NoClone` to implement `Magic`
+ --> $DIR/supertrait-auto-trait.rs:8:12
+ |
+LL | auto trait Magic: Copy {}
+ | ^^^^^
+note: required by a bound in `copy`
+ --> $DIR/supertrait-auto-trait.rs:10:12
+ |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+ | ^^^^^ required by this bound in `copy`
+help: consider annotating `NoClone` with `#[derive(Copy)]`
+ |
+LL | #[derive(Copy)]
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0568.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/inductive-overflow/supertrait.rs b/tests/ui/traits/inductive-overflow/supertrait.rs
new file mode 100644
index 000000000..c7aa4d90f
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/supertrait.rs
@@ -0,0 +1,15 @@
+// Regression test for #29859, supertrait version. This example
+// allowed arbitrary trait bounds to be synthesized.
+
+trait Magic: Copy {}
+impl<T: Magic> Magic for T {}
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+ let (a, b) = copy(NoClone); //~ ERROR E0275
+ println!("{:?} {:?}", a, b);
+}
diff --git a/tests/ui/traits/inductive-overflow/supertrait.stderr b/tests/ui/traits/inductive-overflow/supertrait.stderr
new file mode 100644
index 000000000..b537ecf17
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/supertrait.stderr
@@ -0,0 +1,22 @@
+error[E0275]: overflow evaluating the requirement `NoClone: Magic`
+ --> $DIR/supertrait.rs:13:18
+ |
+LL | let (a, b) = copy(NoClone);
+ | ^^^^
+ |
+note: required for `NoClone` to implement `Magic`
+ --> $DIR/supertrait.rs:5:16
+ |
+LL | impl<T: Magic> Magic for T {}
+ | ----- ^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `copy`
+ --> $DIR/supertrait.rs:7:12
+ |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+ | ^^^^^ required by this bound in `copy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/inductive-overflow/two-traits.rs b/tests/ui/traits/inductive-overflow/two-traits.rs
new file mode 100644
index 000000000..463b55d85
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/two-traits.rs
@@ -0,0 +1,22 @@
+// Regression test for #29859, initial version. This example allowed
+// arbitrary trait bounds to be synthesized.
+
+// Trait that you want all types to implement.
+use std::marker::{Sync as Trait};
+
+pub trait Magic {
+ type X: Trait;
+}
+impl<T: Magic> Magic for T {
+ type X = Self;
+ //~^ ERROR E0277
+}
+
+fn check<T: Trait>() {}
+
+fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
+
+fn main() {
+ wizard::<*mut ()>(); //~ ERROR E0275
+ // check::<*mut ()>();
+}
diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr
new file mode 100644
index 000000000..0d0bf8861
--- /dev/null
+++ b/tests/ui/traits/inductive-overflow/two-traits.stderr
@@ -0,0 +1,32 @@
+error[E0277]: `T` cannot be shared between threads safely
+ --> $DIR/two-traits.rs:11:14
+ |
+LL | type X = Self;
+ | ^^^^ `T` cannot be shared between threads safely
+ |
+note: required by a bound in `Magic::X`
+ --> $DIR/two-traits.rs:8:13
+ |
+LL | type X: Trait;
+ | ^^^^^ required by this bound in `Magic::X`
+help: consider further restricting this bound
+ |
+LL | impl<T: Magic + std::marker::Sync> Magic for T {
+ | +++++++++++++++++++
+
+error[E0275]: overflow evaluating the requirement `*mut (): Magic`
+ --> $DIR/two-traits.rs:20:5
+ |
+LL | wizard::<*mut ()>();
+ | ^^^^^^^^^^^^^^^^^
+ |
+note: required by a bound in `wizard`
+ --> $DIR/two-traits.rs:17:14
+ |
+LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
+ | ^^^^^ required by this bound in `wizard`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0275, E0277.
+For more information about an error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/infer-from-object-issue-26952.rs b/tests/ui/traits/infer-from-object-issue-26952.rs
new file mode 100644
index 000000000..ed258dbb2
--- /dev/null
+++ b/tests/ui/traits/infer-from-object-issue-26952.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test that when we match a trait reference like `Foo<A>: Foo<_#0t>`,
+// we unify with `_#0t` with `A`. In this code, if we failed to do
+// that, then you get an unconstrained type-variable in `call`.
+//
+// Also serves as a regression test for issue #26952, though the test
+// was derived from another reported regression with the same cause.
+
+use std::marker::PhantomData;
+
+trait Trait<A> { fn foo(&self); }
+
+struct Type<A> { a: PhantomData<A> }
+
+fn as_trait<A>(t: &Type<A>) -> &dyn Trait<A> { loop { } }
+
+fn want<A,T:Trait<A>+?Sized>(t: &T) { }
+
+fn call<A>(p: Type<A>) {
+ let q = as_trait(&p);
+ want(q); // parameter A to `want` *would* be unconstrained
+}
+
+fn main() { }
diff --git a/tests/ui/traits/inherent-method-order.rs b/tests/ui/traits/inherent-method-order.rs
new file mode 100644
index 000000000..f632ae8a9
--- /dev/null
+++ b/tests/ui/traits/inherent-method-order.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+struct Foo;
+
+impl Foo {
+ #[allow(dead_code)]
+ fn foo(self) {
+ panic!("wrong method!")
+ }
+}
+
+trait Trait {
+ fn foo(self);
+}
+
+impl<'a,'b,'c> Trait for &'a &'b &'c Foo {
+ fn foo(self) {
+ // ok
+ }
+}
+
+fn main() {
+ let x = &(&(&Foo));
+ x.foo();
+}
diff --git a/tests/ui/traits/inheritance/auto-xc-2.rs b/tests/ui/traits/inheritance/auto-xc-2.rs
new file mode 100644
index 000000000..f2130228d
--- /dev/null
+++ b/tests/ui/traits/inheritance/auto-xc-2.rs
@@ -0,0 +1,23 @@
+// run-pass
+// aux-build:auto_xc_2.rs
+
+
+extern crate auto_xc_2 as aux;
+
+// aux defines impls of Foo, Bar and Baz for A
+use aux::{Foo, Bar, Baz, A};
+
+// We want to extend all Foo, Bar, Bazes to Quuxes
+pub trait Quux: Foo + Bar + Baz { }
+impl<T:Foo + Bar + Baz> Quux for T { }
+
+fn f<T:Quux>(a: &T) {
+ assert_eq!(a.f(), 10);
+ assert_eq!(a.g(), 20);
+ assert_eq!(a.h(), 30);
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ f(a);
+}
diff --git a/tests/ui/traits/inheritance/auto-xc.rs b/tests/ui/traits/inheritance/auto-xc.rs
new file mode 100644
index 000000000..3d5ae182a
--- /dev/null
+++ b/tests/ui/traits/inheritance/auto-xc.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(dead_code)]
+// aux-build:auto_xc.rs
+
+
+extern crate auto_xc as aux;
+
+use aux::{Foo, Bar, Baz, Quux};
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+impl Baz for A { fn h(&self) -> isize { 30 } }
+
+fn f<T:Quux>(a: &T) {
+ assert_eq!(a.f(), 10);
+ assert_eq!(a.g(), 20);
+ assert_eq!(a.h(), 30);
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ f(a);
+}
diff --git a/tests/ui/traits/inheritance/auto.rs b/tests/ui/traits/inheritance/auto.rs
new file mode 100644
index 000000000..0be67a55e
--- /dev/null
+++ b/tests/ui/traits/inheritance/auto.rs
@@ -0,0 +1,29 @@
+// run-pass
+#![allow(dead_code)]
+// Testing that this impl turns A into a Quux, because
+// A is already a Foo Bar Baz
+
+impl<T:Foo + Bar + Baz> Quux for T { }
+
+trait Foo { fn f(&self) -> isize; }
+trait Bar { fn g(&self) -> isize; }
+trait Baz { fn h(&self) -> isize; }
+
+trait Quux: Foo + Bar + Baz { }
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+impl Baz for A { fn h(&self) -> isize { 30 } }
+
+fn f<T:Quux>(a: &T) {
+ assert_eq!(a.f(), 10);
+ assert_eq!(a.g(), 20);
+ assert_eq!(a.h(), 30);
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ f(a);
+}
diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs
new file mode 100644
index 000000000..9af26cb2e
--- /dev/null
+++ b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs
@@ -0,0 +1,7 @@
+pub trait Foo { fn f(&self) -> isize; }
+pub trait Bar { fn g(&self) -> isize; }
+pub trait Baz { fn h(&self) -> isize; }
+
+pub trait Quux: Foo + Bar + Baz { }
+
+impl<T:Foo + Bar + Baz> Quux for T { }
diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs
new file mode 100644
index 000000000..e9327676d
--- /dev/null
+++ b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs
@@ -0,0 +1,9 @@
+pub trait Foo { fn f(&self) -> isize; }
+pub trait Bar { fn g(&self) -> isize; }
+pub trait Baz { fn h(&self) -> isize; }
+
+pub struct A { pub x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+impl Baz for A { fn h(&self) -> isize { 30 } }
diff --git a/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs
new file mode 100644
index 000000000..a25704412
--- /dev/null
+++ b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs
@@ -0,0 +1,38 @@
+use std::cmp::PartialEq;
+use std::ops::{Add, Sub, Mul};
+
+pub trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone {
+}
+
+#[derive(Clone, Debug)]
+pub struct MyInt {
+ pub val: isize
+}
+
+impl Add for MyInt {
+ type Output = MyInt;
+
+ fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) }
+}
+
+impl Sub for MyInt {
+ type Output = MyInt;
+
+ fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) }
+}
+
+impl Mul for MyInt {
+ type Output = MyInt;
+
+ fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) }
+}
+
+impl PartialEq for MyInt {
+ fn eq(&self, other: &MyInt) -> bool { self.val == other.val }
+
+ fn ne(&self, other: &MyInt) -> bool { !self.eq(other) }
+}
+
+impl MyNum for MyInt {}
+
+fn mi(v: isize) -> MyInt { MyInt { val: v } }
diff --git a/tests/ui/traits/inheritance/auxiliary/xc_call.rs b/tests/ui/traits/inheritance/auxiliary/xc_call.rs
new file mode 100644
index 000000000..b76c52e62
--- /dev/null
+++ b/tests/ui/traits/inheritance/auxiliary/xc_call.rs
@@ -0,0 +1,11 @@
+pub trait Foo {
+ fn f(&self) -> isize;
+}
+
+pub struct A {
+ pub x: isize
+}
+
+impl Foo for A {
+ fn f(&self) -> isize { 10 }
+}
diff --git a/tests/ui/traits/inheritance/basic.rs b/tests/ui/traits/inheritance/basic.rs
new file mode 100644
index 000000000..5bfa60b1a
--- /dev/null
+++ b/tests/ui/traits/inheritance/basic.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+
+trait Foo { fn f(&self) -> isize; }
+trait Bar { fn g(&self) -> isize; }
+trait Baz { fn h(&self) -> isize; }
+
+trait Quux: Foo + Bar + Baz { }
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+impl Baz for A { fn h(&self) -> isize { 30 } }
+impl Quux for A {}
+
+fn f<T:Quux + Foo + Bar + Baz>(a: &T) {
+ assert_eq!(a.f(), 10);
+ assert_eq!(a.g(), 20);
+ assert_eq!(a.h(), 30);
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ f(a);
+}
diff --git a/tests/ui/traits/inheritance/call-bound-inherited.rs b/tests/ui/traits/inheritance/call-bound-inherited.rs
new file mode 100644
index 000000000..37c2ff63c
--- /dev/null
+++ b/tests/ui/traits/inheritance/call-bound-inherited.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![allow(dead_code)]
+
+trait Foo { fn f(&self) -> isize; }
+trait Bar : Foo { fn g(&self) -> isize; }
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+
+// Call a function on Foo, given a T: Bar
+fn gg<T:Bar>(a: &T) -> isize {
+ a.f()
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ assert_eq!(gg(a), 10);
+}
diff --git a/tests/ui/traits/inheritance/call-bound-inherited2.rs b/tests/ui/traits/inheritance/call-bound-inherited2.rs
new file mode 100644
index 000000000..8576d29f2
--- /dev/null
+++ b/tests/ui/traits/inheritance/call-bound-inherited2.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+
+trait Foo { fn f(&self) -> isize; }
+trait Bar : Foo { fn g(&self) -> isize; }
+trait Baz : Bar { fn h(&self) -> isize; }
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+impl Baz for A { fn h(&self) -> isize { 30 } }
+
+// Call a function on Foo, given a T: Baz,
+// which is inherited via Bar
+fn gg<T:Baz>(a: &T) -> isize {
+ a.f()
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ assert_eq!(gg(a), 10);
+}
diff --git a/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs
new file mode 100644
index 000000000..25159c1ad
--- /dev/null
+++ b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs
@@ -0,0 +1,33 @@
+// run-pass
+#![allow(dead_code)]
+// Testing that we can cast to a subtrait and call subtrait
+// methods. Not testing supertrait methods
+
+
+trait Foo {
+ fn f(&self) -> isize;
+}
+
+trait Bar : Foo {
+ fn g(&self) -> isize;
+}
+
+struct A {
+ x: isize
+}
+
+impl Foo for A {
+ fn f(&self) -> isize { 10 }
+}
+
+impl Bar for A {
+ fn g(&self) -> isize { 20 }
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ let afoo = a as &dyn Foo;
+ let abar = a as &dyn Bar;
+ assert_eq!(afoo.f(), 10);
+ assert_eq!(abar.g(), 20);
+}
diff --git a/tests/ui/traits/inheritance/cast.rs b/tests/ui/traits/inheritance/cast.rs
new file mode 100644
index 000000000..9070b9d1f
--- /dev/null
+++ b/tests/ui/traits/inheritance/cast.rs
@@ -0,0 +1,33 @@
+// run-pass
+#![allow(dead_code)]
+// Testing that supertrait methods can be called on subtrait object types
+
+
+trait Foo {
+ fn f(&self) -> isize;
+}
+
+trait Bar : Foo {
+ fn g(&self) -> isize;
+}
+
+struct A {
+ x: isize
+}
+
+impl Foo for A {
+ fn f(&self) -> isize { 10 }
+}
+
+impl Bar for A {
+ fn g(&self) -> isize { 20 }
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ let afoo = a as &dyn Foo;
+ let abar = a as &dyn Bar;
+ assert_eq!(afoo.f(), 10);
+ assert_eq!(abar.g(), 20);
+ assert_eq!(abar.f(), 10);
+}
diff --git a/tests/ui/traits/inheritance/cross-trait-call-xc.rs b/tests/ui/traits/inheritance/cross-trait-call-xc.rs
new file mode 100644
index 000000000..99fbb5c61
--- /dev/null
+++ b/tests/ui/traits/inheritance/cross-trait-call-xc.rs
@@ -0,0 +1,20 @@
+// run-pass
+// aux-build:xc_call.rs
+
+
+extern crate xc_call as aux;
+
+use aux::Foo;
+
+trait Bar : Foo {
+ fn g(&self) -> isize;
+}
+
+impl Bar for aux::A {
+ fn g(&self) -> isize { self.f() }
+}
+
+pub fn main() {
+ let a = &aux::A { x: 3 };
+ assert_eq!(a.g(), 10);
+}
diff --git a/tests/ui/traits/inheritance/cross-trait-call.rs b/tests/ui/traits/inheritance/cross-trait-call.rs
new file mode 100644
index 000000000..512c928ca
--- /dev/null
+++ b/tests/ui/traits/inheritance/cross-trait-call.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(dead_code)]
+
+trait Foo { fn f(&self) -> isize; }
+trait Bar : Foo { fn g(&self) -> isize; }
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+
+impl Bar for A {
+ // Testing that this impl can call the impl of Foo
+ fn g(&self) -> isize { self.f() }
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ assert_eq!(a.g(), 10);
+}
diff --git a/tests/ui/traits/inheritance/diamond.rs b/tests/ui/traits/inheritance/diamond.rs
new file mode 100644
index 000000000..32ad0fb4d
--- /dev/null
+++ b/tests/ui/traits/inheritance/diamond.rs
@@ -0,0 +1,28 @@
+// run-pass
+#![allow(dead_code)]
+// B and C both require A, so D does as well, twice, but that's just fine
+
+
+trait A { fn a(&self) -> isize; }
+trait B: A { fn b(&self) -> isize; }
+trait C: A { fn c(&self) -> isize; }
+trait D: B + C { fn d(&self) -> isize; }
+
+struct S { bogus: () }
+
+impl A for S { fn a(&self) -> isize { 10 } }
+impl B for S { fn b(&self) -> isize { 20 } }
+impl C for S { fn c(&self) -> isize { 30 } }
+impl D for S { fn d(&self) -> isize { 40 } }
+
+fn f<T:D>(x: &T) {
+ assert_eq!(x.a(), 10);
+ assert_eq!(x.b(), 20);
+ assert_eq!(x.c(), 30);
+ assert_eq!(x.d(), 40);
+}
+
+pub fn main() {
+ let value = &S { bogus: () };
+ f(value);
+}
diff --git a/tests/ui/traits/inheritance/multiple-inheritors.rs b/tests/ui/traits/inheritance/multiple-inheritors.rs
new file mode 100644
index 000000000..77ecbd8eb
--- /dev/null
+++ b/tests/ui/traits/inheritance/multiple-inheritors.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+
+trait A { fn a(&self) -> isize; }
+trait B: A { fn b(&self) -> isize; }
+trait C: A { fn c(&self) -> isize; }
+
+struct S { bogus: () }
+
+impl A for S { fn a(&self) -> isize { 10 } }
+impl B for S { fn b(&self) -> isize { 20 } }
+impl C for S { fn c(&self) -> isize { 30 } }
+
+// Both B and C inherit from A
+fn f<T:B + C>(x: &T) {
+ assert_eq!(x.a(), 10);
+ assert_eq!(x.b(), 20);
+ assert_eq!(x.c(), 30);
+}
+
+pub fn main() {
+ f(&S { bogus: () })
+}
diff --git a/tests/ui/traits/inheritance/multiple-params.rs b/tests/ui/traits/inheritance/multiple-params.rs
new file mode 100644
index 000000000..8ff5ba541
--- /dev/null
+++ b/tests/ui/traits/inheritance/multiple-params.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+
+trait A { fn a(&self) -> isize; }
+trait B: A { fn b(&self) -> isize; }
+trait C: A { fn c(&self) -> isize; }
+
+struct S { bogus: () }
+
+impl A for S { fn a(&self) -> isize { 10 } }
+impl B for S { fn b(&self) -> isize { 20 } }
+impl C for S { fn c(&self) -> isize { 30 } }
+
+// Multiple type params, multiple levels of inheritance
+fn f<X:A,Y:B,Z:C>(x: &X, y: &Y, z: &Z) {
+ assert_eq!(x.a(), 10);
+ assert_eq!(y.a(), 10);
+ assert_eq!(y.b(), 20);
+ assert_eq!(z.a(), 10);
+ assert_eq!(z.c(), 30);
+}
+
+pub fn main() {
+ let s = &S { bogus: () };
+ f(s, s, s);
+}
diff --git a/tests/ui/traits/inheritance/num.rs b/tests/ui/traits/inheritance/num.rs
new file mode 100644
index 000000000..3d63d78ca
--- /dev/null
+++ b/tests/ui/traits/inheritance/num.rs
@@ -0,0 +1,13 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// pretty-expanded FIXME #23616
+
+pub trait NumExt: PartialEq + PartialOrd {}
+
+pub trait FloatExt: NumExt {}
+
+fn greater_than_one<T: NumExt>(n: &T) -> bool { loop {} }
+fn greater_than_one_float<T: FloatExt>(n: &T) -> bool { loop {} }
+
+pub fn main() {}
diff --git a/tests/ui/traits/inheritance/num0.rs b/tests/ui/traits/inheritance/num0.rs
new file mode 100644
index 000000000..cee52542d
--- /dev/null
+++ b/tests/ui/traits/inheritance/num0.rs
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(dead_code)]
+// Extending Num and using inherited static methods
+
+// pretty-expanded FIXME #23616
+
+use std::cmp::PartialOrd;
+
+pub trait NumCast: Sized {
+ fn from(i: i32) -> Option<Self>;
+}
+
+pub trait Num {
+ fn from_int(i: isize) -> Self;
+ fn gt(&self, other: &Self) -> bool;
+}
+
+pub trait NumExt: NumCast + PartialOrd { }
+
+fn greater_than_one<T:NumExt>(n: &T) -> bool {
+ n.gt(&NumCast::from(1).unwrap())
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/inheritance/num1.rs b/tests/ui/traits/inheritance/num1.rs
new file mode 100644
index 000000000..663dd3a5e
--- /dev/null
+++ b/tests/ui/traits/inheritance/num1.rs
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+pub trait NumCast: Sized {
+ fn from(i: i32) -> Option<Self>;
+}
+
+pub trait NumExt: NumCast + PartialOrd { }
+
+fn greater_than_one<T:NumExt>(n: &T) -> bool {
+ *n > NumCast::from(1).unwrap()
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/inheritance/num2.rs b/tests/ui/traits/inheritance/num2.rs
new file mode 100644
index 000000000..b713c66a3
--- /dev/null
+++ b/tests/ui/traits/inheritance/num2.rs
@@ -0,0 +1,86 @@
+// run-pass
+// A more complex example of numeric extensions
+
+pub trait TypeExt {}
+
+impl TypeExt for u8 {}
+impl TypeExt for u16 {}
+impl TypeExt for u32 {}
+impl TypeExt for u64 {}
+impl TypeExt for usize {}
+
+impl TypeExt for i8 {}
+impl TypeExt for i16 {}
+impl TypeExt for i32 {}
+impl TypeExt for i64 {}
+impl TypeExt for isize {}
+
+impl TypeExt for f32 {}
+impl TypeExt for f64 {}
+
+
+pub trait NumExt: TypeExt + PartialEq + PartialOrd {}
+
+impl NumExt for u8 {}
+impl NumExt for u16 {}
+impl NumExt for u32 {}
+impl NumExt for u64 {}
+impl NumExt for usize {}
+
+impl NumExt for i8 {}
+impl NumExt for i16 {}
+impl NumExt for i32 {}
+impl NumExt for i64 {}
+impl NumExt for isize {}
+
+impl NumExt for f32 {}
+impl NumExt for f64 {}
+
+
+pub trait UnSignedExt: NumExt {}
+
+impl UnSignedExt for u8 {}
+impl UnSignedExt for u16 {}
+impl UnSignedExt for u32 {}
+impl UnSignedExt for u64 {}
+impl UnSignedExt for usize {}
+
+
+pub trait SignedExt: NumExt {}
+
+impl SignedExt for i8 {}
+impl SignedExt for i16 {}
+impl SignedExt for i32 {}
+impl SignedExt for i64 {}
+impl SignedExt for isize {}
+
+impl SignedExt for f32 {}
+impl SignedExt for f64 {}
+
+
+pub trait IntegerExt: NumExt {}
+
+impl IntegerExt for u8 {}
+impl IntegerExt for u16 {}
+impl IntegerExt for u32 {}
+impl IntegerExt for u64 {}
+impl IntegerExt for usize {}
+
+impl IntegerExt for i8 {}
+impl IntegerExt for i16 {}
+impl IntegerExt for i32 {}
+impl IntegerExt for i64 {}
+impl IntegerExt for isize {}
+
+
+pub trait FloatExt: NumExt {}
+
+impl FloatExt for f32 {}
+impl FloatExt for f64 {}
+
+
+fn test_float_ext<T:FloatExt>(n: T) { println!("{}", n < n) }
+
+pub fn main() {
+ test_float_ext(1f32);
+}
diff --git a/tests/ui/traits/inheritance/num3.rs b/tests/ui/traits/inheritance/num3.rs
new file mode 100644
index 000000000..c40be6f83
--- /dev/null
+++ b/tests/ui/traits/inheritance/num3.rs
@@ -0,0 +1,19 @@
+// run-pass
+pub trait NumCast: Sized {
+ fn from(i: i32) -> Option<Self>;
+}
+
+pub trait NumExt: PartialEq + PartialOrd + NumCast {}
+
+impl NumExt for f32 {}
+impl NumCast for f32 {
+ fn from(i: i32) -> Option<f32> { Some(i as f32) }
+}
+
+fn num_eq_one<T: NumExt>(n: T) {
+ println!("{}", n == NumCast::from(1).unwrap())
+}
+
+pub fn main() {
+ num_eq_one(1f32); // you need to actually use the function to trigger the ICE
+}
diff --git a/tests/ui/traits/inheritance/num5.rs b/tests/ui/traits/inheritance/num5.rs
new file mode 100644
index 000000000..f478618f7
--- /dev/null
+++ b/tests/ui/traits/inheritance/num5.rs
@@ -0,0 +1,26 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub trait NumCast: Sized {
+ fn from(i: i32) -> Option<Self>;
+}
+
+pub trait NumExt: PartialEq + NumCast {}
+
+impl NumExt for f32 {}
+impl NumExt for isize {}
+
+impl NumCast for f32 {
+ fn from(i: i32) -> Option<f32> { Some(i as f32) }
+}
+impl NumCast for isize {
+ fn from(i: i32) -> Option<isize> { Some(i as isize) }
+}
+
+fn num_eq_one<T:NumExt>() -> T {
+ NumCast::from(1).unwrap()
+}
+
+pub fn main() {
+ num_eq_one::<isize>(); // you need to actually use the function to trigger the ICE
+}
diff --git a/tests/ui/traits/inheritance/overloading-simple.rs b/tests/ui/traits/inheritance/overloading-simple.rs
new file mode 100644
index 000000000..c306aa2cd
--- /dev/null
+++ b/tests/ui/traits/inheritance/overloading-simple.rs
@@ -0,0 +1,27 @@
+// run-pass
+#![allow(dead_code)]
+use std::cmp::PartialEq;
+
+trait MyNum : PartialEq { }
+
+#[derive(Debug)]
+struct MyInt { val: isize }
+
+impl PartialEq for MyInt {
+ fn eq(&self, other: &MyInt) -> bool { self.val == other.val }
+ fn ne(&self, other: &MyInt) -> bool { !self.eq(other) }
+}
+
+impl MyNum for MyInt {}
+
+fn f<T:MyNum>(x: T, y: T) -> bool {
+ return x == y;
+}
+
+fn mi(v: isize) -> MyInt { MyInt { val: v } }
+
+pub fn main() {
+ let (x, y, z) = (mi(3), mi(5), mi(3));
+ assert!(x != y);
+ assert_eq!(x, z);
+}
diff --git a/tests/ui/traits/inheritance/overloading-xc-exe.rs b/tests/ui/traits/inheritance/overloading-xc-exe.rs
new file mode 100644
index 000000000..08778061b
--- /dev/null
+++ b/tests/ui/traits/inheritance/overloading-xc-exe.rs
@@ -0,0 +1,20 @@
+// run-pass
+// aux-build:overloading_xc.rs
+
+
+extern crate overloading_xc;
+use overloading_xc::{MyNum, MyInt};
+
+fn f<T:MyNum>(x: T, y: T) -> (T, T, T) {
+ return (x.clone() + y.clone(), x.clone() - y.clone(), x * y);
+}
+
+fn mi(v: isize) -> MyInt { MyInt { val: v } }
+
+pub fn main() {
+ let (x, y) = (mi(3), mi(5));
+ let (a, b, c) = f(x, y);
+ assert_eq!(a, mi(8));
+ assert_eq!(b, mi(-2));
+ assert_eq!(c, mi(15));
+}
diff --git a/tests/ui/traits/inheritance/overloading.rs b/tests/ui/traits/inheritance/overloading.rs
new file mode 100644
index 000000000..083643e82
--- /dev/null
+++ b/tests/ui/traits/inheritance/overloading.rs
@@ -0,0 +1,47 @@
+// run-pass
+use std::cmp::PartialEq;
+use std::ops::{Add, Sub, Mul};
+
+trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone { }
+
+#[derive(Clone, Debug)]
+struct MyInt { val: isize }
+
+impl Add for MyInt {
+ type Output = MyInt;
+
+ fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) }
+}
+
+impl Sub for MyInt {
+ type Output = MyInt;
+
+ fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) }
+}
+
+impl Mul for MyInt {
+ type Output = MyInt;
+
+ fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) }
+}
+
+impl PartialEq for MyInt {
+ fn eq(&self, other: &MyInt) -> bool { self.val == other.val }
+ fn ne(&self, other: &MyInt) -> bool { !self.eq(other) }
+}
+
+impl MyNum for MyInt {}
+
+fn f<T:MyNum>(x: T, y: T) -> (T, T, T) {
+ return (x.clone() + y.clone(), x.clone() - y.clone(), x * y);
+}
+
+fn mi(v: isize) -> MyInt { MyInt { val: v } }
+
+pub fn main() {
+ let (x, y) = (mi(3), mi(5));
+ let (a, b, c) = f(x, y);
+ assert_eq!(a, mi(8));
+ assert_eq!(b, mi(-2));
+ assert_eq!(c, mi(15));
+}
diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs
new file mode 100644
index 000000000..727897d20
--- /dev/null
+++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs
@@ -0,0 +1,43 @@
+// Test a case of a trait which extends the same supertrait twice, but
+// with difference type parameters. Test then that when we don't give
+// enough information to pick between these, no selection is made. In
+// this particular case, the two choices are i64/u64 -- so when we use
+// an integer literal, we wind up falling this literal back to i32.
+// See also `run-pass/trait-repeated-supertrait.rs`.
+
+trait CompareTo<T> {
+ fn same_as(&self, t: T) -> bool;
+}
+
+trait CompareToInts : CompareTo<i64> + CompareTo<u64> {
+}
+
+impl CompareTo<i64> for i64 {
+ fn same_as(&self, t: i64) -> bool { *self == t }
+}
+
+impl CompareTo<u64> for i64 {
+ fn same_as(&self, t: u64) -> bool { *self == (t as i64) }
+}
+
+impl CompareToInts for i64 { }
+
+fn with_obj(c: &dyn CompareToInts) -> bool {
+ c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
+}
+
+fn with_trait<C:CompareToInts>(c: &C) -> bool {
+ c.same_as(22) //~ ERROR `C: CompareTo<i32>` is not satisfied
+}
+
+fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
+ <dyn CompareToInts>::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfi
+}
+
+fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {
+ CompareTo::same_as(c, 22) //~ ERROR `C: CompareTo<i32>` is not satisfied
+}
+
+fn main() {
+ assert_eq!(22_i64.same_as(22), true); //~ ERROR `i64: CompareTo<i32>` is not satisfied
+}
diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
new file mode 100644
index 000000000..656e0d0bf
--- /dev/null
+++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
@@ -0,0 +1,65 @@
+error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
+ --> $DIR/repeated-supertrait-ambig.rs:26:15
+ |
+LL | c.same_as(22)
+ | ------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `CompareTo<T>`:
+ <i64 as CompareTo<i64>>
+ <i64 as CompareTo<u64>>
+
+error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
+ --> $DIR/repeated-supertrait-ambig.rs:30:15
+ |
+LL | c.same_as(22)
+ | ------- ^^ the trait `CompareTo<i32>` is not implemented for `C`
+ | |
+ | required by a bound introduced by this call
+ |
+help: consider further restricting this bound
+ |
+LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
+ | ++++++++++++++++
+
+error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
+ --> $DIR/repeated-supertrait-ambig.rs:34:37
+ |
+LL | <dyn CompareToInts>::same_as(c, 22)
+ | ---------------------------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `CompareTo<T>`:
+ <i64 as CompareTo<i64>>
+ <i64 as CompareTo<u64>>
+
+error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
+ --> $DIR/repeated-supertrait-ambig.rs:38:27
+ |
+LL | CompareTo::same_as(c, 22)
+ | ------------------ ^^ the trait `CompareTo<i32>` is not implemented for `C`
+ | |
+ | required by a bound introduced by this call
+ |
+help: consider further restricting this bound
+ |
+LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
+ | ++++++++++++++++
+
+error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied
+ --> $DIR/repeated-supertrait-ambig.rs:42:31
+ |
+LL | assert_eq!(22_i64.same_as(22), true);
+ | ------- ^^ the trait `CompareTo<i32>` is not implemented for `i64`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `CompareTo<T>`:
+ <i64 as CompareTo<i64>>
+ <i64 as CompareTo<u64>>
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/inheritance/repeated-supertrait.rs b/tests/ui/traits/inheritance/repeated-supertrait.rs
new file mode 100644
index 000000000..cb2581ffa
--- /dev/null
+++ b/tests/ui/traits/inheritance/repeated-supertrait.rs
@@ -0,0 +1,48 @@
+// run-pass
+// Test a case of a trait which extends the same supertrait twice, but
+// with difference type parameters. Test that we can invoke the
+// various methods in various ways successfully.
+// See also `ui/traits/trait-repeated-supertrait-ambig.rs`.
+
+
+trait CompareTo<T> {
+ fn same_as(&self, t: T) -> bool;
+}
+
+trait CompareToInts : CompareTo<i64> + CompareTo<u64> {
+}
+
+impl CompareTo<i64> for i64 {
+ fn same_as(&self, t: i64) -> bool { *self == t }
+}
+
+impl CompareTo<u64> for i64 {
+ fn same_as(&self, t: u64) -> bool { *self == (t as i64) }
+}
+
+impl CompareToInts for i64 { }
+
+fn with_obj(c: &dyn CompareToInts) -> bool {
+ c.same_as(22_i64) && c.same_as(22_u64)
+}
+
+fn with_trait<C:CompareToInts>(c: &C) -> bool {
+ c.same_as(22_i64) && c.same_as(22_u64)
+}
+
+fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
+ <dyn CompareToInts>::same_as(c, 22_i64) && <dyn CompareToInts>::same_as(c, 22_u64)
+}
+
+fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {
+ CompareTo::same_as(c, 22_i64) && CompareTo::same_as(c, 22_u64)
+}
+
+fn main() {
+ assert_eq!(22_i64.same_as(22_i64), true);
+ assert_eq!(22_i64.same_as(22_u64), true);
+ assert_eq!(with_trait(&22), true);
+ assert_eq!(with_obj(&22), true);
+ assert_eq!(with_ufcs1(&22), true);
+ assert_eq!(with_ufcs2(&22), true);
+}
diff --git a/tests/ui/traits/inheritance/self-in-supertype.rs b/tests/ui/traits/inheritance/self-in-supertype.rs
new file mode 100644
index 000000000..e8a2bd791
--- /dev/null
+++ b/tests/ui/traits/inheritance/self-in-supertype.rs
@@ -0,0 +1,62 @@
+// run-pass
+// Test for issue #4183: use of Self in supertraits.
+
+pub static FUZZY_EPSILON: f64 = 0.1;
+
+pub trait FuzzyEq<Eps> {
+ fn fuzzy_eq(&self, other: &Self) -> bool;
+ fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
+}
+
+trait Float: Sized+FuzzyEq<Self> {
+ fn two_pi() -> Self;
+}
+
+impl FuzzyEq<f32> for f32 {
+ fn fuzzy_eq(&self, other: &f32) -> bool {
+ self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32))
+ }
+
+ fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool {
+ (*self - *other).abs() < *epsilon
+ }
+}
+
+impl Float for f32 {
+ fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 }
+}
+
+impl FuzzyEq<f64> for f64 {
+ fn fuzzy_eq(&self, other: &f64) -> bool {
+ self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64))
+ }
+
+ fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool {
+ (*self - *other).abs() < *epsilon
+ }
+}
+
+impl Float for f64 {
+ fn two_pi() -> f64 { 6.28318530717958647692528676655900576_f64 }
+}
+
+fn compare<F:Float>(f1: F) -> bool {
+ let f2 = Float::two_pi();
+ f1.fuzzy_eq(&f2)
+}
+
+pub fn main() {
+ assert!(compare::<f32>(6.28318530717958647692528676655900576));
+ assert!(compare::<f32>(6.29));
+ assert!(compare::<f32>(6.3));
+ assert!(compare::<f32>(6.19));
+ assert!(!compare::<f32>(7.28318530717958647692528676655900576));
+ assert!(!compare::<f32>(6.18));
+
+ assert!(compare::<f64>(6.28318530717958647692528676655900576));
+ assert!(compare::<f64>(6.29));
+ assert!(compare::<f64>(6.3));
+ assert!(compare::<f64>(6.19));
+ assert!(!compare::<f64>(7.28318530717958647692528676655900576));
+ assert!(!compare::<f64>(6.18));
+}
diff --git a/tests/ui/traits/inheritance/self.rs b/tests/ui/traits/inheritance/self.rs
new file mode 100644
index 000000000..5f2559f48
--- /dev/null
+++ b/tests/ui/traits/inheritance/self.rs
@@ -0,0 +1,29 @@
+// run-pass
+trait Foo<T> {
+ fn f(&self, x: &T);
+}
+
+trait Bar : Sized + Foo<Self> {
+ fn g(&self);
+}
+
+struct S {
+ x: isize
+}
+
+impl Foo<S> for S {
+ fn f(&self, x: &S) {
+ println!("{}", x.x);
+ }
+}
+
+impl Bar for S {
+ fn g(&self) {
+ self.f(self);
+ }
+}
+
+pub fn main() {
+ let s = S { x: 1 };
+ s.g();
+}
diff --git a/tests/ui/traits/inheritance/simple.rs b/tests/ui/traits/inheritance/simple.rs
new file mode 100644
index 000000000..ca3a284e5
--- /dev/null
+++ b/tests/ui/traits/inheritance/simple.rs
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(dead_code)]
+
+trait Foo { fn f(&self) -> isize; }
+trait Bar : Foo { fn g(&self) -> isize; }
+
+struct A { x: isize }
+
+impl Foo for A { fn f(&self) -> isize { 10 } }
+impl Bar for A { fn g(&self) -> isize { 20 } }
+
+fn ff<T:Foo>(a: &T) -> isize {
+ a.f()
+}
+
+fn gg<T:Bar>(a: &T) -> isize {
+ a.g()
+}
+
+pub fn main() {
+ let a = &A { x: 3 };
+ assert_eq!(ff(a), 10);
+ assert_eq!(gg(a), 20);
+}
diff --git a/tests/ui/traits/inheritance/static.rs b/tests/ui/traits/inheritance/static.rs
new file mode 100644
index 000000000..16218fbd2
--- /dev/null
+++ b/tests/ui/traits/inheritance/static.rs
@@ -0,0 +1,26 @@
+// run-pass
+
+pub trait MyNum {
+ fn from_int(_: isize) -> Self;
+}
+
+pub trait NumExt: MyNum { }
+
+struct S { v: isize }
+
+impl MyNum for S {
+ fn from_int(i: isize) -> S {
+ S {
+ v: i
+ }
+ }
+}
+
+impl NumExt for S { }
+
+fn greater_than_one<T:NumExt>() -> T { MyNum::from_int(1) }
+
+pub fn main() {
+ let v: S = greater_than_one();
+ assert_eq!(v.v, 1);
+}
diff --git a/tests/ui/traits/inheritance/static2.rs b/tests/ui/traits/inheritance/static2.rs
new file mode 100644
index 000000000..bc78e1e23
--- /dev/null
+++ b/tests/ui/traits/inheritance/static2.rs
@@ -0,0 +1,29 @@
+// run-pass
+pub trait MyEq {}
+
+pub trait MyNum {
+ fn from_int(_: isize) -> Self;
+}
+
+pub trait NumExt: MyEq + MyNum { }
+
+struct S { v: isize }
+
+impl MyEq for S { }
+
+impl MyNum for S {
+ fn from_int(i: isize) -> S {
+ S {
+ v: i
+ }
+ }
+}
+
+impl NumExt for S { }
+
+fn greater_than_one<T:NumExt>() -> T { MyNum::from_int(1) }
+
+pub fn main() {
+ let v: S = greater_than_one();
+ assert_eq!(v.v, 1);
+}
diff --git a/tests/ui/traits/inheritance/subst.rs b/tests/ui/traits/inheritance/subst.rs
new file mode 100644
index 000000000..b2b650366
--- /dev/null
+++ b/tests/ui/traits/inheritance/subst.rs
@@ -0,0 +1,27 @@
+// run-pass
+
+pub trait Add<RHS,Result> {
+ fn add(&self, rhs: &RHS) -> Result;
+}
+
+trait MyNum : Sized + Add<Self,Self> { }
+
+struct MyInt { val: isize }
+
+impl Add<MyInt, MyInt> for MyInt {
+ fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) }
+}
+
+impl MyNum for MyInt {}
+
+fn f<T:MyNum>(x: T, y: T) -> T {
+ return x.add(&y);
+}
+
+fn mi(v: isize) -> MyInt { MyInt { val: v } }
+
+pub fn main() {
+ let (x, y) = (mi(3), mi(5));
+ let z = f(x, y);
+ assert_eq!(z.val, 8)
+}
diff --git a/tests/ui/traits/inheritance/subst2.rs b/tests/ui/traits/inheritance/subst2.rs
new file mode 100644
index 000000000..ccc9628c7
--- /dev/null
+++ b/tests/ui/traits/inheritance/subst2.rs
@@ -0,0 +1,37 @@
+// run-pass
+
+trait Panda<T> {
+ fn chomp(&self, bamboo: &T) -> T;
+}
+
+trait Add<RHS,Result>: Panda<RHS> {
+ fn add(&self, rhs: &RHS) -> Result;
+}
+
+trait MyNum : Sized + Add<Self,Self> { }
+
+struct MyInt { val: isize }
+
+impl Panda<MyInt> for MyInt {
+ fn chomp(&self, bamboo: &MyInt) -> MyInt {
+ mi(self.val + bamboo.val)
+ }
+}
+
+impl Add<MyInt, MyInt> for MyInt {
+ fn add(&self, other: &MyInt) -> MyInt { self.chomp(other) }
+}
+
+impl MyNum for MyInt {}
+
+fn f<T:MyNum>(x: T, y: T) -> T {
+ return x.add(&y).chomp(&y);
+}
+
+fn mi(v: isize) -> MyInt { MyInt { val: v } }
+
+pub fn main() {
+ let (x, y) = (mi(3), mi(5));
+ let z = f(x, y);
+ assert_eq!(z.val, 13);
+}
diff --git a/tests/ui/traits/inheritance/visibility.rs b/tests/ui/traits/inheritance/visibility.rs
new file mode 100644
index 000000000..6ad864926
--- /dev/null
+++ b/tests/ui/traits/inheritance/visibility.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+mod traits {
+ pub trait Foo { fn f(&self) -> isize; }
+
+ impl Foo for isize { fn f(&self) -> isize { 10 } }
+}
+
+trait Quux: traits::Foo { }
+impl<T:traits::Foo> Quux for T { }
+
+// Foo is not in scope but because Quux is we can still access
+// Foo's methods on a Quux bound typaram
+fn f<T:Quux>(x: &T) {
+ assert_eq!(x.f(), 10);
+}
+
+pub fn main() {
+ f(&0)
+}
diff --git a/tests/ui/traits/invalid_operator_trait.rs b/tests/ui/traits/invalid_operator_trait.rs
new file mode 100644
index 000000000..7ea3b0d5b
--- /dev/null
+++ b/tests/ui/traits/invalid_operator_trait.rs
@@ -0,0 +1,23 @@
+#![crate_type = "lib"]
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+
+#[lang="sized"]
+pub trait Sized {
+ // Empty.
+}
+
+#[lang = "add"]
+trait Add<RHS=Self> {
+ type Output;
+
+ fn add<Y>(self, _: RHS) -> Self::Output;
+ //~^ ERROR `add` must not have any generic parameters
+}
+
+#[allow(unreachable_code)]
+fn ice(a: usize) {
+ let r = loop {};
+ r = r + a;
+}
diff --git a/tests/ui/traits/invalid_operator_trait.stderr b/tests/ui/traits/invalid_operator_trait.stderr
new file mode 100644
index 000000000..8c6e36959
--- /dev/null
+++ b/tests/ui/traits/invalid_operator_trait.stderr
@@ -0,0 +1,8 @@
+error: `add` must not have any generic parameters
+ --> $DIR/invalid_operator_trait.rs:15:5
+ |
+LL | fn add<Y>(self, _: RHS) -> Self::Output;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/issue-102989.rs b/tests/ui/traits/issue-102989.rs
new file mode 100644
index 000000000..216cd78e5
--- /dev/null
+++ b/tests/ui/traits/issue-102989.rs
@@ -0,0 +1,14 @@
+// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib"
+
+#![feature(lang_items)]
+#[lang="sized"]
+trait Sized { } //~ ERROR found duplicate lang item `sized`
+
+fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ //~^ ERROR `self` parameter is only allowed in associated functions
+ //~| ERROR cannot find type `Struct` in this scope
+ let x = x << 1;
+ //~^ ERROR cannot find value `x` in this scope
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-102989.stderr b/tests/ui/traits/issue-102989.stderr
new file mode 100644
index 000000000..7d0098fe8
--- /dev/null
+++ b/tests/ui/traits/issue-102989.stderr
@@ -0,0 +1,34 @@
+error: `self` parameter is only allowed in associated functions
+ --> $DIR/issue-102989.rs:7:15
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ^^^^ not semantically valid as function parameter
+ |
+ = note: associated functions are those in `impl` or `trait` definitions
+
+error[E0412]: cannot find type `Struct` in this scope
+ --> $DIR/issue-102989.rs:7:22
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-102989.rs:10:13
+ |
+LL | let x = x << 1;
+ | ^ help: a local variable with a similar name exists: `f`
+
+error[E0152]: found duplicate lang item `sized`
+ --> $DIR/issue-102989.rs:5:1
+ |
+LL | trait Sized { }
+ | ^^^^^^^^^^^
+ |
+ = note: the lang item is first defined in crate `core` (which `std` depends on)
+ = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib
+ = note: second definition in the local crate (`issue_102989`)
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0152, E0412, E0425.
+For more information about an error, try `rustc --explain E0152`.
diff --git a/tests/ui/traits/issue-104322.rs b/tests/ui/traits/issue-104322.rs
new file mode 100644
index 000000000..dcc27f1f0
--- /dev/null
+++ b/tests/ui/traits/issue-104322.rs
@@ -0,0 +1,80 @@
+// build-pass
+//
+// Tests that overflows do not occur in certain situations
+// related to generic diesel code
+
+use mini_diesel::*;
+
+pub trait HandleDelete<K> {}
+
+pub fn handle_delete<D, R>()
+where
+ R: HasTable,
+ R::Table: HandleDelete<D> + 'static,
+{
+}
+
+impl<K, T> HandleDelete<K> for T
+where
+ T: Table + HasTable<Table = T> + 'static,
+ K: 'static,
+ &'static K: Identifiable<Table = T>,
+ T::PrimaryKey: EqAll<<&'static K as Identifiable>::Id>,
+ T::Query: FilterDsl<<T::PrimaryKey as EqAll<<&'static K as Identifiable>::Id>>::Output>,
+ Filter<T::Query, <T::PrimaryKey as EqAll<<&'static K as Identifiable>::Id>>::Output>:
+ IntoUpdateTarget<Table = T>,
+{
+}
+
+mod mini_diesel {
+ pub trait HasTable {
+ type Table: Table;
+ }
+
+ pub trait Identifiable: HasTable {
+ type Id;
+ }
+
+ pub trait EqAll<Rhs> {
+ type Output;
+ }
+
+ pub trait IntoUpdateTarget: HasTable {
+ type WhereClause;
+ }
+
+ pub trait Query {
+ type SqlType;
+ }
+
+ pub trait AsQuery {
+ type Query: Query;
+ }
+ impl<T: Query> AsQuery for T {
+ type Query = Self;
+ }
+
+ pub trait FilterDsl<Predicate> {
+ type Output;
+ }
+
+ impl<T, Predicate> FilterDsl<Predicate> for T
+ where
+ T: Table,
+ T::Query: FilterDsl<Predicate>,
+ {
+ type Output = Filter<T::Query, Predicate>;
+ }
+
+ pub trait QuerySource {
+ type FromClause;
+ }
+
+ pub trait Table: QuerySource + AsQuery + Sized {
+ type PrimaryKey;
+ }
+
+ pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs
new file mode 100644
index 000000000..7064a39d2
--- /dev/null
+++ b/tests/ui/traits/issue-106072.rs
@@ -0,0 +1,5 @@
+#[derive(Clone)] //~ trait objects must include the `dyn` keyword
+ //~| trait objects must include the `dyn` keyword
+struct Foo;
+trait Foo {} //~ the name `Foo` is defined multiple times
+fn main() {}
diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr
new file mode 100644
index 000000000..f9b7b8146
--- /dev/null
+++ b/tests/ui/traits/issue-106072.stderr
@@ -0,0 +1,30 @@
+error[E0428]: the name `Foo` is defined multiple times
+ --> $DIR/issue-106072.rs:4:1
+ |
+LL | struct Foo;
+ | ----------- previous definition of the type `Foo` here
+LL | trait Foo {}
+ | ^^^^^^^^^ `Foo` redefined here
+ |
+ = note: `Foo` must be defined only once in the type namespace of this module
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/issue-106072.rs:1:10
+ |
+LL | #[derive(Clone)]
+ | ^^^^^
+ |
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/issue-106072.rs:1:10
+ |
+LL | #[derive(Clone)]
+ | ^^^^^
+ |
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0428, E0782.
+For more information about an error, try `rustc --explain E0428`.
diff --git a/tests/ui/traits/issue-18400.rs b/tests/ui/traits/issue-18400.rs
new file mode 100644
index 000000000..fdd11512d
--- /dev/null
+++ b/tests/ui/traits/issue-18400.rs
@@ -0,0 +1,26 @@
+trait Set<T> {
+ fn contains(&self, _: T) -> bool;
+ fn set(&mut self, _: T);
+}
+
+impl<'a, T, S> Set<&'a [T]> for S where
+ T: Copy,
+ S: Set<T>,
+{
+ fn contains(&self, bits: &[T]) -> bool {
+ bits.iter().all(|&bit| self.contains(bit))
+ }
+
+ fn set(&mut self, bits: &[T]) {
+ for &bit in bits {
+ self.set(bit)
+ }
+ }
+}
+
+fn main() {
+ let bits: &[_] = &[0, 1];
+
+ 0.contains(bits);
+ //~^ ERROR overflow
+}
diff --git a/tests/ui/traits/issue-18400.stderr b/tests/ui/traits/issue-18400.stderr
new file mode 100644
index 000000000..edaf08f49
--- /dev/null
+++ b/tests/ui/traits/issue-18400.stderr
@@ -0,0 +1,20 @@
+error[E0275]: overflow evaluating the requirement `_: Sized`
+ --> $DIR/issue-18400.rs:24:7
+ |
+LL | 0.contains(bits);
+ | ^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_18400`)
+note: required for `{integer}` to implement `Set<&[_]>`
+ --> $DIR/issue-18400.rs:6:16
+ |
+LL | impl<'a, T, S> Set<&'a [T]> for S where
+ | - ^^^^^^^^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 128 redundant requirements hidden
+ = note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/issue-18412.rs b/tests/ui/traits/issue-18412.rs
new file mode 100644
index 000000000..fe1cfb3df
--- /dev/null
+++ b/tests/ui/traits/issue-18412.rs
@@ -0,0 +1,26 @@
+// run-pass
+// Test that non-static methods can be assigned to local variables as
+// function pointers.
+
+
+trait Foo {
+ fn foo(&self) -> usize;
+}
+
+struct A(usize);
+
+impl A {
+ fn bar(&self) -> usize { self.0 }
+}
+
+impl Foo for A {
+ fn foo(&self) -> usize { self.bar() }
+}
+
+fn main() {
+ let f = A::bar;
+ let g = Foo::foo;
+ let a = A(42);
+
+ assert_eq!(f(&a), g(&a));
+}
diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs
new file mode 100644
index 000000000..1cb2d8c73
--- /dev/null
+++ b/tests/ui/traits/issue-20692.rs
@@ -0,0 +1,11 @@
+trait Array: Sized + Copy {}
+
+fn f<T: Array>(x: &T) {
+ let _ = x
+ //~^ ERROR `Array` cannot be made into an object
+ as
+ &dyn Array;
+ //~^ ERROR `Array` cannot be made into an object
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr
new file mode 100644
index 000000000..2028994cd
--- /dev/null
+++ b/tests/ui/traits/issue-20692.stderr
@@ -0,0 +1,35 @@
+error[E0038]: the trait `Array` cannot be made into an object
+ --> $DIR/issue-20692.rs:7:5
+ |
+LL | &dyn Array;
+ | ^^^^^^^^^^ `Array` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-20692.rs:1:14
+ |
+LL | trait Array: Sized + Copy {}
+ | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized`
+ | | |
+ | | ...because it requires `Self: Sized`
+ | this trait cannot be made into an object...
+
+error[E0038]: the trait `Array` cannot be made into an object
+ --> $DIR/issue-20692.rs:4:13
+ |
+LL | let _ = x
+ | ^ `Array` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-20692.rs:1:14
+ |
+LL | trait Array: Sized + Copy {}
+ | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized`
+ | | |
+ | | ...because it requires `Self: Sized`
+ | this trait cannot be made into an object...
+ = note: required for `&T` to implement `CoerceUnsized<&dyn Array>`
+ = note: required by cast to type `&dyn Array`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/issue-22019.rs b/tests/ui/traits/issue-22019.rs
new file mode 100644
index 000000000..1a887f0f3
--- /dev/null
+++ b/tests/ui/traits/issue-22019.rs
@@ -0,0 +1,34 @@
+// run-pass
+// Test an issue where global caching was causing free regions from
+// distinct scopes to be compared (`'g` and `'h`). The only important
+// thing is that compilation succeeds here.
+
+// pretty-expanded FIXME #23616
+
+#![allow(missing_copy_implementations)]
+#![allow(unused_variables)]
+
+use std::borrow::ToOwned;
+
+pub struct CFGNode;
+
+pub type Node<'a> = &'a CFGNode;
+
+pub trait GraphWalk<'c, N> {
+ /// Returns all the nodes in this graph.
+ fn nodes(&'c self) where [N]:ToOwned<Owned=Vec<N>>;
+}
+
+impl<'g> GraphWalk<'g, Node<'g>> for u32
+{
+ fn nodes(&'g self) where [Node<'g>]:ToOwned<Owned=Vec<Node<'g>>>
+ { loop { } }
+}
+
+impl<'h> GraphWalk<'h, Node<'h>> for u64
+{
+ fn nodes(&'h self) where [Node<'h>]:ToOwned<Owned=Vec<Node<'h>>>
+ { loop { } }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/issue-22110.rs b/tests/ui/traits/issue-22110.rs
new file mode 100644
index 000000000..bdbfee799
--- /dev/null
+++ b/tests/ui/traits/issue-22110.rs
@@ -0,0 +1,27 @@
+// run-pass
+// Test an issue where we reported ambiguity between the where-clause
+// and the blanket impl. The only important thing is that compilation
+// succeeds here. Issue #22110.
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+trait Foo<A> {
+ fn foo(&self, a: A);
+}
+
+impl<A,F:Fn(A)> Foo<A> for F {
+ fn foo(&self, _: A) { }
+}
+
+fn baz<A,F:for<'a> Foo<(&'a A,)>>(_: F) { }
+
+fn components<T,A>(t: fn(&A))
+ where fn(&A) : for<'a> Foo<(&'a A,)>,
+{
+ baz(t)
+}
+
+fn main() {
+}
diff --git a/tests/ui/traits/issue-22655.rs b/tests/ui/traits/issue-22655.rs
new file mode 100644
index 000000000..bc08ca0a2
--- /dev/null
+++ b/tests/ui/traits/issue-22655.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+// Regression test for issue #22655: This test should not lead to
+// infinite recursion.
+
+// pretty-expanded FIXME #23616
+
+unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
+
+pub struct Unique<T:?Sized> {
+ pointer: *const T,
+}
+
+pub struct Node<V> {
+ vals: V,
+ edges: Unique<Node<V>>,
+}
+
+fn is_send<T: Send>() {}
+
+fn main() {
+ is_send::<Node<&'static ()>>();
+}
diff --git a/tests/ui/traits/issue-23003-overflow.rs b/tests/ui/traits/issue-23003-overflow.rs
new file mode 100644
index 000000000..c5f471f23
--- /dev/null
+++ b/tests/ui/traits/issue-23003-overflow.rs
@@ -0,0 +1,29 @@
+// A variant of traits-issue-23003 in which an infinite series of
+// types are required. This test now just compiles fine, since the
+// relevant rules that triggered the overflow were removed.
+
+// check-pass
+#![allow(dead_code)]
+
+use std::marker::PhantomData;
+
+trait Async {
+ type Cancel;
+}
+
+struct Receipt<A:Async> {
+ marker: PhantomData<A>,
+}
+
+struct Complete<B> {
+ core: Option<B>,
+}
+
+impl<B> Async for Complete<B> {
+ type Cancel = Receipt<Complete<Option<B>>>;
+}
+
+fn foo(_: Receipt<Complete<()>>) { }
+
+
+fn main() { }
diff --git a/tests/ui/traits/issue-23003.rs b/tests/ui/traits/issue-23003.rs
new file mode 100644
index 000000000..24c2b2ad6
--- /dev/null
+++ b/tests/ui/traits/issue-23003.rs
@@ -0,0 +1,32 @@
+// run-pass
+// Test stack overflow triggered by evaluating the implications. To be
+// WF, the type `Receipt<Complete>` would require that `<Complete as
+// Async>::Cancel` be WF. This normalizes to `Receipt<Complete>`
+// again, leading to an infinite cycle. Issue #23003.
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+use std::marker::PhantomData;
+
+trait Async {
+ type Cancel;
+}
+
+struct Receipt<A:Async> {
+ marker: PhantomData<A>,
+}
+
+struct Complete {
+ core: Option<()>,
+}
+
+impl Async for Complete {
+ type Cancel = Receipt<Complete>;
+}
+
+fn foo(r: Receipt<Complete>) { }
+
+fn main() { }
diff --git a/tests/ui/traits/issue-23825.rs b/tests/ui/traits/issue-23825.rs
new file mode 100644
index 000000000..a9f0095d2
--- /dev/null
+++ b/tests/ui/traits/issue-23825.rs
@@ -0,0 +1,21 @@
+// run-pass
+trait Stringify {
+ fn to_string(&self) -> String;
+}
+
+impl Stringify for u32 {
+ fn to_string(&self) -> String { format!("u32: {}", *self) }
+}
+
+impl Stringify for f32 {
+ fn to_string(&self) -> String { format!("f32: {}", *self) }
+}
+
+fn print<T: Stringify>(x: T) -> String {
+ x.to_string()
+}
+
+fn main() {
+ assert_eq!(&print(5), "u32: 5");
+ assert_eq!(&print(5.0), "f32: 5");
+}
diff --git a/tests/ui/traits/issue-24010.rs b/tests/ui/traits/issue-24010.rs
new file mode 100644
index 000000000..f18185334
--- /dev/null
+++ b/tests/ui/traits/issue-24010.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+trait Foo: Fn(i32) -> i32 + Send {}
+
+impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
+
+fn wants_foo(f: Box<dyn Foo>) -> i32 {
+ f(42)
+}
+
+fn main() {
+ let f = Box::new(|x| x);
+ assert_eq!(wants_foo(f), 42);
+}
diff --git a/tests/ui/traits/issue-26339.rs b/tests/ui/traits/issue-26339.rs
new file mode 100644
index 000000000..bedd87cc4
--- /dev/null
+++ b/tests/ui/traits/issue-26339.rs
@@ -0,0 +1,31 @@
+// run-pass
+// Test that the right implementation is called through a trait
+// object when supertraits include multiple references to the
+// same trait, with different type parameters.
+
+trait A: PartialEq<Foo> + PartialEq<Bar> { }
+
+struct Foo;
+struct Bar;
+
+struct Aimpl;
+
+impl PartialEq<Foo> for Aimpl {
+ fn eq(&self, _rhs: &Foo) -> bool {
+ true
+ }
+}
+
+impl PartialEq<Bar> for Aimpl {
+ fn eq(&self, _rhs: &Bar) -> bool {
+ false
+ }
+}
+
+impl A for Aimpl { }
+
+fn main() {
+ let a = &Aimpl as &dyn A;
+
+ assert!(*a == Foo);
+}
diff --git a/tests/ui/traits/issue-28576.rs b/tests/ui/traits/issue-28576.rs
new file mode 100644
index 000000000..972c839b6
--- /dev/null
+++ b/tests/ui/traits/issue-28576.rs
@@ -0,0 +1,12 @@
+pub trait Foo<RHS=Self> {
+ type Assoc;
+}
+
+pub trait Bar: Foo<Assoc=()> {
+ fn new(&self, b: &
+ dyn Bar //~ ERROR the trait `Bar` cannot be made into an object
+ <Assoc=()>
+ );
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr
new file mode 100644
index 000000000..203cd0630
--- /dev/null
+++ b/tests/ui/traits/issue-28576.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+ --> $DIR/issue-28576.rs:7:12
+ |
+LL | / dyn Bar
+LL | | <Assoc=()>
+ | |________________________^ `Bar` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-28576.rs:5:16
+ |
+LL | pub trait Bar: Foo<Assoc=()> {
+ | --- ^^^^^^^^^^^^^
+ | | | |
+ | | | ...because it uses `Self` as a type parameter
+ | | ...because it uses `Self` as a type parameter
+ | this trait cannot be made into an object...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/issue-32963.rs b/tests/ui/traits/issue-32963.rs
new file mode 100644
index 000000000..56a68f3a2
--- /dev/null
+++ b/tests/ui/traits/issue-32963.rs
@@ -0,0 +1,11 @@
+use std::mem;
+
+trait Misc {}
+
+fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
+
+fn main() {
+ size_of_copy::<dyn Misc + Copy>();
+ //~^ ERROR only auto traits can be used as additional traits in a trait object
+ //~| ERROR the trait bound `dyn Misc: Copy` is not satisfied
+}
diff --git a/tests/ui/traits/issue-32963.stderr b/tests/ui/traits/issue-32963.stderr
new file mode 100644
index 000000000..bad45e54d
--- /dev/null
+++ b/tests/ui/traits/issue-32963.stderr
@@ -0,0 +1,27 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/issue-32963.rs:8:31
+ |
+LL | size_of_copy::<dyn Misc + Copy>();
+ | ---- ^^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0277]: the trait bound `dyn Misc: Copy` is not satisfied
+ --> $DIR/issue-32963.rs:8:20
+ |
+LL | size_of_copy::<dyn Misc + Copy>();
+ | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc`
+ |
+note: required by a bound in `size_of_copy`
+ --> $DIR/issue-32963.rs:5:20
+ |
+LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
+ | ^^^^ required by this bound in `size_of_copy`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0225, E0277.
+For more information about an error, try `rustc --explain E0225`.
diff --git a/tests/ui/traits/issue-33140-hack-boundaries.rs b/tests/ui/traits/issue-33140-hack-boundaries.rs
new file mode 100644
index 000000000..d091162fc
--- /dev/null
+++ b/tests/ui/traits/issue-33140-hack-boundaries.rs
@@ -0,0 +1,70 @@
+#![feature(negative_impls)]
+#![allow(order_dependent_trait_objects)]
+
+// Check that the issue #33140 hack does not allow unintended things.
+
+// OK
+trait Trait0 {}
+
+impl Trait0 for dyn Send {}
+impl Trait0 for dyn Send {}
+
+// Problem 1: associated types
+trait Trait1 {
+ fn my_fn(&self) {}
+}
+
+impl Trait1 for dyn Send {}
+impl Trait1 for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 2: negative impl
+trait Trait2 {}
+
+impl Trait2 for dyn Send {}
+impl !Trait2 for dyn Send {}
+//~^ ERROR E0751
+
+// Problem 3: type parameter
+trait Trait3<T: ?Sized> {}
+
+impl Trait3<dyn Sync> for dyn Send {}
+impl Trait3<dyn Sync> for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 4a: not a trait object - generic
+trait Trait4a {}
+
+impl<T: ?Sized> Trait4a for T {}
+impl Trait4a for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 4b: not a trait object - misc
+trait Trait4b {}
+
+impl Trait4b for () {}
+impl Trait4b for () {}
+//~^ ERROR E0119
+
+// Problem 4c: not a principal-less trait object
+trait Trait4c {}
+
+impl Trait4c for dyn Trait1 + Send {}
+impl Trait4c for dyn Trait1 + Send {}
+//~^ ERROR E0119
+
+// Problem 4d: lifetimes
+trait Trait4d {}
+
+impl<'a> Trait4d for dyn Send + 'a {}
+impl<'a> Trait4d for dyn Send + 'a {}
+//~^ ERROR E0119
+
+// Problem 5: where-clauses
+trait Trait5 {}
+
+impl Trait5 for dyn Send {}
+impl Trait5 for dyn Send where u32: Copy {}
+//~^ ERROR E0119
+
+fn main() {}
diff --git a/tests/ui/traits/issue-33140-hack-boundaries.stderr b/tests/ui/traits/issue-33140-hack-boundaries.stderr
new file mode 100644
index 000000000..80a502c63
--- /dev/null
+++ b/tests/ui/traits/issue-33140-hack-boundaries.stderr
@@ -0,0 +1,85 @@
+error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn Send + 'static)`
+ --> $DIR/issue-33140-hack-boundaries.rs:18:1
+ |
+LL | impl Trait1 for dyn Send {}
+ | ------------------------ first implementation here
+LL | impl Trait1 for dyn Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)`
+
+error[E0751]: found both positive and negative implementation of trait `Trait2` for type `(dyn Send + 'static)`:
+ --> $DIR/issue-33140-hack-boundaries.rs:25:1
+ |
+LL | impl Trait2 for dyn Send {}
+ | ------------------------ positive implementation here
+LL | impl !Trait2 for dyn Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error[E0119]: conflicting implementations of trait `Trait3<(dyn Sync + 'static)>` for type `(dyn Send + 'static)`
+ --> $DIR/issue-33140-hack-boundaries.rs:32:1
+ |
+LL | impl Trait3<dyn Sync> for dyn Send {}
+ | ---------------------------------- first implementation here
+LL | impl Trait3<dyn Sync> for dyn Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn Send + 'static)`
+ --> $DIR/issue-33140-hack-boundaries.rs:39:1
+ |
+LL | impl<T: ?Sized> Trait4a for T {}
+ | ----------------------------- first implementation here
+LL | impl Trait4a for dyn Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4b` for type `()`
+ --> $DIR/issue-33140-hack-boundaries.rs:46:1
+ |
+LL | impl Trait4b for () {}
+ | ------------------- first implementation here
+LL | impl Trait4b for () {}
+ | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + Send + 'static)`
+ --> $DIR/issue-33140-hack-boundaries.rs:53:1
+ |
+LL | impl Trait4c for dyn Trait1 + Send {}
+ | ---------------------------------- first implementation here
+LL | impl Trait4c for dyn Trait1 + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn Send`
+ --> $DIR/issue-33140-hack-boundaries.rs:60:1
+ |
+LL | impl<'a> Trait4d for dyn Send + 'a {}
+ | ---------------------------------- first implementation here
+LL | impl<'a> Trait4d for dyn Send + 'a {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn Send`
+
+error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn Send + 'static)`
+ --> $DIR/issue-33140-hack-boundaries.rs:67:1
+ |
+LL | impl Trait5 for dyn Send {}
+ | ------------------------ first implementation here
+LL | impl Trait5 for dyn Send where u32: Copy {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0119, E0751.
+For more information about an error, try `rustc --explain E0119`.
+Future incompatibility report: Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait0` for type `(dyn Send + 'static)`: (E0119)
+ --> $DIR/issue-33140-hack-boundaries.rs:10:1
+ |
+LL | impl Trait0 for dyn Send {}
+ | ------------------------ first implementation here
+LL | impl Trait0 for dyn Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-hack-boundaries.rs:2:10
+ |
+LL | #![allow(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/traits/issue-33140.rs b/tests/ui/traits/issue-33140.rs
new file mode 100644
index 000000000..9bdac4b83
--- /dev/null
+++ b/tests/ui/traits/issue-33140.rs
@@ -0,0 +1,47 @@
+trait Trait {
+ fn xyz() -> bool;
+}
+
+impl Trait for dyn Send + Sync {
+ fn xyz() -> bool { false }
+}
+
+impl Trait for dyn Sync + Send {
+//~^ ERROR conflicting implementations
+ fn xyz() -> bool { true }
+}
+
+trait Trait2 {
+ fn uvw() -> bool;
+}
+
+impl Trait2 for dyn Send + Sync {
+ fn uvw() -> bool { false }
+}
+
+impl Trait2 for dyn Sync + Send + Sync {
+//~^ ERROR conflicting implementations
+ fn uvw() -> bool { true }
+}
+
+struct Foo<T: ?Sized>(T);
+impl Foo<dyn Send + Sync> {
+ fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
+ false
+ }
+}
+
+impl Foo<dyn Sync + Send> {
+ fn abc() -> bool {
+ true
+ }
+}
+
+fn main() {
+ assert_eq!(<dyn Send + Sync>::xyz(), false);
+ assert_eq!(<dyn Sync + Send>::xyz(), true);
+ assert_eq!(<dyn Send + Sync>::uvw(), false);
+ assert_eq!(<dyn Sync + Send+ Sync>::uvw(), true);
+ assert_eq!(<Foo<dyn Send + Sync>>::abc(), false);
+ assert_eq!(<Foo<dyn Sync + Send>>::abc(), true);
+}
diff --git a/tests/ui/traits/issue-33140.stderr b/tests/ui/traits/issue-33140.stderr
new file mode 100644
index 000000000..d31281f72
--- /dev/null
+++ b/tests/ui/traits/issue-33140.stderr
@@ -0,0 +1,31 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`
+ --> $DIR/issue-33140.rs:9:1
+ |
+LL | impl Trait for dyn Send + Sync {
+ | ------------------------------ first implementation here
+...
+LL | impl Trait for dyn Sync + Send {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn Send + Sync + 'static)`
+ --> $DIR/issue-33140.rs:22:1
+ |
+LL | impl Trait2 for dyn Send + Sync {
+ | ------------------------------- first implementation here
+...
+LL | impl Trait2 for dyn Sync + Send + Sync {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+
+error[E0592]: duplicate definitions with name `abc`
+ --> $DIR/issue-33140.rs:29:5
+ |
+LL | fn abc() -> bool {
+ | ^^^^^^^^^^^^^^^^ duplicate definitions for `abc`
+...
+LL | fn abc() -> bool {
+ | ---------------- other definition for `abc`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0119, E0592.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/issue-35869.rs b/tests/ui/traits/issue-35869.rs
new file mode 100644
index 000000000..b9b4c972e
--- /dev/null
+++ b/tests/ui/traits/issue-35869.rs
@@ -0,0 +1,21 @@
+trait Foo {
+ fn foo(_: fn(u8) -> ());
+ fn bar(_: Option<u8>);
+ fn baz(_: (u8, u16));
+ fn qux() -> u8;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+ fn foo(_: fn(u16) -> ()) {}
+ //~^ ERROR method `foo` has an incompatible type for trait
+ fn bar(_: Option<u16>) {}
+ //~^ ERROR method `bar` has an incompatible type for trait
+ fn baz(_: (u16, u16)) {}
+ //~^ ERROR method `baz` has an incompatible type for trait
+ fn qux() -> u16 { 5u16 }
+ //~^ ERROR method `qux` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-35869.stderr b/tests/ui/traits/issue-35869.stderr
new file mode 100644
index 000000000..6d985bdea
--- /dev/null
+++ b/tests/ui/traits/issue-35869.stderr
@@ -0,0 +1,71 @@
+error[E0053]: method `foo` has an incompatible type for trait
+ --> $DIR/issue-35869.rs:11:15
+ |
+LL | fn foo(_: fn(u16) -> ()) {}
+ | ^^^^^^^^^^^^^
+ | |
+ | expected `u8`, found `u16`
+ | help: change the parameter type to match the trait: `fn(u8)`
+ |
+note: type in trait
+ --> $DIR/issue-35869.rs:2:15
+ |
+LL | fn foo(_: fn(u8) -> ());
+ | ^^^^^^^^^^^^
+ = note: expected signature `fn(fn(u8))`
+ found signature `fn(fn(u16))`
+
+error[E0053]: method `bar` has an incompatible type for trait
+ --> $DIR/issue-35869.rs:13:15
+ |
+LL | fn bar(_: Option<u16>) {}
+ | ^^^^^^^^^^^
+ | |
+ | expected `u8`, found `u16`
+ | help: change the parameter type to match the trait: `Option<u8>`
+ |
+note: type in trait
+ --> $DIR/issue-35869.rs:3:15
+ |
+LL | fn bar(_: Option<u8>);
+ | ^^^^^^^^^^
+ = note: expected signature `fn(Option<u8>)`
+ found signature `fn(Option<u16>)`
+
+error[E0053]: method `baz` has an incompatible type for trait
+ --> $DIR/issue-35869.rs:15:15
+ |
+LL | fn baz(_: (u16, u16)) {}
+ | ^^^^^^^^^^
+ | |
+ | expected `u8`, found `u16`
+ | help: change the parameter type to match the trait: `(u8, u16)`
+ |
+note: type in trait
+ --> $DIR/issue-35869.rs:4:15
+ |
+LL | fn baz(_: (u8, u16));
+ | ^^^^^^^^^
+ = note: expected signature `fn((u8, _))`
+ found signature `fn((u16, _))`
+
+error[E0053]: method `qux` has an incompatible type for trait
+ --> $DIR/issue-35869.rs:17:17
+ |
+LL | fn qux() -> u16 { 5u16 }
+ | ^^^
+ | |
+ | expected `u8`, found `u16`
+ | help: change the output type to match the trait: `u8`
+ |
+note: type in trait
+ --> $DIR/issue-35869.rs:5:17
+ |
+LL | fn qux() -> u8;
+ | ^^
+ = note: expected signature `fn() -> u8`
+ found signature `fn() -> u16`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/traits/issue-3683.rs b/tests/ui/traits/issue-3683.rs
new file mode 100644
index 000000000..b12c450c9
--- /dev/null
+++ b/tests/ui/traits/issue-3683.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+trait Foo {
+ fn a(&self) -> isize;
+ fn b(&self) -> isize {
+ self.a() + 2
+ }
+}
+
+impl Foo for isize {
+ fn a(&self) -> isize {
+ 3
+ }
+}
+
+pub fn main() {
+ assert_eq!(3.b(), 5);
+}
diff --git a/tests/ui/traits/issue-38033.rs b/tests/ui/traits/issue-38033.rs
new file mode 100644
index 000000000..16b867ec8
--- /dev/null
+++ b/tests/ui/traits/issue-38033.rs
@@ -0,0 +1,79 @@
+// run-pass
+use std::marker;
+use std::mem;
+
+fn main() {
+ let workers = (0..0).map(|_| result::<u32, ()>());
+ drop(join_all(workers).poll());
+}
+
+trait Future {
+ type Item;
+ type Error;
+
+ fn poll(&mut self) -> Result<Self::Item, Self::Error>;
+}
+
+trait IntoFuture {
+ type Future: Future<Item=Self::Item, Error=Self::Error>;
+ type Item;
+ type Error;
+
+ fn into_future(self) -> Self::Future;
+}
+
+impl<F: Future> IntoFuture for F {
+ type Future = F;
+ type Item = F::Item;
+ type Error = F::Error;
+
+ fn into_future(self) -> F {
+ self
+ }
+}
+
+struct FutureResult<T, E> {
+ _inner: marker::PhantomData<(T, E)>,
+}
+
+fn result<T, E>() -> FutureResult<T, E> {
+ loop {}
+}
+
+impl<T, E> Future for FutureResult<T, E> {
+ type Item = T;
+ type Error = E;
+
+ fn poll(&mut self) -> Result<T, E> {
+ loop {}
+ }
+}
+
+struct JoinAll<I>
+ where I: IntoIterator,
+ I::Item: IntoFuture,
+{
+ elems: Vec<<I::Item as IntoFuture>::Item>,
+}
+
+fn join_all<I>(_: I) -> JoinAll<I>
+ where I: IntoIterator,
+ I::Item: IntoFuture,
+{
+ JoinAll { elems: vec![] }
+}
+
+impl<I> Future for JoinAll<I>
+ where I: IntoIterator,
+ I::Item: IntoFuture,
+{
+ type Item = Vec<<I::Item as IntoFuture>::Item>;
+ type Error = <I::Item as IntoFuture>::Error;
+
+ fn poll(&mut self) -> Result<Self::Item, Self::Error> {
+ let elems = mem::replace(&mut self.elems, Vec::new());
+ Ok(elems.into_iter().map(|e| {
+ e
+ }).collect::<Vec<_>>())
+ }
+}
diff --git a/tests/ui/traits/issue-38404.rs b/tests/ui/traits/issue-38404.rs
new file mode 100644
index 000000000..1a92acc34
--- /dev/null
+++ b/tests/ui/traits/issue-38404.rs
@@ -0,0 +1,6 @@
+trait A<T>: std::ops::Add<Self> + Sized {}
+trait B<T>: A<T> {}
+trait C<T>: A<dyn B<T, Output=usize>> {}
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr
new file mode 100644
index 000000000..d7721d7e6
--- /dev/null
+++ b/tests/ui/traits/issue-38404.stderr
@@ -0,0 +1,17 @@
+error[E0038]: the trait `B` cannot be made into an object
+ --> $DIR/issue-38404.rs:3:15
+ |
+LL | trait C<T>: A<dyn B<T, Output=usize>> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-38404.rs:1:13
+ |
+LL | trait A<T>: std::ops::Add<Self> + Sized {}
+ | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
+LL | trait B<T>: A<T> {}
+ | - this trait cannot be made into an object...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs
new file mode 100644
index 000000000..002a3c43f
--- /dev/null
+++ b/tests/ui/traits/issue-38604.rs
@@ -0,0 +1,16 @@
+trait Q<T:?Sized> {}
+trait Foo where u32: Q<Self> {
+ fn foo(&self);
+}
+
+impl Q<()> for u32 {}
+impl Foo for () {
+ fn foo(&self) {
+ println!("foo!");
+ }
+}
+
+fn main() {
+ let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
+ Box::new(()); //~ ERROR `Foo` cannot be made into an object
+}
diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr
new file mode 100644
index 000000000..50d6fb054
--- /dev/null
+++ b/tests/ui/traits/issue-38604.stderr
@@ -0,0 +1,33 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+ --> $DIR/issue-38604.rs:14:13
+ |
+LL | let _f: Box<dyn Foo> =
+ | ^^^^^^^^^^^^ `Foo` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-38604.rs:2:22
+ |
+LL | trait Foo where u32: Q<Self> {
+ | --- ^^^^^^^ ...because it uses `Self` as a type parameter
+ | |
+ | this trait cannot be made into an object...
+
+error[E0038]: the trait `Foo` cannot be made into an object
+ --> $DIR/issue-38604.rs:15:9
+ |
+LL | Box::new(());
+ | ^^^^^^^^^^^^ `Foo` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-38604.rs:2:22
+ |
+LL | trait Foo where u32: Q<Self> {
+ | --- ^^^^^^^ ...because it uses `Self` as a type parameter
+ | |
+ | this trait cannot be made into an object...
+ = note: required for `Box<()>` to implement `CoerceUnsized<Box<dyn Foo>>`
+ = note: required by cast to type `Box<dyn Foo>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/issue-3973.rs b/tests/ui/traits/issue-3973.rs
new file mode 100644
index 000000000..a5ed5b870
--- /dev/null
+++ b/tests/ui/traits/issue-3973.rs
@@ -0,0 +1,25 @@
+struct Point {
+ x: f64,
+ y: f64,
+}
+
+trait ToString_ {
+ fn to_string(&self) -> String;
+}
+
+impl ToString_ for Point {
+ fn new(x: f64, y: f64) -> Point {
+ //~^ ERROR method `new` is not a member of trait `ToString_`
+ Point { x: x, y: y }
+ }
+
+ fn to_string(&self) -> String {
+ format!("({}, {})", self.x, self.y)
+ }
+}
+
+fn main() {
+ let p = Point::new(0.0, 0.0);
+ //~^ ERROR no function or associated item named `new` found for struct `Point`
+ println!("{}", p.to_string());
+}
diff --git a/tests/ui/traits/issue-3973.stderr b/tests/ui/traits/issue-3973.stderr
new file mode 100644
index 000000000..87ee08049
--- /dev/null
+++ b/tests/ui/traits/issue-3973.stderr
@@ -0,0 +1,22 @@
+error[E0407]: method `new` is not a member of trait `ToString_`
+ --> $DIR/issue-3973.rs:11:5
+ |
+LL | / fn new(x: f64, y: f64) -> Point {
+LL | |
+LL | | Point { x: x, y: y }
+LL | | }
+ | |_____^ not a member of trait `ToString_`
+
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
+ --> $DIR/issue-3973.rs:22:20
+ |
+LL | struct Point {
+ | ------------ function or associated item `new` not found for this struct
+...
+LL | let p = Point::new(0.0, 0.0);
+ | ^^^ function or associated item not found in `Point`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0407, E0599.
+For more information about an error, try `rustc --explain E0407`.
diff --git a/tests/ui/traits/issue-4107.rs b/tests/ui/traits/issue-4107.rs
new file mode 100644
index 000000000..98433e806
--- /dev/null
+++ b/tests/ui/traits/issue-4107.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+
+pub fn main() {
+ let _id: &Mat2<f64> = &Matrix::identity(1.0);
+}
+
+pub trait Index<Index,Result> { fn get(&self, _: Index) -> Result { panic!() } }
+pub trait Dimensional<T>: Index<usize, T> { }
+
+pub struct Mat2<T> { x: T }
+pub struct Vec2<T> { x: T }
+
+impl<T> Dimensional<Vec2<T>> for Mat2<T> { }
+impl<T> Index<usize, Vec2<T>> for Mat2<T> { }
+
+impl<T> Dimensional<T> for Vec2<T> { }
+impl<T> Index<usize, T> for Vec2<T> { }
+
+pub trait Matrix<T,V>: Dimensional<V> {
+ fn identity(t:T) -> Self;
+}
+
+impl<T> Matrix<T, Vec2<T>> for Mat2<T> {
+ fn identity(t:T) -> Mat2<T> { Mat2{ x: t } }
+}
diff --git a/tests/ui/traits/issue-43132.rs b/tests/ui/traits/issue-43132.rs
new file mode 100644
index 000000000..c886f4b0a
--- /dev/null
+++ b/tests/ui/traits/issue-43132.rs
@@ -0,0 +1,65 @@
+// run-pass
+#![allow(unused)]
+
+fn main() {
+}
+
+fn foo() {
+ let b = mk::<
+ Forward<(Box<dyn Future<Error = u32>>,)>,
+ >();
+ b.map_err(|_| ()).join();
+}
+
+fn mk<T>() -> T {
+ loop {}
+}
+
+impl<I: Future<Error = E>, E> Future for (I,) {
+ type Error = E;
+}
+
+struct Forward<T: Future> {
+ _a: T,
+}
+
+impl<T: Future> Future for Forward<T>
+where
+ T::Error: From<u32>,
+{
+ type Error = T::Error;
+}
+
+trait Future {
+ type Error;
+
+ fn map_err<F, E>(self, _: F) -> (Self, F)
+ where
+ F: FnOnce(Self::Error) -> E,
+ Self: Sized,
+ {
+ loop {}
+ }
+
+ fn join(self) -> (MaybeDone<Self>, ())
+ where
+ Self: Sized,
+ {
+ loop {}
+ }
+}
+
+impl<S: ?Sized + Future> Future for Box<S> {
+ type Error = S::Error;
+}
+
+enum MaybeDone<A: Future> {
+ _Done(A::Error),
+}
+
+impl<U, A: Future, F> Future for (A, F)
+where
+ F: FnOnce(A::Error) -> U,
+{
+ type Error = U;
+}
diff --git a/tests/ui/traits/issue-43784-supertrait.rs b/tests/ui/traits/issue-43784-supertrait.rs
new file mode 100644
index 000000000..55c26ccd2
--- /dev/null
+++ b/tests/ui/traits/issue-43784-supertrait.rs
@@ -0,0 +1,10 @@
+pub trait Partial: Copy {
+}
+
+pub trait Complete: Partial {
+}
+
+impl<T> Partial for T where T: Complete {}
+impl<T> Complete for T {} //~ ERROR the trait bound `T: Copy` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr
new file mode 100644
index 000000000..6b5b72138
--- /dev/null
+++ b/tests/ui/traits/issue-43784-supertrait.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: Copy` is not satisfied
+ --> $DIR/issue-43784-supertrait.rs:8:22
+ |
+LL | impl<T> Complete for T {}
+ | ^ the trait `Copy` is not implemented for `T`
+ |
+note: required for `T` to implement `Partial`
+ --> $DIR/issue-43784-supertrait.rs:1:11
+ |
+LL | pub trait Partial: Copy {
+ | ^^^^^^^
+note: required by a bound in `Complete`
+ --> $DIR/issue-43784-supertrait.rs:4:21
+ |
+LL | pub trait Complete: Partial {
+ | ^^^^^^^ required by this bound in `Complete`
+help: consider restricting type parameter `T`
+ |
+LL | impl<T: std::marker::Copy> Complete for T {}
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs
new file mode 100644
index 000000000..005939e0c
--- /dev/null
+++ b/tests/ui/traits/issue-50480.rs
@@ -0,0 +1,15 @@
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR cannot find type `N` in this scope
+
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+
+fn main() {}
diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr
new file mode 100644
index 000000000..5063fdca0
--- /dev/null
+++ b/tests/ui/traits/issue-50480.stderr
@@ -0,0 +1,92 @@
+error[E0412]: cannot find type `N` in this scope
+ --> $DIR/issue-50480.rs:3:12
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | +++
+
+error[E0412]: cannot find type `NotDefined` in this scope
+ --> $DIR/issue-50480.rs:3:15
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `N` in this scope
+ --> $DIR/issue-50480.rs:3:12
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | +++
+
+error[E0412]: cannot find type `NotDefined` in this scope
+ --> $DIR/issue-50480.rs:3:15
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | struct Foo<NotDefined>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ++++++++++++
+
+error[E0412]: cannot find type `N` in this scope
+ --> $DIR/issue-50480.rs:11:18
+ |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | - ^
+ | |
+ | similarly named type parameter `T` defined here
+ |
+help: a type parameter with a similar name exists
+ |
+LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ~
+help: you might be missing a type parameter
+ |
+LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | +++
+
+error[E0412]: cannot find type `NotDefined` in this scope
+ --> $DIR/issue-50480.rs:11:21
+ |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^ not found in this scope
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/issue-50480.rs:1:17
+ |
+LL | #[derive(Clone, Copy)]
+ | ^^^^
+LL |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | -------- ------ this field does not implement `Copy`
+ | |
+ | this field does not implement `Copy`
+ |
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/issue-50480.rs:9:17
+ |
+LL | #[derive(Clone, Copy)]
+ | ^^^^
+LL |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | -------- ------ this field does not implement `Copy`
+ | |
+ | this field does not implement `Copy`
+ |
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0204, E0412.
+For more information about an error, try `rustc --explain E0204`.
diff --git a/tests/ui/traits/issue-52893.rs b/tests/ui/traits/issue-52893.rs
new file mode 100644
index 000000000..d72598d5d
--- /dev/null
+++ b/tests/ui/traits/issue-52893.rs
@@ -0,0 +1,57 @@
+// check-fail
+//
+// regression test for issue 52893
+trait At<Name> {
+ type AtRes;
+ fn at(self) -> Self::AtRes;
+}
+
+trait Push<T> {
+ type PushRes;
+ fn push(self, other: T) -> Self::PushRes;
+}
+
+trait AddClass<Name, F> {
+ type AddRes;
+ fn init(self, func: F);
+}
+
+trait ToRef {
+ type RefRes;
+ fn to_ref(&self) -> Self::RefRes;
+}
+
+struct Class<P>(P);
+
+impl<P> Class<P> {
+ fn with<Name, F>(self) -> <Self as AddClass<Name, F>>::AddRes
+ where
+ Self: AddClass<Name, F>,
+ {
+ todo!()
+ }
+
+ fn from<F>(self) -> <Self as AddClass<P, F>>::AddRes
+ where
+ Self: AddClass<P, F>,
+ {
+ todo!()
+ }
+}
+
+impl<F, Name, P> AddClass<Name, F> for Class<P>
+where
+ Self: At<Name>,
+ <Self as At<Name>>::AtRes: Push<F>,
+ <<Self as At<Name>>::AtRes as Push<F>>::PushRes: ToRef<RefRes = Self> + Push<F>,
+{
+ type AddRes = ();
+
+ fn init(self, func: F) {
+ let builder = self.at().push(func);
+ let output = builder.to_ref();
+ builder.push(output); //~ ERROR mismatched types [E0308]
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr
new file mode 100644
index 000000000..a11867c03
--- /dev/null
+++ b/tests/ui/traits/issue-52893.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-52893.rs:53:22
+ |
+LL | impl<F, Name, P> AddClass<Name, F> for Class<P>
+ | - this type parameter
+...
+LL | builder.push(output);
+ | ---- ^^^^^^ expected type parameter `F`, found struct `Class`
+ | |
+ | arguments to this method are incorrect
+ |
+ = note: expected type parameter `F`
+ found struct `Class<P>`
+help: the return type of this call is `Class<P>` due to the type of the argument passed
+ --> $DIR/issue-52893.rs:53:9
+ |
+LL | builder.push(output);
+ | ^^^^^^^^^^^^^------^
+ | |
+ | this argument influences the return type of `push`
+note: associated function defined here
+ --> $DIR/issue-52893.rs:11:8
+ |
+LL | fn push(self, other: T) -> Self::PushRes;
+ | ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/issue-56202.rs b/tests/ui/traits/issue-56202.rs
new file mode 100644
index 000000000..0952843e6
--- /dev/null
+++ b/tests/ui/traits/issue-56202.rs
@@ -0,0 +1,17 @@
+// build-pass
+
+trait FooTrait {}
+
+trait BarTrait {
+ fn foo<T: FooTrait>(_: T) -> Self;
+}
+
+struct FooStruct(u32);
+
+impl BarTrait for FooStruct {
+ fn foo<T: FooTrait>(_: T) -> Self {
+ Self(u32::default())
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-56488.rs b/tests/ui/traits/issue-56488.rs
new file mode 100644
index 000000000..e2f399692
--- /dev/null
+++ b/tests/ui/traits/issue-56488.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod alpha {
+ pub trait A {}
+ pub trait C = A;
+}
+
+#[allow(unused_imports)]
+use alpha::C;
+
+fn main() {}
diff --git a/tests/ui/traits/issue-59029-1.rs b/tests/ui/traits/issue-59029-1.rs
new file mode 100644
index 000000000..8ab47a4af
--- /dev/null
+++ b/tests/ui/traits/issue-59029-1.rs
@@ -0,0 +1,9 @@
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+//~^ ERROR associated type `Res` not found for `Self`
+//~| ERROR associated type `Res` not found for `Self`
+
+fn main() {}
diff --git a/tests/ui/traits/issue-59029-1.stderr b/tests/ui/traits/issue-59029-1.stderr
new file mode 100644
index 000000000..203a89285
--- /dev/null
+++ b/tests/ui/traits/issue-59029-1.stderr
@@ -0,0 +1,15 @@
+error[E0220]: associated type `Res` not found for `Self`
+ --> $DIR/issue-59029-1.rs:5:52
+ |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+ | ^^^ there is a similarly named associated type `Res` in the trait `Svc`
+
+error[E0220]: associated type `Res` not found for `Self`
+ --> $DIR/issue-59029-1.rs:5:52
+ |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+ | ^^^ there is a similarly named associated type `Res` in the trait `Svc`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/traits/issue-59029-2.rs b/tests/ui/traits/issue-59029-2.rs
new file mode 100644
index 000000000..2bdb128d8
--- /dev/null
+++ b/tests/ui/traits/issue-59029-2.rs
@@ -0,0 +1,8 @@
+// run-pass
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where <Self as Svc<Target>>::Res: Svc<Req>;
+
+fn main() {}
diff --git a/tests/ui/traits/issue-6128.rs b/tests/ui/traits/issue-6128.rs
new file mode 100644
index 000000000..07d92f8f8
--- /dev/null
+++ b/tests/ui/traits/issue-6128.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+use std::collections::HashMap;
+
+trait Graph<Node, Edge> {
+ fn f(&self, _: Edge);
+ fn g(&self, _: Node);
+}
+
+impl<E> Graph<isize, E> for HashMap<isize, isize> {
+ fn f(&self, _e: E) {
+ panic!();
+ }
+ fn g(&self, _e: isize) {
+ panic!();
+ }
+}
+
+pub fn main() {
+ let g : Box<HashMap<isize,isize>> = Box::new(HashMap::new());
+ let _g2 : Box<dyn Graph<isize,isize>> = g as Box<dyn Graph<isize,isize>>;
+}
diff --git a/tests/ui/traits/issue-6334.rs b/tests/ui/traits/issue-6334.rs
new file mode 100644
index 000000000..acf48da15
--- /dev/null
+++ b/tests/ui/traits/issue-6334.rs
@@ -0,0 +1,46 @@
+// run-pass
+// Tests that everything still compiles and runs fine even when
+// we reorder the bounds.
+
+
+trait A {
+ fn a(&self) -> usize;
+}
+
+trait B {
+ fn b(&self) -> usize;
+}
+
+trait C {
+ fn combine<T:A+B>(&self, t: &T) -> usize;
+}
+
+struct Foo;
+
+impl A for Foo {
+ fn a(&self) -> usize { 1 }
+}
+
+impl B for Foo {
+ fn b(&self) -> usize { 2 }
+}
+
+struct Bar;
+
+impl C for Bar {
+ // Note below: bounds in impl decl are in reverse order.
+ fn combine<T:B+A>(&self, t: &T) -> usize {
+ (t.a() * 100) + t.b()
+ }
+}
+
+fn use_c<S:C, T:B+A>(s: &S, t: &T) -> usize {
+ s.combine(t)
+}
+
+pub fn main() {
+ let foo = Foo;
+ let bar = Bar;
+ let r = use_c(&bar, &foo);
+ assert_eq!(r, 102);
+}
diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs
new file mode 100644
index 000000000..018ce0459
--- /dev/null
+++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs
@@ -0,0 +1,11 @@
+trait Foo {
+ fn foo(&self);
+}
+
+trait Bar {}
+
+fn do_stuff<T : Bar>(t : T) {
+ t.foo() //~ ERROR no method named `foo` found
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr
new file mode 100644
index 000000000..ae33e61d8
--- /dev/null
+++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `foo` found for type parameter `T` in the current scope
+ --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
+ |
+LL | fn do_stuff<T : Bar>(t : T) {
+ | - method `foo` not found for this type parameter
+LL | t.foo()
+ | ^^^ method not found in `T`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it:
+ |
+LL | fn do_stuff<T : Bar + Foo>(t : T) {
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/issue-65673.rs b/tests/ui/traits/issue-65673.rs
new file mode 100644
index 000000000..e5c2fccb2
--- /dev/null
+++ b/tests/ui/traits/issue-65673.rs
@@ -0,0 +1,12 @@
+#![feature(trait_alias)] // Enabled to reduce stderr output, but can be triggered even if disabled.
+trait Trait {}
+trait WithType {
+ type Ctx;
+}
+trait Alias<T> = where T: Trait;
+
+impl<T> WithType for T {
+ type Ctx = dyn Alias<T>;
+ //~^ ERROR at least one trait is required for an object type [E0224]
+}
+fn main() {}
diff --git a/tests/ui/traits/issue-65673.stderr b/tests/ui/traits/issue-65673.stderr
new file mode 100644
index 000000000..8f01d7c53
--- /dev/null
+++ b/tests/ui/traits/issue-65673.stderr
@@ -0,0 +1,12 @@
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/issue-65673.rs:9:16
+ |
+LL | trait Alias<T> = where T: Trait;
+ | -------------- this alias does not contain a trait
+...
+LL | type Ctx = dyn Alias<T>;
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/traits/issue-68295.rs b/tests/ui/traits/issue-68295.rs
new file mode 100644
index 000000000..7ff54539a
--- /dev/null
+++ b/tests/ui/traits/issue-68295.rs
@@ -0,0 +1,47 @@
+// check-fail
+//
+// regression test for #68295
+
+struct Matrix<R, C, S>(R, C, S);
+
+impl<R, C, S> Matrix<R, C, S> {
+ fn into_owned(self) -> Matrix<R, C, Owned<R, C, ()>>
+ where
+ (): Allocator<R, C>,
+ {
+ unimplemented!()
+ }
+}
+
+impl<D, S> Matrix<D, D, S> {
+ fn hermitian_part(&self) -> Matrix<D, D, Owned<D, D, ()>>
+ where
+ (): Allocator<D, D>,
+ {
+ unimplemented!()
+ }
+}
+
+trait Allocator<R, C> {
+ type Buffer;
+}
+
+trait Trait<R, C, A> {
+ type Power;
+}
+
+impl<R, C, A: Allocator<R, C>> Trait<R, C, A> for () {
+ type Power = A::Buffer;
+}
+
+type Owned<R, C, G> = <G as Trait<R, C, ()>>::Power;
+
+fn crash<R, C>(input: Matrix<R, C, ()>) -> Matrix<R, C, u32>
+where
+ (): Allocator<R, C>,
+{
+ input.into_owned()
+ //~^ ERROR mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-68295.stderr b/tests/ui/traits/issue-68295.stderr
new file mode 100644
index 000000000..cb6e6e076
--- /dev/null
+++ b/tests/ui/traits/issue-68295.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-68295.rs:43:5
+ |
+LL | fn crash<R, C>(input: Matrix<R, C, ()>) -> Matrix<R, C, u32>
+ | ----------------- expected `Matrix<R, C, u32>` because of return type
+...
+LL | input.into_owned()
+ | ^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type
+ |
+ = note: expected struct `Matrix<_, _, u32>`
+ found struct `Matrix<_, _, <() as Allocator<R, C>>::Buffer>`
+ = help: consider constraining the associated type `<() as Allocator<R, C>>::Buffer` to `u32`
+ = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/issue-7013.rs b/tests/ui/traits/issue-7013.rs
new file mode 100644
index 000000000..1fb01303c
--- /dev/null
+++ b/tests/ui/traits/issue-7013.rs
@@ -0,0 +1,26 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
+trait Foo {
+ fn set(&mut self, v: Rc<RefCell<A>>);
+}
+
+struct B {
+ v: Option<Rc<RefCell<A>>>
+}
+
+impl Foo for B {
+ fn set(&mut self, v: Rc<RefCell<A>>)
+ {
+ self.v = Some(v);
+ }
+}
+
+struct A {
+ v: Box<dyn Foo + Send>,
+}
+
+fn main() {
+ let a = A {v: Box::new(B{v: None}) as Box<dyn Foo + Send>};
+ //~^ ERROR `Rc<RefCell<A>>` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr
new file mode 100644
index 000000000..4575f4dba
--- /dev/null
+++ b/tests/ui/traits/issue-7013.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `Rc<RefCell<A>>` cannot be sent between threads safely
+ --> $DIR/issue-7013.rs:24:19
+ |
+LL | let a = A {v: Box::new(B{v: None}) as Box<dyn Foo + Send>};
+ | ^^^^^^^^^^^^^^^^^^^^ `Rc<RefCell<A>>` cannot be sent between threads safely
+ |
+ = help: within `B`, the trait `Send` is not implemented for `Rc<RefCell<A>>`
+ = note: required because it appears within the type `Option<Rc<RefCell<A>>>`
+note: required because it appears within the type `B`
+ --> $DIR/issue-7013.rs:8:8
+ |
+LL | struct B {
+ | ^
+ = note: required for the cast from `B` to the object type `dyn Foo + Send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-70944.rs b/tests/ui/traits/issue-70944.rs
new file mode 100644
index 000000000..3286de9d5
--- /dev/null
+++ b/tests/ui/traits/issue-70944.rs
@@ -0,0 +1,23 @@
+// check-pass
+// Regression test of #70944, should compile fine.
+
+use std::ops::Index;
+
+pub struct KeyA;
+pub struct KeyB;
+pub struct KeyC;
+
+pub trait Foo: Index<KeyA> + Index<KeyB> + Index<KeyC> {}
+pub trait FooBuilder {
+ type Inner: Foo;
+ fn inner(&self) -> &Self::Inner;
+}
+
+pub fn do_stuff(foo: &impl FooBuilder) {
+ let inner = foo.inner();
+ &inner[KeyA];
+ &inner[KeyB];
+ &inner[KeyC];
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-71036.rs b/tests/ui/traits/issue-71036.rs
new file mode 100644
index 000000000..69eed0c04
--- /dev/null
+++ b/tests/ui/traits/issue-71036.rs
@@ -0,0 +1,17 @@
+#![feature(unsize, dispatch_from_dyn)]
+
+use std::marker::Unsize;
+use std::ops::DispatchFromDyn;
+
+#[allow(unused)]
+struct Foo<'a, T: ?Sized> {
+ _inner: &'a &'a T,
+}
+
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied
+//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T`
+//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
+//~| NOTE required for
+
+fn main() {}
diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr
new file mode 100644
index 000000000..79eb7a2ae
--- /dev/null
+++ b/tests/ui/traits/issue-71036.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied
+ --> $DIR/issue-71036.rs:11:1
+ |
+LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
+ |
+ = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
+ = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-71136.rs b/tests/ui/traits/issue-71136.rs
new file mode 100644
index 000000000..b21756e2b
--- /dev/null
+++ b/tests/ui/traits/issue-71136.rs
@@ -0,0 +1,8 @@
+struct Foo(u8);
+
+#[derive(Clone)]
+struct FooHolster {
+ the_foos: Vec<Foo>, //~ERROR Clone
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr
new file mode 100644
index 000000000..f54173392
--- /dev/null
+++ b/tests/ui/traits/issue-71136.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `Foo: Clone` is not satisfied
+ --> $DIR/issue-71136.rs:5:5
+ |
+LL | #[derive(Clone)]
+ | ----- in this derive macro expansion
+LL | struct FooHolster {
+LL | the_foos: Vec<Foo>,
+ | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
+ |
+ = note: required for `Vec<Foo>` to implement `Clone`
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider annotating `Foo` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-72410.rs b/tests/ui/traits/issue-72410.rs
new file mode 100644
index 000000000..c95f1dfdc
--- /dev/null
+++ b/tests/ui/traits/issue-72410.rs
@@ -0,0 +1,18 @@
+// Regression test for #72410, this should be used with debug assertion enabled.
+
+// should be fine
+pub trait Foo {
+ fn map()
+ where
+ Self: Sized,
+ for<'a> &'a mut [u8]: ;
+}
+
+// should fail
+pub trait Bar {
+ fn map()
+ where for<'a> &'a mut [dyn Bar]: ;
+ //~^ ERROR: the trait `Bar` cannot be made into an object
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr
new file mode 100644
index 000000000..c7beb834b
--- /dev/null
+++ b/tests/ui/traits/issue-72410.stderr
@@ -0,0 +1,25 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+ --> $DIR/issue-72410.rs:14:19
+ |
+LL | where for<'a> &'a mut [dyn Bar]: ;
+ | ^^^^^^^^^^^^^^^^^ `Bar` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-72410.rs:13:8
+ |
+LL | pub trait Bar {
+ | --- this trait cannot be made into an object...
+LL | fn map()
+ | ^^^ ...because associated function `map` has no `self` parameter
+help: consider turning `map` into a method by giving it a `&self` argument
+ |
+LL | fn map(&self)
+ | +++++
+help: alternatively, consider constraining `map` so it does not apply to trait objects
+ |
+LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ;
+ | +++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/issue-72455.rs b/tests/ui/traits/issue-72455.rs
new file mode 100644
index 000000000..b6c3bb222
--- /dev/null
+++ b/tests/ui/traits/issue-72455.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+pub trait ResultExt {
+ type Ok;
+ fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
+}
+
+impl<O, E> ResultExt for std::result::Result<O, E>
+where
+ E: std::error::Error,
+{
+ type Ok = O;
+ fn err_eprint_and_ignore(self) -> Option<O>
+ where
+ Self: ,
+ {
+ match self {
+ Err(e) => {
+ eprintln!("{}", e);
+ None
+ }
+ Ok(o) => Some(o),
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-75627.rs b/tests/ui/traits/issue-75627.rs
new file mode 100644
index 000000000..93a2ec1cc
--- /dev/null
+++ b/tests/ui/traits/issue-75627.rs
@@ -0,0 +1,6 @@
+struct Foo<T>(T, *const ());
+
+unsafe impl Send for Foo<T> {}
+//~^ ERROR cannot find type
+
+fn main() {}
diff --git a/tests/ui/traits/issue-75627.stderr b/tests/ui/traits/issue-75627.stderr
new file mode 100644
index 000000000..1675edc9f
--- /dev/null
+++ b/tests/ui/traits/issue-75627.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `T` in this scope
+ --> $DIR/issue-75627.rs:3:26
+ |
+LL | unsafe impl Send for Foo<T> {}
+ | ^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | unsafe impl<T> Send for Foo<T> {}
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs
new file mode 100644
index 000000000..f5be6cf21
--- /dev/null
+++ b/tests/ui/traits/issue-77982.rs
@@ -0,0 +1,41 @@
+use std::collections::HashMap;
+
+fn what() {
+ let descr = String::new();
+ let mut opts = HashMap::<String, ()>::new();
+ let opt = String::new();
+
+ opts.get(opt.as_ref()); //~ ERROR type annotations needed
+ //~^ ERROR type annotations needed
+}
+
+fn main() {
+ let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
+ //~^ ERROR type annotations needed
+}
+
+trait Foo<'a, T: ?Sized> {
+ fn foo(&self) -> Box<T> {
+ todo!()
+ }
+}
+
+trait Bar<'a, T: ?Sized> {
+ fn bar(&self) -> Box<T> {
+ todo!()
+ }
+}
+
+impl Foo<'static, u32> for () {}
+impl<'a> Foo<'a, i16> for () {}
+
+impl<'a> Bar<'static, u32> for &'a () {}
+impl<'a> Bar<'a, i16> for &'a () {}
+
+fn foo() {
+ let _ = ().foo(); //~ ERROR type annotations needed
+}
+
+fn bar() {
+ let _ = (&()).bar(); //~ ERROR type annotations needed
+}
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
new file mode 100644
index 000000000..0b57a8212
--- /dev/null
+++ b/tests/ui/traits/issue-77982.stderr
@@ -0,0 +1,98 @@
+error[E0283]: type annotations needed
+ --> $DIR/issue-77982.rs:8:10
+ |
+LL | opts.get(opt.as_ref());
+ | ^^^ ------------ type must be known at this point
+ | |
+ | cannot infer type of the type parameter `Q` declared on the associated function `get`
+ |
+ = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
+ - impl Borrow<str> for String;
+ - impl<T> Borrow<T> for T
+ where T: ?Sized;
+note: required by a bound in `HashMap::<K, V, S>::get`
+ --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+help: consider specifying the generic argument
+ |
+LL | opts.get::<Q>(opt.as_ref());
+ | +++++
+
+error[E0283]: type annotations needed
+ --> $DIR/issue-77982.rs:8:10
+ |
+LL | opts.get(opt.as_ref());
+ | ^^^ ------ type must be known at this point
+ | |
+ | cannot infer type of the type parameter `Q` declared on the associated function `get`
+ |
+ = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`:
+ - impl AsRef<OsStr> for String;
+ - impl AsRef<Path> for String;
+ - impl AsRef<[u8]> for String;
+ - impl AsRef<str> for String;
+help: consider specifying the generic argument
+ |
+LL | opts.get::<Q>(opt.as_ref());
+ | +++++
+
+error[E0283]: type annotations needed
+ --> $DIR/issue-77982.rs:13:59
+ |
+LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
+ | --------- ^^^^
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+ - impl From<Ipv4Addr> for u32;
+ - impl From<NonZeroU32> for u32;
+ - impl From<bool> for u32;
+ - impl From<char> for u32;
+ - impl From<u16> for u32;
+ - impl From<u8> for u32;
+ - impl<T> From<!> for T;
+ - impl<T> From<T> for T;
+help: try using a fully qualified path to specify the expected types
+ |
+LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
+ | +++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed for `Box<T>`
+ --> $DIR/issue-77982.rs:36:9
+ |
+LL | let _ = ().foo();
+ | ^ --- type must be known at this point
+ |
+note: multiple `impl`s satisfying `(): Foo<'_, _>` found
+ --> $DIR/issue-77982.rs:29:1
+ |
+LL | impl Foo<'static, u32> for () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'a> Foo<'a, i16> for () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider giving this pattern a type, where the type for type parameter `T` is specified
+ |
+LL | let _: Box<T> = ().foo();
+ | ++++++++
+
+error[E0283]: type annotations needed for `Box<T>`
+ --> $DIR/issue-77982.rs:40:9
+ |
+LL | let _ = (&()).bar();
+ | ^ --- type must be known at this point
+ |
+note: multiple `impl`s satisfying `&(): Bar<'_, _>` found
+ --> $DIR/issue-77982.rs:32:1
+ |
+LL | impl<'a> Bar<'static, u32> for &'a () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'a> Bar<'a, i16> for &'a () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider giving this pattern a type, where the type for type parameter `T` is specified
+ |
+LL | let _: Box<T> = (&()).bar();
+ | ++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs
new file mode 100644
index 000000000..92f9f4b46
--- /dev/null
+++ b/tests/ui/traits/issue-78372.rs
@@ -0,0 +1,13 @@
+use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature 'dispatch_from_dyn'
+struct Smaht<T, MISC>(PhantomData); //~ ERROR cannot find type `PhantomData` in this scope
+impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` in this scope
+//~^ ERROR cannot find type `MISC` in this scope
+//~| ERROR use of unstable library feature 'dispatch_from_dyn'
+//~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+trait Foo: X<u32> {}
+trait X<T> {
+ fn foo(self: Smaht<Self, T>);
+}
+trait Marker {}
+impl Marker for dyn Foo {}
+fn main() {}
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
new file mode 100644
index 000000000..8e7fd5f25
--- /dev/null
+++ b/tests/ui/traits/issue-78372.stderr
@@ -0,0 +1,65 @@
+error[E0412]: cannot find type `PhantomData` in this scope
+ --> $DIR/issue-78372.rs:2:23
+ |
+LL | struct Smaht<T, MISC>(PhantomData);
+ | ^^^^^^^^^^^ not found in this scope
+ |
+help: consider importing this struct
+ |
+LL | use std::marker::PhantomData;
+ |
+
+error[E0412]: cannot find type `U` in this scope
+ --> $DIR/issue-78372.rs:3:31
+ |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+ | - ^
+ | |
+ | similarly named type parameter `T` defined here
+ |
+help: a type parameter with a similar name exists
+ |
+LL | impl<T> DispatchFromDyn<Smaht<T, MISC>> for T {}
+ | ~
+help: you might be missing a type parameter
+ |
+LL | impl<T, U> DispatchFromDyn<Smaht<U, MISC>> for T {}
+ | +++
+
+error[E0412]: cannot find type `MISC` in this scope
+ --> $DIR/issue-78372.rs:3:34
+ |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+ | ^^^^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | impl<T, MISC> DispatchFromDyn<Smaht<U, MISC>> for T {}
+ | ++++++
+
+error[E0658]: use of unstable library feature 'dispatch_from_dyn'
+ --> $DIR/issue-78372.rs:1:5
+ |
+LL | use std::ops::DispatchFromDyn;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'dispatch_from_dyn'
+ --> $DIR/issue-78372.rs:3:9
+ |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
+
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+ --> $DIR/issue-78372.rs:3:1
+ |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0378, E0412, E0658.
+For more information about an error, try `rustc --explain E0378`.
diff --git a/tests/ui/traits/issue-78632.rs b/tests/ui/traits/issue-78632.rs
new file mode 100644
index 000000000..c72a2aef4
--- /dev/null
+++ b/tests/ui/traits/issue-78632.rs
@@ -0,0 +1,59 @@
+// check-pass
+//
+// Regression test for issue #78632
+
+#![crate_type = "lib"]
+
+pub trait Corge<T> {
+ type Fred;
+}
+
+impl Corge<u8> for () {
+ type Fred = u32;
+}
+
+pub trait Waldo {
+ type Quax;
+}
+
+impl Waldo for u32 {
+ type Quax = u8;
+}
+
+pub trait Grault
+where
+ (): Corge<Self::Thud>,
+{
+ type Thud;
+ fn bar(_: <() as Corge<Self::Thud>>::Fred) {}
+}
+
+impl<T> Grault for T
+where
+ T: Waldo,
+ (): Corge<T::Quax>,
+ <() as Corge<T::Quax>>::Fred: Waldo,
+{
+ type Thud = u8;
+}
+
+pub trait Plugh<I> {
+ fn baz();
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct Qiz<T> {
+ foo: T,
+}
+
+impl<T> Plugh<<() as Corge<T::Thud>>::Fred> for Qiz<T>
+where
+ T: Grault,
+ (): Corge<T::Thud>,
+{
+ fn baz() {}
+}
+
+pub fn test() {
+ <Qiz<u32> as Plugh<u32>>::baz();
+}
diff --git a/tests/ui/traits/issue-79458.rs b/tests/ui/traits/issue-79458.rs
new file mode 100644
index 000000000..a41add6a1
--- /dev/null
+++ b/tests/ui/traits/issue-79458.rs
@@ -0,0 +1,10 @@
+// Negative implementations should not be shown in trait suggestions.
+// This is a regression test of #79458.
+
+#[derive(Clone)]
+struct Foo<'a, T> {
+ bar: &'a mut T
+ //~^ ERROR the trait bound `&mut T: Clone` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-79458.stderr b/tests/ui/traits/issue-79458.stderr
new file mode 100644
index 000000000..08f7bbbf0
--- /dev/null
+++ b/tests/ui/traits/issue-79458.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `&mut T: Clone` is not satisfied
+ --> $DIR/issue-79458.rs:6:5
+ |
+LL | #[derive(Clone)]
+ | ----- in this derive macro expansion
+LL | struct Foo<'a, T> {
+LL | bar: &'a mut T
+ | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T`
+ |
+ = help: the trait `Clone` is implemented for `&T`
+ = note: `Clone` is implemented for `&T`, but not for `&mut T`
+ = note: this error originates in the derive macro `Clone` (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/traits/issue-8153.rs b/tests/ui/traits/issue-8153.rs
new file mode 100644
index 000000000..81a8f5338
--- /dev/null
+++ b/tests/ui/traits/issue-8153.rs
@@ -0,0 +1,16 @@
+// Test that duplicate methods in impls are not allowed
+
+struct Foo;
+
+trait Bar {
+ fn bar(&self) -> isize;
+}
+
+impl Bar for Foo {
+ fn bar(&self) -> isize {1}
+ fn bar(&self) -> isize {2} //~ ERROR duplicate definitions
+}
+
+fn main() {
+ println!("{}", Foo.bar());
+}
diff --git a/tests/ui/traits/issue-8153.stderr b/tests/ui/traits/issue-8153.stderr
new file mode 100644
index 000000000..ae214bb9e
--- /dev/null
+++ b/tests/ui/traits/issue-8153.stderr
@@ -0,0 +1,14 @@
+error[E0201]: duplicate definitions with name `bar`:
+ --> $DIR/issue-8153.rs:11:5
+ |
+LL | fn bar(&self) -> isize;
+ | ----------------------- item in trait
+...
+LL | fn bar(&self) -> isize {1}
+ | -------------------------- previous definition here
+LL | fn bar(&self) -> isize {2}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/tests/ui/traits/issue-82830.rs b/tests/ui/traits/issue-82830.rs
new file mode 100644
index 000000000..37bae2e90
--- /dev/null
+++ b/tests/ui/traits/issue-82830.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+trait A<Y, N> {
+ type B;
+}
+
+type MaybeBox<T> = <T as A<T, Box<T>>>::B;
+struct P {
+ t: MaybeBox<P>,
+}
+
+impl<Y, N> A<Y, N> for P {
+ type B = N;
+}
+
+fn main() {
+ let t: MaybeBox<P>;
+}
diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs
new file mode 100644
index 000000000..3cd68ff6f
--- /dev/null
+++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs
@@ -0,0 +1,66 @@
+// Regression test for issue #83538. The problem here is that we have
+// two cycles:
+//
+// * `Ty` embeds `Box<Ty>` indirectly, which depends on `Global: 'static`, which is OkModuloRegions.
+// * But `Ty` also references `First`, which has a cycle on itself. That should just be `Ok`.
+//
+// But our caching mechanism was blending both cycles and giving the incorrect result.
+
+#![feature(rustc_attrs)]
+#![allow(bad_style)]
+
+struct First {
+ b: Vec<First>,
+}
+
+pub struct Second {
+ d: Vec<First>,
+}
+
+struct Third<'a, f> {
+ g: Vec<(f, &'a f)>,
+}
+
+enum Ty {
+ j(Fourth, Fifth, Sixth),
+}
+
+struct Fourth {
+ o: Vec<Ty>,
+}
+
+struct Fifth {
+ bounds: First,
+}
+
+struct Sixth {
+ p: Box<Ty>,
+}
+
+#[rustc_evaluate_where_clauses]
+fn forward<'a>()
+where
+ Vec<First>: Unpin,
+ Third<'a, Ty>: Unpin,
+{
+}
+
+#[rustc_evaluate_where_clauses]
+fn reverse<'a>()
+where
+ Third<'a, Ty>: Unpin,
+ Vec<First>: Unpin,
+{
+}
+
+fn main() {
+ // Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions":
+
+ forward();
+ //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+
+ reverse();
+ //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+}
diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr
new file mode 100644
index 000000000..7c4041144
--- /dev/null
+++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr
@@ -0,0 +1,38 @@
+error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
+ |
+LL | Vec<First>: Unpin,
+ | ----- predicate
+...
+LL | forward();
+ | ^^^^^^^
+
+error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
+ |
+LL | Third<'a, Ty>: Unpin,
+ | ----- predicate
+...
+LL | forward();
+ | ^^^^^^^
+
+error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
+ |
+LL | Third<'a, Ty>: Unpin,
+ | ----- predicate
+...
+LL | reverse();
+ | ^^^^^^^
+
+error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
+ |
+LL | Vec<First>: Unpin,
+ | ----- predicate
+...
+LL | reverse();
+ | ^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/traits/issue-84399-bad-fresh-caching.rs b/tests/ui/traits/issue-84399-bad-fresh-caching.rs
new file mode 100644
index 000000000..149400156
--- /dev/null
+++ b/tests/ui/traits/issue-84399-bad-fresh-caching.rs
@@ -0,0 +1,55 @@
+// compile-flags: --crate-type lib
+// check-pass
+//
+// Regression test for issue #84399
+// Tests that we keep the full `ParamEnv` when
+// caching predicates with freshened types in the global cache
+
+use std::marker::PhantomData;
+pub trait Allocator<R> {
+ type Buffer;
+}
+pub struct DefaultAllocator;
+impl <R> Allocator<R> for DefaultAllocator {
+ type Buffer = ();
+}
+pub type Owned<R> = <DefaultAllocator as Allocator<R>>::Buffer;
+pub type MatrixMN<R> = Matrix<R, Owned<R>>;
+pub type Matrix4<N> = Matrix<N, ()>;
+pub struct Matrix<R, S> {
+ pub data: S,
+ _phantoms: PhantomData<R>,
+}
+pub fn set_object_transform(matrix: &Matrix4<()>) {
+ matrix.js_buffer_view();
+}
+pub trait Storable {
+ type Cell;
+ fn slice_to_items(_buffer: &()) -> &[Self::Cell] {
+ unimplemented!()
+ }
+}
+pub type Cell<T> = <T as Storable>::Cell;
+impl<R> Storable for MatrixMN<R>
+where
+ DefaultAllocator: Allocator<R>,
+{
+ type Cell = ();
+}
+pub trait JsBufferView {
+ fn js_buffer_view(&self) -> usize {
+ unimplemented!()
+ }
+}
+impl<R> JsBufferView for [MatrixMN<R>]
+where
+ DefaultAllocator: Allocator<R>,
+ MatrixMN<R>: Storable,
+ [Cell<MatrixMN<R>>]: JsBufferView,
+{
+ fn js_buffer_view(&self) -> usize {
+ <MatrixMN<R> as Storable>::slice_to_items(&()).js_buffer_view()
+ }
+}
+impl JsBufferView for [()] {}
+impl<R> JsBufferView for MatrixMN<R> where DefaultAllocator: Allocator<R> {}
diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs
new file mode 100644
index 000000000..19131684a
--- /dev/null
+++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs
@@ -0,0 +1,143 @@
+// compile-flags: --edition=2021
+
+#![feature(rustc_attrs)]
+
+use core::any::Any;
+use core::marker::PhantomData;
+
+fn main() {
+ test::<MaskedStorage<GenericComp<Pos>>>(make());
+ //~^ ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ //~| ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+
+ test::<MaskedStorage<GenericComp2<Pos>>>(make());
+ //~^ ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ //~| ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+}
+
+#[rustc_evaluate_where_clauses]
+fn test<T: Sized>(_: T) {}
+
+fn make<T>() -> T {
+ todo!()
+}
+
+struct DerefWrap<T>(T);
+
+impl<T> core::ops::Deref for DerefWrap<T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+struct Storage<T, D> {
+ phantom: PhantomData<(T, D)>,
+}
+
+type ReadStorage<T> = Storage<T, DerefWrap<MaskedStorage<T>>>;
+
+pub trait Component {
+ type Storage;
+}
+
+struct VecStorage;
+
+struct Pos;
+
+impl Component for Pos {
+ type Storage = VecStorage;
+}
+
+struct GenericComp<T> {
+ _t: T,
+}
+
+impl<T: 'static> Component for GenericComp<T> {
+ type Storage = VecStorage;
+}
+
+struct GenericComp2<T> {
+ _t: T,
+}
+
+impl<T: 'static> Component for GenericComp2<T> where for<'a> &'a bool: 'a {
+ type Storage = VecStorage;
+}
+
+struct ReadData {
+ pos_interpdata: ReadStorage<GenericComp<Pos>>,
+}
+
+trait System {
+ type SystemData;
+
+ fn run(data: Self::SystemData, any: Box<dyn Any>);
+}
+
+struct Sys;
+
+impl System for Sys {
+ type SystemData = (ReadData, ReadStorage<Pos>);
+
+ fn run((data, pos): Self::SystemData, any: Box<dyn Any>) {
+ <ReadStorage<GenericComp<Pos>> as SystemData>::setup(any);
+
+ ParJoin::par_join((&pos, &data.pos_interpdata));
+ }
+}
+
+trait ParJoin {
+ fn par_join(self)
+ where
+ Self: Sized,
+ {
+ }
+}
+
+impl<'a, T, D> ParJoin for &'a Storage<T, D>
+where
+ T: Component,
+ D: core::ops::Deref<Target = MaskedStorage<T>>,
+ T::Storage: Sync,
+{
+}
+
+impl<A, B> ParJoin for (A, B)
+where
+ A: ParJoin,
+ B: ParJoin,
+{
+}
+
+pub trait SystemData {
+ fn setup(any: Box<dyn Any>);
+}
+
+impl<T: 'static> SystemData for ReadStorage<T>
+where
+ T: Component,
+{
+ fn setup(any: Box<dyn Any>) {
+ let storage: &MaskedStorage<T> = any.downcast_ref().unwrap();
+
+ <dyn Any as CastFrom<MaskedStorage<T>>>::cast(&storage);
+ }
+}
+
+pub struct MaskedStorage<T: Component> {
+ _inner: T::Storage,
+}
+
+pub unsafe trait CastFrom<T> {
+ fn cast(t: &T) -> &Self;
+}
+
+unsafe impl<T> CastFrom<T> for dyn Any
+where
+ T: Any + 'static,
+{
+ fn cast(t: &T) -> &Self {
+ t
+ }
+}
diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr
new file mode 100644
index 000000000..ebf977dd6
--- /dev/null
+++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr
@@ -0,0 +1,38 @@
+error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ --> $DIR/issue-85360-eval-obligation-ice.rs:9:5
+ |
+LL | test::<MaskedStorage<GenericComp<Pos>>>(make());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn test<T: Sized>(_: T) {}
+ | - predicate
+
+error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ --> $DIR/issue-85360-eval-obligation-ice.rs:9:5
+ |
+LL | test::<MaskedStorage<GenericComp<Pos>>>(make());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn test<T: Sized>(_: T) {}
+ | ----- predicate
+
+error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ --> $DIR/issue-85360-eval-obligation-ice.rs:13:5
+ |
+LL | test::<MaskedStorage<GenericComp2<Pos>>>(make());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn test<T: Sized>(_: T) {}
+ | - predicate
+
+error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ --> $DIR/issue-85360-eval-obligation-ice.rs:13:5
+ |
+LL | test::<MaskedStorage<GenericComp2<Pos>>>(make());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn test<T: Sized>(_: T) {}
+ | ----- predicate
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/traits/issue-85735.rs b/tests/ui/traits/issue-85735.rs
new file mode 100644
index 000000000..fb387a9c9
--- /dev/null
+++ b/tests/ui/traits/issue-85735.rs
@@ -0,0 +1,13 @@
+// Regression test for the invalid suggestion in #85735 (the
+// underlying issue #21974 still exists here).
+
+trait Foo {}
+impl<'a, 'b, T> Foo for T
+where
+ T: FnMut(&'a ()),
+ //~^ ERROR: type annotations needed
+ T: FnMut(&'b ()),
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-85735.stderr b/tests/ui/traits/issue-85735.stderr
new file mode 100644
index 000000000..9e80497ca
--- /dev/null
+++ b/tests/ui/traits/issue-85735.stderr
@@ -0,0 +1,18 @@
+error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>`
+ --> $DIR/issue-85735.rs:7:8
+ |
+LL | T: FnMut(&'a ()),
+ | ^^^^^^^^^^^^^
+ |
+note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found
+ --> $DIR/issue-85735.rs:7:8
+ |
+LL | T: FnMut(&'a ()),
+ | ^^^^^^^^^^^^^
+LL |
+LL | T: FnMut(&'b ()),
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/issue-87558.rs b/tests/ui/traits/issue-87558.rs
new file mode 100644
index 000000000..c5d86bd63
--- /dev/null
+++ b/tests/ui/traits/issue-87558.rs
@@ -0,0 +1,9 @@
+struct ErrorKind;
+struct Error(ErrorKind);
+impl Fn(&isize) for Error {
+ //~^ ERROR manual implementations of `Fn` are experimental
+ //~| ERROR associated type bindings are not allowed here
+ fn from() {} //~ ERROR method `from` is not a member of trait `Fn`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr
new file mode 100644
index 000000000..494274d8c
--- /dev/null
+++ b/tests/ui/traits/issue-87558.stderr
@@ -0,0 +1,24 @@
+error[E0407]: method `from` is not a member of trait `Fn`
+ --> $DIR/issue-87558.rs:6:5
+ |
+LL | fn from() {}
+ | ^^^^^^^^^^^^ not a member of trait `Fn`
+
+error[E0183]: manual implementations of `Fn` are experimental
+ --> $DIR/issue-87558.rs:3:6
+ |
+LL | impl Fn(&isize) for Error {
+ | ^^^^^^^^^^ manual implementations of `Fn` are experimental
+ |
+ = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0229]: associated type bindings are not allowed here
+ --> $DIR/issue-87558.rs:3:6
+ |
+LL | impl Fn(&isize) for Error {
+ | ^^^^^^^^^^ associated type not allowed here
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0183, E0229, E0407.
+For more information about an error, try `rustc --explain E0183`.
diff --git a/tests/ui/traits/issue-89119.rs b/tests/ui/traits/issue-89119.rs
new file mode 100644
index 000000000..170f69915
--- /dev/null
+++ b/tests/ui/traits/issue-89119.rs
@@ -0,0 +1,11 @@
+// This is a regression test for issue #89119: an issue in intercrate mode caching.
+//
+// It requires multiple crates, of course, but the bug is triggered by the code in the dependency,
+// not the main crate. This is why this file is empty.
+//
+// The auxiliary crate used in the test contains the code minimized from `zvariant-2.8.0`.
+
+// check-pass
+// aux-build: issue_89119_intercrate_caching.rs
+
+fn main() {}
diff --git a/tests/ui/traits/issue-90195-2.rs b/tests/ui/traits/issue-90195-2.rs
new file mode 100644
index 000000000..b739dc46e
--- /dev/null
+++ b/tests/ui/traits/issue-90195-2.rs
@@ -0,0 +1,20 @@
+// check-pass
+pub trait Archive {
+ type Archived;
+}
+
+impl<T> Archive for Option<T> {
+ type Archived = ();
+}
+pub type Archived<T> = <T as Archive>::Archived;
+
+pub trait Deserialize<D> {}
+
+const ARRAY_SIZE: usize = 32;
+impl<__D> Deserialize<__D> for ()
+where
+ Option<[u8; ARRAY_SIZE]>: Archive,
+ Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>,
+{
+}
+fn main() {}
diff --git a/tests/ui/traits/issue-90195.rs b/tests/ui/traits/issue-90195.rs
new file mode 100644
index 000000000..543c9f197
--- /dev/null
+++ b/tests/ui/traits/issue-90195.rs
@@ -0,0 +1,21 @@
+// check-pass
+pub trait Archive {
+ type Archived;
+}
+
+impl<T> Archive for Option<T> {
+ type Archived = ();
+}
+pub type Archived<T> = <T as Archive>::Archived;
+
+pub trait Deserialize<D> {}
+
+const ARRAY_SIZE: usize = 32;
+impl<__D> Deserialize<__D> for ()
+where
+ Option<[u8; ARRAY_SIZE]>: Archive,
+ Option<[u8; ARRAY_SIZE]>: Archive,
+ Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>,
+{
+}
+fn main() {}
diff --git a/tests/ui/traits/issue-90662-projection-caching.rs b/tests/ui/traits/issue-90662-projection-caching.rs
new file mode 100644
index 000000000..879f30071
--- /dev/null
+++ b/tests/ui/traits/issue-90662-projection-caching.rs
@@ -0,0 +1,34 @@
+// check-pass
+
+// Regression test for issue #90662
+// Tests that projection caching does not cause a spurious error
+
+trait HasProvider<T: ?Sized> {}
+trait Provider<M> {
+ type Interface: ?Sized;
+}
+
+trait Repository {}
+trait Service {}
+
+struct DbConnection;
+impl<M> Provider<M> for DbConnection {
+ type Interface = DbConnection;
+}
+
+struct RepositoryImpl;
+impl<M: HasProvider<DbConnection>> Provider<M> for RepositoryImpl {
+ type Interface = dyn Repository;
+}
+
+struct ServiceImpl;
+impl<M: HasProvider<dyn Repository>> Provider<M> for ServiceImpl {
+ type Interface = dyn Service;
+}
+
+struct TestModule;
+impl HasProvider<<DbConnection as Provider<Self>>::Interface> for TestModule {}
+impl HasProvider<<RepositoryImpl as Provider<Self>>::Interface> for TestModule {}
+impl HasProvider<<ServiceImpl as Provider<Self>>::Interface> for TestModule {}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-91594.rs b/tests/ui/traits/issue-91594.rs
new file mode 100644
index 000000000..930f7f0c6
--- /dev/null
+++ b/tests/ui/traits/issue-91594.rs
@@ -0,0 +1,17 @@
+// #91594: This used to ICE.
+
+trait Component<M> {
+ type Interface;
+}
+trait HasComponent<I> {}
+
+struct Foo;
+
+impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
+//~^ ERROR the trait bound `Foo: HasComponent<()>` is not satisfied
+
+impl<M: HasComponent<()>> Component<M> for Foo {
+ type Interface = u8;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr
new file mode 100644
index 000000000..85d903fad
--- /dev/null
+++ b/tests/ui/traits/issue-91594.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
+ --> $DIR/issue-91594.rs:10:19
+ |
+LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
+ |
+ = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
+note: required for `Foo` to implement `Component<Foo>`
+ --> $DIR/issue-91594.rs:13:27
+ |
+LL | impl<M: HasComponent<()>> Component<M> for Foo {
+ | ---------------- ^^^^^^^^^^^^ ^^^
+ | |
+ | unsatisfied trait bound introduced here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.rs b/tests/ui/traits/issue-91949-hangs-on-recursion.rs
new file mode 100644
index 000000000..6474b2b38
--- /dev/null
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.rs
@@ -0,0 +1,32 @@
+// build-fail
+// compile-flags: -Zinline-mir=no
+// error-pattern: overflow evaluating the requirement `(): Sized`
+// error-pattern: function cannot return without recursing
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+// Regression test for #91949.
+// This hanged *forever* on 1.56, fixed by #90423.
+
+#![recursion_limit = "256"]
+
+struct Wrapped<T>(T);
+
+struct IteratorOfWrapped<T, I: Iterator<Item = T>>(I);
+
+impl<T, I: Iterator<Item = T>> Iterator for IteratorOfWrapped<T, I> {
+ type Item = Wrapped<T>;
+ fn next(&mut self) -> Option<Wrapped<T>> {
+ self.0.next().map(Wrapped)
+ }
+}
+
+fn recurse<T>(elements: T) -> Vec<char>
+where
+ T: Iterator<Item = ()>,
+{
+ recurse(IteratorOfWrapped(elements).map(|t| t.0))
+}
+
+fn main() {
+ recurse(std::iter::empty());
+}
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
new file mode 100644
index 000000000..1f18c5daf
--- /dev/null
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -0,0 +1,25 @@
+warning: function cannot return without recursing
+ --> $DIR/issue-91949-hangs-on-recursion.rs:23:1
+ |
+LL | / fn recurse<T>(elements: T) -> Vec<char>
+LL | | where
+LL | | T: Iterator<Item = ()>,
+ | |___________________________^ cannot return without recursing
+LL | {
+LL | recurse(IteratorOfWrapped(elements).map(|t| t.0))
+ | ------------------------------------------------- recursive call site
+ |
+ = help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
+
+error[E0275]: overflow evaluating the requirement `(): Sized`
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
+ = note: required for `std::iter::Empty<()>` to implement `Iterator`
+ = note: 171 redundant requirements hidden
+ = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
+ = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/issue-92292.rs b/tests/ui/traits/issue-92292.rs
new file mode 100644
index 000000000..bb3700a2b
--- /dev/null
+++ b/tests/ui/traits/issue-92292.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+pub struct MyGenericType<T> {
+ _marker: PhantomData<*const T>,
+}
+
+pub struct MyNonGenericType;
+
+impl<T> From<MyGenericType<T>> for MyNonGenericType {
+ fn from(_: MyGenericType<T>) -> Self {
+ todo!()
+ }
+}
+
+pub trait MyTrait {
+ const MY_CONSTANT: i32;
+}
+
+impl<T> MyTrait for MyGenericType<T>
+where
+ Self: Into<MyNonGenericType>,
+{
+ const MY_CONSTANT: i32 = 1;
+}
+
+impl<T> MyGenericType<T> {
+ const MY_OTHER_CONSTANT: i32 = <MyGenericType<T> as MyTrait>::MY_CONSTANT;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-9394-inherited-calls.rs b/tests/ui/traits/issue-9394-inherited-calls.rs
new file mode 100644
index 000000000..cc0dd4fc1
--- /dev/null
+++ b/tests/ui/traits/issue-9394-inherited-calls.rs
@@ -0,0 +1,62 @@
+// run-pass
+
+trait Base: Base2 + Base3{
+ fn foo(&self) -> String;
+ fn foo1(&self) -> String;
+ fn foo2(&self) -> String{
+ "base foo2".to_string()
+ }
+}
+
+trait Base2: Base3{
+ fn baz(&self) -> String;
+}
+
+trait Base3{
+ fn root(&self) -> String;
+}
+
+trait Super: Base{
+ fn bar(&self) -> String;
+}
+
+struct X;
+
+impl Base for X {
+ fn foo(&self) -> String{
+ "base foo".to_string()
+ }
+ fn foo1(&self) -> String{
+ "base foo1".to_string()
+ }
+
+}
+
+impl Base2 for X {
+ fn baz(&self) -> String{
+ "base2 baz".to_string()
+ }
+}
+
+impl Base3 for X {
+ fn root(&self) -> String{
+ "base3 root".to_string()
+ }
+}
+
+impl Super for X {
+ fn bar(&self) -> String{
+ "super bar".to_string()
+ }
+}
+
+pub fn main() {
+ let n = X;
+ let s = &n as &dyn Super;
+ assert_eq!(s.bar(),"super bar".to_string());
+ assert_eq!(s.foo(),"base foo".to_string());
+ assert_eq!(s.foo1(),"base foo1".to_string());
+ assert_eq!(s.foo2(),"base foo2".to_string());
+ assert_eq!(s.baz(),"base2 baz".to_string());
+ assert_eq!(s.root(),"base3 root".to_string());
+}
diff --git a/tests/ui/traits/issue-95311.rs b/tests/ui/traits/issue-95311.rs
new file mode 100644
index 000000000..9d40d254a
--- /dev/null
+++ b/tests/ui/traits/issue-95311.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// Test to check that pointee trait doesn't let region variables escape into the cache
+
+#![feature(ptr_metadata)]
+
+trait Bar: Sized + 'static {}
+
+struct Foo<B: Bar> {
+ marker: std::marker::PhantomData<B>,
+}
+
+impl<B: Bar> Foo<B> {
+ fn foo<T: ?Sized>(value: &T) {
+ std::ptr::metadata(value);
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-95898.rs b/tests/ui/traits/issue-95898.rs
new file mode 100644
index 000000000..41a20b899
--- /dev/null
+++ b/tests/ui/traits/issue-95898.rs
@@ -0,0 +1,9 @@
+// Test for #95898: The trait suggestion had an extra `:` after the trait.
+// edition:2021
+
+fn foo<T:>(t: T) {
+ t.clone();
+ //~^ ERROR no method named `clone` found for type parameter `T` in the current scope
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-95898.stderr b/tests/ui/traits/issue-95898.stderr
new file mode 100644
index 000000000..ca7bacdbf
--- /dev/null
+++ b/tests/ui/traits/issue-95898.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `clone` found for type parameter `T` in the current scope
+ --> $DIR/issue-95898.rs:5:7
+ |
+LL | fn foo<T:>(t: T) {
+ | - method `clone` not found for this type parameter
+LL | t.clone();
+ | ^^^^^ method not found in `T`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `clone`, perhaps you need to restrict type parameter `T` with it:
+ |
+LL | fn foo<T: Clone>(t: T) {
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/issue-96664.rs b/tests/ui/traits/issue-96664.rs
new file mode 100644
index 000000000..3c5314af7
--- /dev/null
+++ b/tests/ui/traits/issue-96664.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+pub trait State = Clone + Send + Sync + PartialOrd + PartialEq + std::fmt::Display;
+pub trait RandState<S: State> = FnMut() -> S + Send;
+
+pub trait Evaluator {
+ type State;
+}
+
+pub struct Evolver<E: Evaluator> {
+ rand_state: Box<dyn RandState<E::State>>,
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-96665.rs b/tests/ui/traits/issue-96665.rs
new file mode 100644
index 000000000..a571d48d9
--- /dev/null
+++ b/tests/ui/traits/issue-96665.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+pub trait Sequence<Item, Subsequence: Sequence<Item, Subsequence>> {}
+
+pub trait NodeWalk<Graph: GraphBase, NodeSubwalk: NodeWalk<Graph, NodeSubwalk>>:
+ Sequence<Graph::NodeIndex, NodeSubwalk>
+{
+}
+
+pub trait GraphBase {
+ type NodeIndex;
+}
+
+pub trait WalkableGraph: GraphBase {}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-97576.rs b/tests/ui/traits/issue-97576.rs
new file mode 100644
index 000000000..fdc85e9fa
--- /dev/null
+++ b/tests/ui/traits/issue-97576.rs
@@ -0,0 +1,13 @@
+struct Foo {
+ bar: String,
+}
+
+impl Foo {
+ pub fn new(bar: impl ToString) -> Self {
+ Self {
+ bar: bar.into(), //~ ERROR the trait bound `String: From<impl ToString>` is not satisfied
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr
new file mode 100644
index 000000000..9062a0fab
--- /dev/null
+++ b/tests/ui/traits/issue-97576.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
+ --> $DIR/issue-97576.rs:8:22
+ |
+LL | bar: bar.into(),
+ | ^^^^ the trait `From<impl ToString>` is not implemented for `String`
+ |
+ = note: required for `impl ToString` to implement `Into<String>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-97695-double-trivial-bound.rs b/tests/ui/traits/issue-97695-double-trivial-bound.rs
new file mode 100644
index 000000000..213605b51
--- /dev/null
+++ b/tests/ui/traits/issue-97695-double-trivial-bound.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Zinline-mir --emit=mir
+// build-pass
+
+pub trait Associate {
+ type Associated;
+}
+
+pub struct Wrap<'a> {
+ pub field: &'a i32,
+}
+
+pub trait Create<T> {
+ fn create() -> Self;
+}
+
+pub fn oh_no<'a, T>()
+where
+ Wrap<'a>: Associate,
+ <Wrap<'a> as Associate>::Associated: Create<T>,
+{
+ <Wrap<'a> as Associate>::Associated::create();
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/issue-99875.rs b/tests/ui/traits/issue-99875.rs
new file mode 100644
index 000000000..cf73fd8d3
--- /dev/null
+++ b/tests/ui/traits/issue-99875.rs
@@ -0,0 +1,16 @@
+struct Argument;
+struct Return;
+
+fn function(_: Argument) -> Return { todo!() }
+
+trait Trait {}
+impl Trait for fn(Argument) -> Return {}
+
+fn takes(_: impl Trait) {}
+
+fn main() {
+ takes(function);
+ //~^ ERROR the trait bound
+ takes(|_: Argument| -> Return { todo!() });
+ //~^ ERROR the trait bound
+}
diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr
new file mode 100644
index 000000000..fb6eebbd2
--- /dev/null
+++ b/tests/ui/traits/issue-99875.stderr
@@ -0,0 +1,36 @@
+error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
+ --> $DIR/issue-99875.rs:12:11
+ |
+LL | takes(function);
+ | ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `takes`
+ --> $DIR/issue-99875.rs:9:18
+ |
+LL | fn takes(_: impl Trait) {}
+ | ^^^^^ required by this bound in `takes`
+help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as`
+ |
+LL | takes(function as fn(Argument) -> Return);
+ | +++++++++++++++++++++++++
+
+error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
+ --> $DIR/issue-99875.rs:14:11
+ |
+LL | takes(|_: Argument| -> Return { todo!() });
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+ --> $DIR/issue-99875.rs:9:18
+ |
+LL | fn takes(_: impl Trait) {}
+ | ^^^^^ required by this bound in `takes`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/item-inside-macro.rs b/tests/ui/traits/item-inside-macro.rs
new file mode 100644
index 000000000..54bf872d0
--- /dev/null
+++ b/tests/ui/traits/item-inside-macro.rs
@@ -0,0 +1,30 @@
+// run-pass
+// Issue #34183
+
+macro_rules! foo {
+ () => {
+ fn foo() { }
+ }
+}
+
+macro_rules! bar {
+ () => {
+ fn bar();
+ }
+}
+
+trait Bleh {
+ foo!();
+ bar!();
+}
+
+struct Test;
+
+impl Bleh for Test {
+ fn bar() {}
+}
+
+fn main() {
+ Test::bar();
+ Test::foo();
+}
diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs
new file mode 100644
index 000000000..38d06b967
--- /dev/null
+++ b/tests/ui/traits/item-privacy.rs
@@ -0,0 +1,134 @@
+#![feature(associated_type_defaults)]
+
+struct S;
+
+mod method {
+ trait A {
+ fn a(&self) { }
+ }
+
+ pub trait B {
+ fn b(&self) { }
+ }
+
+ pub trait C: A + B {
+ fn c(&self) { }
+ }
+
+ impl A for ::S {}
+ impl B for ::S {}
+ impl C for ::S {}
+}
+
+mod assoc_const {
+ trait A {
+ const A: u8 = 0;
+ }
+
+ pub trait B {
+ const B: u8 = 0;
+ }
+
+ pub trait C: A + B {
+ const C: u8 = 0;
+ }
+
+ impl A for ::S {}
+ impl B for ::S {}
+ impl C for ::S {}
+}
+
+mod assoc_ty {
+ trait A {
+ type A = u8;
+ }
+
+ pub trait B {
+ type B = u8;
+ }
+
+ pub trait C: A + B {
+ type C = u8;
+ }
+
+ impl A for ::S {}
+ impl B for ::S {}
+ impl C for ::S {}
+}
+
+fn check_method() {
+ // A is private
+ // B is pub, not in scope
+ // C : A + B is pub, in scope
+ use method::C;
+
+ // Methods, method call
+ // a, b, c are resolved as trait items, their traits need to be in scope
+ S.a(); //~ ERROR no method named `a` found
+ S.b(); //~ ERROR no method named `b` found
+ S.c(); // OK
+ // a, b, c are resolved as inherent items, their traits don't need to be in scope
+ let c = &S as &dyn C;
+ c.a(); //~ ERROR associated function `a` is private
+ c.b(); // OK
+ c.c(); // OK
+
+ // Methods, UFCS
+ // a, b, c are resolved as trait items, their traits need to be in scope
+ S::a(&S);
+ //~^ ERROR no function or associated item named `a` found
+ S::b(&S);
+ //~^ ERROR no function or associated item named `b` found
+ S::c(&S); // OK
+ // a, b, c are resolved as inherent items, their traits don't need to be in scope
+ <dyn C>::a(&S); //~ ERROR associated function `a` is private
+ <dyn C>::b(&S); // OK
+ C::c(&S); // OK
+}
+
+fn check_assoc_const() {
+ // A is private
+ // B is pub, not in scope
+ // C : A + B is pub, in scope
+ use assoc_const::C;
+
+ // Associated constants
+ // A, B, C are resolved as trait items, their traits need to be in scope
+ S::A; //~ ERROR no associated item named `A` found
+ S::B; //~ ERROR no associated item named `B` found
+ S::C; // OK
+ // A, B, C are resolved as inherent items, their traits don't need to be in scope
+ <dyn C>::A; //~ ERROR associated constant `A` is private
+ //~^ ERROR the trait `assoc_const::C` cannot be made into an object
+ <dyn C>::B; // ERROR the trait `assoc_const::C` cannot be made into an object
+ C::C; // OK
+}
+
+fn check_assoc_ty<T: assoc_ty::C>() {
+ // A is private
+ // B is pub, not in scope
+ // C : A + B is pub, in scope
+ use assoc_ty::C;
+
+ // Associated types
+ // A, B, C are resolved as trait items, their traits need to be in scope, not implemented yet
+ let _: S::A; //~ ERROR ambiguous associated type
+ let _: S::B; //~ ERROR ambiguous associated type
+ let _: S::C; //~ ERROR ambiguous associated type
+ // A, B, C are resolved as inherent items, their traits don't need to be in scope
+ let _: T::A; //~ ERROR associated type `A` is private
+ let _: T::B; // OK
+ let _: T::C; // OK
+
+ // Associated types, bindings
+ let _: dyn assoc_ty::B<
+ B = u8, // OK
+ >;
+ let _: dyn C<
+ A = u8, //~ ERROR associated type `A` is private
+ B = u8, // OK
+ C = u8, // OK
+ >;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
new file mode 100644
index 000000000..293cfbda8
--- /dev/null
+++ b/tests/ui/traits/item-privacy.stderr
@@ -0,0 +1,188 @@
+error[E0599]: no method named `a` found for struct `S` in the current scope
+ --> $DIR/item-privacy.rs:67:7
+ |
+LL | struct S;
+ | -------- method `a` not found for this struct
+...
+LL | S.a();
+ | ^ method not found in `S`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `method::A` defines an item `a`, perhaps you need to implement it
+ --> $DIR/item-privacy.rs:6:5
+ |
+LL | trait A {
+ | ^^^^^^^
+
+error[E0599]: no method named `b` found for struct `S` in the current scope
+ --> $DIR/item-privacy.rs:68:7
+ |
+LL | struct S;
+ | -------- method `b` not found for this struct
+...
+LL | fn b(&self) { }
+ | - the method is available for `S` here
+...
+LL | S.b();
+ | ^ method not found in `S`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use method::B;
+ |
+
+error[E0624]: associated function `a` is private
+ --> $DIR/item-privacy.rs:72:7
+ |
+LL | fn a(&self) { }
+ | ----------- private associated function defined here
+...
+LL | c.a();
+ | ^ private associated function
+
+error[E0599]: no function or associated item named `a` found for struct `S` in the current scope
+ --> $DIR/item-privacy.rs:78:8
+ |
+LL | struct S;
+ | -------- function or associated item `a` not found for this struct
+...
+LL | S::a(&S);
+ | ^ function or associated item not found in `S`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `method::A` defines an item `a`, perhaps you need to implement it
+ --> $DIR/item-privacy.rs:6:5
+ |
+LL | trait A {
+ | ^^^^^^^
+
+error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
+ --> $DIR/item-privacy.rs:80:8
+ |
+LL | struct S;
+ | -------- function or associated item `b` not found for this struct
+...
+LL | S::b(&S);
+ | ^ function or associated item not found in `S`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use method::B;
+ |
+
+error[E0624]: associated function `a` is private
+ --> $DIR/item-privacy.rs:84:14
+ |
+LL | fn a(&self) { }
+ | ----------- private associated function defined here
+...
+LL | <dyn C>::a(&S);
+ | ^ private associated function
+
+error[E0599]: no associated item named `A` found for struct `S` in the current scope
+ --> $DIR/item-privacy.rs:97:8
+ |
+LL | struct S;
+ | -------- associated item `A` not found for this struct
+...
+LL | S::A;
+ | ^ associated item not found in `S`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `assoc_const::A` defines an item `A`, perhaps you need to implement it
+ --> $DIR/item-privacy.rs:24:5
+ |
+LL | trait A {
+ | ^^^^^^^
+
+error[E0599]: no associated item named `B` found for struct `S` in the current scope
+ --> $DIR/item-privacy.rs:98:8
+ |
+LL | struct S;
+ | -------- associated item `B` not found for this struct
+...
+LL | S::B;
+ | ^ associated item not found in `S`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use assoc_const::B;
+ |
+
+error[E0624]: associated constant `A` is private
+ --> $DIR/item-privacy.rs:101:14
+ |
+LL | const A: u8 = 0;
+ | ----------- private associated constant defined here
+...
+LL | <dyn C>::A;
+ | ^ private associated constant
+
+error[E0038]: the trait `assoc_const::C` cannot be made into an object
+ --> $DIR/item-privacy.rs:101:6
+ |
+LL | <dyn C>::A;
+ | ^^^^^ `assoc_const::C` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/item-privacy.rs:25:15
+ |
+LL | const A: u8 = 0;
+ | ^ ...because it contains this associated `const`
+...
+LL | const B: u8 = 0;
+ | ^ ...because it contains this associated `const`
+...
+LL | pub trait C: A + B {
+ | - this trait cannot be made into an object...
+LL | const C: u8 = 0;
+ | ^ ...because it contains this associated `const`
+ = help: consider moving `C` to another trait
+ = help: consider moving `A` to another trait
+ = help: consider moving `B` to another trait
+
+error[E0223]: ambiguous associated type
+ --> $DIR/item-privacy.rs:115:12
+ |
+LL | let _: S::A;
+ | ^^^^
+ |
+help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path
+ |
+LL | let _: <S as Example>::A;
+ | ~~~~~~~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+ --> $DIR/item-privacy.rs:116:12
+ |
+LL | let _: S::B;
+ | ^^^^ help: use the fully-qualified path: `<S as assoc_ty::B>::B`
+
+error[E0223]: ambiguous associated type
+ --> $DIR/item-privacy.rs:117:12
+ |
+LL | let _: S::C;
+ | ^^^^ help: use the fully-qualified path: `<S as assoc_ty::C>::C`
+
+error[E0624]: associated type `A` is private
+ --> $DIR/item-privacy.rs:119:12
+ |
+LL | type A = u8;
+ | ------ associated type defined here
+...
+LL | let _: T::A;
+ | ^^^^ private associated type
+
+error: associated type `A` is private
+ --> $DIR/item-privacy.rs:128:9
+ |
+LL | A = u8,
+ | ^^^^^^ private associated type
+
+error: aborting due to 15 previous errors
+
+Some errors have detailed explanations: E0038, E0223, E0599, E0624.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/kindck-owned-contains-1.rs b/tests/ui/traits/kindck-owned-contains-1.rs
new file mode 100644
index 000000000..8adb06ba3
--- /dev/null
+++ b/tests/ui/traits/kindck-owned-contains-1.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(non_snake_case)]
+#![allow(non_camel_case_types)]
+
+trait repeat<A> { fn get(&self) -> A; }
+
+impl<A:Clone + 'static> repeat<A> for Box<A> {
+ fn get(&self) -> A {
+ (**self).clone()
+ }
+}
+
+fn repeater<A:Clone + 'static>(v: Box<A>) -> Box<dyn repeat<A>+'static> {
+ Box::new(v) as Box<dyn repeat<A>+'static> // No
+}
+
+pub fn main() {
+ let x = 3;
+ let y = repeater(Box::new(x));
+ assert_eq!(x, y.get());
+}
diff --git a/tests/ui/traits/map-types.rs b/tests/ui/traits/map-types.rs
new file mode 100644
index 000000000..dc33b9618
--- /dev/null
+++ b/tests/ui/traits/map-types.rs
@@ -0,0 +1,19 @@
+use std::collections::HashMap;
+
+
+
+trait Map<K, V>
+{
+ fn get(&self, k: K) -> V { panic!() }
+}
+
+impl<K, V> Map<K, V> for HashMap<K, V> {}
+
+// Test that trait types printed in error msgs include the type arguments.
+
+fn main() {
+ let x: Box<HashMap<isize, isize>> = HashMap::new().into();
+ let x: Box<dyn Map<isize, isize>> = x;
+ let y: Box<dyn Map<usize, isize>> = Box::new(x);
+ //~^ ERROR `Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
+}
diff --git a/tests/ui/traits/map-types.stderr b/tests/ui/traits/map-types.stderr
new file mode 100644
index 000000000..f685c50b0
--- /dev/null
+++ b/tests/ui/traits/map-types.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
+ --> $DIR/map-types.rs:17:41
+ |
+LL | let y: Box<dyn Map<usize, isize>> = Box::new(x);
+ | ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `Box<dyn Map<isize, isize>>`
+ |
+ = help: the trait `Map<K, V>` is implemented for `HashMap<K, V>`
+ = note: required for the cast from `Box<dyn Map<isize, isize>>` to the object type `dyn Map<usize, isize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/matching-lifetimes.rs b/tests/ui/traits/matching-lifetimes.rs
new file mode 100644
index 000000000..1430dc655
--- /dev/null
+++ b/tests/ui/traits/matching-lifetimes.rs
@@ -0,0 +1,20 @@
+// Tests that the trait matching code takes lifetime parameters into account.
+// (Issue #15517.)
+
+struct Foo<'a,'b> {
+ x: &'a isize,
+ y: &'b isize,
+}
+
+trait Tr : Sized {
+ fn foo(x: Self) {}
+}
+
+impl<'a,'b> Tr for Foo<'a,'b> {
+ fn foo(x: Foo<'b,'a>) {
+ //~^ ERROR method not compatible with trait
+ //~^^ ERROR method not compatible with trait
+ }
+}
+
+fn main(){}
diff --git a/tests/ui/traits/matching-lifetimes.stderr b/tests/ui/traits/matching-lifetimes.stderr
new file mode 100644
index 000000000..f8119ed41
--- /dev/null
+++ b/tests/ui/traits/matching-lifetimes.stderr
@@ -0,0 +1,41 @@
+error[E0308]: method not compatible with trait
+ --> $DIR/matching-lifetimes.rs:14:5
+ |
+LL | fn foo(x: Foo<'b,'a>) {
+ | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ |
+ = note: expected signature `fn(Foo<'a, 'b>)`
+ found signature `fn(Foo<'b, 'a>)`
+note: the lifetime `'b` as defined here...
+ --> $DIR/matching-lifetimes.rs:13:9
+ |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+ | ^^
+note: ...does not necessarily outlive the lifetime `'a` as defined here
+ --> $DIR/matching-lifetimes.rs:13:6
+ |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+ | ^^
+
+error[E0308]: method not compatible with trait
+ --> $DIR/matching-lifetimes.rs:14:5
+ |
+LL | fn foo(x: Foo<'b,'a>) {
+ | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ |
+ = note: expected signature `fn(Foo<'a, 'b>)`
+ found signature `fn(Foo<'b, 'a>)`
+note: the lifetime `'a` as defined here...
+ --> $DIR/matching-lifetimes.rs:13:6
+ |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+ | ^^
+note: ...does not necessarily outlive the lifetime `'b` as defined here
+ --> $DIR/matching-lifetimes.rs:13:9
+ |
+LL | impl<'a,'b> Tr for Foo<'a,'b> {
+ | ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/method-private.rs b/tests/ui/traits/method-private.rs
new file mode 100644
index 000000000..4cd184854
--- /dev/null
+++ b/tests/ui/traits/method-private.rs
@@ -0,0 +1,20 @@
+mod inner {
+ pub trait Bar {
+ fn method(&self);
+ }
+
+ pub struct Foo;
+
+ impl Foo {
+ fn method(&self) {}
+ }
+
+ impl Bar for Foo {
+ fn method(&self) {}
+ }
+}
+
+fn main() {
+ let foo = inner::Foo;
+ foo.method(); //~ ERROR is private
+}
diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr
new file mode 100644
index 000000000..8e991ec01
--- /dev/null
+++ b/tests/ui/traits/method-private.stderr
@@ -0,0 +1,18 @@
+error[E0624]: associated function `method` is private
+ --> $DIR/method-private.rs:19:9
+ |
+LL | fn method(&self) {}
+ | ---------------- private associated function defined here
+...
+LL | foo.method();
+ | ^^^^^^ private associated function
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use inner::Bar;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0624`.
diff --git a/tests/ui/traits/monad.rs b/tests/ui/traits/monad.rs
new file mode 100644
index 000000000..5d0612cf8
--- /dev/null
+++ b/tests/ui/traits/monad.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+
+
+
+trait vec_monad<A> {
+ fn bind<B, F>(&self, f: F ) -> Vec<B> where F: FnMut(&A) -> Vec<B> ;
+}
+
+impl<A> vec_monad<A> for Vec<A> {
+ fn bind<B, F>(&self, mut f: F) -> Vec<B> where F: FnMut(&A) -> Vec<B> {
+ let mut r = Vec::new();
+ for elt in self {
+ r.extend(f(elt));
+ }
+ r
+ }
+}
+
+trait option_monad<A> {
+ fn bind<B, F>(&self, f: F) -> Option<B> where F: FnOnce(&A) -> Option<B>;
+}
+
+impl<A> option_monad<A> for Option<A> {
+ fn bind<B, F>(&self, f: F) -> Option<B> where F: FnOnce(&A) -> Option<B> {
+ match *self {
+ Some(ref a) => { f(a) }
+ None => { None }
+ }
+ }
+}
+
+fn transform(x: Option<isize>) -> Option<String> {
+ x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_string()) )
+}
+
+pub fn main() {
+ assert_eq!(transform(Some(10)), Some("11".to_string()));
+ assert_eq!(transform(None), None);
+ assert_eq!((vec!["hi".to_string()])
+ .bind(|x| vec![x.clone(), format!("{}!", x)] )
+ .bind(|x| vec![x.clone(), format!("{}?", x)] ),
+ ["hi".to_string(),
+ "hi?".to_string(),
+ "hi!".to_string(),
+ "hi!?".to_string()]);
+}
diff --git a/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs b/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs
new file mode 100644
index 000000000..bc314a39d
--- /dev/null
+++ b/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs
@@ -0,0 +1,32 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+trait Serializer {
+}
+
+trait Serializable {
+ fn serialize<S:Serializer>(&self, s: S);
+}
+
+impl Serializable for isize {
+ fn serialize<S:Serializer>(&self, _s: S) { }
+}
+
+struct F<A> { a: A }
+
+impl<A:Serializable> Serializable for F<A> {
+ fn serialize<S:Serializer>(&self, s: S) {
+ self.a.serialize(s);
+ }
+}
+
+impl Serializer for isize {
+}
+
+pub fn main() {
+ let foo = F { a: 1 };
+ foo.serialize(1);
+
+ let bar = F { a: F {a: 1 } };
+ bar.serialize(2);
+}
diff --git a/tests/ui/traits/multidispatch-bad.rs b/tests/ui/traits/multidispatch-bad.rs
new file mode 100644
index 000000000..b625b9615
--- /dev/null
+++ b/tests/ui/traits/multidispatch-bad.rs
@@ -0,0 +1,22 @@
+// Test that we detect an illegal combination of types.
+
+trait Convert<Target> {
+ fn convert(&self) -> Target;
+}
+
+impl Convert<u32> for i32 {
+ fn convert(&self) -> u32 {
+ *self as u32
+ }
+}
+
+fn test<T,U>(_: T, _: U)
+where T : Convert<U>
+{
+}
+
+fn a() {
+ test(22i32, 44i32); //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/traits/multidispatch-bad.stderr b/tests/ui/traits/multidispatch-bad.stderr
new file mode 100644
index 000000000..d58f1e2d9
--- /dev/null
+++ b/tests/ui/traits/multidispatch-bad.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/multidispatch-bad.rs:19:17
+ |
+LL | test(22i32, 44i32);
+ | ---- ^^^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/multidispatch-bad.rs:13:4
+ |
+LL | fn test<T,U>(_: T, _: U)
+ | ^^^^ ----
+help: change the type of the numeric literal from `i32` to `u32`
+ |
+LL | test(22i32, 44u32);
+ | ~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs
new file mode 100644
index 000000000..f845e198a
--- /dev/null
+++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs
@@ -0,0 +1,24 @@
+// run-pass
+// Test that we correctly ignore the blanket impl
+// because (in this case) `T` does not impl `Clone`.
+//
+// Issue #17594.
+
+use std::cell::RefCell;
+
+trait Foo {
+ fn foo(&self) {}
+}
+
+impl<T> Foo for T where T: Clone {}
+
+struct Bar;
+
+impl Bar {
+ fn foo(&self) {}
+}
+
+fn main() {
+ let b = RefCell::new(Bar);
+ b.borrow().foo();
+}
diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.rs b/tests/ui/traits/multidispatch-convert-ambig-dest.rs
new file mode 100644
index 000000000..aa74e11c3
--- /dev/null
+++ b/tests/ui/traits/multidispatch-convert-ambig-dest.rs
@@ -0,0 +1,31 @@
+// Check that we get an error in a multidisptach scenario where the
+// set of impls is ambiguous.
+
+trait Convert<Target> {
+ fn convert(&self) -> Target;
+}
+
+impl Convert<i8> for i32 {
+ fn convert(&self) -> i8 {
+ *self as i8
+ }
+}
+
+impl Convert<i16> for i32 {
+ fn convert(&self) -> i16 {
+ *self as i16
+ }
+}
+
+fn test<T,U>(_: T, _: U)
+where T : Convert<U>
+{
+}
+
+fn a() {
+ test(22, std::default::Default::default());
+ //~^ ERROR type annotations needed
+ //~| ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
new file mode 100644
index 000000000..6e6172eea
--- /dev/null
+++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
@@ -0,0 +1,43 @@
+error[E0282]: type annotations needed
+ --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
+ |
+LL | test(22, std::default::Default::default());
+ | ^^^^ cannot infer type of the type parameter `U` declared on the function `test`
+ |
+help: consider specifying the generic arguments
+ |
+LL | test::<i32, U>(22, std::default::Default::default());
+ | ++++++++++
+
+error[E0283]: type annotations needed
+ --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
+ |
+LL | test(22, std::default::Default::default());
+ | ^^^^ -------------------------------- type must be known at this point
+ | |
+ | cannot infer type of the type parameter `U` declared on the function `test`
+ |
+note: multiple `impl`s satisfying `i32: Convert<_>` found
+ --> $DIR/multidispatch-convert-ambig-dest.rs:8:1
+ |
+LL | impl Convert<i8> for i32 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Convert<i16> for i32 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `test`
+ --> $DIR/multidispatch-convert-ambig-dest.rs:21:11
+ |
+LL | fn test<T,U>(_: T, _: U)
+ | ---- required by a bound in this
+LL | where T : Convert<U>
+ | ^^^^^^^^^^ required by this bound in `test`
+help: consider specifying the generic arguments
+ |
+LL | test::<i32, U>(22, std::default::Default::default());
+ | ++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/multidispatch-infer-convert-target.rs b/tests/ui/traits/multidispatch-infer-convert-target.rs
new file mode 100644
index 000000000..626e1ae71
--- /dev/null
+++ b/tests/ui/traits/multidispatch-infer-convert-target.rs
@@ -0,0 +1,36 @@
+// run-pass
+// Test that we can infer the Target based on the Self or vice versa.
+
+
+use std::mem;
+
+trait Convert<Target> {
+ fn convert(&self) -> Target;
+}
+
+impl Convert<u32> for i16 {
+ fn convert(&self) -> u32 {
+ *self as u32
+ }
+}
+
+impl Convert<i16> for u32 {
+ fn convert(&self) -> i16 {
+ *self as i16
+ }
+}
+
+fn test<T,U>(_: T, _: U, t_size: usize, u_size: usize)
+where T : Convert<U>
+{
+ assert_eq!(mem::size_of::<T>(), t_size);
+ assert_eq!(mem::size_of::<U>(), u_size);
+}
+
+fn main() {
+ // T = i16, U = u32
+ test(22_i16, Default::default(), 2, 4);
+
+ // T = u32, U = i16
+ test(22_u32, Default::default(), 4, 2);
+}
diff --git a/tests/ui/traits/multidispatch1.rs b/tests/ui/traits/multidispatch1.rs
new file mode 100644
index 000000000..f2469e149
--- /dev/null
+++ b/tests/ui/traits/multidispatch1.rs
@@ -0,0 +1,33 @@
+// run-pass
+
+use std::fmt::Debug;
+
+trait MyTrait<T> {
+ fn get(&self) -> T;
+}
+
+#[derive(Copy, Clone)]
+struct MyType {
+ dummy: usize
+}
+
+impl MyTrait<usize> for MyType {
+ fn get(&self) -> usize { self.dummy }
+}
+
+impl MyTrait<u8> for MyType {
+ fn get(&self) -> u8 { self.dummy as u8 }
+}
+
+fn test_eq<T,M>(m: M, v: T)
+where T : Eq + Debug,
+ M : MyTrait<T>
+{
+ assert_eq!(m.get(), v);
+}
+
+pub fn main() {
+ let value = MyType { dummy: 256 + 22 };
+ test_eq::<usize, _>(value, value.dummy);
+ test_eq::<u8, _>(value, value.dummy as u8);
+}
diff --git a/tests/ui/traits/multidispatch2.rs b/tests/ui/traits/multidispatch2.rs
new file mode 100644
index 000000000..20608aabb
--- /dev/null
+++ b/tests/ui/traits/multidispatch2.rs
@@ -0,0 +1,39 @@
+// run-pass
+
+use std::fmt::Debug;
+use std::default::Default;
+
+trait MyTrait<T> {
+ fn get(&self) -> T;
+}
+
+impl<T> MyTrait<T> for T
+ where T : Default
+{
+ fn get(&self) -> T {
+ Default::default()
+ }
+}
+
+#[derive(Copy, Clone)]
+struct MyType {
+ dummy: usize
+}
+
+impl MyTrait<usize> for MyType {
+ fn get(&self) -> usize { self.dummy }
+}
+
+fn test_eq<T,M>(m: M, v: T)
+where T : Eq + Debug,
+ M : MyTrait<T>
+{
+ assert_eq!(m.get(), v);
+}
+
+pub fn main() {
+ test_eq(22_usize, 0_usize);
+
+ let value = MyType { dummy: 256 + 22 };
+ test_eq(value, value.dummy);
+}
diff --git a/tests/ui/traits/mutual-recursion-issue-75860.rs b/tests/ui/traits/mutual-recursion-issue-75860.rs
new file mode 100644
index 000000000..d7d7307b4
--- /dev/null
+++ b/tests/ui/traits/mutual-recursion-issue-75860.rs
@@ -0,0 +1,15 @@
+pub fn iso<A, B, F1, F2>(a: F1, b: F2) -> (Box<dyn Fn(A) -> B>, Box<dyn Fn(B) -> A>)
+ where
+ F1: (Fn(A) -> B) + 'static,
+ F2: (Fn(B) -> A) + 'static,
+{
+ (Box::new(a), Box::new(b))
+}
+pub fn iso_un_option<A, B>() -> (Box<dyn Fn(A) -> B>, Box<dyn Fn(B) -> A>) {
+ let left = |o_a: Option<_>| o_a.unwrap();
+ let right = |o_b: Option<_>| o_b.unwrap();
+ iso(left, right)
+ //~^ ERROR overflow
+}
+
+fn main() {}
diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr
new file mode 100644
index 000000000..23e182738
--- /dev/null
+++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr
@@ -0,0 +1,13 @@
+error[E0275]: overflow evaluating the requirement `Option<_>: Sized`
+ --> $DIR/mutual-recursion-issue-75860.rs:11:5
+ |
+LL | iso(left, right)
+ | ^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`)
+note: required by a bound in `Option`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs
new file mode 100644
index 000000000..0e17f0890
--- /dev/null
+++ b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs
@@ -0,0 +1,7 @@
+#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
+
+pub trait ForeignTrait {}
+
+impl ForeignTrait for u32 {}
+impl !ForeignTrait for String {}
diff --git a/tests/ui/traits/negative-impls/eager-mono.rs b/tests/ui/traits/negative-impls/eager-mono.rs
new file mode 100644
index 000000000..ce770376c
--- /dev/null
+++ b/tests/ui/traits/negative-impls/eager-mono.rs
@@ -0,0 +1,12 @@
+// build-pass
+// compile-flags:-C link-dead-code=y
+
+#![feature(negative_impls)]
+
+trait Foo {
+ fn foo() {}
+}
+
+impl !Foo for () {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
new file mode 100644
index 000000000..17ddaa312
--- /dev/null
+++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
@@ -0,0 +1,53 @@
+// This tests issue #79683: note in the error message that the trait is
+// explicitly unimplemented instead of suggesting to implement it.
+
+#![feature(negative_impls)]
+
+struct Qux;
+//~^ NOTE method `clone` not found for this
+//~^^ NOTE method `foo` not found for this
+
+impl !Clone for Qux {}
+
+trait Bar {
+ fn bar(&self);
+}
+
+impl !Bar for u32 {}
+
+trait Foo {
+ fn foo(&self);
+}
+//~^^^ NOTE `Foo` defines an item `foo`, perhaps you need to implement it
+
+trait FooBar {
+ fn foo(&self);
+}
+
+impl !Foo for Qux {}
+
+impl !FooBar for Qux {}
+
+impl !FooBar for u32 {}
+
+fn main() {
+ Qux.clone();
+ //~^ ERROR no method named `clone` found for struct `Qux`
+ //~| NOTE method not found in `Qux`
+ //~| NOTE `Clone` defines an item `clone`, but is explicitly unimplemented
+
+ 0_u32.bar();
+ //~^ ERROR no method named `bar` found for type `u32`
+ //~| NOTE method not found in `u32`
+ //~| NOTE `Bar` defines an item `bar`, but is explicitly unimplemented
+
+ Qux.foo();
+ //~^ ERROR no method named `foo` found for struct `Qux`
+ //~| NOTE method not found in `Qux`
+ //~| NOTE the following traits define an item `foo`, but are explicitly unimplemented
+
+ 0_u32.foo();
+ //~^ ERROR no method named `foo` found for type `u32`
+ //~| NOTE method not found in `u32`
+ //~| NOTE `FooBar` defines an item `foo`, but is explicitly unimplemented
+}
diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
new file mode 100644
index 000000000..b29442d7b
--- /dev/null
+++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
@@ -0,0 +1,52 @@
+error[E0599]: no method named `clone` found for struct `Qux` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:34:9
+ |
+LL | struct Qux;
+ | ---------- method `clone` not found for this struct
+...
+LL | Qux.clone();
+ | ^^^^^ method not found in `Qux`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the trait `Clone` defines an item `clone`, but is explicitly unimplemented
+
+error[E0599]: no method named `bar` found for type `u32` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:39:11
+ |
+LL | 0_u32.bar();
+ | ^^^ method not found in `u32`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the trait `Bar` defines an item `bar`, but is explicitly unimplemented
+
+error[E0599]: no method named `foo` found for struct `Qux` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:44:9
+ |
+LL | struct Qux;
+ | ---------- method `foo` not found for this struct
+...
+LL | Qux.foo();
+ | ^^^ method not found in `Qux`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following traits define an item `foo`, but are explicitly unimplemented:
+ Foo
+ FooBar
+
+error[E0599]: no method named `foo` found for type `u32` in the current scope
+ --> $DIR/explicitly-unimplemented-error-message.rs:49:11
+ |
+LL | 0_u32.foo();
+ | ^^^ method not found in `u32`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Foo` defines an item `foo`, perhaps you need to implement it
+ --> $DIR/explicitly-unimplemented-error-message.rs:18:1
+ |
+LL | trait Foo {
+ | ^^^^^^^^^
+ = note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
new file mode 100644
index 000000000..683fd6db6
--- /dev/null
+++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs
@@ -0,0 +1,3 @@
+trait MyTrait {}
+impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
new file mode 100644
index 000000000..b253fbd0d
--- /dev/null
+++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr
@@ -0,0 +1,12 @@
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
+ --> $DIR/feature-gate-negative_impls.rs:2:6
+ |
+LL | impl !MyTrait for u32 {}
+ | ^^^^^^^^
+ |
+ = note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
+ = help: add `#![feature(negative_impls)]` 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/traits/negative-impls/negated-auto-traits-error.rs b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs
new file mode 100644
index 000000000..4bdad5dc5
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs
@@ -0,0 +1,68 @@
+// The dummy functions are used to avoid adding new cfail files.
+// What happens is that the compiler attempts to squash duplicates and some
+// errors are not reported. This way, we make sure that, for each function, different
+// typeck phases are involved and all errors are reported.
+
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn dummy() {
+ struct TestType;
+ impl !Send for TestType {}
+
+ Outer(TestType);
+ //~^ ERROR `dummy::TestType` cannot be sent between threads safely
+ //~| ERROR `dummy::TestType` cannot be sent between threads safely
+}
+
+fn dummy1b() {
+ struct TestType;
+ impl !Send for TestType {}
+
+ is_send(TestType);
+ //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely
+}
+
+fn dummy1c() {
+ struct TestType;
+ impl !Send for TestType {}
+
+ is_send((8, TestType));
+ //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely
+}
+
+fn dummy2() {
+ struct TestType;
+ impl !Send for TestType {}
+
+ is_send(Box::new(TestType));
+ //~^ ERROR `dummy2::TestType` cannot be sent between threads safely
+}
+
+fn dummy3() {
+ struct TestType;
+ impl !Send for TestType {}
+
+ is_send(Box::new(Outer2(TestType)));
+ //~^ ERROR `dummy3::TestType` cannot be sent between threads safely
+}
+
+fn main() {
+ struct TestType;
+ impl !Send for TestType {}
+
+ // This will complain about a missing Send impl because `Sync` is implement *just*
+ // for T that are `Send`. Look at #20366 and #19950
+ is_sync(Outer2(TestType));
+ //~^ ERROR `main::TestType` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
new file mode 100644
index 000000000..ce690b749
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -0,0 +1,127 @@
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:23:11
+ |
+LL | Outer(TestType);
+ | ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `dummy::TestType`
+note: required by a bound in `Outer`
+ --> $DIR/negated-auto-traits-error.rs:10:17
+ |
+LL | struct Outer<T: Send>(T);
+ | ^^^^ required by this bound in `Outer`
+
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:23:5
+ |
+LL | Outer(TestType);
+ | ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+ |
+ = help: the trait `Send` is not implemented for `dummy::TestType`
+note: required by a bound in `Outer`
+ --> $DIR/negated-auto-traits-error.rs:10:17
+ |
+LL | struct Outer<T: Send>(T);
+ | ^^^^ required by this bound in `Outer`
+
+error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:32:13
+ |
+LL | is_send(TestType);
+ | ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `dummy1b::TestType`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:40:13
+ |
+LL | is_send((8, TestType));
+ | ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
+ = note: required because it appears within the type `({integer}, TestType)`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `dummy2::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:48:13
+ |
+LL | is_send(Box::new(TestType));
+ | ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique<dummy2::TestType>`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied
+ = note: required for `Unique<dummy2::TestType>` to implement `Send`
+ = note: required because it appears within the type `Box<TestType>`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+help: consider borrowing here
+ |
+LL | is_send(&Box::new(TestType));
+ | +
+
+error[E0277]: `dummy3::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:56:13
+ |
+LL | is_send(Box::new(Outer2(TestType)));
+ | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
+note: required because it appears within the type `Outer2<TestType>`
+ --> $DIR/negated-auto-traits-error.rs:12:8
+ |
+LL | struct Outer2<T>(T);
+ | ^^^^^^
+ = note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send`
+ = note: required because it appears within the type `Box<Outer2<TestType>>`
+note: required by a bound in `is_send`
+ --> $DIR/negated-auto-traits-error.rs:16:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `main::TestType` cannot be sent between threads safely
+ --> $DIR/negated-auto-traits-error.rs:66:13
+ |
+LL | is_sync(Outer2(TestType));
+ | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `main::TestType`
+note: required for `Outer2<main::TestType>` to implement `Sync`
+ --> $DIR/negated-auto-traits-error.rs:14:22
+ |
+LL | unsafe impl<T: Send> Sync for Outer2<T> {}
+ | ---- ^^^^ ^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `is_sync`
+ --> $DIR/negated-auto-traits-error.rs:17:15
+ |
+LL | fn is_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `is_sync`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
new file mode 100644
index 000000000..a1042f831
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(unused_variables)]
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+pub struct WaitToken;
+impl !Send for WaitToken {}
+
+pub struct Test<T>(#[allow(unused_tuple_struct_fields)] T);
+unsafe impl<T: 'static> Send for Test<T> {}
+
+pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
+
+fn main() {
+ let wt = Test(WaitToken);
+ spawn(move || {
+ let x = wt;
+ println!("Hello, World!");
+ });
+}
diff --git a/tests/ui/traits/negative-impls/negative-default-impls.rs b/tests/ui/traits/negative-impls/negative-default-impls.rs
new file mode 100644
index 000000000..c68bca432
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-default-impls.rs
@@ -0,0 +1,11 @@
+#![feature(negative_impls)]
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait MyTrait {
+ type Foo;
+}
+
+default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-default-impls.stderr b/tests/ui/traits/negative-impls/negative-default-impls.stderr
new file mode 100644
index 000000000..7b54cf542
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-default-impls.stderr
@@ -0,0 +1,19 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-default-impls.rs:2:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0750]: negative impls cannot be default impls
+ --> $DIR/negative-default-impls.rs:9:1
+ |
+LL | default impl !MyTrait for u32 {}
+ | ^^^^^^^ ^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0750`.
diff --git a/tests/ui/traits/negative-impls/negative-impls-basic.rs b/tests/ui/traits/negative-impls/negative-impls-basic.rs
new file mode 100644
index 000000000..474e03817
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-impls-basic.rs
@@ -0,0 +1,17 @@
+// A simple test that we are able to create negative impls, when the
+// feature gate is given.
+//
+// run-pass
+
+#![feature(negative_impls)]
+#![allow(dead_code)]
+
+struct TestType;
+
+trait TestTrait {
+ fn dummy(&self) {}
+}
+
+impl !TestTrait for TestType {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs
new file mode 100644
index 000000000..35297ab12
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs
@@ -0,0 +1,13 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+// Test a negative impl that "specializes" another negative impl.
+//
+// run-pass
+
+trait MyTrait {}
+
+impl<T> !MyTrait for T {}
+impl !MyTrait for u32 {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.stderr b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr
new file mode 100644
index 000000000..751e29c3b
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-specializes-negative.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
new file mode 100644
index 000000000..4281eedaf
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -0,0 +1,13 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+// Negative impl for u32 cannot "specialize" the base impl.
+trait MyTrait {
+ fn foo();
+}
+impl<T> MyTrait for T {
+ default fn foo() {}
+}
+impl !MyTrait for u32 {} //~ ERROR E0751
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
new file mode 100644
index 000000000..1cfa49b20
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -0,0 +1,22 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-specializes-positive-item.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
+ --> $DIR/negative-specializes-positive-item.rs:11:1
+ |
+LL | impl<T> MyTrait for T {
+ | --------------------- positive implementation here
+...
+LL | impl !MyTrait for u32 {}
+ | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.rs b/tests/ui/traits/negative-impls/negative-specializes-positive.rs
new file mode 100644
index 000000000..0e227691e
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -0,0 +1,14 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+// Negative impl for u32 cannot "specialize" the base impl.
+trait MyTrait {}
+impl<T> MyTrait for T {}
+impl !MyTrait for u32 {} //~ ERROR E0751
+
+// The second impl specializes the first, no error.
+trait MyTrait2 {}
+impl<T> MyTrait2 for T {}
+impl MyTrait2 for u32 {}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
new file mode 100644
index 000000000..9f9e28678
--- /dev/null
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/negative-specializes-positive.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
+ --> $DIR/negative-specializes-positive.rs:7:1
+ |
+LL | impl<T> MyTrait for T {}
+ | --------------------- positive implementation here
+LL | impl !MyTrait for u32 {}
+ | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/no-items.rs b/tests/ui/traits/negative-impls/no-items.rs
new file mode 100644
index 000000000..5fc6be9b3
--- /dev/null
+++ b/tests/ui/traits/negative-impls/no-items.rs
@@ -0,0 +1,11 @@
+#![feature(negative_impls)]
+
+trait MyTrait {
+ type Foo;
+}
+
+impl !MyTrait for u32 {
+ type Foo = i32; //~ ERROR negative impls cannot have any items
+}
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr
new file mode 100644
index 000000000..67b94bba1
--- /dev/null
+++ b/tests/ui/traits/negative-impls/no-items.stderr
@@ -0,0 +1,9 @@
+error[E0749]: negative impls cannot have any items
+ --> $DIR/no-items.rs:8:5
+ |
+LL | type Foo = i32;
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0749`.
diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
new file mode 100644
index 000000000..a5b856465
--- /dev/null
+++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
@@ -0,0 +1,26 @@
+use std::cell::Cell;
+use std::marker::PhantomPinned;
+use std::pin::Pin;
+
+struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
+
+impl<'a> Clone for &'a mut MyType<'a> {
+ //~^ ERROR E0751
+ fn clone(&self) -> &'a mut MyType<'a> {
+ self.0.take().unwrap()
+ }
+}
+
+fn main() {
+ let mut unpinned = MyType(Cell::new(None), PhantomPinned);
+ let bad_addr = &unpinned as *const MyType<'_> as usize;
+ let mut p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned));
+
+ // p_mut1 is okay: it does not point to the bad_addr
+ let p_mut1: Pin<&mut MyType<'_>> = p.as_mut();
+ assert_ne!(bad_addr, &*p_mut1 as *const _ as usize);
+
+ // but p_mut2 does point to bad_addr! this is unsound
+ let p_mut2: Pin<&mut MyType<'_>> = p_mut1.clone();
+ assert_eq!(bad_addr, &*p_mut2 as *const _ as usize);
+}
diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
new file mode 100644
index 000000000..a87acb1fb
--- /dev/null
+++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
@@ -0,0 +1,11 @@
+error[E0751]: found both positive and negative implementation of trait `Clone` for type `&mut MyType<'_>`:
+ --> $DIR/pin-unsound-issue-66544-clone.rs:7:1
+ |
+LL | impl<'a> Clone for &'a mut MyType<'a> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here
+ |
+ = note: negative implementation in crate `core`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
new file mode 100644
index 000000000..606cc65a8
--- /dev/null
+++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
@@ -0,0 +1,33 @@
+// Demonstrate that "rogue" `DerefMut` impls for `&T` are not allowed.
+//
+// https://github.com/rust-lang/rust/issues/66544
+
+use std::cell::Cell;
+use std::marker::PhantomPinned;
+use std::ops::DerefMut;
+use std::pin::Pin;
+
+struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
+
+impl<'a> DerefMut for &'a MyType<'a> {
+ //~^ ERROR E0751
+ fn deref_mut(&mut self) -> &mut MyType<'a> {
+ self.0.take().unwrap()
+ }
+}
+
+fn main() {
+ let mut unpinned = MyType(Cell::new(None), PhantomPinned);
+ let bad_addr = &unpinned as *const MyType<'_> as usize;
+ let p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned));
+
+ // p_ref is okay: it does not point to the bad_addr
+ let mut p_ref: Pin<&MyType<'_>> = p.as_ref();
+ assert_ne!(bad_addr, &*p_ref as *const _ as usize);
+
+ // but p_mut does point to bad_addr! this is unsound
+ let p_mut: Pin<&mut MyType<'_>> = p_ref.as_mut();
+ assert_eq!(bad_addr, &*p_mut as *const _ as usize);
+
+ println!("oh no!");
+}
diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
new file mode 100644
index 000000000..9185e8f84
--- /dev/null
+++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
@@ -0,0 +1,11 @@
+error[E0751]: found both positive and negative implementation of trait `DerefMut` for type `&MyType<'_>`:
+ --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1
+ |
+LL | impl<'a> DerefMut for &'a MyType<'a> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here
+ |
+ = note: negative implementation in crate `core`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.rs b/tests/ui/traits/negative-impls/positive-specializes-negative.rs
new file mode 100644
index 000000000..a06b35765
--- /dev/null
+++ b/tests/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -0,0 +1,9 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(negative_impls)]
+
+trait MyTrait {}
+
+impl<T> !MyTrait for T {}
+impl MyTrait for u32 {} //~ ERROR E0751
+
+fn main() {}
diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
new file mode 100644
index 000000000..545f94143
--- /dev/null
+++ b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/positive-specializes-negative.rs:1:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
+ --> $DIR/positive-specializes-negative.rs:7:1
+ |
+LL | impl<T> !MyTrait for T {}
+ | ---------------------- negative implementation here
+LL | impl MyTrait for u32 {}
+ | ^^^^^^^^^^^^^^^^^^^^ positive implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
new file mode 100644
index 000000000..c1f96ab8c
--- /dev/null
+++ b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
+
+// aux-build: foreign_trait.rs
+
+// Test that we cannot implement `LocalTrait` for `String`,
+// even though there is a `String: !ForeignTrait` impl.
+//
+// This may not be the behavior we want long term, but it's the
+// current semantics that we implemented so as to land `!Foo` impls
+// quickly. See internals thread:
+//
+// https://internals.rust-lang.org/t/foo/11587/
+
+extern crate foreign_trait;
+use foreign_trait::ForeignTrait;
+
+trait LocalTrait {}
+impl<T: ForeignTrait> LocalTrait for T {}
+impl LocalTrait for String {}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/fn-trait-closure.rs b/tests/ui/traits/new-solver/fn-trait-closure.rs
new file mode 100644
index 000000000..c0ecf1c91
--- /dev/null
+++ b/tests/ui/traits/new-solver/fn-trait-closure.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: unknown
+// failure-status: 101
+// dont-check-compiler-stderr
+
+// This test will fail until we fix `FulfillmentCtxt::relationships`. That's
+// because we create a type variable for closure upvar types, which is not
+// constrained until after we try to do fallback on diverging type variables.
+// Thus, we will call that function, which is unimplemented.
+
+fn require_fn(_: impl Fn() -> i32) {}
+
+fn main() {
+ require_fn(|| -> i32 { 1i32 });
+}
diff --git a/tests/ui/traits/new-solver/fn-trait.rs b/tests/ui/traits/new-solver/fn-trait.rs
new file mode 100644
index 000000000..d566ead10
--- /dev/null
+++ b/tests/ui/traits/new-solver/fn-trait.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn require_fn(_: impl Fn() -> i32) {}
+
+fn f() -> i32 {
+ 1i32
+}
+
+fn main() {
+ require_fn(f);
+ require_fn(f as fn() -> i32);
+}
diff --git a/tests/ui/traits/new-solver/pointer-sized.rs b/tests/ui/traits/new-solver/pointer-sized.rs
new file mode 100644
index 000000000..15681cd13
--- /dev/null
+++ b/tests/ui/traits/new-solver/pointer-sized.rs
@@ -0,0 +1,12 @@
+#![feature(pointer_sized_trait)]
+
+use std::marker::PointerSized;
+
+fn require_pointer_sized(_: impl PointerSized) {}
+
+fn main() {
+ require_pointer_sized(1usize);
+ require_pointer_sized(1u16);
+ //~^ ERROR `u16` needs to be a pointer-sized type
+ require_pointer_sized(&1i16);
+}
diff --git a/tests/ui/traits/new-solver/pointer-sized.stderr b/tests/ui/traits/new-solver/pointer-sized.stderr
new file mode 100644
index 000000000..b250b1331
--- /dev/null
+++ b/tests/ui/traits/new-solver/pointer-sized.stderr
@@ -0,0 +1,24 @@
+error[E0277]: `u16` needs to be a pointer-sized type
+ --> $DIR/pointer-sized.rs:9:27
+ |
+LL | require_pointer_sized(1u16);
+ | --------------------- ^^^^ the trait `PointerSized` is not implemented for `u16`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `u16: PointerSized` is not satisfied
+note: required by a bound in `require_pointer_sized`
+ --> $DIR/pointer-sized.rs:5:34
+ |
+LL | fn require_pointer_sized(_: impl PointerSized) {}
+ | ^^^^^^^^^^^^ required by this bound in `require_pointer_sized`
+help: consider borrowing here
+ |
+LL | require_pointer_sized(&1u16);
+ | +
+LL | require_pointer_sized(&mut 1u16);
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/no-fallback-multiple-impls.rs b/tests/ui/traits/no-fallback-multiple-impls.rs
new file mode 100644
index 000000000..7ed3796f0
--- /dev/null
+++ b/tests/ui/traits/no-fallback-multiple-impls.rs
@@ -0,0 +1,16 @@
+trait Fallback {
+ fn foo(&self) {}
+}
+
+impl Fallback for i32 {}
+
+impl Fallback for u64 {}
+
+impl Fallback for usize {}
+
+fn main() {
+ missing();
+ //~^ ERROR cannot find function `missing` in this scope
+ 0.foo();
+ // But then we shouldn't report an inference ambiguity here...
+}
diff --git a/tests/ui/traits/no-fallback-multiple-impls.stderr b/tests/ui/traits/no-fallback-multiple-impls.stderr
new file mode 100644
index 000000000..61c9e5aaa
--- /dev/null
+++ b/tests/ui/traits/no-fallback-multiple-impls.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `missing` in this scope
+ --> $DIR/no-fallback-multiple-impls.rs:12:5
+ |
+LL | missing();
+ | ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/traits/no_send-struct.rs b/tests/ui/traits/no_send-struct.rs
new file mode 100644
index 000000000..75a363f9f
--- /dev/null
+++ b/tests/ui/traits/no_send-struct.rs
@@ -0,0 +1,17 @@
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+struct Foo {
+ a: isize,
+}
+
+impl !Send for Foo {}
+
+fn bar<T: Send>(_: T) {}
+
+fn main() {
+ let x = Foo { a: 5 };
+ bar(x);
+ //~^ ERROR `Foo` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/no_send-struct.stderr b/tests/ui/traits/no_send-struct.stderr
new file mode 100644
index 000000000..ee7bdf282
--- /dev/null
+++ b/tests/ui/traits/no_send-struct.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `Foo` cannot be sent between threads safely
+ --> $DIR/no_send-struct.rs:15:9
+ |
+LL | bar(x);
+ | --- ^ `Foo` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Send` is not implemented for `Foo`
+note: required by a bound in `bar`
+ --> $DIR/no_send-struct.rs:11:11
+ |
+LL | fn bar<T: Send>(_: T) {}
+ | ^^^^ 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/traits/normalize-supertrait.rs b/tests/ui/traits/normalize-supertrait.rs
new file mode 100644
index 000000000..021a93eac
--- /dev/null
+++ b/tests/ui/traits/normalize-supertrait.rs
@@ -0,0 +1,37 @@
+// Regression test for #77653
+// When monomorphizing `f` we need to prove `dyn Derived<()>: Base<()>`. This
+// requires us to normalize the `Base<<() as Proj>::S>` to `Base<()>` when
+// comparing the supertrait `Derived<()>` to the expected trait.
+
+// build-pass
+
+trait Proj {
+ type S;
+}
+
+impl Proj for () {
+ type S = ();
+}
+
+impl Proj for i32 {
+ type S = i32;
+}
+
+trait Base<T> {
+ fn is_base(&self);
+}
+
+trait Derived<B: Proj>: Base<B::S> + Base<()> {
+ fn is_derived(&self);
+}
+
+fn f<P: Proj>(obj: &dyn Derived<P>) {
+ obj.is_derived();
+ Base::<P::S>::is_base(obj);
+ Base::<()>::is_base(obj);
+}
+
+fn main() {
+ let x: fn(_) = f::<()>;
+ let x: fn(_) = f::<i32>;
+}
diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs
new file mode 100644
index 000000000..538e74ee1
--- /dev/null
+++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs
@@ -0,0 +1,24 @@
+struct A<T>(T);
+struct B;
+
+trait I<T> {}
+impl I<i32> for B {}
+impl I<u32> for B {}
+
+trait V<U> {
+ fn method(self) -> U;
+}
+
+impl<T, U> V<U> for A<T>
+where
+ T: I<U>,
+{
+ fn method(self) -> U { unimplemented!() }
+}
+
+fn main() {
+ let a = A(B);
+ a.method();
+ //~^ ERROR type annotations needed
+ //~| ERROR type annotations needed
+}
diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
new file mode 100644
index 000000000..92d9d32cf
--- /dev/null
+++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
@@ -0,0 +1,41 @@
+error[E0282]: type annotations needed
+ --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7
+ |
+LL | a.method();
+ | ^^^^^^
+ |
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <A<B> as V<U>>::method(a);
+ | +++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7
+ |
+LL | a.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `B: I<_>` found
+ --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:5:1
+ |
+LL | impl I<i32> for B {}
+ | ^^^^^^^^^^^^^^^^^
+LL | impl I<u32> for B {}
+ | ^^^^^^^^^^^^^^^^^
+note: required for `A<B>` to implement `V<_>`
+ --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:12:12
+ |
+LL | impl<T, U> V<U> for A<T>
+ | ^^^^ ^^^^
+LL | where
+LL | T: I<U>,
+ | ---- unsatisfied trait bound introduced here
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <A<B> as V<U>>::method(a);
+ | +++++++++++++++++++++++ ~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/object-does-not-impl-trait.rs b/tests/ui/traits/object-does-not-impl-trait.rs
new file mode 100644
index 000000000..b3b679813
--- /dev/null
+++ b/tests/ui/traits/object-does-not-impl-trait.rs
@@ -0,0 +1,8 @@
+// Test that an object type `Box<Foo>` is not considered to implement the
+// trait `Foo`. Issue #5087.
+
+trait Foo {}
+fn take_foo<F:Foo>(f: F) {}
+fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
+fn main() {}
diff --git a/tests/ui/traits/object-does-not-impl-trait.stderr b/tests/ui/traits/object-does-not-impl-trait.stderr
new file mode 100644
index 000000000..f1dd508a4
--- /dev/null
+++ b/tests/ui/traits/object-does-not-impl-trait.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
+ --> $DIR/object-does-not-impl-trait.rs:6:44
+ |
+LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+ | -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `take_foo`
+ --> $DIR/object-does-not-impl-trait.rs:5:15
+ |
+LL | fn take_foo<F:Foo>(f: F) {}
+ | ^^^ required by this bound in `take_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/object-one-type-two-traits.rs b/tests/ui/traits/object-one-type-two-traits.rs
new file mode 100644
index 000000000..86a2094ee
--- /dev/null
+++ b/tests/ui/traits/object-one-type-two-traits.rs
@@ -0,0 +1,31 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Testing creating two vtables with the same self type, but different
+// traits.
+
+use std::any::Any;
+
+trait Wrap {
+ fn get(&self) -> isize;
+ fn wrap(self: Box<Self>) -> Box<dyn Any+'static>;
+}
+
+impl Wrap for isize {
+ fn get(&self) -> isize {
+ *self
+ }
+ fn wrap(self: Box<isize>) -> Box<dyn Any+'static> {
+ self as Box<dyn Any+'static>
+ }
+}
+
+fn is<T:Any>(x: &dyn Any) -> bool {
+ x.is::<T>()
+}
+
+fn main() {
+ let x = Box::new(22isize) as Box<dyn Wrap>;
+ println!("x={}", x.get());
+ let y = x.wrap();
+}
diff --git a/tests/ui/traits/object/auto-dedup-in-impl.rs b/tests/ui/traits/object/auto-dedup-in-impl.rs
new file mode 100644
index 000000000..85698f194
--- /dev/null
+++ b/tests/ui/traits/object/auto-dedup-in-impl.rs
@@ -0,0 +1,19 @@
+// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type.
+// Issue: #47010
+
+struct Struct;
+impl Trait for Struct {}
+trait Trait {}
+
+type Send1 = dyn Trait + Send;
+type Send2 = dyn Trait + Send + Send;
+
+fn main () {}
+
+impl dyn Trait + Send {
+ fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
+}
+
+impl dyn Trait + Send + Send {
+ fn test(&self) { println!("two"); }
+}
diff --git a/tests/ui/traits/object/auto-dedup-in-impl.stderr b/tests/ui/traits/object/auto-dedup-in-impl.stderr
new file mode 100644
index 000000000..5f13c7813
--- /dev/null
+++ b/tests/ui/traits/object/auto-dedup-in-impl.stderr
@@ -0,0 +1,12 @@
+error[E0592]: duplicate definitions with name `test`
+ --> $DIR/auto-dedup-in-impl.rs:14:5
+ |
+LL | fn test(&self) { println!("one"); }
+ | ^^^^^^^^^^^^^^ duplicate definitions for `test`
+...
+LL | fn test(&self) { println!("two"); }
+ | -------------- other definition for `test`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/traits/object/auto-dedup.rs b/tests/ui/traits/object/auto-dedup.rs
new file mode 100644
index 000000000..39d25eb7f
--- /dev/null
+++ b/tests/ui/traits/object/auto-dedup.rs
@@ -0,0 +1,46 @@
+// run-pass
+
+#![allow(unused_assignments)]
+
+// Test that duplicate auto trait bounds in trait objects don't create new types.
+#[allow(unused_assignments)]
+use std::marker::Send as SendAlias;
+
+// A dummy trait for the non-auto trait.
+trait Trait {}
+
+// A dummy struct to implement `Trait` and `Send`.
+struct Struct;
+
+impl Trait for Struct {}
+
+// These three functions should be equivalent.
+fn takes_dyn_trait_send(_: Box<dyn Trait + Send>) {}
+fn takes_dyn_trait_send_send(_: Box<dyn Trait + Send + Send>) {}
+fn takes_dyn_trait_send_sendalias(_: Box<dyn Trait + Send + SendAlias>) {}
+
+impl dyn Trait + Send + Send {
+ fn do_nothing(&self) {}
+}
+
+fn main() {
+ // 1. Moving into a variable with more `Send`s and back.
+ let mut dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+ let dyn_trait_send_send: Box<dyn Trait + Send + Send> = dyn_trait_send;
+ dyn_trait_send = dyn_trait_send_send;
+
+ // 2. Calling methods with different number of `Send`s.
+ let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+ takes_dyn_trait_send_send(dyn_trait_send);
+
+ let dyn_trait_send_send = Box::new(Struct) as Box<dyn Trait + Send + Send>;
+ takes_dyn_trait_send(dyn_trait_send_send);
+
+ // 3. Aliases to the trait are transparent.
+ let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+ takes_dyn_trait_send_sendalias(dyn_trait_send);
+
+ // 4. Calling an impl that duplicates an auto trait.
+ let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+ dyn_trait_send.do_nothing();
+}
diff --git a/tests/ui/traits/object/bounds-cycle-1.rs b/tests/ui/traits/object/bounds-cycle-1.rs
new file mode 100644
index 000000000..314676492
--- /dev/null
+++ b/tests/ui/traits/object/bounds-cycle-1.rs
@@ -0,0 +1,24 @@
+// Check that we don't have a cycle when we try to normalize `Self::U` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj {
+ type U: Is<T = Self::U>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/bounds-cycle-2.rs b/tests/ui/traits/object/bounds-cycle-2.rs
new file mode 100644
index 000000000..4c1df3805
--- /dev/null
+++ b/tests/ui/traits/object/bounds-cycle-2.rs
@@ -0,0 +1,28 @@
+// Check that we don't have a cycle when we try to normalize `Self::V` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Super {
+ type V;
+}
+
+trait Obj: Super {
+ type U: Is<T = Self::V>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/bounds-cycle-3.rs b/tests/ui/traits/object/bounds-cycle-3.rs
new file mode 100644
index 000000000..55726a5ae
--- /dev/null
+++ b/tests/ui/traits/object/bounds-cycle-3.rs
@@ -0,0 +1,25 @@
+// Check that we don't have a cycle when we try to normalize `Self::V` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj {
+ type U: Is<T = Self::V>;
+ type V;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/bounds-cycle-4.rs b/tests/ui/traits/object/bounds-cycle-4.rs
new file mode 100644
index 000000000..f83cb75c7
--- /dev/null
+++ b/tests/ui/traits/object/bounds-cycle-4.rs
@@ -0,0 +1,25 @@
+// Check that we don't have a cycle when we try to normalize `Self::U` in the
+// bound below. Make sure that having a lifetime on the trait object doesn't break things
+
+// check-pass
+
+trait Is {
+ type T;
+}
+
+impl<U> Is for U {
+ type T = U;
+}
+
+trait Obj<'a> {
+ type U: Is<T = Self::V>;
+ type V;
+}
+
+fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {}
+
+fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) {
+ is_obj(x)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/enforce-supertrait-projection.rs b/tests/ui/traits/object/enforce-supertrait-projection.rs
new file mode 100644
index 000000000..2c9b41eea
--- /dev/null
+++ b/tests/ui/traits/object/enforce-supertrait-projection.rs
@@ -0,0 +1,24 @@
+trait SuperTrait {
+ type A;
+ type B;
+}
+
+trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
+
+fn transmute<A, B>(x: A) -> B {
+ foo::<A, B, dyn Trait<A = A, B = B>>(x)
+ //~^ ERROR type mismatch resolving `<dyn Trait<B = B, A = A> as SuperTrait>::A == B`
+}
+
+fn foo<A, B, T: ?Sized>(x: T::A) -> B
+where
+ T: Trait<B = B>,
+{
+ x
+}
+
+static X: u8 = 0;
+fn main() {
+ let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
+ println!("{:?}", x[100_000]);
+}
diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr
new file mode 100644
index 000000000..cbf093866
--- /dev/null
+++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr
@@ -0,0 +1,26 @@
+error[E0271]: type mismatch resolving `<dyn Trait<B = B, A = A> as SuperTrait>::A == B`
+ --> $DIR/enforce-supertrait-projection.rs:9:17
+ |
+LL | fn transmute<A, B>(x: A) -> B {
+ | - - expected type parameter
+ | |
+ | found type parameter
+LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A`
+ |
+ = note: expected type parameter `B`
+ found type parameter `A`
+ = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+ = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+note: required by a bound in `foo`
+ --> $DIR/enforce-supertrait-projection.rs:15:8
+ |
+LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
+ | --- required by a bound in this
+LL | where
+LL | T: Trait<B = B>,
+ | ^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/object/exclusion.rs b/tests/ui/traits/object/exclusion.rs
new file mode 100644
index 000000000..766dceeaf
--- /dev/null
+++ b/tests/ui/traits/object/exclusion.rs
@@ -0,0 +1,19 @@
+// run-pass
+trait Future: 'static {
+ // The requirement for Self: Sized must prevent instantiation of
+ // Future::forget in vtables, otherwise there's an infinite type
+ // recursion through <Map<...> as Future>::forget.
+ fn forget(self) where Self: Sized {
+ Box::new(Map(self)) as Box<dyn Future>;
+ }
+}
+
+struct Map<A>(#[allow(unused_tuple_struct_fields)] A);
+impl<A: Future> Future for Map<A> {}
+
+pub struct Promise;
+impl Future for Promise {}
+
+fn main() {
+ Promise.forget();
+}
diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs
new file mode 100644
index 000000000..5a4a6aecc
--- /dev/null
+++ b/tests/ui/traits/object/generics.rs
@@ -0,0 +1,41 @@
+// run-pass
+// test for #8664
+
+use std::marker;
+
+pub trait Trait2<A> {
+ fn doit(&self) -> A;
+}
+
+pub struct Impl<A1, A2, A3> {
+ m1: marker::PhantomData<(A1,A2,A3)>,
+ /*
+ * With A2 we get the ICE:
+ * task <unnamed> failed at 'index out of bounds: the len is 1 but the index is 1',
+ * src/librustc/middle/subst.rs:58
+ */
+ t: Box<dyn Trait2<A2>+'static>
+}
+
+impl<A1, A2, A3> Impl<A1, A2, A3> {
+ pub fn step(&self) {
+ self.t.doit();
+ }
+}
+
+// test for #8601
+
+enum Type<T> { Constant(#[allow(unused_tuple_struct_fields)] T) }
+
+trait Trait<K,V> {
+ fn method(&self, _: Type<(K,V)>) -> isize;
+}
+
+impl<V> Trait<u8,V> for () {
+ fn method(&self, _x: Type<(u8,V)>) -> isize { 0 }
+}
+
+pub fn main() {
+ let a = Box::new(()) as Box<dyn Trait<u8, u8>>;
+ assert_eq!(a.method(Type::Constant((1, 2))), 0);
+}
diff --git a/tests/ui/traits/object/issue-33140-traitobject-crate.rs b/tests/ui/traits/object/issue-33140-traitobject-crate.rs
new file mode 100644
index 000000000..8abd92da3
--- /dev/null
+++ b/tests/ui/traits/object/issue-33140-traitobject-crate.rs
@@ -0,0 +1,108 @@
+// check-pass
+
+#![warn(order_dependent_trait_objects)]
+#![allow(dyn_drop)]
+
+// Check that traitobject 0.1.0 compiles
+
+//! # traitobject
+//!
+//! Unsafe helpers for working with raw TraitObjects.
+
+/// A trait implemented for all trait objects.
+///
+/// Implementations for all traits in std are provided.
+pub unsafe trait Trait {}
+
+unsafe impl Trait for dyn (::std::any::Any) + Send { }
+unsafe impl Trait for dyn (::std::any::Any) + Sync { }
+unsafe impl Trait for dyn (::std::any::Any) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Send + Sync { }
+unsafe impl Trait for dyn (::std::error::Error) + Send { }
+unsafe impl Trait for dyn (::std::error::Error) + Sync { }
+unsafe impl Trait for dyn (::std::error::Error) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Binary) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Binary) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Binary) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Debug) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Debug) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Debug) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Display) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Display) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Display) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send { }
+unsafe impl Trait for dyn (::std::fmt::LowerExp) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send { }
+unsafe impl Trait for dyn (::std::fmt::LowerHex) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Octal) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Octal) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Octal) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Pointer) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Pointer) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Pointer) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send { }
+unsafe impl Trait for dyn (::std::fmt::UpperExp) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send { }
+unsafe impl Trait for dyn (::std::fmt::UpperHex) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Write) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Write) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Write) + Send + Sync { }
+unsafe impl Trait for dyn (::std::hash::Hasher) + Send { }
+unsafe impl Trait for dyn (::std::hash::Hasher) + Sync { }
+unsafe impl Trait for dyn (::std::hash::Hasher) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::BufRead) + Send { }
+unsafe impl Trait for dyn (::std::io::BufRead) + Sync { }
+unsafe impl Trait for dyn (::std::io::BufRead) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::Read) + Send { }
+unsafe impl Trait for dyn (::std::io::Read) + Sync { }
+unsafe impl Trait for dyn (::std::io::Read) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::Seek) + Send { }
+unsafe impl Trait for dyn (::std::io::Seek) + Sync { }
+unsafe impl Trait for dyn (::std::io::Seek) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::Write) + Send { }
+unsafe impl Trait for dyn (::std::io::Write) + Sync { }
+unsafe impl Trait for dyn (::std::io::Write) + Send + Sync { }
+unsafe impl<T, I> Trait for dyn (::std::iter::IntoIterator<IntoIter=I, Item=T>) { }
+unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Send { }
+unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Sync { }
+unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Send + Sync { }
+unsafe impl Trait for dyn (::std::marker::Send) + Send { }
+unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+//~^ WARNING conflicting implementations of trait `Trait` for type
+//~| WARNING this was previously accepted by the compiler but is being phased out
+unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+//~^ WARNING conflicting implementations of trait `Trait` for type
+//~| WARNING this was previously accepted by the compiler but is being phased out
+unsafe impl Trait for dyn (::std::marker::Sync) + Sync { }
+unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+//~^ WARNING conflicting implementations of trait `Trait` for type
+//~| WARNING this was previously accepted by the compiler but is being phased out
+unsafe impl Trait for dyn (::std::ops::Drop) + Send { }
+unsafe impl Trait for dyn (::std::ops::Drop) + Sync { }
+unsafe impl Trait for dyn (::std::ops::Drop) + Send + Sync { }
+unsafe impl Trait for dyn (::std::string::ToString) + Send { }
+unsafe impl Trait for dyn (::std::string::ToString) + Sync { }
+unsafe impl Trait for dyn (::std::string::ToString) + Send + Sync { }
+fn assert_trait<T: Trait + ?Sized>() {}
+
+fn main() {
+ assert_trait::<dyn Send>();
+ assert_trait::<dyn Sync>();
+ assert_trait::<dyn Send + Sync>();
+}
diff --git a/tests/ui/traits/object/issue-33140-traitobject-crate.stderr b/tests/ui/traits/object/issue-33140-traitobject-crate.stderr
new file mode 100644
index 000000000..525401f9d
--- /dev/null
+++ b/tests/ui/traits/object/issue-33140-traitobject-crate.stderr
@@ -0,0 +1,95 @@
+warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:86:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+ | ------------------------------------------------------ first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:89:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ------------------------------------------------------------- first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:93:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ------------------------------------------------------ first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+warning: 3 warnings emitted
+
+Future incompatibility report: Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:86:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+ | ------------------------------------------------------ first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:89:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ------------------------------------------------------------- first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:93:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ------------------------------------------------------ first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/traits/object/issue-44454-1.rs b/tests/ui/traits/object/issue-44454-1.rs
new file mode 100644
index 000000000..bbaf3188a
--- /dev/null
+++ b/tests/ui/traits/object/issue-44454-1.rs
@@ -0,0 +1,22 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333
+
+trait Animal<X>: 'static {}
+
+fn foo<Y, X>()
+where
+ Y: Animal<X> + ?Sized,
+{
+ // `Y` implements `Animal<X>` so `Y` is 'static.
+ baz::<Y>()
+}
+
+fn bar<'a>(_arg: &'a i32) {
+ foo::<dyn Animal<&'a i32>, &'a i32>() //~ ERROR: lifetime may not live long enough
+}
+
+fn baz<T: 'static + ?Sized>() {}
+
+fn main() {
+ let a = 5;
+ bar(&a);
+}
diff --git a/tests/ui/traits/object/issue-44454-1.stderr b/tests/ui/traits/object/issue-44454-1.stderr
new file mode 100644
index 000000000..859487f50
--- /dev/null
+++ b/tests/ui/traits/object/issue-44454-1.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-44454-1.rs:14:5
+ |
+LL | fn bar<'a>(_arg: &'a i32) {
+ | -- lifetime `'a` defined here
+LL | foo::<dyn Animal<&'a i32>, &'a i32>()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/object/issue-44454-2.rs b/tests/ui/traits/object/issue-44454-2.rs
new file mode 100644
index 000000000..f5178bcdb
--- /dev/null
+++ b/tests/ui/traits/object/issue-44454-2.rs
@@ -0,0 +1,22 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928
+
+trait Trait<ARG: 'static>: 'static {
+ type Assoc: AsRef<str>;
+}
+
+fn hr<T: ?Sized, ARG>(x: T::Assoc) -> Box<dyn AsRef<str> + 'static>
+where
+ T: Trait<ARG>
+{
+ Box::new(x)
+}
+
+fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+ type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+ hr::<DynTrait, _>(x) //~ ERROR: borrowed data escapes outside of function
+}
+
+fn main() {
+ let extended = extend_lt(&String::from("hello"));
+ println!("{}", extended.as_ref().as_ref());
+}
diff --git a/tests/ui/traits/object/issue-44454-2.stderr b/tests/ui/traits/object/issue-44454-2.stderr
new file mode 100644
index 000000000..7f574769b
--- /dev/null
+++ b/tests/ui/traits/object/issue-44454-2.stderr
@@ -0,0 +1,17 @@
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/issue-44454-2.rs:16:5
+ |
+LL | fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+ | -- - `x` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+LL | hr::<DynTrait, _>(x)
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `x` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/traits/object/issue-44454-3.rs b/tests/ui/traits/object/issue-44454-3.rs
new file mode 100644
index 000000000..bff727035
--- /dev/null
+++ b/tests/ui/traits/object/issue-44454-3.rs
@@ -0,0 +1,33 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290
+
+use std::any::Any;
+
+trait Animal<X>: 'static {}
+
+trait Projector {
+ type Foo;
+}
+
+impl<X> Projector for dyn Animal<X> {
+ type Foo = X;
+}
+
+fn make_static<'a, T>(t: &'a T) -> &'static T {
+ let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+ let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+ //~^ ERROR: lifetime may not live long enough
+ any.downcast_ref::<&'static T>().unwrap()
+}
+
+fn generic<T: Projector + Animal<U> + ?Sized, U>(x: <T as Projector>::Foo) -> Box<dyn Any> {
+ make_static_any(x)
+}
+
+fn make_static_any<U: 'static>(u: U) -> Box<dyn Any> {
+ Box::new(u)
+}
+
+fn main() {
+ let a = make_static(&"salut".to_string());
+ println!("{}", *a);
+}
diff --git a/tests/ui/traits/object/issue-44454-3.stderr b/tests/ui/traits/object/issue-44454-3.stderr
new file mode 100644
index 000000000..294684d26
--- /dev/null
+++ b/tests/ui/traits/object/issue-44454-3.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-44454-3.rs:17:15
+ |
+LL | fn make_static<'a, T>(t: &'a T) -> &'static T {
+ | -- lifetime `'a` defined here
+LL | let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+LL | let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/object/lifetime-first.rs b/tests/ui/traits/object/lifetime-first.rs
new file mode 100644
index 000000000..33757cb7c
--- /dev/null
+++ b/tests/ui/traits/object/lifetime-first.rs
@@ -0,0 +1,13 @@
+// run-pass
+use std::fmt::Display;
+
+static BYTE: u8 = 33;
+
+fn main() {
+ let x: &(dyn 'static + Display) = &BYTE;
+ let y: Box<dyn 'static + Display> = Box::new(BYTE);
+ let xstr = format!("{}", x);
+ let ystr = format!("{}", y);
+ assert_eq!(xstr, "33");
+ assert_eq!(ystr, "33");
+}
diff --git a/tests/ui/traits/object/macro-matcher.rs b/tests/ui/traits/object/macro-matcher.rs
new file mode 100644
index 000000000..910978749
--- /dev/null
+++ b/tests/ui/traits/object/macro-matcher.rs
@@ -0,0 +1,12 @@
+// `ty` matcher accepts trait object types
+
+macro_rules! m {
+ ($t: ty) => ( let _: $t; )
+}
+
+fn main() {
+ m!(dyn Copy + Send + 'static);
+ //~^ ERROR the trait `Copy` cannot be made into an object
+ m!(dyn 'static + Send);
+ m!(dyn 'static +); //~ ERROR at least one trait is required for an object type
+}
diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr
new file mode 100644
index 000000000..6d1e236c0
--- /dev/null
+++ b/tests/ui/traits/object/macro-matcher.stderr
@@ -0,0 +1,19 @@
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/macro-matcher.rs:11:8
+ |
+LL | m!(dyn 'static +);
+ | ^^^^^^^^^^^^^
+
+error[E0038]: the trait `Copy` cannot be made into an object
+ --> $DIR/macro-matcher.rs:8:8
+ |
+LL | m!(dyn Copy + Send + 'static);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object
+ |
+ = note: the trait cannot be made into an object because it requires `Self: Sized`
+ = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0038, E0224.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs
new file mode 100644
index 000000000..f43d332d6
--- /dev/null
+++ b/tests/ui/traits/object/safety.rs
@@ -0,0 +1,17 @@
+// Check that static methods are not object-safe.
+
+trait Tr {
+ fn foo();
+ fn bar(&self) { }
+}
+
+struct St;
+
+impl Tr for St {
+ fn foo() {}
+}
+
+fn main() {
+ let _: &dyn Tr = &St; //~ ERROR E0038
+ //~^ ERROR E0038
+}
diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr
new file mode 100644
index 000000000..dc18adeaf
--- /dev/null
+++ b/tests/ui/traits/object/safety.stderr
@@ -0,0 +1,49 @@
+error[E0038]: the trait `Tr` cannot be made into an object
+ --> $DIR/safety.rs:15:22
+ |
+LL | let _: &dyn Tr = &St;
+ | ^^^ `Tr` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/safety.rs:4:8
+ |
+LL | trait Tr {
+ | -- this trait cannot be made into an object...
+LL | fn foo();
+ | ^^^ ...because associated function `foo` has no `self` parameter
+ = note: required for `&St` to implement `CoerceUnsized<&dyn Tr>`
+ = note: required by cast to type `&dyn Tr`
+help: consider turning `foo` into a method by giving it a `&self` argument
+ |
+LL | fn foo(&self);
+ | +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+ |
+LL | fn foo() where Self: Sized;
+ | +++++++++++++++++
+
+error[E0038]: the trait `Tr` cannot be made into an object
+ --> $DIR/safety.rs:15:12
+ |
+LL | let _: &dyn Tr = &St;
+ | ^^^^^^^ `Tr` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/safety.rs:4:8
+ |
+LL | trait Tr {
+ | -- this trait cannot be made into an object...
+LL | fn foo();
+ | ^^^ ...because associated function `foo` has no `self` parameter
+help: consider turning `foo` into a method by giving it a `&self` argument
+ |
+LL | fn foo(&self);
+ | +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+ |
+LL | fn foo() where Self: Sized;
+ | +++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.rs b/tests/ui/traits/object/supertrait-lifetime-bound.rs
new file mode 100644
index 000000000..f929a9bb6
--- /dev/null
+++ b/tests/ui/traits/object/supertrait-lifetime-bound.rs
@@ -0,0 +1,14 @@
+trait Foo: 'static { }
+
+trait Bar<T>: Foo { }
+
+fn test1<T: ?Sized + Bar<S>, S>() { }
+
+fn test2<'a>() {
+ // Here: the type `dyn Bar<&'a u32>` references `'a`,
+ // and so it does not outlive `'static`.
+ test1::<dyn Bar<&'a u32>, _>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() { }
diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.stderr b/tests/ui/traits/object/supertrait-lifetime-bound.stderr
new file mode 100644
index 000000000..ed2f86243
--- /dev/null
+++ b/tests/ui/traits/object/supertrait-lifetime-bound.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/supertrait-lifetime-bound.rs:10:5
+ |
+LL | fn test2<'a>() {
+ | -- lifetime `'a` defined here
+...
+LL | test1::<dyn Bar<&'a u32>, _>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/object/vs-lifetime-2.rs b/tests/ui/traits/object/vs-lifetime-2.rs
new file mode 100644
index 000000000..0b33dc7f6
--- /dev/null
+++ b/tests/ui/traits/object/vs-lifetime-2.rs
@@ -0,0 +1,11 @@
+// A few contrived examples where lifetime should (or should not) be parsed as an object type.
+// Lifetimes parsed as types are still rejected later by semantic checks.
+
+// `'static` is a lifetime, `'static +` is a type, `'a` is a type
+fn g() where
+ 'static: 'static,
+ dyn 'static +: 'static + Copy,
+ //~^ ERROR at least one trait is required for an object type
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/object/vs-lifetime-2.stderr b/tests/ui/traits/object/vs-lifetime-2.stderr
new file mode 100644
index 000000000..9b8e793df
--- /dev/null
+++ b/tests/ui/traits/object/vs-lifetime-2.stderr
@@ -0,0 +1,9 @@
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/vs-lifetime-2.rs:7:5
+ |
+LL | dyn 'static +: 'static + Copy,
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/traits/object/vs-lifetime.rs b/tests/ui/traits/object/vs-lifetime.rs
new file mode 100644
index 000000000..14ae67cff
--- /dev/null
+++ b/tests/ui/traits/object/vs-lifetime.rs
@@ -0,0 +1,17 @@
+// A few contrived examples where lifetime should (or should not) be parsed as an object type.
+// Lifetimes parsed as types are still rejected later by semantic checks.
+
+struct S<'a, T>(&'a u8, T);
+
+fn main() {
+ // `'static` is a lifetime argument, `'static +` is a type argument
+ let _: S<'static, u8>;
+ let _: S<'static, dyn 'static +>;
+ //~^ at least one trait is required for an object type
+ let _: S<'static, 'static>;
+ //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~| ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
+ let _: S<dyn 'static +, 'static>;
+ //~^ ERROR type provided when a lifetime was expected
+ //~| ERROR at least one trait is required for an object type
+}
diff --git a/tests/ui/traits/object/vs-lifetime.stderr b/tests/ui/traits/object/vs-lifetime.stderr
new file mode 100644
index 000000000..224465228
--- /dev/null
+++ b/tests/ui/traits/object/vs-lifetime.stderr
@@ -0,0 +1,52 @@
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/vs-lifetime.rs:9:23
+ |
+LL | let _: S<'static, dyn 'static +>;
+ | ^^^^^^^^^^^^^
+
+error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+ --> $DIR/vs-lifetime.rs:11:12
+ |
+LL | let _: S<'static, 'static>;
+ | ^ ------- help: remove this lifetime argument
+ | |
+ | expected 1 lifetime argument
+ |
+note: struct defined here, with 1 lifetime parameter: `'a`
+ --> $DIR/vs-lifetime.rs:4:8
+ |
+LL | struct S<'a, T>(&'a u8, T);
+ | ^ --
+
+error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+ --> $DIR/vs-lifetime.rs:11:12
+ |
+LL | let _: S<'static, 'static>;
+ | ^ expected 1 generic argument
+ |
+note: struct defined here, with 1 generic parameter: `T`
+ --> $DIR/vs-lifetime.rs:4:8
+ |
+LL | struct S<'a, T>(&'a u8, T);
+ | ^ -
+help: add missing generic argument
+ |
+LL | let _: S<'static, 'static, T>;
+ | +++
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/vs-lifetime.rs:14:14
+ |
+LL | let _: S<dyn 'static +, 'static>;
+ | ^^^^^^^^^^^^^
+
+error[E0747]: type provided when a lifetime was expected
+ --> $DIR/vs-lifetime.rs:14:14
+ |
+LL | let _: S<dyn 'static +, 'static>;
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0107, E0224, E0747.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/object/with-lifetime-bound.rs b/tests/ui/traits/object/with-lifetime-bound.rs
new file mode 100644
index 000000000..05aab5e3b
--- /dev/null
+++ b/tests/ui/traits/object/with-lifetime-bound.rs
@@ -0,0 +1,34 @@
+// run-pass
+// Uncovered during work on new scoping rules for safe destructors
+// as an important use case to support properly.
+
+
+pub struct E<'a> {
+ pub f: &'a u8,
+}
+impl<'b> E<'b> {
+ pub fn m(&self) -> &'b u8 { self.f }
+}
+
+pub struct P<'c> {
+ pub g: &'c u8,
+}
+pub trait M {
+ fn n(&self) -> u8;
+}
+impl<'d> M for P<'d> {
+ fn n(&self) -> u8 { *self.g }
+}
+
+fn extension<'e>(x: &'e E<'e>) -> Box<dyn M+'e> {
+ loop {
+ let p = P { g: x.m() };
+ return Box::new(p) as Box<dyn M+'e>;
+ }
+}
+
+fn main() {
+ let w = E { f: &10 };
+ let o = extension(&w);
+ assert_eq!(o.n(), 10);
+}
diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.rs b/tests/ui/traits/object/with-self-in-projection-output-bad.rs
new file mode 100644
index 000000000..f34fa80a0
--- /dev/null
+++ b/tests/ui/traits/object/with-self-in-projection-output-bad.rs
@@ -0,0 +1,50 @@
+// Regression test for #56288. Checks that if a supertrait defines an associated type
+// projection that references `Self`, then that associated type must still be explicitly
+// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore.
+
+trait Base {
+ type Output;
+}
+
+trait Helper: Base<Output=<Self as Helper>::Target> {
+ type Target;
+}
+
+impl Base for u32
+{
+ type Output = i32;
+}
+
+impl Helper for u32
+{
+ type Target = i32;
+}
+
+trait ConstI32 {
+ type Out;
+}
+
+impl<T: ?Sized> ConstI32 for T {
+ type Out = i32;
+}
+
+// Test that you still need to manually give a projection type if the Output type
+// is normalizable.
+trait NormalizableHelper:
+ Base<Output=<Self as ConstI32>::Out>
+{
+ type Target;
+}
+
+impl NormalizableHelper for u32
+{
+ type Target = i32;
+}
+
+fn main() {
+ let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32);
+ //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified
+
+ let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32);
+ //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified
+}
diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.stderr b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr
new file mode 100644
index 000000000..641bfe236
--- /dev/null
+++ b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr
@@ -0,0 +1,21 @@
+error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified
+ --> $DIR/with-self-in-projection-output-bad.rs:45:21
+ |
+LL | type Output;
+ | ----------- `Output` defined here
+...
+LL | let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32);
+ | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper<Target=i32, Output = Type>`
+
+error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified
+ --> $DIR/with-self-in-projection-output-bad.rs:48:21
+ |
+LL | type Output;
+ | ----------- `Output` defined here
+...
+LL | let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper<Target=i32, Output = Type>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/traits/object/with-self-in-projection-output-good.rs b/tests/ui/traits/object/with-self-in-projection-output-good.rs
new file mode 100644
index 000000000..d1b7bf6c2
--- /dev/null
+++ b/tests/ui/traits/object/with-self-in-projection-output-good.rs
@@ -0,0 +1,28 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+// Regression test related to #56288. Check that a supertrait projection (of
+// `Output`) that references `Self` can be ok if it is referencing a projection (of
+// `Self::Target`, in this case). Note that we still require the user to manually
+// specify both `Target` and `Output` for now.
+
+trait Base {
+ type Output;
+}
+
+trait Helper: Base<Output=<Self as Helper>::Target> {
+ type Target;
+}
+
+impl Base for u32
+{
+ type Output = i32;
+}
+
+impl Helper for u32
+{
+ type Target = i32;
+}
+
+fn main() {
+ let _x: Box<dyn Helper<Target=i32, Output=i32>> = Box::new(2u32);
+}
diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs
new file mode 100644
index 000000000..39e817168
--- /dev/null
+++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs
@@ -0,0 +1,51 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+// FIXME(eddyb) shorten the name so windows doesn't choke on it.
+#![crate_name = "trait_test"]
+
+// Regression test related to #56288. Check that a supertrait projection (of
+// `Output`) that references `Self` is ok if there is another occurrence of
+// the same supertrait that specifies the projection explicitly, even if
+// the projection's associated type is not explicitly specified in the object type.
+//
+// Note that in order for this to compile, we need the `Self`-referencing projection
+// to normalize fairly directly to a concrete type, otherwise the trait resolver
+// will hate us.
+//
+// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that
+// having a normalizing, but `Self`-containing projection does not *by itself*
+// allow you to avoid writing the projected type (`Output`, in this example)
+// explicitly.
+
+trait ConstI32 {
+ type Out;
+}
+
+impl<T: ?Sized> ConstI32 for T {
+ type Out = i32;
+}
+
+trait Base {
+ type Output;
+}
+
+trait NormalizingHelper: Base<Output=<Self as ConstI32>::Out> + Base<Output=i32> {
+ type Target;
+}
+
+impl Base for u32
+{
+ type Output = i32;
+}
+
+impl NormalizingHelper for u32
+{
+ type Target = i32;
+}
+
+fn main() {
+ // Make sure this works both with and without the associated type
+ // being specified.
+ let _x: Box<dyn NormalizingHelper<Target=i32>> = Box::new(2u32);
+ let _y: Box<dyn NormalizingHelper<Target=i32, Output=i32>> = Box::new(2u32);
+}
diff --git a/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs b/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs
new file mode 100644
index 000000000..fce1341fc
--- /dev/null
+++ b/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs
@@ -0,0 +1,30 @@
+// run-pass
+// Test invoked `&self` methods on owned objects where the values
+// closed over do not contain managed values, and thus the boxes do
+// not have headers.
+
+trait FooTrait {
+ fn foo(&self) -> usize;
+}
+
+struct BarStruct {
+ x: usize
+}
+
+impl FooTrait for BarStruct {
+ fn foo(&self) -> usize {
+ self.x
+ }
+}
+
+pub fn main() {
+ let foos: Vec<Box<dyn FooTrait>> = vec![
+ Box::new(BarStruct{ x: 0 }) as Box<dyn FooTrait>,
+ Box::new(BarStruct{ x: 1 }) as Box<dyn FooTrait>,
+ Box::new(BarStruct{ x: 2 }) as Box<dyn FooTrait>,
+ ];
+
+ for i in 0..foos.len() {
+ assert_eq!(i, foos[i].foo());
+ }
+}
diff --git a/tests/ui/traits/operator-overloading-issue-52025.rs b/tests/ui/traits/operator-overloading-issue-52025.rs
new file mode 100644
index 000000000..7ce638832
--- /dev/null
+++ b/tests/ui/traits/operator-overloading-issue-52025.rs
@@ -0,0 +1,57 @@
+// only-x86_64
+// build-pass
+
+use std::arch::x86_64::*;
+use std::fmt::Debug;
+use std::ops::*;
+
+pub trait Simd {
+ type Vf32: Copy + Debug + Add<Self::Vf32, Output = Self::Vf32> + Add<f32, Output = Self::Vf32>;
+
+ unsafe fn set1_ps(a: f32) -> Self::Vf32;
+ unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32;
+}
+
+#[derive(Copy, Debug, Clone)]
+pub struct F32x4(pub __m128);
+
+impl Add<F32x4> for F32x4 {
+ type Output = F32x4;
+
+ fn add(self, rhs: F32x4) -> F32x4 {
+ F32x4(unsafe { _mm_add_ps(self.0, rhs.0) })
+ }
+}
+
+impl Add<f32> for F32x4 {
+ type Output = F32x4;
+ fn add(self, rhs: f32) -> F32x4 {
+ F32x4(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) })
+ }
+}
+
+pub struct Sse2;
+impl Simd for Sse2 {
+ type Vf32 = F32x4;
+
+ #[inline(always)]
+ unsafe fn set1_ps(a: f32) -> Self::Vf32 {
+ F32x4(_mm_set1_ps(a))
+ }
+
+ #[inline(always)]
+ unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32 {
+ F32x4(_mm_add_ps(a.0, b.0))
+ }
+}
+
+unsafe fn test<S: Simd>() -> S::Vf32 {
+ let a = S::set1_ps(3.0);
+ let b = S::set1_ps(2.0);
+ let result = a + b;
+ result
+}
+
+fn main() {
+ println!("{:?}", unsafe { test::<Sse2>() });
+}
diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs
new file mode 100644
index 000000000..4106f56d6
--- /dev/null
+++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs
@@ -0,0 +1,10 @@
+#![allow(dead_code)]
+#![feature(negative_impls)]
+
+// Overlapping negative impls for `MyStruct` are not permitted:
+struct MyStruct;
+impl !Send for MyStruct {}
+impl !Send for MyStruct {}
+//~^ ERROR conflicting implementations of trait
+
+fn main() {}
diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr
new file mode 100644
index 000000000..e24ed695d
--- /dev/null
+++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Send` for type `MyStruct`
+ --> $DIR/overlap-not-permitted-for-builtin-trait.rs:7:1
+ |
+LL | impl !Send for MyStruct {}
+ | ----------------------- first implementation here
+LL | impl !Send for MyStruct {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/overlap-permitted-for-marker-traits.rs b/tests/ui/traits/overlap-permitted-for-marker-traits.rs
new file mode 100644
index 000000000..00823d13b
--- /dev/null
+++ b/tests/ui/traits/overlap-permitted-for-marker-traits.rs
@@ -0,0 +1,28 @@
+// run-pass
+// Tests for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits without items. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`.
+
+#![feature(marker_trait_attr)]
+#![feature(negative_impls)]
+
+use std::fmt::{Debug, Display};
+
+#[marker]
+trait MyMarker {}
+
+impl<T: Debug> MyMarker for T {}
+impl<T: Display> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+ t
+}
+
+fn main() {
+ // Debug && Display:
+ assert_eq!(1, foo(1));
+ assert_eq!(2.0, foo(2.0));
+
+ // Debug && !Display:
+ assert_eq!(vec![1], foo(vec![1]));
+}
diff --git a/tests/ui/traits/param-without-lifetime-constraint.rs b/tests/ui/traits/param-without-lifetime-constraint.rs
new file mode 100644
index 000000000..a79b74dcd
--- /dev/null
+++ b/tests/ui/traits/param-without-lifetime-constraint.rs
@@ -0,0 +1,20 @@
+struct Article {
+ proof_reader: ProofReader,
+}
+
+struct ProofReader {
+ name: String,
+}
+
+pub trait HaveRelationship<To> {
+ fn get_relation(&self) -> To;
+}
+
+impl HaveRelationship<&ProofReader> for Article {
+ fn get_relation(&self) -> &ProofReader {
+ //~^ ERROR `impl` item signature doesn't match `trait` item signature
+ &self.proof_reader
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/param-without-lifetime-constraint.stderr b/tests/ui/traits/param-without-lifetime-constraint.stderr
new file mode 100644
index 000000000..b128b6518
--- /dev/null
+++ b/tests/ui/traits/param-without-lifetime-constraint.stderr
@@ -0,0 +1,19 @@
+error: `impl` item signature doesn't match `trait` item signature
+ --> $DIR/param-without-lifetime-constraint.rs:14:5
+ |
+LL | fn get_relation(&self) -> To;
+ | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader`
+...
+LL | fn get_relation(&self) -> &ProofReader {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader`
+ |
+ = note: expected signature `fn(&'1 Article) -> &'2 ProofReader`
+ found signature `fn(&'1 Article) -> &'1 ProofReader`
+help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+ --> $DIR/param-without-lifetime-constraint.rs:10:31
+ |
+LL | fn get_relation(&self) -> To;
+ | ^^ consider borrowing this type parameter in the trait
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/parameterized-with-bounds.rs b/tests/ui/traits/parameterized-with-bounds.rs
new file mode 100644
index 000000000..832d4f6c8
--- /dev/null
+++ b/tests/ui/traits/parameterized-with-bounds.rs
@@ -0,0 +1,21 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+
+trait A<T> { fn get(self) -> T; }
+trait B<T, U> { fn get(self) -> (T,U); }
+trait C<'a, U> { fn get(self) -> &'a U; }
+
+mod foo {
+ pub trait D<'a, T> { fn get(self) -> &'a T; }
+}
+
+fn foo1<T>(_: &(dyn A<T> + Send)) {}
+fn foo2<T>(_: Box<dyn A<T> + Send + Sync>) {}
+fn foo3<T>(_: Box<dyn B<isize, usize> + 'static>) {}
+fn foo4<'a, T>(_: Box<dyn C<'a, T> + 'static + Send>) {}
+fn foo5<'a, T>(_: Box<dyn foo::D<'a, T> + 'static + Send>) {}
+
+pub fn main() {}
diff --git a/tests/ui/traits/pointee-deduction.rs b/tests/ui/traits/pointee-deduction.rs
new file mode 100644
index 000000000..c333b0129
--- /dev/null
+++ b/tests/ui/traits/pointee-deduction.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+#![feature(ptr_metadata)]
+
+use std::alloc::Layout;
+use std::ptr::Pointee;
+
+trait Foo {
+ type Bar;
+}
+
+impl Foo for () {
+ type Bar = ();
+}
+
+struct Wrapper1<T: Foo>(#[allow(unused_tuple_struct_fields)] <T as Foo>::Bar);
+struct Wrapper2<T: Foo>(#[allow(unused_tuple_struct_fields)] <Wrapper1<T> as Pointee>::Metadata);
+
+fn main() {
+ let _: Wrapper2<()> = Wrapper2(());
+ let _ = Layout::new::<Wrapper2<()>>();
+}
diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.rs b/tests/ui/traits/pointee-tail-is-generic-errors.rs
new file mode 100644
index 000000000..28bc1da96
--- /dev/null
+++ b/tests/ui/traits/pointee-tail-is-generic-errors.rs
@@ -0,0 +1,22 @@
+// edition:2018
+
+#![feature(ptr_metadata)]
+#![feature(type_alias_impl_trait)]
+
+type Opaque = impl std::fmt::Debug + ?Sized;
+
+fn opaque() -> &'static Opaque {
+ &[1] as &[i32]
+}
+
+fn a<T: ?Sized>() {
+ is_thin::<T>();
+ //~^ ERROR type mismatch resolving `<T as Pointee>::Metadata == ()`
+
+ is_thin::<Opaque>();
+ //~^ ERROR type mismatch resolving `<Opaque as Pointee>::Metadata == ()`
+}
+
+fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
+
+fn main() {}
diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.stderr b/tests/ui/traits/pointee-tail-is-generic-errors.stderr
new file mode 100644
index 000000000..0c3d7060d
--- /dev/null
+++ b/tests/ui/traits/pointee-tail-is-generic-errors.stderr
@@ -0,0 +1,40 @@
+error[E0271]: type mismatch resolving `<T as Pointee>::Metadata == ()`
+ --> $DIR/pointee-tail-is-generic-errors.rs:13:15
+ |
+LL | is_thin::<T>();
+ | ^ expected `()`, found associated type
+ |
+ = note: expected unit type `()`
+ found associated type `<T as Pointee>::Metadata`
+ = help: consider constraining the associated type `<T as Pointee>::Metadata` to `()`
+ = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+note: required by a bound in `is_thin`
+ --> $DIR/pointee-tail-is-generic-errors.rs:20:33
+ |
+LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
+ | ^^^^^^^^^^^^^ required by this bound in `is_thin`
+
+error[E0271]: type mismatch resolving `<Opaque as Pointee>::Metadata == ()`
+ --> $DIR/pointee-tail-is-generic-errors.rs:16:15
+ |
+LL | type Opaque = impl std::fmt::Debug + ?Sized;
+ | ----------------------------- the found opaque type
+...
+LL | is_thin::<Opaque>();
+ | ^^^^^^ expected `()`, found associated type
+ |
+ = note: expected unit type `()`
+ found associated type `<Opaque as Pointee>::Metadata`
+note: required by a bound in `is_thin`
+ --> $DIR/pointee-tail-is-generic-errors.rs:20:33
+ |
+LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
+ | ^^^^^^^^^^^^^ required by this bound in `is_thin`
+help: consider constraining the associated type `<Opaque as Pointee>::Metadata` to `()`
+ |
+LL | type Opaque = impl std::fmt::Debug<Metadata = ()> + ?Sized;
+ | +++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/pointee-tail-is-generic.rs b/tests/ui/traits/pointee-tail-is-generic.rs
new file mode 100644
index 000000000..e0da0fc38
--- /dev/null
+++ b/tests/ui/traits/pointee-tail-is-generic.rs
@@ -0,0 +1,29 @@
+// check-pass
+// edition:2018
+
+#![feature(ptr_metadata)]
+#![feature(type_alias_impl_trait)]
+
+type Opaque = impl std::future::Future;
+
+fn opaque() -> Opaque {
+ async {}
+}
+
+fn a<T>() {
+ // type parameter T is known to be sized
+ is_thin::<T>();
+ // tail of ADT (which is a type param) is known to be sized
+ is_thin::<std::cell::Cell<T>>();
+ // opaque type is known to be sized
+ is_thin::<Opaque>();
+}
+
+fn a2<T: Iterator>() {
+ // associated type is known to be sized
+ is_thin::<T::Item>();
+}
+
+fn is_thin<T: std::ptr::Pointee<Metadata = ()>>() {}
+
+fn main() {}
diff --git a/tests/ui/traits/principal-less-objects.rs b/tests/ui/traits/principal-less-objects.rs
new file mode 100644
index 000000000..62bad0d7d
--- /dev/null
+++ b/tests/ui/traits/principal-less-objects.rs
@@ -0,0 +1,42 @@
+// run-pass
+// Check that trait objects without a principal codegen properly.
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::mem;
+
+// Array is to make sure the size is not exactly pointer-size, so
+// we can be sure we are measuring the right size in the
+// `size_of_val` test.
+struct SetOnDrop<'a>(&'a AtomicUsize, #[allow(unused_tuple_struct_fields)] [u8; 64]);
+impl<'a> Drop for SetOnDrop<'a> {
+ fn drop(&mut self) {
+ self.0.store(self.0.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
+ }
+}
+
+trait TypeEq<V: ?Sized> {}
+impl<T: ?Sized> TypeEq<T> for T {}
+fn assert_types_eq<U: ?Sized, V: ?Sized>() where U: TypeEq<V> {}
+
+fn main() {
+ // Check that different ways of writing the same type are equal.
+ assert_types_eq::<dyn Sync, dyn Sync + Sync>();
+ assert_types_eq::<dyn Sync + Send, dyn Send + Sync>();
+ assert_types_eq::<dyn Sync + Send + Sync, dyn Send + Sync>();
+
+ // Check that codegen works.
+ //
+ // Using `AtomicUsize` here because `Cell<u32>` is not `Sync`, and
+ // so can't be made into a `Box<dyn Sync>`.
+ let c = AtomicUsize::new(0);
+ {
+ let d: Box<dyn Sync> = Box::new(SetOnDrop(&c, [0; 64]));
+
+ assert_eq!(mem::size_of_val(&*d),
+ mem::size_of::<SetOnDrop>());
+ assert_eq!(mem::align_of_val(&*d),
+ mem::align_of::<SetOnDrop>());
+ assert_eq!(c.load(Ordering::Relaxed), 0);
+ }
+ assert_eq!(c.load(Ordering::Relaxed), 1);
+}
diff --git a/tests/ui/traits/privacy.rs b/tests/ui/traits/privacy.rs
new file mode 100644
index 000000000..17a2e05e9
--- /dev/null
+++ b/tests/ui/traits/privacy.rs
@@ -0,0 +1,24 @@
+// build-pass (FIXME(62277): could be check-pass?)
+#![allow(dead_code)]
+mod foo {
+ pub use self::bar::T;
+ mod bar {
+ pub trait T {
+ fn f(&self) {}
+ }
+ impl T for () {}
+ }
+}
+
+fn g() {
+ use foo::T;
+ ().f(); // Check that this does not trigger a privacy error
+}
+
+fn f() {
+ let error = ::std::thread::spawn(|| {}).join().unwrap_err();
+ error.type_id(); // Regression test for #21670
+}
+
+
+fn main() {}
diff --git a/tests/ui/traits/project-modulo-regions.rs b/tests/ui/traits/project-modulo-regions.rs
new file mode 100644
index 000000000..f0c0dd3ed
--- /dev/null
+++ b/tests/ui/traits/project-modulo-regions.rs
@@ -0,0 +1,55 @@
+// revisions: with_clause without_clause
+// Tests that `EvaluatedToOkModuloRegions` from a projection sub-obligation
+// is correctly propagated
+
+#![feature(rustc_attrs)]
+
+trait MyTrait {
+ type Assoc;
+}
+
+struct MyStruct;
+
+impl MyTrait for MyStruct {
+ // Evaluating this projection will result in `EvaluatedToOkModuloRegions`
+ // (when `with_clause` is enabled)
+ type Assoc = <Bar as MyTrait>::Assoc;
+}
+
+struct Bar;
+
+// The `where` clause on this impl will cause us to produce `EvaluatedToOkModuloRegions`
+// when evaluating a projection involving this impl
+#[cfg(with_clause)]
+impl MyTrait for Bar where for<'b> &'b (): 'b {
+ type Assoc = bool;
+}
+
+// This impl tests that the `EvaluatedToOkModuoRegions` result that we get
+// is really due to the `where` clause on the `with_clause` impl
+#[cfg(without_clause)]
+impl MyTrait for Bar {
+ type Assoc = bool;
+}
+
+// The implementation of `#[rustc_evaluate_where_clauses]` doesn't perform
+// normalization, so we need to place the projection predicate behind a normal
+// trait predicate
+struct Helper {}
+trait HelperTrait {}
+impl HelperTrait for Helper where <MyStruct as MyTrait>::Assoc: Sized {}
+
+// Evaluating this 'where' clause will (recursively) end up evaluating
+// `for<'b> &'b (): 'b`, which will produce `EvaluatedToOkModuloRegions`
+#[rustc_evaluate_where_clauses]
+fn test(val: MyStruct) where Helper: HelperTrait {
+ panic!()
+}
+
+fn foo(val: MyStruct) {
+ test(val);
+ //[with_clause]~^ ERROR evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ //[without_clause]~^^ ERROR evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/project-modulo-regions.with_clause.stderr b/tests/ui/traits/project-modulo-regions.with_clause.stderr
new file mode 100644
index 000000000..2434c32c8
--- /dev/null
+++ b/tests/ui/traits/project-modulo-regions.with_clause.stderr
@@ -0,0 +1,11 @@
+error: evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
+ --> $DIR/project-modulo-regions.rs:50:5
+ |
+LL | fn test(val: MyStruct) where Helper: HelperTrait {
+ | ----------- predicate
+...
+LL | test(val);
+ | ^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/project-modulo-regions.without_clause.stderr b/tests/ui/traits/project-modulo-regions.without_clause.stderr
new file mode 100644
index 000000000..9d35690d5
--- /dev/null
+++ b/tests/ui/traits/project-modulo-regions.without_clause.stderr
@@ -0,0 +1,11 @@
+error: evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+ --> $DIR/project-modulo-regions.rs:50:5
+ |
+LL | fn test(val: MyStruct) where Helper: HelperTrait {
+ | ----------- predicate
+...
+LL | test(val);
+ | ^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/region-pointer-simple.rs b/tests/ui/traits/region-pointer-simple.rs
new file mode 100644
index 000000000..0456ca931
--- /dev/null
+++ b/tests/ui/traits/region-pointer-simple.rs
@@ -0,0 +1,21 @@
+// run-pass
+trait Foo {
+ fn f(&self) -> isize;
+}
+
+struct A {
+ x: isize
+}
+
+impl Foo for A {
+ fn f(&self) -> isize {
+ println!("Today's number is {}", self.x);
+ return self.x;
+ }
+}
+
+pub fn main() {
+ let a = A { x: 3 };
+ let b = (&a) as &dyn Foo;
+ assert_eq!(b.f(), 3);
+}
diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.rs b/tests/ui/traits/reservation-impl/coherence-conflict.rs
new file mode 100644
index 000000000..fa4a30931
--- /dev/null
+++ b/tests/ui/traits/reservation-impl/coherence-conflict.rs
@@ -0,0 +1,14 @@
+// check that reservation impls are accounted for in negative reasoning.
+
+#![feature(rustc_attrs)]
+
+trait MyTrait {}
+#[rustc_reservation_impl="this impl is reserved"]
+impl MyTrait for () {}
+
+trait OtherTrait {}
+impl OtherTrait for () {}
+impl<T: MyTrait> OtherTrait for T {}
+//~^ ERROR conflicting implementations
+
+fn main() {}
diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.stderr b/tests/ui/traits/reservation-impl/coherence-conflict.stderr
new file mode 100644
index 000000000..a811d7e32
--- /dev/null
+++ b/tests/ui/traits/reservation-impl/coherence-conflict.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `OtherTrait` for type `()`
+ --> $DIR/coherence-conflict.rs:11:1
+ |
+LL | impl OtherTrait for () {}
+ | ---------------------- first implementation here
+LL | impl<T: MyTrait> OtherTrait for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+ |
+ = note: this impl is reserved
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/reservation-impl/no-use.rs b/tests/ui/traits/reservation-impl/no-use.rs
new file mode 100644
index 000000000..65a55d9e2
--- /dev/null
+++ b/tests/ui/traits/reservation-impl/no-use.rs
@@ -0,0 +1,12 @@
+// check that reservation impls can't be used as normal impls in positive reasoning.
+
+#![feature(rustc_attrs)]
+
+trait MyTrait { fn foo(&self); }
+#[rustc_reservation_impl = "foo"]
+impl MyTrait for () { fn foo(&self) {} }
+
+fn main() {
+ <() as MyTrait>::foo(&());
+ //~^ ERROR the trait bound `(): MyTrait` is not satisfied
+}
diff --git a/tests/ui/traits/reservation-impl/no-use.stderr b/tests/ui/traits/reservation-impl/no-use.stderr
new file mode 100644
index 000000000..cefb2a879
--- /dev/null
+++ b/tests/ui/traits/reservation-impl/no-use.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `(): MyTrait` is not satisfied
+ --> $DIR/no-use.rs:10:26
+ |
+LL | <() as MyTrait>::foo(&());
+ | -------------------- ^^^ the trait `MyTrait` is not implemented for `()`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `MyTrait` is implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/reservation-impl/non-lattice-ok.rs b/tests/ui/traits/reservation-impl/non-lattice-ok.rs
new file mode 100644
index 000000000..a71051243
--- /dev/null
+++ b/tests/ui/traits/reservation-impl/non-lattice-ok.rs
@@ -0,0 +1,59 @@
+// build-pass
+
+// Check that a reservation impl does not force other impls to follow
+// a lattice discipline.
+
+// Why did we ever want to do this?
+//
+// We want to eventually add an `impl<T> From<!> for T` impl. That impl conflicts
+// with existing impls - at least the `impl<T> From<T> for T` impl. There are
+// 2 ways we thought of for dealing with that conflict:
+//
+// 1. Using specialization and doing some handling for the
+// overlap. The current thought is to require ["intersection
+// impls"][ii], specialization", which means providing an
+// (higher-priority) impl for the intersection of every 2 conflicting
+// impls that determines what happens in the intersection case. That's
+// the first thing we thought about - see e.g.
+// https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775
+//
+// 2. The other way is to notice that `impl From<!> for T` is basically a
+// marker trait since its only method is uninhabited, and allow for "marker
+// trait overlap", where the conflict "doesn't matter" because it can't
+// actually cause any ambiguity.
+//
+// Now it turned out lattice specialization doesn't work it, because an
+// `impl<T> From<T> for Smaht<T>` would require an `impl From<!> for Smaht<!>`,
+// breaking backwards-compatibility in a fairly painful way. So if we want to
+// go with a known approach, we should go with a "marker trait overlap"-style
+// approach.
+//
+// [ii]: https://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/
+
+#![feature(rustc_attrs, never_type)]
+
+trait MyTrait {}
+
+impl MyTrait for ! {}
+
+trait MyFrom<T> {
+ fn my_from(x: T) -> Self;
+}
+
+// Given the "normal" impls for From
+#[rustc_reservation_impl="this impl is reserved"]
+impl<T> MyFrom<!> for T {
+ fn my_from(x: !) -> Self { match x {} }
+}
+
+impl<T> MyFrom<T> for T {
+ fn my_from(x: T) -> Self { x }
+}
+
+// ... we *do* want to allow this common pattern, of `From<!> for MySmaht<T>`
+struct MySmaht<T>(T);
+impl<T> MyFrom<T> for MySmaht<T> {
+ fn my_from(x: T) -> Self { MySmaht(x) }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/reservation-impl/ok.rs b/tests/ui/traits/reservation-impl/ok.rs
new file mode 100644
index 000000000..611c8d884
--- /dev/null
+++ b/tests/ui/traits/reservation-impl/ok.rs
@@ -0,0 +1,28 @@
+// run-pass
+
+// rpass test for reservation impls. Not 100% required because `From` uses them,
+// but still.
+
+#![feature(rustc_attrs)]
+
+use std::mem;
+
+trait MyTrait<S> {
+ fn foo(&self, s: S) -> usize;
+}
+
+#[rustc_reservation_impl = "foo"]
+impl<T> MyTrait<u64> for T {
+ fn foo(&self, _x: u64) -> usize { 0 }
+}
+
+// reservation impls don't create coherence conflicts, even with
+// non-chain overlap.
+impl<S> MyTrait<S> for u32 {
+ fn foo(&self, _x: S) -> usize { mem::size_of::<S>() }
+}
+
+fn main() {
+ // ...and the non-reservation impl gets picked.XS
+ assert_eq!(0u32.foo(0u64), mem::size_of::<u64>());
+}
diff --git a/tests/ui/traits/resolution-in-overloaded-op.rs b/tests/ui/traits/resolution-in-overloaded-op.rs
new file mode 100644
index 000000000..a9bacc357
--- /dev/null
+++ b/tests/ui/traits/resolution-in-overloaded-op.rs
@@ -0,0 +1,11 @@
+// #12402 Operator overloading only considers the method name, not which trait is implemented
+
+trait MyMul<Rhs, Res> {
+ fn mul(&self, rhs: &Rhs) -> Res;
+}
+
+fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 {
+ a * b //~ ERROR cannot multiply `&T` by `f64`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/resolution-in-overloaded-op.stderr b/tests/ui/traits/resolution-in-overloaded-op.stderr
new file mode 100644
index 000000000..fe5e1d6d2
--- /dev/null
+++ b/tests/ui/traits/resolution-in-overloaded-op.stderr
@@ -0,0 +1,16 @@
+error[E0369]: cannot multiply `&T` by `f64`
+ --> $DIR/resolution-in-overloaded-op.rs:8:7
+ |
+LL | a * b
+ | - ^ - f64
+ | |
+ | &T
+ |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 where &T: Mul<f64, Output = f64> {
+ | ++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/traits/safety-fn-body.mir.stderr b/tests/ui/traits/safety-fn-body.mir.stderr
new file mode 100644
index 000000000..ea7b2048e
--- /dev/null
+++ b/tests/ui/traits/safety-fn-body.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/safety-fn-body.rs:14:9
+ |
+LL | *self += 1;
+ | ^^^^^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/traits/safety-fn-body.rs b/tests/ui/traits/safety-fn-body.rs
new file mode 100644
index 000000000..2cc4fe1b3
--- /dev/null
+++ b/tests/ui/traits/safety-fn-body.rs
@@ -0,0 +1,19 @@
+// Check that an unsafe impl does not imply that unsafe actions are
+// legal in the methods.
+
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+unsafe trait UnsafeTrait : Sized {
+ fn foo(self) { }
+}
+
+unsafe impl UnsafeTrait for *mut isize {
+ fn foo(self) {
+ // Unsafe actions are not made legal by taking place in an unsafe trait:
+ *self += 1;
+ //~^ ERROR E0133
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/safety-fn-body.thir.stderr b/tests/ui/traits/safety-fn-body.thir.stderr
new file mode 100644
index 000000000..23696c32b
--- /dev/null
+++ b/tests/ui/traits/safety-fn-body.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/safety-fn-body.rs:14:9
+ |
+LL | *self += 1;
+ | ^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/traits/safety-inherent-impl.rs b/tests/ui/traits/safety-inherent-impl.rs
new file mode 100644
index 000000000..50e15f0d2
--- /dev/null
+++ b/tests/ui/traits/safety-inherent-impl.rs
@@ -0,0 +1,9 @@
+// Check that inherent impls cannot be unsafe.
+
+struct SomeStruct;
+
+unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe
+ fn foo(self) { }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/safety-inherent-impl.stderr b/tests/ui/traits/safety-inherent-impl.stderr
new file mode 100644
index 000000000..1c8f43fec
--- /dev/null
+++ b/tests/ui/traits/safety-inherent-impl.stderr
@@ -0,0 +1,11 @@
+error[E0197]: inherent impls cannot be unsafe
+ --> $DIR/safety-inherent-impl.rs:5:13
+ |
+LL | unsafe impl SomeStruct {
+ | ------ ^^^^^^^^^^ inherent impl for this type
+ | |
+ | unsafe because of this
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0197`.
diff --git a/tests/ui/traits/safety-ok-cc.rs b/tests/ui/traits/safety-ok-cc.rs
new file mode 100644
index 000000000..099ba80e5
--- /dev/null
+++ b/tests/ui/traits/safety-ok-cc.rs
@@ -0,0 +1,24 @@
+// run-pass
+// aux-build:trait_safety_lib.rs
+
+// Simple smoke test that unsafe traits can be compiled across crates.
+
+
+extern crate trait_safety_lib as lib;
+
+use lib::Foo;
+
+struct Bar { x: isize }
+unsafe impl Foo for Bar {
+ fn foo(&self) -> isize { self.x }
+}
+
+fn take_foo<F:Foo>(f: &F) -> isize { f.foo() }
+
+fn main() {
+ let x: isize = 22;
+ assert_eq!(22, take_foo(&x));
+
+ let x: Bar = Bar { x: 23 };
+ assert_eq!(23, take_foo(&x));
+}
diff --git a/tests/ui/traits/safety-ok.rs b/tests/ui/traits/safety-ok.rs
new file mode 100644
index 000000000..d456a78b6
--- /dev/null
+++ b/tests/ui/traits/safety-ok.rs
@@ -0,0 +1,18 @@
+// run-pass
+// Simple smoke test that unsafe traits can be compiled etc.
+
+
+unsafe trait Foo {
+ fn foo(&self) -> isize;
+}
+
+unsafe impl Foo for isize {
+ fn foo(&self) -> isize { *self }
+}
+
+fn take_foo<F:Foo>(f: &F) -> isize { f.foo() }
+
+fn main() {
+ let x: isize = 22;
+ assert_eq!(22, take_foo(&x));
+}
diff --git a/tests/ui/traits/safety-trait-impl-cc.rs b/tests/ui/traits/safety-trait-impl-cc.rs
new file mode 100644
index 000000000..6f125e5f9
--- /dev/null
+++ b/tests/ui/traits/safety-trait-impl-cc.rs
@@ -0,0 +1,15 @@
+// aux-build:trait_safety_lib.rs
+
+// Check that unsafe traits require unsafe impls and that inherent
+// impls cannot be unsafe.
+
+extern crate trait_safety_lib as lib;
+
+struct Bar;
+impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration
+ fn foo(&self) -> isize {
+ panic!();
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/safety-trait-impl-cc.stderr b/tests/ui/traits/safety-trait-impl-cc.stderr
new file mode 100644
index 000000000..0ca565787
--- /dev/null
+++ b/tests/ui/traits/safety-trait-impl-cc.stderr
@@ -0,0 +1,15 @@
+error[E0200]: the trait `Foo` requires an `unsafe impl` declaration
+ --> $DIR/safety-trait-impl-cc.rs:9:1
+ |
+LL | impl lib::Foo for Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl lib::Foo for Bar {
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0200`.
diff --git a/tests/ui/traits/safety-trait-impl.rs b/tests/ui/traits/safety-trait-impl.rs
new file mode 100644
index 000000000..45258b78d
--- /dev/null
+++ b/tests/ui/traits/safety-trait-impl.rs
@@ -0,0 +1,18 @@
+// Check that unsafe traits require unsafe impls and that inherent
+// impls cannot be unsafe.
+
+trait SafeTrait {
+ fn foo(&self) { }
+}
+
+unsafe trait UnsafeTrait {
+ fn foo(&self) { }
+}
+
+unsafe impl UnsafeTrait for u8 { } // OK
+
+impl UnsafeTrait for u16 { } //~ ERROR requires an `unsafe impl` declaration
+
+unsafe impl SafeTrait for u32 { } //~ ERROR the trait `SafeTrait` is not unsafe
+
+fn main() { }
diff --git a/tests/ui/traits/safety-trait-impl.stderr b/tests/ui/traits/safety-trait-impl.stderr
new file mode 100644
index 000000000..e78e0e3a6
--- /dev/null
+++ b/tests/ui/traits/safety-trait-impl.stderr
@@ -0,0 +1,28 @@
+error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration
+ --> $DIR/safety-trait-impl.rs:14:1
+ |
+LL | impl UnsafeTrait for u16 { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl UnsafeTrait for u16 { }
+ | ++++++
+
+error[E0199]: implementing the trait `SafeTrait` is not unsafe
+ --> $DIR/safety-trait-impl.rs:16:1
+ |
+LL | unsafe impl SafeTrait for u32 { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: remove `unsafe` from this trait implementation
+ |
+LL - unsafe impl SafeTrait for u32 { }
+LL + impl SafeTrait for u32 { }
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0199, E0200.
+For more information about an error, try `rustc --explain E0199`.
diff --git a/tests/ui/traits/self-without-lifetime-constraint.rs b/tests/ui/traits/self-without-lifetime-constraint.rs
new file mode 100644
index 000000000..99013d32a
--- /dev/null
+++ b/tests/ui/traits/self-without-lifetime-constraint.rs
@@ -0,0 +1,53 @@
+use std::error::Error;
+use std::fmt;
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum ValueRef<'a> {
+ Null,
+ Integer(i64),
+ Real(f64),
+ Text(&'a [u8]),
+ Blob(&'a [u8]),
+}
+
+impl<'a> ValueRef<'a> {
+ pub fn as_str(&self) -> FromSqlResult<&'a str, &'a &'a str> {
+ match *self {
+ ValueRef::Text(t) => {
+ std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x))
+ }
+ _ => Err(FromSqlError::InvalidType),
+ }
+ }
+}
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub enum FromSqlError {
+ InvalidType
+}
+
+impl fmt::Display for FromSqlError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "InvalidType")
+ }
+}
+
+impl Error for FromSqlError {}
+
+pub type FromSqlResult<T, K> = Result<(T, K), FromSqlError>;
+
+pub trait FromSql: Sized {
+ fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
+}
+
+impl FromSql for &str {
+ fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> {
+ //~^ ERROR `impl` item signature doesn't match `trait` item signature
+ value.as_str()
+ }
+}
+
+pub fn main() {
+ println!("{}", "Hello World");
+}
diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr
new file mode 100644
index 000000000..05a49820a
--- /dev/null
+++ b/tests/ui/traits/self-without-lifetime-constraint.stderr
@@ -0,0 +1,19 @@
+error: `impl` item signature doesn't match `trait` item signature
+ --> $DIR/self-without-lifetime-constraint.rs:45:5
+ |
+LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
+ | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>`
+...
+LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
+ |
+ = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>`
+ found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
+help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+ --> $DIR/self-without-lifetime-constraint.rs:41:60
+ |
+LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
+ | ^^^^ consider borrowing this type parameter in the trait
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs
new file mode 100644
index 000000000..5449f5f00
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs
@@ -0,0 +1,69 @@
+// check-pass
+
+// This test checks that we're correctly dealing with inductive cycles
+// with canonical inference variables.
+
+trait Trait<T, U> {}
+
+trait IsNotU32 {}
+impl IsNotU32 for i32 {}
+impl<T: IsNotU32, U> Trait<T, U> for () // impl 1
+where
+ (): Trait<U, T>
+{}
+
+impl<T> Trait<u32, T> for () {} // impl 2
+
+// If we now check whether `(): Trait<?0, ?1>` holds this has to
+// result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>`
+// applies. The remainder of this test asserts that.
+
+// If we were to error on inductive cycles with canonical inference variables
+// this would be wrong:
+
+// (): Trait<?0, ?1>
+// - impl 1
+// - ?0: IsNotU32 // ambig
+// - (): Trait<?1, ?0> // canonical cycle -> err
+// - ERR
+// - impl 2
+// - OK ?0 == u32
+//
+// Result: OK ?0 == u32.
+
+// (): Trait<i32, u32>
+// - impl 1
+// - i32: IsNotU32 // ok
+// - (): Trait<u32, i32>
+// - impl 1
+// - u32: IsNotU32 // err
+// - ERR
+// - impl 2
+// - OK
+// - OK
+// - impl 2 (trivial ERR)
+//
+// Result OK
+
+// This would mean that `(): Trait<?0, ?1>` is not complete,
+// which is unsound if we're in coherence.
+
+fn implements_trait<T, U>() -> (T, U)
+where
+ (): Trait<T, U>,
+{
+ todo!()
+}
+
+// A hack to only constrain the infer vars after first checking
+// the `(): Trait<_, _>`.
+trait Constrain<T> {}
+impl<T> Constrain<T> for T {}
+fn constrain<T: Constrain<U>, U>(_: U) {}
+
+fn main() {
+ let (x, y) = implements_trait::<_, _>();
+
+ constrain::<i32, _>(x);
+ constrain::<u32, _>(y);
+}
diff --git a/tests/ui/traits/static-method-generic-inference.rs b/tests/ui/traits/static-method-generic-inference.rs
new file mode 100644
index 000000000..f4e94c4f7
--- /dev/null
+++ b/tests/ui/traits/static-method-generic-inference.rs
@@ -0,0 +1,28 @@
+// Issue #3902. We are (at least currently) unable to infer `Self`
+// based on `T`, even though there is only a single impl, because of
+// the possibility of associated types and other things (basically: no
+// constraints on `Self` here at all).
+
+mod base {
+ pub trait HasNew<T> {
+ fn new() -> T;
+ fn dummy(&self) { }
+ }
+
+ pub struct Foo {
+ dummy: (),
+ }
+
+ impl HasNew<Foo> for Foo {
+ fn new() -> Foo {
+ Foo { dummy: () }
+ }
+ }
+}
+
+pub fn foo() {
+ let _f: base::Foo = base::HasNew::new();
+ //~^ ERROR E0790
+}
+
+fn main() { }
diff --git a/tests/ui/traits/static-method-generic-inference.stderr b/tests/ui/traits/static-method-generic-inference.stderr
new file mode 100644
index 000000000..575ace237
--- /dev/null
+++ b/tests/ui/traits/static-method-generic-inference.stderr
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+ --> $DIR/static-method-generic-inference.rs:24:25
+ |
+LL | fn new() -> T;
+ | -------------- `HasNew::new` defined here
+...
+LL | let _f: base::Foo = base::HasNew::new();
+ | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL | let _f: base::Foo = <Foo as base::HasNew>::new();
+ | +++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/tests/ui/traits/static-method-overwriting.rs b/tests/ui/traits/static-method-overwriting.rs
new file mode 100644
index 000000000..f669ffae6
--- /dev/null
+++ b/tests/ui/traits/static-method-overwriting.rs
@@ -0,0 +1,34 @@
+// run-pass
+#![allow(dead_code)]
+mod base {
+ pub trait HasNew {
+ fn new() -> Self;
+ }
+
+ pub struct Foo {
+ dummy: (),
+ }
+
+ impl ::base::HasNew for Foo {
+ fn new() -> Foo {
+ println!("Foo");
+ Foo { dummy: () }
+ }
+ }
+
+ pub struct Bar {
+ dummy: (),
+ }
+
+ impl ::base::HasNew for Bar {
+ fn new() -> Bar {
+ println!("Bar");
+ Bar { dummy: () }
+ }
+ }
+}
+
+pub fn main() {
+ let _f: base::Foo = base::HasNew::new();
+ let _b: base::Bar = base::HasNew::new();
+}
diff --git a/tests/ui/traits/static-outlives-a-where-clause.rs b/tests/ui/traits/static-outlives-a-where-clause.rs
new file mode 100644
index 000000000..f0c2c1082
--- /dev/null
+++ b/tests/ui/traits/static-outlives-a-where-clause.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+trait Foo<'a> {
+ fn xyz(self);
+}
+impl<'a, T> Foo<'a> for T where 'static: 'a {
+ fn xyz(self) {}
+}
+
+trait Bar {
+ fn uvw(self);
+}
+impl<T> Bar for T where for<'a> T: Foo<'a> {
+ fn uvw(self) { self.xyz(); }
+}
+
+fn foo<T>(t: T) where T: Bar {
+ t.uvw();
+}
+
+fn main() {
+ foo(0);
+}
diff --git a/tests/ui/traits/staticness-mismatch.rs b/tests/ui/traits/staticness-mismatch.rs
new file mode 100644
index 000000000..8710d0112
--- /dev/null
+++ b/tests/ui/traits/staticness-mismatch.rs
@@ -0,0 +1,11 @@
+trait Foo {
+ fn dummy(&self) { }
+ fn bar();
+}
+
+impl Foo for isize {
+ fn bar(&self) {}
+ //~^ ERROR method `bar` has a `&self` declaration in the impl, but not in the trait
+}
+
+fn main() {}
diff --git a/tests/ui/traits/staticness-mismatch.stderr b/tests/ui/traits/staticness-mismatch.stderr
new file mode 100644
index 000000000..b67ac5adb
--- /dev/null
+++ b/tests/ui/traits/staticness-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0185]: method `bar` has a `&self` declaration in the impl, but not in the trait
+ --> $DIR/staticness-mismatch.rs:7:5
+ |
+LL | fn bar();
+ | --------- trait method declared without `&self`
+...
+LL | fn bar(&self) {}
+ | ^^^^^^^^^^^^^ `&self` used in impl
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0185`.
diff --git a/tests/ui/traits/suggest-deferences/issue-39029.fixed b/tests/ui/traits/suggest-deferences/issue-39029.fixed
new file mode 100644
index 000000000..a1abf668b
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/issue-39029.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+use std::net::TcpListener;
+
+struct NoToSocketAddrs(String);
+
+impl std::ops::Deref for NoToSocketAddrs {
+ type Target = String;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+fn main() {
+ let _works = TcpListener::bind("some string");
+ let bad = NoToSocketAddrs("bad".to_owned());
+ let _errors = TcpListener::bind(&*bad);
+ //~^ ERROR the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/issue-39029.rs b/tests/ui/traits/suggest-deferences/issue-39029.rs
new file mode 100644
index 000000000..90d097105
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/issue-39029.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+use std::net::TcpListener;
+
+struct NoToSocketAddrs(String);
+
+impl std::ops::Deref for NoToSocketAddrs {
+ type Target = String;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+fn main() {
+ let _works = TcpListener::bind("some string");
+ let bad = NoToSocketAddrs("bad".to_owned());
+ let _errors = TcpListener::bind(&bad);
+ //~^ ERROR the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/issue-39029.stderr b/tests/ui/traits/suggest-deferences/issue-39029.stderr
new file mode 100644
index 000000000..49e20c6a7
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/issue-39029.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
+ --> $DIR/issue-39029.rs:16:37
+ |
+LL | let _errors = TcpListener::bind(&bad);
+ | ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
+note: required by a bound in `TcpListener::bind`
+ --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
+help: consider dereferencing here
+ |
+LL | let _errors = TcpListener::bind(&*bad);
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/suggest-deferences/issue-62530.fixed b/tests/ui/traits/suggest-deferences/issue-62530.fixed
new file mode 100644
index 000000000..406caaa00
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/issue-62530.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+fn takes_str(_x: &str) {}
+
+fn takes_type_parameter<T>(_x: T) where T: SomeTrait {}
+
+trait SomeTrait {}
+impl SomeTrait for &'_ str {}
+impl SomeTrait for char {}
+
+fn main() {
+ let string = String::new();
+ takes_str(&string); // Ok
+ takes_type_parameter(&*string); // Error
+ //~^ ERROR the trait bound `&String: SomeTrait` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/issue-62530.rs b/tests/ui/traits/suggest-deferences/issue-62530.rs
new file mode 100644
index 000000000..53846be73
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/issue-62530.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+fn takes_str(_x: &str) {}
+
+fn takes_type_parameter<T>(_x: T) where T: SomeTrait {}
+
+trait SomeTrait {}
+impl SomeTrait for &'_ str {}
+impl SomeTrait for char {}
+
+fn main() {
+ let string = String::new();
+ takes_str(&string); // Ok
+ takes_type_parameter(&string); // Error
+ //~^ ERROR the trait bound `&String: SomeTrait` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/issue-62530.stderr b/tests/ui/traits/suggest-deferences/issue-62530.stderr
new file mode 100644
index 000000000..e47ae0b65
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/issue-62530.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `&String: SomeTrait` is not satisfied
+ --> $DIR/issue-62530.rs:13:26
+ |
+LL | takes_type_parameter(&string); // Error
+ | -------------------- ^^^^^^^ the trait `SomeTrait` is not implemented for `&String`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `takes_type_parameter`
+ --> $DIR/issue-62530.rs:4:44
+ |
+LL | fn takes_type_parameter<T>(_x: T) where T: SomeTrait {}
+ | ^^^^^^^^^ required by this bound in `takes_type_parameter`
+help: consider dereferencing here
+ |
+LL | takes_type_parameter(&*string); // Error
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/suggest-deferences/multiple-0.fixed b/tests/ui/traits/suggest-deferences/multiple-0.fixed
new file mode 100644
index 000000000..b7160b75c
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/multiple-0.fixed
@@ -0,0 +1,36 @@
+// run-rustfix
+use std::ops::Deref;
+
+trait Happy {}
+struct LDM;
+impl Happy for &LDM {}
+
+struct Foo(LDM);
+struct Bar(Foo);
+struct Baz(Bar);
+impl Deref for Foo {
+ type Target = LDM;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl Deref for Bar {
+ type Target = Foo;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl Deref for Baz {
+ type Target = Bar;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+fn foo<T>(_: T) where T: Happy {}
+
+fn main() {
+ let baz = Baz(Bar(Foo(LDM)));
+ foo(&***baz);
+ //~^ ERROR the trait bound `&Baz: Happy` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/multiple-0.rs b/tests/ui/traits/suggest-deferences/multiple-0.rs
new file mode 100644
index 000000000..9ac55177f
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/multiple-0.rs
@@ -0,0 +1,36 @@
+// run-rustfix
+use std::ops::Deref;
+
+trait Happy {}
+struct LDM;
+impl Happy for &LDM {}
+
+struct Foo(LDM);
+struct Bar(Foo);
+struct Baz(Bar);
+impl Deref for Foo {
+ type Target = LDM;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl Deref for Bar {
+ type Target = Foo;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl Deref for Baz {
+ type Target = Bar;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+fn foo<T>(_: T) where T: Happy {}
+
+fn main() {
+ let baz = Baz(Bar(Foo(LDM)));
+ foo(&baz);
+ //~^ ERROR the trait bound `&Baz: Happy` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/multiple-0.stderr b/tests/ui/traits/suggest-deferences/multiple-0.stderr
new file mode 100644
index 000000000..6a4d4b8d5
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/multiple-0.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `&Baz: Happy` is not satisfied
+ --> $DIR/multiple-0.rs:34:9
+ |
+LL | foo(&baz);
+ | --- ^^^^ the trait `Happy` is not implemented for `&Baz`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/multiple-0.rs:30:26
+ |
+LL | fn foo<T>(_: T) where T: Happy {}
+ | ^^^^^ required by this bound in `foo`
+help: consider dereferencing here
+ |
+LL | foo(&***baz);
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/suggest-deferences/multiple-1.rs b/tests/ui/traits/suggest-deferences/multiple-1.rs
new file mode 100644
index 000000000..91c6c7924
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/multiple-1.rs
@@ -0,0 +1,54 @@
+use std::ops::{Deref, DerefMut};
+
+trait Happy {}
+struct LDM;
+impl Happy for &mut LDM {}
+
+struct Foo(LDM);
+struct Bar(Foo);
+struct Baz(Bar);
+impl Deref for Foo {
+ type Target = LDM;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl Deref for Bar {
+ type Target = Foo;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl Deref for Baz {
+ type Target = Bar;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl DerefMut for Foo {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+impl DerefMut for Bar {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+impl DerefMut for Baz {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+
+fn foo<T>(_: T) where T: Happy {}
+
+fn main() {
+ // Currently the compiler doesn't try to suggest dereferences for situations
+ // where DerefMut involves. So this test is meant to ensure compiler doesn't
+ // generate incorrect help message.
+ let mut baz = Baz(Bar(Foo(LDM)));
+ foo(&mut baz);
+ //~^ ERROR the trait bound `&mut Baz: Happy` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/multiple-1.stderr b/tests/ui/traits/suggest-deferences/multiple-1.stderr
new file mode 100644
index 000000000..6e12321c2
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/multiple-1.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied
+ --> $DIR/multiple-1.rs:52:9
+ |
+LL | foo(&mut baz);
+ | --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Happy` is implemented for `&mut LDM`
+note: required by a bound in `foo`
+ --> $DIR/multiple-1.rs:45:26
+ |
+LL | fn foo<T>(_: T) where T: Happy {}
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/suggest-deferences/root-obligation.fixed b/tests/ui/traits/suggest-deferences/root-obligation.fixed
new file mode 100644
index 000000000..7a8433f90
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/root-obligation.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+fn get_vowel_count(string: &str) -> usize {
+ string
+ .chars()
+ .filter(|c| "aeiou".contains(*c))
+ //~^ ERROR expected a `Fn<(char,)>` closure, found `char`
+ .count()
+}
+
+fn main() {
+ let _ = get_vowel_count("asdf");
+}
diff --git a/tests/ui/traits/suggest-deferences/root-obligation.rs b/tests/ui/traits/suggest-deferences/root-obligation.rs
new file mode 100644
index 000000000..51bac2107
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/root-obligation.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+
+fn get_vowel_count(string: &str) -> usize {
+ string
+ .chars()
+ .filter(|c| "aeiou".contains(c))
+ //~^ ERROR expected a `Fn<(char,)>` closure, found `char`
+ .count()
+}
+
+fn main() {
+ let _ = get_vowel_count("asdf");
+}
diff --git a/tests/ui/traits/suggest-deferences/root-obligation.stderr b/tests/ui/traits/suggest-deferences/root-obligation.stderr
new file mode 100644
index 000000000..1363fb8c4
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/root-obligation.stderr
@@ -0,0 +1,21 @@
+error[E0277]: expected a `Fn<(char,)>` closure, found `char`
+ --> $DIR/root-obligation.rs:6:38
+ |
+LL | .filter(|c| "aeiou".contains(c))
+ | -------- ^ expected an `Fn<(char,)>` closure, found `char`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<(char,)>` is not implemented for `char`
+ = note: required for `&char` to implement `FnOnce<(char,)>`
+ = note: required for `&char` to implement `Pattern<'_>`
+note: required by a bound in `core::str::<impl str>::contains`
+ --> $SRC_DIR/core/src/str/mod.rs:LL:COL
+help: consider dereferencing here
+ |
+LL | .filter(|c| "aeiou".contains(*c))
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed
new file mode 100644
index 000000000..ea3d1bf85
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+ fn from(_unchecked: usize) -> Self {
+ TargetStruct
+ }
+}
+
+fn main() {
+ let a = &3;
+ let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs
new file mode 100644
index 000000000..9eda68027
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+ fn from(_unchecked: usize) -> Self {
+ TargetStruct
+ }
+}
+
+fn main() {
+ let a = &3;
+ let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr
new file mode 100644
index 000000000..ede31a2c7
--- /dev/null
+++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+ --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30
+ |
+LL | let _b: TargetStruct = a.into();
+ | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`
+ |
+ = note: required for `&{integer}` to implement `Into<TargetStruct>`
+help: consider dereferencing here
+ |
+LL | let _b: TargetStruct = (*a).into();
+ | ++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/suggest-fully-qualified-closure.rs b/tests/ui/traits/suggest-fully-qualified-closure.rs
new file mode 100644
index 000000000..c077921c0
--- /dev/null
+++ b/tests/ui/traits/suggest-fully-qualified-closure.rs
@@ -0,0 +1,24 @@
+// check-fail
+// known-bug: #103705
+// normalize-stderr-test "\[closure@.*\]" -> "[closure@]"
+// normalize-stderr-test "\+* ~" -> "+++ ~"
+
+// The output of this currently suggests writing a closure in the qualified path.
+
+trait MyTrait<T> {
+ fn lol<F:FnOnce()>(&self, f:F) -> u16;
+}
+
+struct Qqq;
+
+impl MyTrait<u32> for Qqq{
+ fn lol<F:FnOnce()>(&self, _f:F) -> u16 { 5 }
+}
+impl MyTrait<u64> for Qqq{
+ fn lol<F:FnOnce()>(&self, _f:F) -> u16 { 6 }
+}
+
+fn main() {
+ let q = Qqq;
+ q.lol(||());
+}
diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr
new file mode 100644
index 000000000..3df623c14
--- /dev/null
+++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr
@@ -0,0 +1,34 @@
+error[E0282]: type annotations needed
+ --> $DIR/suggest-fully-qualified-closure.rs:23:7
+ |
+LL | q.lol(||());
+ | ^^^
+ |
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Qqq as MyTrait<T>>::lol::<[closure@]>(&q, ||());
+ | +++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-closure.rs:23:7
+ |
+LL | q.lol(||());
+ | ^^^
+ |
+note: multiple `impl`s satisfying `Qqq: MyTrait<_>` found
+ --> $DIR/suggest-fully-qualified-closure.rs:14:1
+ |
+LL | impl MyTrait<u32> for Qqq{
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MyTrait<u64> for Qqq{
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Qqq as MyTrait<T>>::lol::<[closure@]>(&q, ||());
+ | +++ ~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs
new file mode 100644
index 000000000..9a2cf469d
--- /dev/null
+++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs
@@ -0,0 +1,60 @@
+use std::ops::{Deref, DerefMut};
+
+struct Thing;
+
+trait Method<T> {
+ fn method(&self) -> T;
+ fn mut_method(&mut self) -> T;
+}
+
+impl Method<i32> for Thing {
+ fn method(&self) -> i32 { 0 }
+ fn mut_method(&mut self) -> i32 { 0 }
+}
+
+impl Method<u32> for Thing {
+ fn method(&self) -> u32 { 0 }
+ fn mut_method(&mut self) -> u32 { 0 }
+}
+trait MethodRef<T> {
+ fn by_self(self);
+}
+impl MethodRef<i32> for &Thing {
+ fn by_self(self) {}
+}
+impl MethodRef<u32> for &Thing {
+ fn by_self(self) {}
+}
+
+
+struct DerefsTo<T>(T);
+impl<T> Deref for DerefsTo<T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<T> DerefMut for DerefsTo<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+fn main() {
+ let mut thing = Thing;
+ thing.method();
+ //~^ ERROR type annotations needed
+ //~| ERROR type annotations needed
+ thing.mut_method(); //~ ERROR type annotations needed
+ thing.by_self(); //~ ERROR type annotations needed
+
+ let mut deref_to = DerefsTo(Thing);
+ deref_to.method(); //~ ERROR type annotations needed
+ deref_to.mut_method(); //~ ERROR type annotations needed
+ deref_to.by_self(); //~ ERROR type annotations needed
+
+ let mut deref_deref_to = DerefsTo(DerefsTo(Thing));
+ deref_deref_to.method(); //~ ERROR type annotations needed
+ deref_deref_to.mut_method(); //~ ERROR type annotations needed
+ deref_deref_to.by_self(); //~ ERROR type annotations needed
+}
diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr
new file mode 100644
index 000000000..68b31a1ca
--- /dev/null
+++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr
@@ -0,0 +1,186 @@
+error[E0282]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11
+ |
+LL | thing.method();
+ | ^^^^^^
+ |
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(&thing);
+ | ++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11
+ |
+LL | thing.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(&thing);
+ | ++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:48:11
+ |
+LL | thing.mut_method();
+ | ^^^^^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::mut_method(&mut thing);
+ | +++++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:49:11
+ |
+LL | thing.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(&thing);
+ | +++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14
+ |
+LL | deref_to.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(&deref_to);
+ | ++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:53:14
+ |
+LL | deref_to.mut_method();
+ | ^^^^^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::mut_method(&mut deref_to);
+ | +++++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:54:14
+ |
+LL | deref_to.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(&deref_to);
+ | +++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20
+ |
+LL | deref_deref_to.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(&deref_deref_to);
+ | ++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:58:20
+ |
+LL | deref_deref_to.mut_method();
+ | ^^^^^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::mut_method(&mut deref_deref_to);
+ | +++++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:59:20
+ |
+LL | deref_deref_to.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(&deref_deref_to);
+ | +++++++++++++++++++++++++++++++++++ ~
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs
new file mode 100644
index 000000000..da640c8c8
--- /dev/null
+++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs
@@ -0,0 +1,64 @@
+use std::ops::{Deref, DerefMut};
+
+struct Thing;
+
+trait Method<T> {
+ fn method(&self) -> T;
+ fn mut_method(&mut self) -> T;
+}
+
+impl Method<i32> for Thing {
+ fn method(&self) -> i32 { 0 }
+ fn mut_method(&mut self) -> i32 { 0 }
+}
+
+impl Method<u32> for Thing {
+ fn method(&self) -> u32 { 0 }
+ fn mut_method(&mut self) -> u32 { 0 }
+}
+
+trait MethodRef<T> {
+ fn by_self(self);
+}
+impl MethodRef<i32> for &Thing {
+ fn by_self(self) {}
+}
+impl MethodRef<u32> for &Thing {
+ fn by_self(self) {}
+}
+
+struct DerefsTo<T>(T);
+impl<T> Deref for DerefsTo<T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<T> DerefMut for DerefsTo<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+fn main() {
+ let mut ref_thing = &Thing;
+ ref_thing.method();
+ //~^ ERROR type annotations needed
+ //~| ERROR type annotations needed
+ ref_thing.by_self(); //~ ERROR type annotations needed
+
+ let mut mut_thing = &mut Thing;
+ mut_thing.method(); //~ ERROR type annotations needed
+ mut_thing.mut_method(); //~ ERROR type annotations needed
+ mut_thing.by_self(); //~ ERROR type annotations needed
+
+ let mut deref_to = &DerefsTo(Thing);
+ deref_to.method(); //~ ERROR type annotations needed
+ deref_to.mut_method(); //~ ERROR type annotations needed
+ deref_to.by_self(); //~ ERROR type annotations needed
+
+ let mut deref_deref_to = &DerefsTo(DerefsTo(Thing));
+ deref_deref_to.method(); //~ ERROR type annotations needed
+ deref_deref_to.mut_method(); //~ ERROR type annotations needed
+ deref_deref_to.by_self(); //~ ERROR type annotations needed
+}
diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr
new file mode 100644
index 000000000..27518a54e
--- /dev/null
+++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr
@@ -0,0 +1,224 @@
+error[E0282]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15
+ |
+LL | ref_thing.method();
+ | ^^^^^^
+ |
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(ref_thing);
+ | +++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15
+ |
+LL | ref_thing.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(ref_thing);
+ | +++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:48:15
+ |
+LL | ref_thing.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(ref_thing);
+ | ++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15
+ |
+LL | mut_thing.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(mut_thing);
+ | +++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:52:15
+ |
+LL | mut_thing.mut_method();
+ | ^^^^^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::mut_method(mut_thing);
+ | +++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:53:15
+ |
+LL | mut_thing.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(mut_thing);
+ | ++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14
+ |
+LL | deref_to.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(deref_to);
+ | +++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:57:14
+ |
+LL | deref_to.mut_method();
+ | ^^^^^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::mut_method(deref_to);
+ | +++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:58:14
+ |
+LL | deref_to.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(deref_to);
+ | ++++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20
+ |
+LL | deref_deref_to.method();
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::method(deref_deref_to);
+ | +++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:62:20
+ |
+LL | deref_deref_to.mut_method();
+ | ^^^^^^^^^^
+ |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1
+ |
+LL | impl Method<i32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Thing as Method<T>>::mut_method(deref_deref_to);
+ | +++++++++++++++++++++++++++++++++ ~
+
+error[E0283]: type annotations needed
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:63:20
+ |
+LL | deref_deref_to.by_self();
+ | ^^^^^^^
+ |
+note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found
+ --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1
+ |
+LL | impl MethodRef<i32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl MethodRef<u32> for &Thing {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <&Thing as MethodRef<T>>::by_self(deref_deref_to);
+ | ++++++++++++++++++++++++++++++++++ ~
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/suggest-where-clause.rs b/tests/ui/traits/suggest-where-clause.rs
new file mode 100644
index 000000000..46d047a2d
--- /dev/null
+++ b/tests/ui/traits/suggest-where-clause.rs
@@ -0,0 +1,36 @@
+use std::mem;
+
+struct Misc<T:?Sized>(T);
+
+fn check<T: Iterator, U: ?Sized>() {
+ // suggest a where-clause, if needed
+ mem::size_of::<U>();
+ //~^ ERROR the size for values of type
+
+ mem::size_of::<Misc<U>>();
+ //~^ ERROR the size for values of type
+
+ // ... even if T occurs as a type parameter
+
+ <u64 as From<T>>::from;
+ //~^ ERROR `u64: From<T>` is not satisfied
+
+ <u64 as From<<T as Iterator>::Item>>::from;
+ //~^ ERROR `u64: From<<T as Iterator>::Item>` is not satisfied
+
+ // ... but not if there are inference variables
+
+ <Misc<_> as From<T>>::from;
+ //~^ ERROR `Misc<_>: From<T>` is not satisfied
+
+ // ... and also not if the error is not related to the type
+
+ mem::size_of::<[T]>();
+ //~^ ERROR the size for values of type
+
+ mem::size_of::<[&U]>();
+ //~^ ERROR the size for values of type
+}
+
+fn main() {
+}
diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr
new file mode 100644
index 000000000..44e63b78c
--- /dev/null
+++ b/tests/ui/traits/suggest-where-clause.stderr
@@ -0,0 +1,90 @@
+error[E0277]: the size for values of type `U` cannot be known at compilation time
+ --> $DIR/suggest-where-clause.rs:7:20
+ |
+LL | fn check<T: Iterator, U: ?Sized>() {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | // suggest a where-clause, if needed
+LL | mem::size_of::<U>();
+ | ^ doesn't have a size known at compile-time
+ |
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn check<T: Iterator, U: ?Sized>() {
+LL + fn check<T: Iterator, U>() {
+ |
+
+error[E0277]: the size for values of type `U` cannot be known at compilation time
+ --> $DIR/suggest-where-clause.rs:10:20
+ |
+LL | fn check<T: Iterator, U: ?Sized>() {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | mem::size_of::<Misc<U>>();
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+note: required because it appears within the type `Misc<U>`
+ --> $DIR/suggest-where-clause.rs:3:8
+ |
+LL | struct Misc<T:?Sized>(T);
+ | ^^^^
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn check<T: Iterator, U: ?Sized>() {
+LL + fn check<T: Iterator, U>() {
+ |
+
+error[E0277]: the trait bound `u64: From<T>` is not satisfied
+ --> $DIR/suggest-where-clause.rs:15:5
+ |
+LL | <u64 as From<T>>::from;
+ | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64`
+ |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> {
+ | ++++++++++++++++++
+
+error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied
+ --> $DIR/suggest-where-clause.rs:18:5
+ |
+LL | <u64 as From<<T as Iterator>::Item>>::from;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
+ |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> {
+ | ++++++++++++++++++++++++++++++++++++++
+
+error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied
+ --> $DIR/suggest-where-clause.rs:23:5
+ |
+LL | <Misc<_> as From<T>>::from;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>`
+
+error[E0277]: the size for values of type `[T]` cannot be known at compilation time
+ --> $DIR/suggest-where-clause.rs:28:20
+ |
+LL | mem::size_of::<[T]>();
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[T]`
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+
+error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
+ --> $DIR/suggest-where-clause.rs:31:20
+ |
+LL | mem::size_of::<[&U]>();
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[&U]`
+note: required by a bound in `std::mem::size_of`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/superdefault-generics.rs b/tests/ui/traits/superdefault-generics.rs
new file mode 100644
index 000000000..e862c0e97
--- /dev/null
+++ b/tests/ui/traits/superdefault-generics.rs
@@ -0,0 +1,39 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_snake_case)]
+
+// There is some other borrowck bug, so we make the stuff not mut.
+
+
+use std::ops::Add;
+
+trait Positioned<S> {
+ fn SetX(&mut self, _: S);
+ fn X(&self) -> S;
+}
+
+trait Movable<S: Add<Output=S>>: Positioned<S> {
+ fn translate(&mut self, dx: S) {
+ let x = self.X() + dx;
+ self.SetX(x);
+ }
+}
+
+struct Point<S> { x: S, y: S }
+
+impl<S: Clone> Positioned<S> for Point<S> {
+ fn SetX(&mut self, x: S) {
+ self.x = x;
+ }
+ fn X(&self) -> S {
+ self.x.clone()
+ }
+}
+
+impl<S: Clone + Add<Output=S>> Movable<S> for Point<S> {}
+
+pub fn main() {
+ let mut p = Point{ x: 1, y: 2};
+ p.translate(3);
+ assert_eq!(p.X(), 4);
+}
diff --git a/tests/ui/traits/syntax-polarity.rs b/tests/ui/traits/syntax-polarity.rs
new file mode 100644
index 000000000..c809f9e89
--- /dev/null
+++ b/tests/ui/traits/syntax-polarity.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#![feature(negative_impls)]
+
+struct TestType;
+
+impl TestType {}
+
+trait TestTrait {}
+
+impl !Send for TestType {}
+
+struct TestType2<T>(T);
+
+impl<T> TestType2<T> {}
+
+impl<T> !Send for TestType2<T> {}
+
+fn main() {}
diff --git a/tests/ui/traits/syntax-trait-polarity.rs b/tests/ui/traits/syntax-trait-polarity.rs
new file mode 100644
index 000000000..ed2947493
--- /dev/null
+++ b/tests/ui/traits/syntax-trait-polarity.rs
@@ -0,0 +1,25 @@
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
diff --git a/tests/ui/traits/syntax-trait-polarity.stderr b/tests/ui/traits/syntax-trait-polarity.stderr
new file mode 100644
index 000000000..1fd40fb66
--- /dev/null
+++ b/tests/ui/traits/syntax-trait-polarity.stderr
@@ -0,0 +1,37 @@
+error: inherent impls cannot be negative
+ --> $DIR/syntax-trait-polarity.rs:7:7
+ |
+LL | impl !TestType {}
+ | -^^^^^^^^ inherent impl for this type
+ | |
+ | negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+ --> $DIR/syntax-trait-polarity.rs:12:13
+ |
+LL | unsafe impl !Send for TestType {}
+ | ------ -^^^^
+ | | |
+ | | negative because of this
+ | unsafe because of this
+
+error: inherent impls cannot be negative
+ --> $DIR/syntax-trait-polarity.rs:18:10
+ |
+LL | impl<T> !TestType2<T> {}
+ | -^^^^^^^^^^^^ inherent impl for this type
+ | |
+ | negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+ --> $DIR/syntax-trait-polarity.rs:21:16
+ |
+LL | unsafe impl<T> !Send for TestType2<T> {}
+ | ------ -^^^^
+ | | |
+ | | negative because of this
+ | unsafe because of this
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0198`.
diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs
new file mode 100644
index 000000000..342928e88
--- /dev/null
+++ b/tests/ui/traits/test-2.rs
@@ -0,0 +1,17 @@
+#[allow(non_camel_case_types)]
+
+
+trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
+impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
+
+fn main() {
+ 10.dup::<i32>();
+ //~^ ERROR this associated function takes 0 generic arguments but 1
+ 10.blah::<i32, i32>();
+ //~^ ERROR this associated function takes 1 generic argument but 2
+ (Box::new(10) as Box<dyn bar>).dup();
+ //~^ ERROR E0038
+ //~| ERROR E0038
+ //~| ERROR E0038
+}
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
new file mode 100644
index 000000000..eaa20b0b4
--- /dev/null
+++ b/tests/ui/traits/test-2.stderr
@@ -0,0 +1,85 @@
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/test-2.rs:9:8
+ |
+LL | 10.dup::<i32>();
+ | ^^^------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: associated function defined here, with 0 generic parameters
+ --> $DIR/test-2.rs:4:16
+ |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+ | ^^^
+
+error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied
+ --> $DIR/test-2.rs:11:8
+ |
+LL | 10.blah::<i32, i32>();
+ | ^^^^ --- help: remove this generic argument
+ | |
+ | expected 1 generic argument
+ |
+note: associated function defined here, with 1 generic parameter: `X`
+ --> $DIR/test-2.rs:4:39
+ |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+ | ^^^^ -
+
+error[E0038]: the trait `bar` cannot be made into an object
+ --> $DIR/test-2.rs:13:22
+ |
+LL | (Box::new(10) as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^ `bar` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/test-2.rs:4:30
+ |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+ | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters
+ | | |
+ | | ...because method `dup` references the `Self` type in its return type
+ | this trait cannot be made into an object...
+ = help: consider moving `dup` to another trait
+ = help: consider moving `blah` to another trait
+
+error[E0038]: the trait `bar` cannot be made into an object
+ --> $DIR/test-2.rs:13:5
+ |
+LL | (Box::new(10) as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/test-2.rs:4:30
+ |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+ | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters
+ | | |
+ | | ...because method `dup` references the `Self` type in its return type
+ | this trait cannot be made into an object...
+ = help: consider moving `dup` to another trait
+ = help: consider moving `blah` to another trait
+
+error[E0038]: the trait `bar` cannot be made into an object
+ --> $DIR/test-2.rs:13:6
+ |
+LL | (Box::new(10) as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^ `bar` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/test-2.rs:4:30
+ |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+ | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters
+ | | |
+ | | ...because method `dup` references the `Self` type in its return type
+ | this trait cannot be made into an object...
+ = help: consider moving `dup` to another trait
+ = help: consider moving `blah` to another trait
+ = note: required for `Box<{integer}>` to implement `CoerceUnsized<Box<dyn bar>>`
+ = note: required by cast to type `Box<dyn bar>`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/test.rs b/tests/ui/traits/test.rs
new file mode 100644
index 000000000..72fc66f74
--- /dev/null
+++ b/tests/ui/traits/test.rs
@@ -0,0 +1,6 @@
+#[allow(non_camel_case_types)]
+trait foo { fn foo(&self); }
+
+impl isize for usize { fn foo(&self) {} } //~ ERROR trait
+
+fn main() {}
diff --git a/tests/ui/traits/test.stderr b/tests/ui/traits/test.stderr
new file mode 100644
index 000000000..668228abe
--- /dev/null
+++ b/tests/ui/traits/test.stderr
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found builtin type `isize`
+ --> $DIR/test.rs:4:6
+ |
+LL | impl isize for usize { fn foo(&self) {} }
+ | ^^^^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/traits/to-str.rs b/tests/ui/traits/to-str.rs
new file mode 100644
index 000000000..9670edbfa
--- /dev/null
+++ b/tests/ui/traits/to-str.rs
@@ -0,0 +1,36 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+
+trait to_str {
+ fn to_string_(&self) -> String;
+}
+
+impl to_str for isize {
+ fn to_string_(&self) -> String { self.to_string() }
+}
+
+impl<T:to_str> to_str for Vec<T> {
+ fn to_string_(&self) -> String {
+ format!("[{}]",
+ self.iter()
+ .map(|e| e.to_string_())
+ .collect::<Vec<String>>()
+ .join(", "))
+ }
+}
+
+pub fn main() {
+ assert_eq!(1.to_string_(), "1".to_string());
+ assert_eq!((vec![2, 3, 4]).to_string_(), "[2, 3, 4]".to_string());
+
+ fn indirect<T:to_str>(x: T) -> String {
+ format!("{}!", x.to_string_())
+ }
+ assert_eq!(indirect(vec![10, 20]), "[10, 20]!".to_string());
+
+ fn indirect2<T:to_str>(x: T) -> String {
+ indirect(x)
+ }
+ assert_eq!(indirect2(vec![1]), "[1]!".to_string());
+}
diff --git a/tests/ui/traits/track-obligations.rs b/tests/ui/traits/track-obligations.rs
new file mode 100644
index 000000000..77e753c13
--- /dev/null
+++ b/tests/ui/traits/track-obligations.rs
@@ -0,0 +1,88 @@
+// These are simplifications of the tower traits by the same name:
+
+pub trait Service<Request> {
+ type Response;
+}
+
+pub trait Layer<C> {
+ type Service;
+}
+
+// Any type will do here:
+
+pub struct Req;
+pub struct Res;
+
+// This is encoding a trait alias.
+
+pub trait ParticularService:
+ Service<Req, Response = Res> {
+}
+
+impl<T> ParticularService for T
+where
+ T: Service<Req, Response = Res>,
+{
+}
+
+// This is also a trait alias.
+// The weird = <Self as ...> bound is there so that users of the trait do not
+// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671
+// for context, and in particular the workaround in:
+// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828
+
+pub trait ParticularServiceLayer<C>:
+ Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+{
+ type Service: ParticularService;
+}
+
+impl<T, C> ParticularServiceLayer<C> for T
+where
+ T: Layer<C>,
+ T::Service: ParticularService,
+{
+ type Service = T::Service;
+}
+
+// These are types that implement the traits that the trait aliases refer to.
+// They should also implement the alias traits due to the blanket impls.
+
+struct ALayer<C>(C);
+impl<C> Layer<C> for ALayer<C> {
+ type Service = AService;
+}
+
+struct AService;
+impl Service<Req> for AService {
+ // However, AService does _not_ meet the blanket implementation,
+ // since its Response type is bool, not Res as it should be.
+ type Response = bool;
+}
+
+// This is a wrapper type around ALayer that uses the trait alias
+// as a way to communicate the requirements of the provided types.
+struct Client<C>(C);
+
+// The method and the free-standing function below both have the same bounds.
+
+impl<C> Client<C>
+where
+ ALayer<C>: ParticularServiceLayer<C>,
+{
+ fn check(&self) {}
+}
+
+fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
+
+// But, they give very different error messages.
+
+fn main() {
+ // This gives a very poor error message that does nothing to point the user
+ // at the underlying cause of why the types involved do not meet the bounds.
+ Client(()).check(); //~ ERROR E0599
+
+ // This gives a good(ish) error message that points the user at _why_ the
+ // bound isn't met, and thus how they might fix it.
+ check(()); //~ ERROR E0271
+}
diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr
new file mode 100644
index 000000000..894774759
--- /dev/null
+++ b/tests/ui/traits/track-obligations.stderr
@@ -0,0 +1,76 @@
+error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied
+ --> $DIR/track-obligations.rs:83:16
+ |
+LL | struct ALayer<C>(C);
+ | ----------------
+ | |
+ | doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service`
+ | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
+...
+LL | struct Client<C>(C);
+ | ---------------- method `check` not found for this struct
+...
+LL | Client(()).check();
+ | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
+ |
+note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
+ --> $DIR/track-obligations.rs:35:14
+ |
+LL | pub trait ParticularServiceLayer<C>:
+ | ----------------------
+LL | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
+ --> $DIR/track-obligations.rs:71:16
+ |
+LL | impl<C> Client<C>
+ | ---------
+LL | where
+LL | ALayer<C>: ParticularServiceLayer<C>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: the trait `ParticularServiceLayer` must be implemented
+ --> $DIR/track-obligations.rs:34:1
+ |
+LL | / pub trait ParticularServiceLayer<C>:
+LL | | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+ | |____________________________________________________________________^
+
+error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
+ --> $DIR/track-obligations.rs:87:11
+ |
+LL | check(());
+ | ----- ^^ type mismatch resolving `<AService as Service<Req>>::Response == Res`
+ | |
+ | required by a bound introduced by this call
+ |
+note: expected this to be `Res`
+ --> $DIR/track-obligations.rs:60:21
+ |
+LL | type Response = bool;
+ | ^^^^
+note: required for `AService` to implement `ParticularService`
+ --> $DIR/track-obligations.rs:22:9
+ |
+LL | impl<T> ParticularService for T
+ | ^^^^^^^^^^^^^^^^^ ^
+LL | where
+LL | T: Service<Req, Response = Res>,
+ | -------------- unsatisfied trait bound introduced here
+note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>`
+ --> $DIR/track-obligations.rs:40:12
+ |
+LL | impl<T, C> ParticularServiceLayer<C> for T
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^
+...
+LL | T::Service: ParticularService,
+ | ----------------- unsatisfied trait bound introduced here
+note: required by a bound in `check`
+ --> $DIR/track-obligations.rs:76:36
+ |
+LL | fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0271, E0599.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/trait-or-new-type-instead.rs b/tests/ui/traits/trait-or-new-type-instead.rs
new file mode 100644
index 000000000..572b03efc
--- /dev/null
+++ b/tests/ui/traits/trait-or-new-type-instead.rs
@@ -0,0 +1,6 @@
+impl<T> Option<T> {
+//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined
+ pub fn foo(&self) { }
+}
+
+fn main() { }
diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr
new file mode 100644
index 000000000..4726b0668
--- /dev/null
+++ b/tests/ui/traits/trait-or-new-type-instead.stderr
@@ -0,0 +1,14 @@
+error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
+ --> $DIR/trait-or-new-type-instead.rs:1:1
+ |
+LL | / impl<T> Option<T> {
+LL | |
+LL | | pub fn foo(&self) { }
+LL | | }
+ | |_^ impl for type defined outside of crate.
+ |
+ = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0116`.
diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs
new file mode 100644
index 000000000..570ec5160
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/basic.rs
@@ -0,0 +1,86 @@
+// run-pass
+
+#![feature(trait_upcasting)]
+
+trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+ fn a(&self) -> i32 {
+ 10
+ }
+
+ fn z(&self) -> i32 {
+ 11
+ }
+
+ fn y(&self) -> i32 {
+ 12
+ }
+}
+
+trait Bar: Foo {
+ fn b(&self) -> i32 {
+ 20
+ }
+
+ fn w(&self) -> i32 {
+ 21
+ }
+}
+
+trait Baz: Bar {
+ fn c(&self) -> i32 {
+ 30
+ }
+}
+
+impl Foo for i32 {
+ fn a(&self) -> i32 {
+ 100
+ }
+}
+
+impl Bar for i32 {
+ fn b(&self) -> i32 {
+ 200
+ }
+}
+
+impl Baz for i32 {
+ fn c(&self) -> i32 {
+ 300
+ }
+}
+
+fn main() {
+ let baz: &dyn Baz = &1;
+ let _: &dyn std::fmt::Debug = baz;
+ assert_eq!(*baz, 1);
+ assert_eq!(baz.a(), 100);
+ assert_eq!(baz.b(), 200);
+ assert_eq!(baz.c(), 300);
+ assert_eq!(baz.z(), 11);
+ assert_eq!(baz.y(), 12);
+ assert_eq!(baz.w(), 21);
+
+ let bar: &dyn Bar = baz;
+ let _: &dyn std::fmt::Debug = bar;
+ assert_eq!(*bar, 1);
+ assert_eq!(bar.a(), 100);
+ assert_eq!(bar.b(), 200);
+ assert_eq!(bar.z(), 11);
+ assert_eq!(bar.y(), 12);
+ assert_eq!(bar.w(), 21);
+
+ let foo: &dyn Foo = baz;
+ let _: &dyn std::fmt::Debug = foo;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+
+ let foo: &dyn Foo = bar;
+ let _: &dyn std::fmt::Debug = foo;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+}
diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
new file mode 100644
index 000000000..eae5cf8d5
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
@@ -0,0 +1,38 @@
+// run-pass
+#![feature(trait_upcasting)]
+
+trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
+trait Bar<T: Default + ToString> {
+ fn bar(&self) -> String {
+ T::default().to_string()
+ }
+}
+
+struct S1;
+
+impl Bar<i32> for S1 {}
+impl Foo<i32> for S1 {}
+
+struct S2;
+impl Bar<i32> for S2 {}
+impl Bar<bool> for S2 {}
+impl Foo<bool> for S2 {}
+
+fn test1(x: &dyn Foo<i32>) {
+ let s = x as &dyn Bar<i32>;
+ assert_eq!("0", &s.bar().to_string());
+}
+
+fn test2(x: &dyn Foo<bool>) {
+ let p = x as &dyn Bar<i32>;
+ assert_eq!("0", &p.bar().to_string());
+ let q = x as &dyn Bar<bool>;
+ assert_eq!("false", &q.bar().to_string());
+}
+
+fn main() {
+ let s1 = S1;
+ test1(&s1);
+ let s2 = S2;
+ test2(&s2);
+}
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
new file mode 100644
index 000000000..511e41562
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
@@ -0,0 +1,13 @@
+trait A: B + A {}
+//~^ ERROR cycle detected when computing the super predicates of `A` [E0391]
+
+trait B {}
+
+impl A for () {}
+
+impl B for () {}
+
+fn main() {
+ let a: Box<dyn A> = Box::new(());
+ let _b: Box<dyn B> = a;
+}
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
new file mode 100644
index 000000000..15faab16a
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
@@ -0,0 +1,21 @@
+error[E0391]: cycle detected when computing the super predicates of `A`
+ --> $DIR/cyclic-trait-resolution.rs:1:1
+ |
+LL | trait A: B + A {}
+ | ^^^^^^^^^^^^^^
+ |
+note: ...which requires computing the super traits of `A`...
+ --> $DIR/cyclic-trait-resolution.rs:1:14
+ |
+LL | trait A: B + A {}
+ | ^
+ = note: ...which again requires computing the super predicates of `A`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/cyclic-trait-resolution.rs:1:1
+ |
+LL | trait A: B + A {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs
new file mode 100644
index 000000000..a4f81c464
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/diamond.rs
@@ -0,0 +1,114 @@
+// run-pass
+
+#![feature(trait_upcasting)]
+
+trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+ fn a(&self) -> i32 {
+ 10
+ }
+
+ fn z(&self) -> i32 {
+ 11
+ }
+
+ fn y(&self) -> i32 {
+ 12
+ }
+}
+
+trait Bar1: Foo {
+ fn b(&self) -> i32 {
+ 20
+ }
+
+ fn w(&self) -> i32 {
+ 21
+ }
+}
+
+trait Bar2: Foo {
+ fn c(&self) -> i32 {
+ 30
+ }
+
+ fn v(&self) -> i32 {
+ 31
+ }
+}
+
+trait Baz: Bar1 + Bar2 {
+ fn d(&self) -> i32 {
+ 40
+ }
+}
+
+impl Foo for i32 {
+ fn a(&self) -> i32 {
+ 100
+ }
+}
+
+impl Bar1 for i32 {
+ fn b(&self) -> i32 {
+ 200
+ }
+}
+
+impl Bar2 for i32 {
+ fn c(&self) -> i32 {
+ 300
+ }
+}
+
+impl Baz for i32 {
+ fn d(&self) -> i32 {
+ 400
+ }
+}
+
+fn main() {
+ let baz: &dyn Baz = &1;
+ let _: &dyn std::fmt::Debug = baz;
+ assert_eq!(*baz, 1);
+ assert_eq!(baz.a(), 100);
+ assert_eq!(baz.b(), 200);
+ assert_eq!(baz.c(), 300);
+ assert_eq!(baz.d(), 400);
+ assert_eq!(baz.z(), 11);
+ assert_eq!(baz.y(), 12);
+ assert_eq!(baz.w(), 21);
+ assert_eq!(baz.v(), 31);
+
+ let bar1: &dyn Bar1 = baz;
+ let _: &dyn std::fmt::Debug = bar1;
+ assert_eq!(*bar1, 1);
+ assert_eq!(bar1.a(), 100);
+ assert_eq!(bar1.b(), 200);
+ assert_eq!(bar1.z(), 11);
+ assert_eq!(bar1.y(), 12);
+ assert_eq!(bar1.w(), 21);
+
+ let bar2: &dyn Bar2 = baz;
+ let _: &dyn std::fmt::Debug = bar2;
+ assert_eq!(*bar2, 1);
+ assert_eq!(bar2.a(), 100);
+ assert_eq!(bar2.c(), 300);
+ assert_eq!(bar2.z(), 11);
+ assert_eq!(bar2.y(), 12);
+ assert_eq!(bar2.v(), 31);
+
+ let foo: &dyn Foo = baz;
+ let _: &dyn std::fmt::Debug = foo;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+
+ let foo: &dyn Foo = bar1;
+ let _: &dyn std::fmt::Debug = foo;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+
+ let foo: &dyn Foo = bar2;
+ let _: &dyn std::fmt::Debug = foo;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+}
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
new file mode 100644
index 000000000..e634bbd5a
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
@@ -0,0 +1,86 @@
+#![feature(trait_upcasting)]
+
+trait Foo {
+ fn a(&self) -> i32 {
+ 10
+ }
+
+ fn z(&self) -> i32 {
+ 11
+ }
+
+ fn y(&self) -> i32 {
+ 12
+ }
+}
+
+trait Bar {
+ fn b(&self) -> i32 {
+ 20
+ }
+
+ fn w(&self) -> i32 {
+ 21
+ }
+}
+
+trait Baz {
+ fn c(&self) -> i32 {
+ 30
+ }
+}
+
+impl Foo for i32 {
+ fn a(&self) -> i32 {
+ 100
+ }
+}
+
+impl Bar for i32 {
+ fn b(&self) -> i32 {
+ 200
+ }
+}
+
+impl Baz for i32 {
+ fn c(&self) -> i32 {
+ 300
+ }
+}
+
+fn main() {
+ let baz: &dyn Baz = &1;
+ let _: &dyn std::fmt::Debug = baz;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Send = baz;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Sync = baz;
+ //~^ ERROR mismatched types [E0308]
+
+ let bar: &dyn Bar = baz;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn std::fmt::Debug = bar;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Send = bar;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Sync = bar;
+ //~^ ERROR mismatched types [E0308]
+
+ let foo: &dyn Foo = baz;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn std::fmt::Debug = foo;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Send = foo;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Sync = foo;
+ //~^ ERROR mismatched types [E0308]
+
+ let foo: &dyn Foo = bar;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn std::fmt::Debug = foo;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Send = foo;
+ //~^ ERROR mismatched types [E0308]
+ let _: &dyn Sync = foo;
+ //~^ ERROR mismatched types [E0308]
+}
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
new file mode 100644
index 000000000..3aa21ee3d
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
@@ -0,0 +1,168 @@
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:53:35
+ |
+LL | let _: &dyn std::fmt::Debug = baz;
+ | -------------------- ^^^ expected trait `Debug`, found trait `Baz`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Debug`
+ found reference `&dyn Baz`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:55:24
+ |
+LL | let _: &dyn Send = baz;
+ | --------- ^^^ expected trait `Send`, found trait `Baz`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Send`
+ found reference `&dyn Baz`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:57:24
+ |
+LL | let _: &dyn Sync = baz;
+ | --------- ^^^ expected trait `Sync`, found trait `Baz`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Sync`
+ found reference `&dyn Baz`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:60:25
+ |
+LL | let bar: &dyn Bar = baz;
+ | -------- ^^^ expected trait `Bar`, found trait `Baz`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Bar`
+ found reference `&dyn Baz`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:62:35
+ |
+LL | let _: &dyn std::fmt::Debug = bar;
+ | -------------------- ^^^ expected trait `Debug`, found trait `Bar`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Debug`
+ found reference `&dyn Bar`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:64:24
+ |
+LL | let _: &dyn Send = bar;
+ | --------- ^^^ expected trait `Send`, found trait `Bar`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Send`
+ found reference `&dyn Bar`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:66:24
+ |
+LL | let _: &dyn Sync = bar;
+ | --------- ^^^ expected trait `Sync`, found trait `Bar`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Sync`
+ found reference `&dyn Bar`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:69:25
+ |
+LL | let foo: &dyn Foo = baz;
+ | -------- ^^^ expected trait `Foo`, found trait `Baz`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Foo`
+ found reference `&dyn Baz`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:71:35
+ |
+LL | let _: &dyn std::fmt::Debug = foo;
+ | -------------------- ^^^ expected trait `Debug`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Debug`
+ found reference `&dyn Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:73:24
+ |
+LL | let _: &dyn Send = foo;
+ | --------- ^^^ expected trait `Send`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Send`
+ found reference `&dyn Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:75:24
+ |
+LL | let _: &dyn Sync = foo;
+ | --------- ^^^ expected trait `Sync`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Sync`
+ found reference `&dyn Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:78:25
+ |
+LL | let foo: &dyn Foo = bar;
+ | -------- ^^^ expected trait `Foo`, found trait `Bar`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Foo`
+ found reference `&dyn Bar`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:80:35
+ |
+LL | let _: &dyn std::fmt::Debug = foo;
+ | -------------------- ^^^ expected trait `Debug`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Debug`
+ found reference `&dyn Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:82:24
+ |
+LL | let _: &dyn Send = foo;
+ | --------- ^^^ expected trait `Send`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Send`
+ found reference `&dyn Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-upcast.rs:84:24
+ |
+LL | let _: &dyn Sync = foo;
+ | --------- ^^^ expected trait `Sync`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Sync`
+ found reference `&dyn Foo`
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
new file mode 100644
index 000000000..b672963ae
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
@@ -0,0 +1,12 @@
+// run-pass
+#![feature(trait_upcasting)]
+
+struct Test {
+ func: Box<dyn FnMut() + 'static>,
+}
+
+fn main() {
+ let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
+ let mut test = Box::new(Test { func: closure });
+ (test.func)();
+}
diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs
new file mode 100644
index 000000000..9825158c2
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/lifetime.rs
@@ -0,0 +1,94 @@
+// run-pass
+
+#![feature(trait_upcasting)]
+
+trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+ fn a(&self) -> i32 {
+ 10
+ }
+
+ fn z(&self) -> i32 {
+ 11
+ }
+
+ fn y(&self) -> i32 {
+ 12
+ }
+}
+
+trait Bar: Foo {
+ fn b(&self) -> i32 {
+ 20
+ }
+
+ fn w(&self) -> i32 {
+ 21
+ }
+}
+
+trait Baz: Bar {
+ fn c(&self) -> i32 {
+ 30
+ }
+}
+
+impl Foo for i32 {
+ fn a(&self) -> i32 {
+ 100
+ }
+}
+
+impl Bar for i32 {
+ fn b(&self) -> i32 {
+ 200
+ }
+}
+
+impl Baz for i32 {
+ fn c(&self) -> i32 {
+ 300
+ }
+}
+
+// Note: upcast lifetime means a shorter lifetime.
+fn upcast_baz<'a: 'b, 'b, T>(v: Box<dyn Baz + 'a>, _l: &'b T) -> Box<dyn Baz + 'b> {
+ v
+}
+fn upcast_bar<'a: 'b, 'b, T>(v: Box<dyn Bar + 'a>, _l: &'b T) -> Box<dyn Bar + 'b> {
+ v
+}
+fn upcast_foo<'a: 'b, 'b, T>(v: Box<dyn Foo + 'a>, _l: &'b T) -> Box<dyn Foo + 'b> {
+ v
+}
+
+fn main() {
+ let v = Box::new(1);
+ let l = &(); // dummy lifetime (shorter than `baz`)
+
+ let baz: Box<dyn Baz> = v.clone();
+ let u = upcast_baz(baz, &l);
+ assert_eq!(*u, 1);
+ assert_eq!(u.a(), 100);
+ assert_eq!(u.b(), 200);
+ assert_eq!(u.c(), 300);
+
+ let baz: Box<dyn Baz> = v.clone();
+ let bar: Box<dyn Bar> = baz;
+ let u = upcast_bar(bar, &l);
+ assert_eq!(*u, 1);
+ assert_eq!(u.a(), 100);
+ assert_eq!(u.b(), 200);
+
+ let baz: Box<dyn Baz> = v.clone();
+ let foo: Box<dyn Foo> = baz;
+ let u = upcast_foo(foo, &l);
+ assert_eq!(*u, 1);
+ assert_eq!(u.a(), 100);
+
+ let baz: Box<dyn Baz> = v.clone();
+ let bar: Box<dyn Bar> = baz;
+ let foo: Box<dyn Foo> = bar;
+ let u = upcast_foo(foo, &l);
+ assert_eq!(*u, 1);
+ assert_eq!(u.a(), 100);
+}
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
new file mode 100644
index 000000000..d62418756
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
@@ -0,0 +1,27 @@
+#![deny(deref_into_dyn_supertrait)]
+
+extern crate core;
+
+use core::ops::Deref;
+
+// issue 89190
+trait A {}
+trait B: A {}
+
+impl<'a> Deref for dyn 'a + B {
+ //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
+ //~| WARN this was previously accepted by the compiler but is being phased out;
+
+ type Target = dyn A;
+ fn deref(&self) -> &Self::Target {
+ todo!()
+ }
+}
+
+fn take_a(_: &dyn A) {}
+
+fn whoops(b: &dyn B) {
+ take_a(b)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
new file mode 100644
index 000000000..4533b1163
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
@@ -0,0 +1,19 @@
+error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target
+ --> $DIR/migrate-lint-deny.rs:11:1
+ |
+LL | impl<'a> Deref for dyn 'a + B {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | type Target = dyn A;
+ | -------------------- target type is set here
+ |
+ = 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 #89460 <https://github.com/rust-lang/rust/issues/89460>
+note: the lint level is defined here
+ --> $DIR/migrate-lint-deny.rs:1:9
+ |
+LL | #![deny(deref_into_dyn_supertrait)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
new file mode 100644
index 000000000..2e53a00a9
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
@@ -0,0 +1,21 @@
+// check-fail
+#![feature(trait_upcasting)]
+
+trait Bar<T> {
+ fn bar(&self, _: T) {}
+}
+
+trait Foo: Bar<i32> + Bar<u32> {
+ fn foo(&self, _: ()) {}
+}
+
+struct S;
+
+impl Bar<i32> for S {}
+impl Bar<u32> for S {}
+impl Foo for S {}
+
+fn main() {
+ let s: &dyn Foo = &S;
+ let t: &dyn Bar<_> = s; //~ ERROR mismatched types
+}
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
new file mode 100644
index 000000000..0ad18be03
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/multiple-occurrence-ambiguousity.rs:20:26
+ |
+LL | let t: &dyn Bar<_> = s;
+ | ----------- ^ expected trait `Bar`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Bar<_>`
+ found reference `&dyn Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs
new file mode 100644
index 000000000..9ccfc9306
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+#![feature(trait_upcasting)]
+
+trait A {
+ fn foo_a(&self);
+}
+
+trait B {
+ fn foo_b(&self);
+}
+
+trait C: A + B {
+ fn foo_c(&self);
+}
+
+struct S(i32);
+
+impl A for S {
+ fn foo_a(&self) {
+ unreachable!();
+ }
+}
+
+impl B for S {
+ fn foo_b(&self) {
+ assert_eq!(42, self.0);
+ }
+}
+
+impl C for S {
+ fn foo_c(&self) {
+ unreachable!();
+ }
+}
+
+fn invoke_inner(b: &dyn B) {
+ b.foo_b();
+}
+
+fn invoke_outer(c: &dyn C) {
+ invoke_inner(c);
+}
+
+fn main() {
+ let s = S(42);
+ invoke_outer(&s);
+}
diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs
new file mode 100644
index 000000000..a3e416969
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/struct.rs
@@ -0,0 +1,173 @@
+// run-pass
+
+#![feature(trait_upcasting)]
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+ fn a(&self) -> i32 {
+ 10
+ }
+
+ fn z(&self) -> i32 {
+ 11
+ }
+
+ fn y(&self) -> i32 {
+ 12
+ }
+}
+
+trait Bar: Foo {
+ fn b(&self) -> i32 {
+ 20
+ }
+
+ fn w(&self) -> i32 {
+ 21
+ }
+}
+
+trait Baz: Bar {
+ fn c(&self) -> i32 {
+ 30
+ }
+}
+
+impl Foo for i32 {
+ fn a(&self) -> i32 {
+ 100
+ }
+}
+
+impl Bar for i32 {
+ fn b(&self) -> i32 {
+ 200
+ }
+}
+
+impl Baz for i32 {
+ fn c(&self) -> i32 {
+ 300
+ }
+}
+
+fn test_box() {
+ let v = Box::new(1);
+
+ let baz: Box<dyn Baz> = v.clone();
+ assert_eq!(*baz, 1);
+ assert_eq!(baz.a(), 100);
+ assert_eq!(baz.b(), 200);
+ assert_eq!(baz.c(), 300);
+ assert_eq!(baz.z(), 11);
+ assert_eq!(baz.y(), 12);
+ assert_eq!(baz.w(), 21);
+
+ let baz: Box<dyn Baz> = v.clone();
+ let bar: Box<dyn Bar> = baz;
+ assert_eq!(*bar, 1);
+ assert_eq!(bar.a(), 100);
+ assert_eq!(bar.b(), 200);
+ assert_eq!(bar.z(), 11);
+ assert_eq!(bar.y(), 12);
+ assert_eq!(bar.w(), 21);
+
+ let baz: Box<dyn Baz> = v.clone();
+ let foo: Box<dyn Foo> = baz;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+
+ let baz: Box<dyn Baz> = v.clone();
+ let bar: Box<dyn Bar> = baz;
+ let foo: Box<dyn Foo> = bar;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+}
+
+fn test_rc() {
+ let v = Rc::new(1);
+
+ let baz: Rc<dyn Baz> = v.clone();
+ assert_eq!(*baz, 1);
+ assert_eq!(baz.a(), 100);
+ assert_eq!(baz.b(), 200);
+ assert_eq!(baz.c(), 300);
+ assert_eq!(baz.z(), 11);
+ assert_eq!(baz.y(), 12);
+ assert_eq!(baz.w(), 21);
+
+ let baz: Rc<dyn Baz> = v.clone();
+ let bar: Rc<dyn Bar> = baz;
+ assert_eq!(*bar, 1);
+ assert_eq!(bar.a(), 100);
+ assert_eq!(bar.b(), 200);
+ assert_eq!(bar.z(), 11);
+ assert_eq!(bar.y(), 12);
+ assert_eq!(bar.w(), 21);
+
+ let baz: Rc<dyn Baz> = v.clone();
+ let foo: Rc<dyn Foo> = baz;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+
+ let baz: Rc<dyn Baz> = v.clone();
+ let bar: Rc<dyn Bar> = baz;
+ let foo: Rc<dyn Foo> = bar;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+}
+
+fn test_arc() {
+ let v = Arc::new(1);
+
+ let baz: Arc<dyn Baz> = v.clone();
+ assert_eq!(*baz, 1);
+ assert_eq!(baz.a(), 100);
+ assert_eq!(baz.b(), 200);
+ assert_eq!(baz.c(), 300);
+ assert_eq!(baz.z(), 11);
+ assert_eq!(baz.y(), 12);
+ assert_eq!(baz.w(), 21);
+
+ let baz: Arc<dyn Baz> = v.clone();
+ let bar: Arc<dyn Bar> = baz;
+ assert_eq!(*bar, 1);
+ assert_eq!(bar.a(), 100);
+ assert_eq!(bar.b(), 200);
+ assert_eq!(bar.z(), 11);
+ assert_eq!(bar.y(), 12);
+ assert_eq!(bar.w(), 21);
+
+ let baz: Arc<dyn Baz> = v.clone();
+ let foo: Arc<dyn Foo> = baz;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+
+ let baz: Arc<dyn Baz> = v.clone();
+ let bar: Arc<dyn Bar> = baz;
+ let foo: Arc<dyn Foo> = bar;
+ assert_eq!(*foo, 1);
+ assert_eq!(foo.a(), 100);
+ assert_eq!(foo.z(), 11);
+ assert_eq!(foo.y(), 12);
+}
+
+fn main() {
+ test_box();
+ test_rc();
+ test_arc();
+}
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs
new file mode 100644
index 000000000..136d15af0
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs
@@ -0,0 +1,69 @@
+#![feature(trait_upcasting)]
+
+trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+ fn a(&self) -> i32 {
+ 10
+ }
+
+ fn z(&self) -> i32 {
+ 11
+ }
+
+ fn y(&self) -> i32 {
+ 12
+ }
+}
+
+trait Bar: Foo {
+ fn b(&self) -> i32 {
+ 20
+ }
+
+ fn w(&self) -> i32 {
+ 21
+ }
+}
+
+trait Baz: Bar {
+ fn c(&self) -> i32 {
+ 30
+ }
+}
+
+impl Foo for i32 {
+ fn a(&self) -> i32 {
+ 100
+ }
+}
+
+impl Bar for i32 {
+ fn b(&self) -> i32 {
+ 200
+ }
+}
+
+impl Baz for i32 {
+ fn c(&self) -> i32 {
+ 300
+ }
+}
+
+fn main() {
+ let baz: &dyn Baz = &1;
+
+ let bar: &dyn Bar = baz;
+ bar.c();
+ //~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599]
+
+ let foo: &dyn Foo = baz;
+ foo.b();
+ //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599]
+ foo.c();
+ //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599]
+
+ let foo: &dyn Foo = bar;
+ foo.b();
+ //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599]
+ foo.c();
+ //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599]
+}
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
new file mode 100644
index 000000000..918159e84
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
@@ -0,0 +1,68 @@
+error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
+ --> $DIR/subtrait-method.rs:55:9
+ |
+LL | bar.c();
+ | ^ help: there is a method with a similar name: `a`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Baz` defines an item `c`, perhaps you need to implement it
+ --> $DIR/subtrait-method.rs:27:1
+ |
+LL | trait Baz: Bar {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:59:9
+ |
+LL | foo.b();
+ | ^ help: there is a method with a similar name: `a`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Bar` defines an item `b`, perhaps you need to implement it
+ --> $DIR/subtrait-method.rs:17:1
+ |
+LL | trait Bar: Foo {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:61:9
+ |
+LL | foo.c();
+ | ^ help: there is a method with a similar name: `a`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Baz` defines an item `c`, perhaps you need to implement it
+ --> $DIR/subtrait-method.rs:27:1
+ |
+LL | trait Baz: Bar {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:65:9
+ |
+LL | foo.b();
+ | ^ help: there is a method with a similar name: `a`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Bar` defines an item `b`, perhaps you need to implement it
+ --> $DIR/subtrait-method.rs:17:1
+ |
+LL | trait Bar: Foo {
+ | ^^^^^^^^^^^^^^
+
+error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
+ --> $DIR/subtrait-method.rs:67:9
+ |
+LL | foo.c();
+ | ^ help: there is a method with a similar name: `a`
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+note: `Baz` defines an item `c`, perhaps you need to implement it
+ --> $DIR/subtrait-method.rs:27:1
+ |
+LL | trait Baz: Bar {
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
new file mode 100644
index 000000000..6bc9f4a75
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -0,0 +1,26 @@
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+trait Bar<T> {
+ fn bar(&self) -> Option<T> {
+ None
+ }
+}
+
+fn test_specific(x: &dyn Foo) {
+ let _ = x as &dyn Bar<i32>; // OK
+ let _ = x as &dyn Bar<u32>; // OK
+}
+
+fn test_unknown_version(x: &dyn Foo) {
+ let _ = x as &dyn Bar<_>; // Ambiguous
+ //~^ ERROR non-primitive cast
+ //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
+}
+
+fn test_infer_version(x: &dyn Foo) {
+ let a = x as &dyn Bar<_>; // OK
+ let _: Option<u32> = a.bar();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
new file mode 100644
index 000000000..fe269d8e9
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
@@ -0,0 +1,23 @@
+error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
+ --> $DIR/type-checking-test-1.rs:16:13
+ |
+LL | let _ = x as &dyn Bar<_>; // Ambiguous
+ | ^^^^^^^^^^^^^^^^ invalid cast
+ |
+help: consider borrowing the value
+ |
+LL | let _ = &x as &dyn Bar<_>; // Ambiguous
+ | +
+
+error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
+ --> $DIR/type-checking-test-1.rs:16:13
+ |
+LL | let _ = x as &dyn Bar<_>; // Ambiguous
+ | ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
+ |
+ = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0605.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
new file mode 100644
index 000000000..36b11dffd
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -0,0 +1,31 @@
+#![feature(trait_upcasting)]
+
+trait Foo<T>: Bar<i32> + Bar<T> {}
+trait Bar<T> {
+ fn bar(&self) -> Option<T> {
+ None
+ }
+}
+
+fn test_specific(x: &dyn Foo<i32>) {
+ let _ = x as &dyn Bar<i32>; // OK
+}
+
+fn test_specific2(x: &dyn Foo<u32>) {
+ let _ = x as &dyn Bar<i32>; // OK
+}
+
+fn test_specific3(x: &dyn Foo<i32>) {
+ let _ = x as &dyn Bar<u32>; // Error
+ //~^ ERROR non-primitive cast
+ //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
+}
+
+fn test_infer_arg(x: &dyn Foo<u32>) {
+ let a = x as &dyn Bar<_>; // Ambiguous
+ //~^ ERROR non-primitive cast
+ //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
+ let _ = a.bar();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
new file mode 100644
index 000000000..ef007d5cb
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -0,0 +1,42 @@
+error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
+ --> $DIR/type-checking-test-2.rs:19:13
+ |
+LL | let _ = x as &dyn Bar<u32>; // Error
+ | ^^^^^^^^^^^^^^^^^^ invalid cast
+ |
+help: consider borrowing the value
+ |
+LL | let _ = &x as &dyn Bar<u32>; // Error
+ | +
+
+error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
+ --> $DIR/type-checking-test-2.rs:19:13
+ |
+LL | let _ = x as &dyn Bar<u32>; // Error
+ | ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
+ |
+ = note: required for the cast from `&dyn Foo<i32>` to the object type `dyn Bar<u32>`
+
+error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
+ --> $DIR/type-checking-test-2.rs:25:13
+ |
+LL | let a = x as &dyn Bar<_>; // Ambiguous
+ | ^^^^^^^^^^^^^^^^ invalid cast
+ |
+help: consider borrowing the value
+ |
+LL | let a = &x as &dyn Bar<_>; // Ambiguous
+ | +
+
+error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
+ --> $DIR/type-checking-test-2.rs:25:13
+ |
+LL | let a = x as &dyn Bar<_>; // Ambiguous
+ | ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
+ |
+ = note: required for the cast from `&dyn Foo<u32>` to the object type `dyn Bar<_>`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0605.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr
new file mode 100644
index 000000000..e6cb6a753
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:11:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a>; // Error
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:16:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
new file mode 100644
index 000000000..b2db3a127
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
@@ -0,0 +1,20 @@
+#![feature(trait_upcasting)]
+
+trait Foo<'a>: Bar<'a> {}
+trait Bar<'a> {}
+
+fn test_correct(x: &dyn Foo<'static>) {
+ let _ = x as &dyn Bar<'static>;
+}
+
+fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ let _ = x as &dyn Bar<'a>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong2<'a>(x: &dyn Foo<'a>) {
+ let _ = x as &dyn Bar<'static>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
new file mode 100644
index 000000000..e6cb6a753
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
@@ -0,0 +1,18 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:11:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a>; // Error
+ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-3.rs:16:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr
new file mode 100644
index 000000000..8d506e580
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr
@@ -0,0 +1,52 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:15:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static, 'a>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:20:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a, 'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:26:5
+ |
+LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | let y = x as &dyn Bar<'_, '_>;
+LL | y.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:31:5
+ |
+LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:36:5
+ |
+LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:44:5
+ |
+LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+...
+LL | z.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
new file mode 100644
index 000000000..f40c48f0d
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -0,0 +1,48 @@
+#![feature(trait_upcasting)]
+
+trait Foo<'a>: Bar<'a, 'a> {}
+trait Bar<'a, 'b> {
+ fn get_b(&self) -> Option<&'a u32> {
+ None
+ }
+}
+
+fn test_correct(x: &dyn Foo<'static>) {
+ let _ = x as &dyn Bar<'static, 'static>;
+}
+
+fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ let _ = x as &dyn Bar<'static, 'a>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ let _ = x as &dyn Bar<'a, 'static>; // Error
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ let y = x as &dyn Bar<'_, '_>;
+ y.get_b() // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ <_ as Bar>::get_b(x) // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ <_ as Bar<'_, '_>>::get_b(x) // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ let y = x as &dyn Bar<'_, '_>;
+ y.get_b(); // ERROR
+ let z = y;
+ z.get_b() // ERROR
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
new file mode 100644
index 000000000..8d506e580
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -0,0 +1,52 @@
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:15:13
+ |
+LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'static, 'a>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:20:13
+ |
+LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
+ | -- lifetime `'a` defined here
+LL | let _ = x as &dyn Bar<'a, 'static>; // Error
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:26:5
+ |
+LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | let y = x as &dyn Bar<'_, '_>;
+LL | y.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:31:5
+ |
+LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:36:5
+ |
+LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/type-checking-test-4.rs:44:5
+ |
+LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+ | -- lifetime `'a` defined here
+...
+LL | z.get_b() // ERROR
+ | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/traits/typeclasses-eq-example-static.rs b/tests/ui/traits/typeclasses-eq-example-static.rs
new file mode 100644
index 000000000..f982ad6a0
--- /dev/null
+++ b/tests/ui/traits/typeclasses-eq-example-static.rs
@@ -0,0 +1,68 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(dead_code)]
+
+// Example from lkuper's intern talk, August 2012 -- now with static
+// methods!
+use Color::{cyan, magenta, yellow, black};
+use ColorTree::{leaf, branch};
+
+trait Equal {
+ fn isEq(a: &Self, b: &Self) -> bool;
+}
+
+#[derive(Clone, Copy)]
+enum Color { cyan, magenta, yellow, black }
+
+impl Equal for Color {
+ fn isEq(a: &Color, b: &Color) -> bool {
+ match (*a, *b) {
+ (cyan, cyan) => { true }
+ (magenta, magenta) => { true }
+ (yellow, yellow) => { true }
+ (black, black) => { true }
+ _ => { false }
+ }
+ }
+}
+
+#[derive(Clone)]
+enum ColorTree {
+ leaf(Color),
+ branch(Box<ColorTree>, Box<ColorTree>)
+}
+
+impl Equal for ColorTree {
+ fn isEq(a: &ColorTree, b: &ColorTree) -> bool {
+ match (a, b) {
+ (&leaf(ref x), &leaf(ref y)) => {
+ Equal::isEq(&(*x).clone(), &(*y).clone())
+ }
+ (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => {
+ Equal::isEq(&(**l1).clone(), &(**l2).clone()) &&
+ Equal::isEq(&(**r1).clone(), &(**r2).clone())
+ }
+ _ => { false }
+ }
+ }
+}
+
+pub fn main() {
+ assert!(Equal::isEq(&cyan, &cyan));
+ assert!(Equal::isEq(&magenta, &magenta));
+ assert!(!Equal::isEq(&cyan, &yellow));
+ assert!(!Equal::isEq(&magenta, &cyan));
+
+ assert!(Equal::isEq(&leaf(cyan), &leaf(cyan)));
+ assert!(!Equal::isEq(&leaf(cyan), &leaf(yellow)));
+
+ assert!(Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))),
+ &branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))));
+
+ assert!(!Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))),
+ &branch(Box::new(leaf(magenta)), Box::new(leaf(magenta)))));
+
+ println!("Assertions all succeeded!");
+}
diff --git a/tests/ui/traits/typeclasses-eq-example.rs b/tests/ui/traits/typeclasses-eq-example.rs
new file mode 100644
index 000000000..4400301e6
--- /dev/null
+++ b/tests/ui/traits/typeclasses-eq-example.rs
@@ -0,0 +1,64 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(dead_code)]
+
+// Example from lkuper's intern talk, August 2012.
+use Color::{cyan, magenta, yellow, black};
+use ColorTree::{leaf, branch};
+
+trait Equal {
+ fn isEq(&self, a: &Self) -> bool;
+}
+
+#[derive(Clone, Copy)]
+enum Color { cyan, magenta, yellow, black }
+
+impl Equal for Color {
+ fn isEq(&self, a: &Color) -> bool {
+ match (*self, *a) {
+ (cyan, cyan) => { true }
+ (magenta, magenta) => { true }
+ (yellow, yellow) => { true }
+ (black, black) => { true }
+ _ => { false }
+ }
+ }
+}
+
+#[derive(Clone)]
+enum ColorTree {
+ leaf(Color),
+ branch(Box<ColorTree>, Box<ColorTree>)
+}
+
+impl Equal for ColorTree {
+ fn isEq(&self, a: &ColorTree) -> bool {
+ match (self, a) {
+ (&leaf(ref x), &leaf(ref y)) => { x.isEq(&(*y).clone()) }
+ (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => {
+ (*l1).isEq(&(**l2).clone()) && (*r1).isEq(&(**r2).clone())
+ }
+ _ => { false }
+ }
+ }
+}
+
+pub fn main() {
+ assert!(cyan.isEq(&cyan));
+ assert!(magenta.isEq(&magenta));
+ assert!(!cyan.isEq(&yellow));
+ assert!(!magenta.isEq(&cyan));
+
+ assert!(leaf(cyan).isEq(&leaf(cyan)));
+ assert!(!leaf(cyan).isEq(&leaf(yellow)));
+
+ assert!(branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))
+ .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))));
+
+ assert!(!branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))
+ .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(magenta)))));
+
+ println!("Assertions all succeeded!");
+}
diff --git a/tests/ui/traits/ufcs-object.rs b/tests/ui/traits/ufcs-object.rs
new file mode 100644
index 000000000..700488c22
--- /dev/null
+++ b/tests/ui/traits/ufcs-object.rs
@@ -0,0 +1,17 @@
+// run-pass
+// Test that when you use ufcs form to invoke a trait method (on a
+// trait object) everything works fine.
+
+
+trait Foo {
+ fn test(&self) -> i32;
+}
+
+impl Foo for i32 {
+ fn test(&self) -> i32 { *self }
+}
+
+fn main() {
+ let a: &dyn Foo = &22;
+ assert_eq!(Foo::test(a), 22);
+}
diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.rs b/tests/ui/traits/unspecified-self-in-trait-ref.rs
new file mode 100644
index 000000000..158b5a985
--- /dev/null
+++ b/tests/ui/traits/unspecified-self-in-trait-ref.rs
@@ -0,0 +1,30 @@
+pub trait Foo<A=Self> {
+ fn foo(&self);
+}
+
+pub trait Bar<X=usize, A=Self> {
+ fn foo(&self);
+}
+
+fn main() {
+ let a = Foo::lol();
+ //~^ ERROR no function or associated item named
+ //~| WARN trait objects without an explicit `dyn` are deprecated
+ //~| WARN this is accepted in the current edition
+ let b = Foo::<_>::lol();
+ //~^ ERROR no function or associated item named
+ //~| WARN trait objects without an explicit `dyn` are deprecated
+ //~| WARN this is accepted in the current edition
+ let c = Bar::lol();
+ //~^ ERROR no function or associated item named
+ //~| WARN trait objects without an explicit `dyn` are deprecated
+ //~| WARN this is accepted in the current edition
+ let d = Bar::<usize, _>::lol();
+ //~^ ERROR no function or associated item named
+ //~| WARN trait objects without an explicit `dyn` are deprecated
+ //~| WARN this is accepted in the current edition
+ let e = Bar::<usize>::lol();
+ //~^ ERROR must be explicitly specified
+ //~| WARN trait objects without an explicit `dyn` are deprecated
+ //~| WARN this is accepted in the current edition
+}
diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr
new file mode 100644
index 000000000..b5e8e8867
--- /dev/null
+++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr
@@ -0,0 +1,105 @@
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/unspecified-self-in-trait-ref.rs:10:13
+ |
+LL | let a = Foo::lol();
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
+help: use `dyn`
+ |
+LL | let a = <dyn Foo>::lol();
+ | ++++ +
+
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
+ --> $DIR/unspecified-self-in-trait-ref.rs:10:18
+ |
+LL | let a = Foo::lol();
+ | ^^^ function or associated item not found in `dyn Foo<_>`
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/unspecified-self-in-trait-ref.rs:14:13
+ |
+LL | let b = Foo::<_>::lol();
+ | ^^^^^^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | let b = <dyn Foo::<_>>::lol();
+ | ++++ +
+
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
+ --> $DIR/unspecified-self-in-trait-ref.rs:14:23
+ |
+LL | let b = Foo::<_>::lol();
+ | ^^^ function or associated item not found in `dyn Foo<_>`
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/unspecified-self-in-trait-ref.rs:18:13
+ |
+LL | let c = Bar::lol();
+ | ^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | let c = <dyn Bar>::lol();
+ | ++++ +
+
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<_, _>` in the current scope
+ --> $DIR/unspecified-self-in-trait-ref.rs:18:18
+ |
+LL | let c = Bar::lol();
+ | ^^^ function or associated item not found in `dyn Bar<_, _>`
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/unspecified-self-in-trait-ref.rs:22:13
+ |
+LL | let d = Bar::<usize, _>::lol();
+ | ^^^^^^^^^^^^^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | let d = <dyn Bar::<usize, _>>::lol();
+ | ++++ +
+
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<usize, _>` in the current scope
+ --> $DIR/unspecified-self-in-trait-ref.rs:22:30
+ |
+LL | let d = Bar::<usize, _>::lol();
+ | ^^^ function or associated item not found in `dyn Bar<usize, _>`
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/unspecified-self-in-trait-ref.rs:26:13
+ |
+LL | let e = Bar::<usize>::lol();
+ | ^^^^^^^^^^^^
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+ |
+LL | let e = <dyn Bar::<usize>>::lol();
+ | ++++ +
+
+error[E0393]: the type parameter `A` must be explicitly specified
+ --> $DIR/unspecified-self-in-trait-ref.rs:26:13
+ |
+LL | pub trait Bar<X=usize, A=Self> {
+ | ------------------------------ type parameter `A` must be specified for this
+...
+LL | let e = Bar::<usize>::lol();
+ | ^^^^^^^^^^^^ missing reference to `A`
+ |
+ = note: because of the default `Self` reference, type parameters must be specified on object types
+
+error: aborting due to 5 previous errors; 5 warnings emitted
+
+Some errors have detailed explanations: E0393, E0599.
+For more information about an error, try `rustc --explain E0393`.
diff --git a/tests/ui/traits/use-before-def.rs b/tests/ui/traits/use-before-def.rs
new file mode 100644
index 000000000..1ee2b9419
--- /dev/null
+++ b/tests/ui/traits/use-before-def.rs
@@ -0,0 +1,10 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// Issue #1761
+
+// pretty-expanded FIXME #23616
+
+impl foo for isize { fn foo(&self) -> isize { 10 } }
+trait foo { fn foo(&self) -> isize; }
+pub fn main() {}
diff --git a/tests/ui/traits/vtable-res-trait-param.rs b/tests/ui/traits/vtable-res-trait-param.rs
new file mode 100644
index 000000000..3d7c2eb08
--- /dev/null
+++ b/tests/ui/traits/vtable-res-trait-param.rs
@@ -0,0 +1,23 @@
+trait TraitA {
+ fn method_a(&self) -> isize;
+}
+
+trait TraitB {
+ fn gimme_an_a<A:TraitA>(&self, a: A) -> isize;
+}
+
+impl TraitB for isize {
+ fn gimme_an_a<A:TraitA>(&self, a: A) -> isize {
+ a.method_a() + *self
+ }
+}
+
+fn call_it<B:TraitB>(b: B) -> isize {
+ let y = 4;
+ b.gimme_an_a(y) //~ ERROR `{integer}: TraitA` is not satisfied
+}
+
+fn main() {
+ let x = 3;
+ assert_eq!(call_it(x), 22);
+}
diff --git a/tests/ui/traits/vtable-res-trait-param.stderr b/tests/ui/traits/vtable-res-trait-param.stderr
new file mode 100644
index 000000000..2b3e3de9b
--- /dev/null
+++ b/tests/ui/traits/vtable-res-trait-param.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `{integer}: TraitA` is not satisfied
+ --> $DIR/vtable-res-trait-param.rs:17:18
+ |
+LL | b.gimme_an_a(y)
+ | ---------- ^ the trait `TraitA` is not implemented for `{integer}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `TraitB::gimme_an_a`
+ --> $DIR/vtable-res-trait-param.rs:6:21
+ |
+LL | fn gimme_an_a<A:TraitA>(&self, a: A) -> isize;
+ | ^^^^^^ required by this bound in `TraitB::gimme_an_a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/vtable/issue-91807.rs b/tests/ui/traits/vtable/issue-91807.rs
new file mode 100644
index 000000000..f435ff09d
--- /dev/null
+++ b/tests/ui/traits/vtable/issue-91807.rs
@@ -0,0 +1,17 @@
+// check-pass
+// incremental
+
+struct Struct<T>(T);
+
+impl<T> std::ops::Deref for Struct<T> {
+ type Target = dyn Fn(T);
+ fn deref(&self) -> &Self::Target {
+ unimplemented!()
+ }
+}
+
+fn main() {
+ let f = Struct(Default::default());
+ f(0);
+ f(0);
+}
diff --git a/tests/ui/traits/vtable/issue-97381.rs b/tests/ui/traits/vtable/issue-97381.rs
new file mode 100644
index 000000000..393cf91ef
--- /dev/null
+++ b/tests/ui/traits/vtable/issue-97381.rs
@@ -0,0 +1,30 @@
+use std::ops::Deref;
+trait MyTrait: Deref<Target = u32> {}
+struct MyStruct(u32);
+impl MyTrait for MyStruct {}
+impl Deref for MyStruct {
+ type Target = u32;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+fn get_concrete_value(i: u32) -> MyStruct {
+ MyStruct(i)
+}
+fn get_boxed_value(i: u32) -> Box<dyn MyTrait> {
+ Box::new(get_concrete_value(i))
+}
+fn main() {
+ let v = [1, 2, 3]
+ .iter()
+ .map(|i| get_boxed_value(*i))
+ .collect::<Vec<_>>();
+
+ let el = &v[0];
+
+ for _ in v {
+ //~^ ERROR cannot move out of `v` because it is borrowed
+ println!("{}", ***el > 0);
+ }
+}
diff --git a/tests/ui/traits/vtable/issue-97381.stderr b/tests/ui/traits/vtable/issue-97381.stderr
new file mode 100644
index 000000000..c4f8294e2
--- /dev/null
+++ b/tests/ui/traits/vtable/issue-97381.stderr
@@ -0,0 +1,15 @@
+error[E0505]: cannot move out of `v` because it is borrowed
+ --> $DIR/issue-97381.rs:26:14
+ |
+LL | let el = &v[0];
+ | - borrow of `v` occurs here
+LL |
+LL | for _ in v {
+ | ^ move out of `v` occurs here
+LL |
+LL | println!("{}", ***el > 0);
+ | ---- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/tests/ui/traits/vtable/vtable-diamond.rs b/tests/ui/traits/vtable/vtable-diamond.rs
new file mode 100644
index 000000000..dc3c17ac3
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-diamond.rs
@@ -0,0 +1,44 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+#[rustc_dump_vtable]
+trait A {
+ fn foo_a(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait B: A {
+ fn foo_b(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait C: A {
+ //~^ error vtable
+ fn foo_c(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait D: B + C {
+ //~^ error vtable
+ fn foo_d(&self) {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+impl C for S {}
+impl D for S {}
+
+fn foo(d: &dyn D) {
+ d.foo_d();
+}
+
+fn bar(d: &dyn C) {
+ d.foo_c();
+}
+
+fn main() {
+ foo(&S);
+ bar(&S);
+}
diff --git a/tests/ui/traits/vtable/vtable-diamond.stderr b/tests/ui/traits/vtable/vtable-diamond.stderr
new file mode 100644
index 000000000..f3718c5d8
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-diamond.stderr
@@ -0,0 +1,29 @@
+error: vtable entries for `<S as D>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a),
+ Method(<S as B>::foo_b),
+ Method(<S as C>::foo_c),
+ TraitVPtr(<S as C>),
+ Method(<S as D>::foo_d),
+ ]
+ --> $DIR/vtable-diamond.rs:21:1
+ |
+LL | trait D: B + C {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as C>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a),
+ Method(<S as C>::foo_c),
+ ]
+ --> $DIR/vtable-diamond.rs:15:1
+ |
+LL | trait C: A {
+ | ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/vtable/vtable-multi-level.rs b/tests/ui/traits/vtable/vtable-multi-level.rs
new file mode 100644
index 000000000..ebd55bcf3
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-multi-level.rs
@@ -0,0 +1,143 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+// O --> G --> C --> A
+// \ \ \-> B
+// | |-> F --> D
+// | \-> E
+// |-> N --> J --> H
+// \ \-> I
+// |-> M --> K
+// \-> L
+
+#[rustc_dump_vtable]
+trait A {
+ //~^ error vtable
+ fn foo_a(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait B {
+ //~^ error vtable
+ fn foo_b(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait C: A + B {
+ //~^ error vtable
+ fn foo_c(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait D {
+ //~^ error vtable
+ fn foo_d(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait E {
+ //~^ error vtable
+ fn foo_e(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait F: D + E {
+ //~^ error vtable
+ fn foo_f(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait G: C + F {
+ fn foo_g(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait H {
+ //~^ error vtable
+ fn foo_h(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait I {
+ //~^ error vtable
+ fn foo_i(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait J: H + I {
+ //~^ error vtable
+ fn foo_j(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait K {
+ //~^ error vtable
+ fn foo_k(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait L {
+ //~^ error vtable
+ fn foo_l(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait M: K + L {
+ //~^ error vtable
+ fn foo_m(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait N: J + M {
+ //~^ error vtable
+ fn foo_n(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait O: G + N {
+ //~^ error vtable
+ fn foo_o(&self) {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+impl C for S {}
+impl D for S {}
+impl E for S {}
+impl F for S {}
+impl G for S {}
+impl H for S {}
+impl I for S {}
+impl J for S {}
+impl K for S {}
+impl L for S {}
+impl M for S {}
+impl N for S {}
+impl O for S {}
+
+macro_rules! monomorphize_vtable {
+ ($trait:ident) => {{
+ fn foo(_ : &dyn $trait) {}
+ foo(&S);
+ }}
+}
+
+fn main() {
+ monomorphize_vtable!(O);
+
+ monomorphize_vtable!(A);
+ monomorphize_vtable!(B);
+ monomorphize_vtable!(C);
+ monomorphize_vtable!(D);
+ monomorphize_vtable!(E);
+ monomorphize_vtable!(F);
+ monomorphize_vtable!(H);
+ monomorphize_vtable!(I);
+ monomorphize_vtable!(J);
+ monomorphize_vtable!(K);
+ monomorphize_vtable!(L);
+ monomorphize_vtable!(M);
+ monomorphize_vtable!(N);
+}
diff --git a/tests/ui/traits/vtable/vtable-multi-level.stderr b/tests/ui/traits/vtable/vtable-multi-level.stderr
new file mode 100644
index 000000000..c4389e23f
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-multi-level.stderr
@@ -0,0 +1,203 @@
+error: vtable entries for `<S as O>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a),
+ Method(<S as B>::foo_b),
+ TraitVPtr(<S as B>),
+ Method(<S as C>::foo_c),
+ Method(<S as D>::foo_d),
+ TraitVPtr(<S as D>),
+ Method(<S as E>::foo_e),
+ TraitVPtr(<S as E>),
+ Method(<S as F>::foo_f),
+ TraitVPtr(<S as F>),
+ Method(<S as G>::foo_g),
+ Method(<S as H>::foo_h),
+ TraitVPtr(<S as H>),
+ Method(<S as I>::foo_i),
+ TraitVPtr(<S as I>),
+ Method(<S as J>::foo_j),
+ TraitVPtr(<S as J>),
+ Method(<S as K>::foo_k),
+ TraitVPtr(<S as K>),
+ Method(<S as L>::foo_l),
+ TraitVPtr(<S as L>),
+ Method(<S as M>::foo_m),
+ TraitVPtr(<S as M>),
+ Method(<S as N>::foo_n),
+ TraitVPtr(<S as N>),
+ Method(<S as O>::foo_o),
+ ]
+ --> $DIR/vtable-multi-level.rs:97:1
+ |
+LL | trait O: G + N {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as A>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a),
+ ]
+ --> $DIR/vtable-multi-level.rs:14:1
+ |
+LL | trait A {
+ | ^^^^^^^
+
+error: vtable entries for `<S as B>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as B>::foo_b),
+ ]
+ --> $DIR/vtable-multi-level.rs:20:1
+ |
+LL | trait B {
+ | ^^^^^^^
+
+error: vtable entries for `<S as C>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a),
+ Method(<S as B>::foo_b),
+ TraitVPtr(<S as B>),
+ Method(<S as C>::foo_c),
+ ]
+ --> $DIR/vtable-multi-level.rs:26:1
+ |
+LL | trait C: A + B {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as D>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as D>::foo_d),
+ ]
+ --> $DIR/vtable-multi-level.rs:32:1
+ |
+LL | trait D {
+ | ^^^^^^^
+
+error: vtable entries for `<S as E>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as E>::foo_e),
+ ]
+ --> $DIR/vtable-multi-level.rs:38:1
+ |
+LL | trait E {
+ | ^^^^^^^
+
+error: vtable entries for `<S as F>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as D>::foo_d),
+ Method(<S as E>::foo_e),
+ TraitVPtr(<S as E>),
+ Method(<S as F>::foo_f),
+ ]
+ --> $DIR/vtable-multi-level.rs:44:1
+ |
+LL | trait F: D + E {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as H>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as H>::foo_h),
+ ]
+ --> $DIR/vtable-multi-level.rs:55:1
+ |
+LL | trait H {
+ | ^^^^^^^
+
+error: vtable entries for `<S as I>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as I>::foo_i),
+ ]
+ --> $DIR/vtable-multi-level.rs:61:1
+ |
+LL | trait I {
+ | ^^^^^^^
+
+error: vtable entries for `<S as J>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as H>::foo_h),
+ Method(<S as I>::foo_i),
+ TraitVPtr(<S as I>),
+ Method(<S as J>::foo_j),
+ ]
+ --> $DIR/vtable-multi-level.rs:67:1
+ |
+LL | trait J: H + I {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as K>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as K>::foo_k),
+ ]
+ --> $DIR/vtable-multi-level.rs:73:1
+ |
+LL | trait K {
+ | ^^^^^^^
+
+error: vtable entries for `<S as L>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as L>::foo_l),
+ ]
+ --> $DIR/vtable-multi-level.rs:79:1
+ |
+LL | trait L {
+ | ^^^^^^^
+
+error: vtable entries for `<S as M>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as K>::foo_k),
+ Method(<S as L>::foo_l),
+ TraitVPtr(<S as L>),
+ Method(<S as M>::foo_m),
+ ]
+ --> $DIR/vtable-multi-level.rs:85:1
+ |
+LL | trait M: K + L {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as N>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as H>::foo_h),
+ Method(<S as I>::foo_i),
+ TraitVPtr(<S as I>),
+ Method(<S as J>::foo_j),
+ Method(<S as K>::foo_k),
+ TraitVPtr(<S as K>),
+ Method(<S as L>::foo_l),
+ TraitVPtr(<S as L>),
+ Method(<S as M>::foo_m),
+ TraitVPtr(<S as M>),
+ Method(<S as N>::foo_n),
+ ]
+ --> $DIR/vtable-multi-level.rs:91:1
+ |
+LL | trait N: J + M {
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/traits/vtable/vtable-multiple.rs b/tests/ui/traits/vtable/vtable-multiple.rs
new file mode 100644
index 000000000..7a0111c5e
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-multiple.rs
@@ -0,0 +1,33 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+#[rustc_dump_vtable]
+trait A {
+ fn foo_a(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait B {
+ //~^ error vtable
+ fn foo_b(&self) {}
+}
+
+#[rustc_dump_vtable]
+trait C: A + B {
+ //~^ error vtable
+ fn foo_c(&self) {}
+}
+
+struct S;
+
+impl A for S {}
+impl B for S {}
+impl C for S {}
+
+fn foo(c: &dyn C) {}
+fn bar(c: &dyn B) {}
+
+fn main() {
+ foo(&S);
+ bar(&S);
+}
diff --git a/tests/ui/traits/vtable/vtable-multiple.stderr b/tests/ui/traits/vtable/vtable-multiple.stderr
new file mode 100644
index 000000000..0dcd84433
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-multiple.stderr
@@ -0,0 +1,27 @@
+error: vtable entries for `<S as C>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a),
+ Method(<S as B>::foo_b),
+ TraitVPtr(<S as B>),
+ Method(<S as C>::foo_c),
+ ]
+ --> $DIR/vtable-multiple.rs:16:1
+ |
+LL | trait C: A + B {
+ | ^^^^^^^^^^^^^^
+
+error: vtable entries for `<S as B>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as B>::foo_b),
+ ]
+ --> $DIR/vtable-multiple.rs:10:1
+ |
+LL | trait B {
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.rs b/tests/ui/traits/vtable/vtable-non-object-safe.rs
new file mode 100644
index 000000000..7661bb574
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-non-object-safe.rs
@@ -0,0 +1,18 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+// Ensure that non-object-safe methods in Iterator does not generate
+// vtable entries.
+
+#[rustc_dump_vtable]
+trait A: Iterator {}
+//~^ error vtable
+
+impl<T> A for T where T: Iterator {}
+
+fn foo(_a: &mut dyn A<Item=u8>) {
+}
+
+fn main() {
+ foo(&mut vec![0, 1, 2, 3].into_iter());
+}
diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.stderr b/tests/ui/traits/vtable/vtable-non-object-safe.stderr
new file mode 100644
index 000000000..9345c2711
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-non-object-safe.stderr
@@ -0,0 +1,16 @@
+error: vtable entries for `<std::vec::IntoIter<u8> as A>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<std::vec::IntoIter<u8> as Iterator>::next),
+ Method(<std::vec::IntoIter<u8> as Iterator>::size_hint),
+ Method(<std::vec::IntoIter<u8> as Iterator>::advance_by),
+ Method(<std::vec::IntoIter<u8> as Iterator>::nth),
+ ]
+ --> $DIR/vtable-non-object-safe.rs:8:1
+ |
+LL | trait A: Iterator {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/vtable/vtable-vacant.rs b/tests/ui/traits/vtable/vtable-vacant.rs
new file mode 100644
index 000000000..a64796358
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-vacant.rs
@@ -0,0 +1,31 @@
+// build-fail
+#![feature(rustc_attrs)]
+#![feature(negative_impls)]
+#![allow(where_clauses_object_safety)]
+
+// B --> A
+
+#[rustc_dump_vtable]
+trait A {
+ fn foo_a1(&self) {}
+ fn foo_a2(&self) where Self: Send {}
+}
+
+#[rustc_dump_vtable]
+trait B: A {
+ //~^ error vtable
+ fn foo_b1(&self) {}
+ fn foo_b2(&self) where Self: Send {}
+}
+
+struct S;
+impl !Send for S {}
+
+impl A for S {}
+impl B for S {}
+
+fn foo(_: &dyn B) {}
+
+fn main() {
+ foo(&S);
+}
diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr
new file mode 100644
index 000000000..5346a7027
--- /dev/null
+++ b/tests/ui/traits/vtable/vtable-vacant.stderr
@@ -0,0 +1,16 @@
+error: vtable entries for `<S as B>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as A>::foo_a1),
+ Vacant,
+ Method(<S as B>::foo_b1),
+ Vacant,
+ ]
+ --> $DIR/vtable-vacant.rs:15:1
+ |
+LL | trait B: A {
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/wf-object/maybe-bound.rs b/tests/ui/traits/wf-object/maybe-bound.rs
new file mode 100644
index 000000000..17771e976
--- /dev/null
+++ b/tests/ui/traits/wf-object/maybe-bound.rs
@@ -0,0 +1,18 @@
+// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects).
+
+trait Foo {}
+
+type _0 = dyn ?Sized + Foo;
+//~^ ERROR `?Trait` is not permitted in trait object types
+
+type _1 = dyn Foo + ?Sized;
+//~^ ERROR `?Trait` is not permitted in trait object types
+
+type _2 = dyn Foo + ?Sized + ?Sized;
+//~^ ERROR `?Trait` is not permitted in trait object types
+//~| ERROR `?Trait` is not permitted in trait object types
+
+type _3 = dyn ?Sized + Foo;
+//~^ ERROR `?Trait` is not permitted in trait object types
+
+fn main() {}
diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr
new file mode 100644
index 000000000..2fe3f0fc3
--- /dev/null
+++ b/tests/ui/traits/wf-object/maybe-bound.stderr
@@ -0,0 +1,32 @@
+error: `?Trait` is not permitted in trait object types
+ --> $DIR/maybe-bound.rs:5:15
+ |
+LL | type _0 = dyn ?Sized + Foo;
+ | ^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+ --> $DIR/maybe-bound.rs:8:21
+ |
+LL | type _1 = dyn Foo + ?Sized;
+ | ^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+ --> $DIR/maybe-bound.rs:11:21
+ |
+LL | type _2 = dyn Foo + ?Sized + ?Sized;
+ | ^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+ --> $DIR/maybe-bound.rs:11:30
+ |
+LL | type _2 = dyn Foo + ?Sized + ?Sized;
+ | ^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+ --> $DIR/maybe-bound.rs:15:15
+ |
+LL | type _3 = dyn ?Sized + Foo;
+ | ^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/traits/wf-object/no-duplicates.rs b/tests/ui/traits/wf-object/no-duplicates.rs
new file mode 100644
index 000000000..678ede582
--- /dev/null
+++ b/tests/ui/traits/wf-object/no-duplicates.rs
@@ -0,0 +1,33 @@
+// The purpose of this test is to demonstrate that duplicating object safe traits
+// that are not auto-traits is rejected even though one could reasonably accept this.
+
+// Some arbitrary object-safe trait:
+trait Obj {}
+
+// Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior:
+type _0 = dyn Obj + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+// Some variations:
+
+type _1 = dyn Send + Obj + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _2 = dyn Obj + Send + Obj;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+type _3 = dyn Obj + Send + Send; // But it is OK to duplicate auto traits.
+
+// Take higher ranked types into account.
+
+// Note that `'a` and `'b` are intentionally different to make sure we consider
+// them semantically the same.
+trait ObjL<'l> {}
+type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+trait ObjT<T> {}
+type _5 = dyn ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)>;
+//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
+
+fn main() {}
diff --git a/tests/ui/traits/wf-object/no-duplicates.stderr b/tests/ui/traits/wf-object/no-duplicates.stderr
new file mode 100644
index 000000000..50dfcf956
--- /dev/null
+++ b/tests/ui/traits/wf-object/no-duplicates.stderr
@@ -0,0 +1,58 @@
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:8:21
+ |
+LL | type _0 = dyn Obj + Obj;
+ | --- ^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:13:28
+ |
+LL | type _1 = dyn Send + Obj + Obj;
+ | --- ^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:16:28
+ |
+LL | type _2 = dyn Obj + Send + Obj;
+ | --- ^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:26:34
+ |
+LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>;
+ | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+ --> $DIR/no-duplicates.rs:30:42
+ |
+LL | type _5 = dyn ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)>;
+ | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait
+ | |
+ | first non-auto trait
+ |
+ = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0225`.
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs
new file mode 100644
index 000000000..3e6db3e99
--- /dev/null
+++ b/tests/ui/traits/wf-object/only-maybe-bound.rs
@@ -0,0 +1,7 @@
+// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed.
+
+type _0 = dyn ?Sized;
+//~^ ERROR at least one trait is required for an object type [E0224]
+//~| ERROR ?Trait` is not permitted in trait object types
+
+fn main() {}
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr
new file mode 100644
index 000000000..cbc41feec
--- /dev/null
+++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr
@@ -0,0 +1,15 @@
+error: `?Trait` is not permitted in trait object types
+ --> $DIR/only-maybe-bound.rs:3:15
+ |
+LL | type _0 = dyn ?Sized;
+ | ^^^^^^
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/only-maybe-bound.rs:3:11
+ |
+LL | type _0 = dyn ?Sized;
+ | ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs
new file mode 100644
index 000000000..4f676cbe3
--- /dev/null
+++ b/tests/ui/traits/wf-object/reverse-order.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+// Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed.
+
+use std::marker::Unpin;
+
+// Some arbitrary object-safe trait:
+trait Obj {}
+
+type _0 = dyn Unpin;
+type _1 = dyn Send + Obj;
+type _2 = dyn Send + Unpin + Obj;
+type _3 = dyn Send + Unpin + Sync + Obj;
+
+fn main() {}
diff --git a/tests/ui/traits/where-clause-vs-impl.rs b/tests/ui/traits/where-clause-vs-impl.rs
new file mode 100644
index 000000000..7cfee27ef
--- /dev/null
+++ b/tests/ui/traits/where-clause-vs-impl.rs
@@ -0,0 +1,45 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test that when there is a conditional (but blanket) impl and a
+// where clause, we don't get confused in trait resolution.
+//
+// Issue #18453.
+
+// pretty-expanded FIXME #23616
+
+use std::rc::Rc;
+
+pub trait Foo<M> {
+ fn foo(&mut self, msg: M);
+}
+
+pub trait Bar<M> {
+ fn dummy(&self) -> M;
+}
+
+impl<M, F: Bar<M>> Foo<M> for F {
+ fn foo(&mut self, msg: M) {
+ }
+}
+
+pub struct Both<M, F> {
+ inner: Rc<(M, F)>,
+}
+
+impl<M, F: Foo<M>> Clone for Both<M, F> {
+ fn clone(&self) -> Both<M, F> {
+ Both { inner: self.inner.clone() }
+ }
+}
+
+fn repro1<M, F: Foo<M>>(_both: Both<M, F>) {
+}
+
+fn repro2<M, F: Foo<M>>(msg: M, foo: F) {
+ let both = Both { inner: Rc::new((msg, foo)) };
+ repro1(both.clone()); // <--- This clone causes problem
+}
+
+pub fn main() {
+}
diff --git a/tests/ui/traits/with-bounds-default.rs b/tests/ui/traits/with-bounds-default.rs
new file mode 100644
index 000000000..31f73d79c
--- /dev/null
+++ b/tests/ui/traits/with-bounds-default.rs
@@ -0,0 +1,32 @@
+// run-pass
+
+pub trait Clone2 {
+ /// Returns a copy of the value. The contents of boxes
+ /// are copied to maintain uniqueness, while the contents of
+ /// managed pointers are not copied.
+ fn clone(&self) -> Self;
+}
+
+trait Getter<T: Clone> {
+ fn do_get(&self) -> T;
+
+ fn do_get2(&self) -> (T, T) {
+ let x = self.do_get();
+ (x.clone(), x.clone())
+ }
+
+}
+
+impl Getter<isize> for isize {
+ fn do_get(&self) -> isize { *self }
+}
+
+impl<T: Clone> Getter<T> for Option<T> {
+ fn do_get(&self) -> T { self.as_ref().unwrap().clone() }
+}
+
+
+pub fn main() {
+ assert_eq!(3.do_get2(), (3, 3));
+ assert_eq!(Some("hi".to_string()).do_get2(), ("hi".to_string(), "hi".to_string()));
+}
diff --git a/tests/ui/traits/with-dst.rs b/tests/ui/traits/with-dst.rs
new file mode 100644
index 000000000..a3e3b31df
--- /dev/null
+++ b/tests/ui/traits/with-dst.rs
@@ -0,0 +1,22 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// #55266
+
+struct VTable<DST: ?Sized> {
+ _to_dst_ptr: fn(*mut ()) -> *mut DST,
+}
+
+trait HasVTableFor<DST: ?Sized + 'static> {
+ const VTABLE: &'static VTable<DST>;
+}
+
+impl<T, DST: ?Sized + 'static> HasVTableFor<DST> for T {
+ const VTABLE: &'static VTable<DST> = &VTable {
+ _to_dst_ptr: |_: *mut ()| unsafe { std::mem::zeroed() },
+ };
+}
+
+pub fn push<DST: ?Sized + 'static, T>() {
+ <T as HasVTableFor<DST>>::VTABLE;
+}
+
+fn main() {}