Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2752e32

Browse files
committed
Allow opaque types in trait impl headers and rely on coherence to reject unsound cases
1 parent 7fe6f36 commit 2752e32

35 files changed

+224
-229
lines changed

compiler/rustc_hir_analysis/src/coherence/orphan.rs

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet;
55
use rustc_errors::{struct_span_err, DelayDm};
66
use rustc_errors::{Diagnostic, ErrorGuaranteed};
77
use rustc_hir as hir;
8-
use rustc_middle::ty::subst::GenericArgKind;
98
use rustc_middle::ty::subst::InternalSubsts;
109
use rustc_middle::ty::util::IgnoreRegions;
1110
use rustc_middle::ty::{
@@ -47,58 +46,6 @@ fn do_orphan_check_impl<'tcx>(
4746
let sp = tcx.def_span(def_id);
4847
let tr = impl_.of_trait.as_ref().unwrap();
4948

50-
// Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
51-
// and #84660 where it would otherwise allow unsoundness.
52-
if trait_ref.has_opaque_types() {
53-
trace!("{:#?}", item);
54-
// First we find the opaque type in question.
55-
for ty in trait_ref.substs {
56-
for ty in ty.walk() {
57-
let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
58-
let ty::Opaque(def_id, _) = *ty.kind() else { continue };
59-
trace!(?def_id);
60-
61-
// Then we search for mentions of the opaque type's type alias in the HIR
62-
struct SpanFinder<'tcx> {
63-
sp: Span,
64-
def_id: DefId,
65-
tcx: TyCtxt<'tcx>,
66-
}
67-
impl<'v, 'tcx> hir::intravisit::Visitor<'v> for SpanFinder<'tcx> {
68-
#[instrument(level = "trace", skip(self, _id))]
69-
fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
70-
// You can't mention an opaque type directly, so we look for type aliases
71-
if let hir::def::Res::Def(hir::def::DefKind::TyAlias, def_id) = path.res {
72-
// And check if that type alias's type contains the opaque type we're looking for
73-
for arg in self.tcx.type_of(def_id).walk() {
74-
if let GenericArgKind::Type(ty) = arg.unpack() {
75-
if let ty::Opaque(def_id, _) = *ty.kind() {
76-
if def_id == self.def_id {
77-
// Finally we update the span to the mention of the type alias
78-
self.sp = path.span;
79-
return;
80-
}
81-
}
82-
}
83-
}
84-
}
85-
hir::intravisit::walk_path(self, path)
86-
}
87-
}
88-
89-
let mut visitor = SpanFinder { sp, def_id, tcx };
90-
hir::intravisit::walk_item(&mut visitor, item);
91-
let reported = tcx
92-
.sess
93-
.struct_span_err(visitor.sp, "cannot implement trait on type alias impl trait")
94-
.span_note(tcx.def_span(def_id), "type alias impl trait defined here")
95-
.emit();
96-
return Err(reported);
97-
}
98-
}
99-
span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
100-
}
101-
10249
match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
10350
Ok(()) => {}
10451
Err(err) => emit_orphan_check_error(

compiler/rustc_middle/src/ty/fast_reject.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ where
4242
ClosureSimplifiedType(D),
4343
GeneratorSimplifiedType(D),
4444
GeneratorWitnessSimplifiedType(usize),
45-
OpaqueSimplifiedType(D),
4645
FunctionSimplifiedType(usize),
4746
PlaceholderSimplifiedType,
4847
}
@@ -127,7 +126,7 @@ pub fn simplify_type<'tcx>(
127126
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
128127
TreatParams::AsInfer => None,
129128
},
130-
ty::Projection(_) => match treat_params {
129+
ty::Opaque(..) | ty::Projection(_) => match treat_params {
131130
// When treating `ty::Param` as a placeholder, projections also
132131
// don't unify with anything else as long as they are fully normalized.
133132
//
@@ -138,7 +137,6 @@ pub fn simplify_type<'tcx>(
138137
}
139138
TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
140139
},
141-
ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
142140
ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
143141
ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
144142
}
@@ -151,8 +149,7 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
151149
| ForeignSimplifiedType(d)
152150
| TraitSimplifiedType(d)
153151
| ClosureSimplifiedType(d)
154-
| GeneratorSimplifiedType(d)
155-
| OpaqueSimplifiedType(d) => Some(d),
152+
| GeneratorSimplifiedType(d) => Some(d),
156153
_ => None,
157154
}
158155
}
@@ -182,7 +179,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
182179
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
183180
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
184181
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
185-
OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
186182
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
187183
PlaceholderSimplifiedType => PlaceholderSimplifiedType,
188184
}
@@ -229,7 +225,7 @@ impl DeepRejectCtxt {
229225
match impl_ty.kind() {
230226
// Start by checking whether the type in the impl may unify with
231227
// pretty much everything. Just return `true` in that case.
232-
ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
228+
ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
233229
// These types only unify with inference variables or their own
234230
// variant.
235231
ty::Bool
@@ -247,8 +243,7 @@ impl DeepRejectCtxt {
247243
| ty::Never
248244
| ty::Tuple(..)
249245
| ty::FnPtr(..)
250-
| ty::Foreign(..)
251-
| ty::Opaque(..) => {}
246+
| ty::Foreign(..) => {}
252247
ty::FnDef(..)
253248
| ty::Closure(..)
254249
| ty::Generator(..)
@@ -328,10 +323,7 @@ impl DeepRejectCtxt {
328323
_ => false,
329324
},
330325

331-
// Opaque types in impls should be forbidden, but that doesn't
332-
// stop compilation. So this match arm should never return true
333-
// if compilation succeeds.
334-
ty::Opaque(..) => matches!(k, ty::Opaque(..)),
326+
ty::Opaque(..) => true,
335327

336328
// Impls cannot contain these types as these cannot be named directly.
337329
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxIndexSet;
1818
use rustc_errors::Diagnostic;
1919
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
2020
use rustc_hir::CRATE_HIR_ID;
21-
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
21+
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
2222
use rustc_infer::traits::util;
2323
use rustc_middle::traits::specialization_graph::OverlapMode;
2424
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@@ -94,7 +94,7 @@ pub fn overlapping_impls<'tcx>(
9494
return None;
9595
}
9696

97-
let infcx = tcx.infer_ctxt().build();
97+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
9898
let selcx = &mut SelectionContext::intercrate(&infcx);
9999
let overlaps =
100100
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
@@ -105,7 +105,7 @@ pub fn overlapping_impls<'tcx>(
105105
// In the case where we detect an error, run the check again, but
106106
// this time tracking intercrate ambiguity causes for better
107107
// diagnostics. (These take time and can lead to false errors.)
108-
let infcx = tcx.infer_ctxt().build();
108+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
109109
let selcx = &mut SelectionContext::intercrate(&infcx);
110110
selcx.enable_tracking_intercrate_ambiguity_causes();
111111
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())

src/test/ui/coherence/coherence-with-closure.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ fn defining_use() -> OpaqueClosure {
88
struct Wrapper<T>(T);
99
trait Trait {}
1010
impl Trait for Wrapper<OpaqueClosure> {}
11-
//~^ ERROR cannot implement trait on type alias impl trait
1211
impl<T: Sync> Trait for Wrapper<T> {}
1312
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
1413

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
11
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
2-
--> $DIR/coherence-with-closure.rs:12:1
2+
--> $DIR/coherence-with-closure.rs:11:1
33
|
44
LL | impl Trait for Wrapper<OpaqueClosure> {}
55
| ------------------------------------- first implementation here
6-
LL |
76
LL | impl<T: Sync> Trait for Wrapper<T> {}
87
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
98

10-
error: cannot implement trait on type alias impl trait
11-
--> $DIR/coherence-with-closure.rs:10:24
12-
|
13-
LL | impl Trait for Wrapper<OpaqueClosure> {}
14-
| ^^^^^^^^^^^^^
15-
|
16-
note: type alias impl trait defined here
17-
--> $DIR/coherence-with-closure.rs:3:22
18-
|
19-
LL | type OpaqueClosure = impl Sized;
20-
| ^^^^^^^^^^
21-
22-
error: aborting due to 2 previous errors
9+
error: aborting due to previous error
2310

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

src/test/ui/coherence/coherence-with-generator.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ fn defining_use() -> OpaqueGenerator {
1212
struct Wrapper<T>(T);
1313
trait Trait {}
1414
impl Trait for Wrapper<OpaqueGenerator> {}
15-
//~^ ERROR cannot implement trait on type alias impl trait
1615
impl<T: Sync> Trait for Wrapper<T> {}
1716
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
1817

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
11
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
2-
--> $DIR/coherence-with-generator.rs:16:1
2+
--> $DIR/coherence-with-generator.rs:15:1
33
|
44
LL | impl Trait for Wrapper<OpaqueGenerator> {}
55
| --------------------------------------- first implementation here
6-
LL |
76
LL | impl<T: Sync> Trait for Wrapper<T> {}
87
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
98

10-
error: cannot implement trait on type alias impl trait
11-
--> $DIR/coherence-with-generator.rs:14:24
12-
|
13-
LL | impl Trait for Wrapper<OpaqueGenerator> {}
14-
| ^^^^^^^^^^^^^^^
15-
|
16-
note: type alias impl trait defined here
17-
--> $DIR/coherence-with-generator.rs:3:24
18-
|
19-
LL | type OpaqueGenerator = impl Sized;
20-
| ^^^^^^^^^^
21-
22-
error: aborting due to 2 previous errors
9+
error: aborting due to previous error
2310

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

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ 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
2423
}
2524

2625
fn main() {}

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

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,6 @@ LL | impl<T: Send> AnotherTrait for T {}
77
LL | impl AnotherTrait for D<OpaqueType> {
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
99

10-
error: cannot implement trait on type alias impl trait
11-
--> $DIR/auto-trait.rs:21:25
12-
|
13-
LL | impl AnotherTrait for D<OpaqueType> {
14-
| ^^^^^^^^^^
15-
|
16-
note: type alias impl trait defined here
17-
--> $DIR/auto-trait.rs:7:19
18-
|
19-
LL | type OpaqueType = impl OpaqueTrait;
20-
| ^^^^^^^^^^^^^^^^
21-
22-
error: aborting due to 2 previous errors
10+
error: aborting due to previous error
2311

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

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ 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
2221
}
2322

2423
fn main() {}

0 commit comments

Comments
 (0)