diff options
| author | Rémy Rakic <remy.rakic+github@gmail.com> | 2021-07-22 20:21:48 +0200 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-04-11 15:11:27 +0000 |
| commit | 7d5bbf55f22c91f966a0feb130b5ff476da4f017 (patch) | |
| tree | d3e59f29d74fb292deb61535e89111fc1bdb80f0 | |
| parent | d00e77078c0bd003323af67b4deb27627226d2e6 (diff) | |
| download | rust-7d5bbf55f22c91f966a0feb130b5ff476da4f017.tar.gz rust-7d5bbf55f22c91f966a0feb130b5ff476da4f017.zip | |
prevent opaque types from appearing in impl headers
11 files changed, 71 insertions, 42 deletions
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 4b23cc4db85..564c3d31368 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -141,13 +141,22 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua } } - if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() { - let reported = tcx - .sess - .struct_span_err(sp, "cannot implement trait on type alias impl trait") - .span_note(tcx.def_span(def_id), "type alias impl trait defined here") - .emit(); - return Err(reported); + // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples, + // and #84660 where it would otherwise allow unsoundness. + if trait_ref.has_opaque_types() { + for ty in trait_ref.substs { + for ty in ty.walk() { + let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue }; + let ty::Opaque(def_id, _) = ty.kind() else { continue }; + let reported = tcx + .sess + .struct_span_err(sp, "cannot implement trait on type alias impl trait") + .span_note(tcx.def_span(def_id), "type alias impl trait defined here") + .emit(); + return Err(reported); + } + } + span_bug!(sp, "opque type not found, but `has_opaque_types` is set") } Ok(()) diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs index 35994e4a5ba..afa95645a27 100644 --- a/src/test/ui/impl-trait/auto-trait.rs +++ b/src/test/ui/impl-trait/auto-trait.rs @@ -20,6 +20,7 @@ impl<T: Send> AnotherTrait for T {} // in the future.) impl AnotherTrait for D<OpaqueType> { //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` + //~| ERROR cannot implement trait on type alias impl trait } fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr index 81009413c9a..9171cfca5b1 100644 --- a/src/test/ui/impl-trait/auto-trait.stderr +++ b/src/test/ui/impl-trait/auto-trait.stderr @@ -1,3 +1,15 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/auto-trait.rs:21:1 + | +LL | impl AnotherTrait for D<OpaqueType> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type alias impl trait defined here + --> $DIR/auto-trait.rs:7:19 + | +LL | type OpaqueType = impl OpaqueTrait; + | ^^^^^^^^^^^^^^^^ + error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` --> $DIR/auto-trait.rs:21:1 | @@ -7,6 +19,6 @@ LL | impl<T: Send> AnotherTrait for T {} LL | impl AnotherTrait for D<OpaqueType> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs index 70e24a3a9d0..da69bb349ae 100644 --- a/src/test/ui/impl-trait/negative-reasoning.rs +++ b/src/test/ui/impl-trait/negative-reasoning.rs @@ -18,6 +18,7 @@ impl<T: std::fmt::Debug> AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D<OpaqueType> { //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` + //~| ERROR cannot implement trait on type alias impl trait } fn main() {} diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr index 6b8cc9e7374..1a7233bca5c 100644 --- a/src/test/ui/impl-trait/negative-reasoning.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -1,3 +1,15 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/negative-reasoning.rs:19:1 + | +LL | impl AnotherTrait for D<OpaqueType> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type alias impl trait defined here + --> $DIR/negative-reasoning.rs:7:19 + | +LL | type OpaqueType = impl OpaqueTrait; + | ^^^^^^^^^^^^^^^^ + error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>` --> $DIR/negative-reasoning.rs:19:1 | @@ -9,6 +21,6 @@ LL | impl AnotherTrait for D<OpaqueType> { | = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs index 6b200d7e3a8..621c4ea6e0d 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -5,13 +5,14 @@ type Foo = impl PartialEq<(Foo, i32)>; struct Bar; impl PartialEq<(Foo, i32)> for Bar { +//~^ ERROR cannot implement trait on type alias impl trait fn eq(&self, _other: &(Foo, i32)) -> bool { true } } fn foo() -> Foo { - Bar //~ ERROR can't compare `Bar` with `(Bar, i32)` + Bar } fn main() {} diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr index 6cd63db44fa..4e8d4cce0a1 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr @@ -1,12 +1,14 @@ -error[E0277]: can't compare `Bar` with `(Bar, i32)` - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:14:5 +error: cannot implement trait on type alias impl trait + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:1 | -LL | Bar - | ^^^ no implementation for `Bar == (Bar, i32)` +LL | impl PartialEq<(Foo, i32)> for Bar { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` - = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar` +note: type alias impl trait defined here + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs index 6aa832cde71..df7966f00e1 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs @@ -2,7 +2,6 @@ mod a { type Foo = impl PartialEq<(Foo, i32)>; - //~^ ERROR unconstrained opaque type struct Bar; @@ -15,13 +14,12 @@ mod a { mod b { type Foo = impl PartialEq<(Foo, i32)>; - //~^ ERROR unconstrained opaque type struct Bar; impl PartialEq<(Foo, i32)> for Bar { + //~^ ERROR cannot implement trait on type alias impl trait fn eq(&self, _other: &(Bar, i32)) -> bool { - //~^ ERROR impl has stricter requirements than trait true } } diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index 19d5cdb9d0a..ccb0bc0a366 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -1,25 +1,14 @@ -error: unconstrained opaque type - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 +error: cannot implement trait on type alias impl trait + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:5 | -LL | type Foo = impl PartialEq<(Foo, i32)>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl PartialEq<(Foo, i32)> for Bar { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Foo` must be used in combination with a concrete type within the same module - -error: unconstrained opaque type - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:17:16 +note: type alias impl trait defined here + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16 | LL | type Foo = impl PartialEq<(Foo, i32)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module - -error[E0276]: impl has stricter requirements than trait - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:23:9 - | -LL | fn eq(&self, _other: &(Bar, i32)) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `b::Bar: PartialEq<(b::Bar, i32)>` -error: aborting due to 3 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs index fbab5470b4f..ebf3a99bbf9 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -4,11 +4,11 @@ use std::fmt::Debug; type FooX = impl Debug; -//~^ unconstrained opaque type trait Foo<A> { } impl Foo<FooX> for () { } +//~^ cannot implement trait on type alias impl trait fn foo() -> impl Foo<FooX> { () diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr index b1d947a9ccf..bf1582639a2 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -1,10 +1,14 @@ -error: unconstrained opaque type +error: cannot implement trait on type alias impl trait + --> $DIR/nested-tait-inference3.rs:10:1 + | +LL | impl Foo<FooX> for () { } + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: type alias impl trait defined here --> $DIR/nested-tait-inference3.rs:6:13 | LL | type FooX = impl Debug; | ^^^^^^^^^^ - | - = note: `FooX` must be used in combination with a concrete type within the same module error: aborting due to previous error |
