Skip to content

Commit 7d5bbf5

Browse files
lqdoli-obk
authored andcommitted
prevent opaque types from appearing in impl headers
1 parent d00e770 commit 7d5bbf5

11 files changed

+71
-42
lines changed

compiler/rustc_typeck/src/coherence/orphan.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,22 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
141141
}
142142
}
143143

144-
if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
145-
let reported = tcx
146-
.sess
147-
.struct_span_err(sp, "cannot implement trait on type alias impl trait")
148-
.span_note(tcx.def_span(def_id), "type alias impl trait defined here")
149-
.emit();
150-
return Err(reported);
144+
// Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
145+
// and #84660 where it would otherwise allow unsoundness.
146+
if trait_ref.has_opaque_types() {
147+
for ty in trait_ref.substs {
148+
for ty in ty.walk() {
149+
let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
150+
let ty::Opaque(def_id, _) = ty.kind() else { continue };
151+
let reported = tcx
152+
.sess
153+
.struct_span_err(sp, "cannot implement trait on type alias impl trait")
154+
.span_note(tcx.def_span(def_id), "type alias impl trait defined here")
155+
.emit();
156+
return Err(reported);
157+
}
158+
}
159+
span_bug!(sp, "opque type not found, but `has_opaque_types` is set")
151160
}
152161

153162
Ok(())

src/test/ui/impl-trait/auto-trait.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl<T: Send> AnotherTrait for T {}
2020
// in the future.)
2121
impl AnotherTrait for D<OpaqueType> {
2222
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
23+
//~| ERROR cannot implement trait on type alias impl trait
2324
}
2425

2526
fn main() {}

src/test/ui/impl-trait/auto-trait.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/auto-trait.rs:21:1
3+
|
4+
LL | impl AnotherTrait for D<OpaqueType> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: type alias impl trait defined here
8+
--> $DIR/auto-trait.rs:7:19
9+
|
10+
LL | type OpaqueType = impl OpaqueTrait;
11+
| ^^^^^^^^^^^^^^^^
12+
113
error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
214
--> $DIR/auto-trait.rs:21:1
315
|
@@ -7,6 +19,6 @@ LL | impl<T: Send> AnotherTrait for T {}
719
LL | impl AnotherTrait for D<OpaqueType> {
820
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
921

10-
error: aborting due to previous error
22+
error: aborting due to 2 previous errors
1123

1224
For more information about this error, try `rustc --explain E0119`.

src/test/ui/impl-trait/negative-reasoning.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
1818
// This is in error, because we cannot assume that `OpaqueType: !Debug`
1919
impl AnotherTrait for D<OpaqueType> {
2020
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
21+
//~| ERROR cannot implement trait on type alias impl trait
2122
}
2223

2324
fn main() {}

src/test/ui/impl-trait/negative-reasoning.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/negative-reasoning.rs:19:1
3+
|
4+
LL | impl AnotherTrait for D<OpaqueType> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: type alias impl trait defined here
8+
--> $DIR/negative-reasoning.rs:7:19
9+
|
10+
LL | type OpaqueType = impl OpaqueTrait;
11+
| ^^^^^^^^^^^^^^^^
12+
113
error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
214
--> $DIR/negative-reasoning.rs:19:1
315
|
@@ -9,6 +21,6 @@ LL | impl AnotherTrait for D<OpaqueType> {
921
|
1022
= note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
1123

12-
error: aborting due to previous error
24+
error: aborting due to 2 previous errors
1325

1426
For more information about this error, try `rustc --explain E0119`.

src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ type Foo = impl PartialEq<(Foo, i32)>;
55
struct Bar;
66

77
impl PartialEq<(Foo, i32)> for Bar {
8+
//~^ ERROR cannot implement trait on type alias impl trait
89
fn eq(&self, _other: &(Foo, i32)) -> bool {
910
true
1011
}
1112
}
1213

1314
fn foo() -> Foo {
14-
Bar //~ ERROR can't compare `Bar` with `(Bar, i32)`
15+
Bar
1516
}
1617

1718
fn main() {}

src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
error[E0277]: can't compare `Bar` with `(Bar, i32)`
2-
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:14:5
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:1
33
|
4-
LL | Bar
5-
| ^^^ no implementation for `Bar == (Bar, i32)`
4+
LL | impl PartialEq<(Foo, i32)> for Bar {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
8-
= help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar`
7+
note: type alias impl trait defined here
8+
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12
9+
|
10+
LL | type Foo = impl PartialEq<(Foo, i32)>;
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
912

1013
error: aborting due to previous error
1114

12-
For more information about this error, try `rustc --explain E0277`.

src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
mod a {
44
type Foo = impl PartialEq<(Foo, i32)>;
5-
//~^ ERROR unconstrained opaque type
65

76
struct Bar;
87

@@ -15,13 +14,12 @@ mod a {
1514

1615
mod b {
1716
type Foo = impl PartialEq<(Foo, i32)>;
18-
//~^ ERROR unconstrained opaque type
1917

2018
struct Bar;
2119

2220
impl PartialEq<(Foo, i32)> for Bar {
21+
//~^ ERROR cannot implement trait on type alias impl trait
2322
fn eq(&self, _other: &(Bar, i32)) -> bool {
24-
//~^ ERROR impl has stricter requirements than trait
2523
true
2624
}
2725
}
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
1-
error: unconstrained opaque type
2-
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:5
33
|
4-
LL | type Foo = impl PartialEq<(Foo, i32)>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | impl PartialEq<(Foo, i32)> for Bar {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: `Foo` must be used in combination with a concrete type within the same module
8-
9-
error: unconstrained opaque type
10-
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:17:16
7+
note: type alias impl trait defined here
8+
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16
119
|
1210
LL | type Foo = impl PartialEq<(Foo, i32)>;
1311
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
14-
|
15-
= note: `Foo` must be used in combination with a concrete type within the same module
16-
17-
error[E0276]: impl has stricter requirements than trait
18-
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:23:9
19-
|
20-
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `b::Bar: PartialEq<(b::Bar, i32)>`
2212

23-
error: aborting due to 3 previous errors
13+
error: aborting due to previous error
2414

25-
For more information about this error, try `rustc --explain E0276`.

src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
use std::fmt::Debug;
55

66
type FooX = impl Debug;
7-
//~^ unconstrained opaque type
87

98
trait Foo<A> { }
109

1110
impl Foo<FooX> for () { }
11+
//~^ cannot implement trait on type alias impl trait
1212

1313
fn foo() -> impl Foo<FooX> {
1414
()
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
error: unconstrained opaque type
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/nested-tait-inference3.rs:10:1
3+
|
4+
LL | impl Foo<FooX> for () { }
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: type alias impl trait defined here
28
--> $DIR/nested-tait-inference3.rs:6:13
39
|
410
LL | type FooX = impl Debug;
511
| ^^^^^^^^^^
6-
|
7-
= note: `FooX` must be used in combination with a concrete type within the same module
812

913
error: aborting due to previous error
1014

0 commit comments

Comments
 (0)