Skip to content

Commit 06ab841

Browse files
committed
Walk into the right visitor when looking at projections of opaque types
1 parent 802df56 commit 06ab841

File tree

3 files changed

+40
-9
lines changed

3 files changed

+40
-9
lines changed

compiler/rustc_ty_utils/src/opaque_types.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,17 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
112112
}
113113
TaitInBodyFinder { collector: self }.visit_expr(body);
114114
}
115+
}
115116

117+
/// A helper trait that ensures that we can recurse with the right TypeVisitor
118+
/// when looking at projections on the opaque type's bounds.
119+
trait OpaqueFinderVisitor<'tcx>: SpannedTypeVisitor<'tcx> {
120+
fn collector(&mut self) -> &mut OpaqueTypeCollector<'tcx>;
116121
fn visit_opaque_ty(&mut self, alias_ty: &ty::AliasTy<'tcx>) {
117-
if !self.seen.insert(alias_ty.def_id.expect_local()) {
122+
if !self.collector().seen.insert(alias_ty.def_id.expect_local()) {
118123
return;
119124
}
120-
121-
let tcx = self.tcx;
125+
let tcx = self.collector().tcx;
122126

123127
// TAITs outside their defining scopes are ignored.
124128
let origin = tcx.opaque_type_origin(alias_ty.def_id.expect_local());
@@ -127,14 +131,14 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
127131
rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
128132
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
129133
if !in_assoc_ty {
130-
if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
134+
if !self.collector().check_tait_defining_scope(alias_ty.def_id.expect_local()) {
131135
return;
132136
}
133137
}
134138
}
135139
}
136140

137-
self.opaques.push(alias_ty.def_id.expect_local());
141+
self.collector().opaques.push(alias_ty.def_id.expect_local());
138142

139143
let parent_count = tcx.generics_of(alias_ty.def_id).parent_count;
140144
// Only check that the parent generics of the TAIT/RPIT are unique.
@@ -161,21 +165,27 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
161165
Err(NotUniqueParam::NotParam(arg)) => {
162166
tcx.dcx().emit_err(NotParam {
163167
arg,
164-
span: self.span(),
168+
span: self.collector().span(),
165169
opaque_span: tcx.def_span(alias_ty.def_id),
166170
});
167171
}
168172
Err(NotUniqueParam::DuplicateParam(arg)) => {
169173
tcx.dcx().emit_err(DuplicateArg {
170174
arg,
171-
span: self.span(),
175+
span: self.collector().span(),
172176
opaque_span: tcx.def_span(alias_ty.def_id),
173177
});
174178
}
175179
}
176180
}
177181
}
178182

183+
impl<'tcx> OpaqueFinderVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
184+
fn collector(&mut self) -> &mut OpaqueTypeCollector<'tcx> {
185+
self
186+
}
187+
}
188+
179189
impl<'tcx> SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
180190
#[instrument(skip(self), ret, level = "trace")]
181191
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
@@ -273,6 +283,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
273283

274284
struct ImplTraitInAssocTypeCollector<'tcx>(OpaqueTypeCollector<'tcx>);
275285

286+
impl<'tcx> OpaqueFinderVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> {
287+
fn collector(&mut self) -> &mut OpaqueTypeCollector<'tcx> {
288+
&mut self.0
289+
}
290+
}
291+
276292
impl<'tcx> SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> {
277293
#[instrument(skip(self), ret, level = "trace")]
278294
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
@@ -291,7 +307,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInAssocTypeCollector<'tcx> {
291307
t.super_visit_with(self)?;
292308
match t.kind() {
293309
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
294-
self.0.visit_opaque_ty(alias_ty);
310+
self.visit_opaque_ty(alias_ty);
295311
}
296312
ty::Alias(ty::Projection, alias_ty) => {
297313
// This avoids having to do normalization of `Self::AssocTy` by only

tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! This test demonstrates a bug where we accidentally
22
//! detected opaque types in struct fields, but only if nested
33
//! in projections of another opaque type.
4-
//@ check-pass
54
65
#![feature(impl_trait_in_assoc_type)]
76

@@ -18,6 +17,7 @@ impl Trait for Bar {
1817
type Assoc = impl Iterator<Item = Foo>;
1918
fn foo() -> Self::Assoc {
2019
vec![Foo { field: () }].into_iter()
20+
//~^ ERROR item constrains opaque type that is not in its signature
2121
}
2222
}
2323

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: item constrains opaque type that is not in its signature
2+
--> $DIR/hidden_behind_struct_field3.rs:19:27
3+
|
4+
LL | vec![Foo { field: () }].into_iter()
5+
| ^^
6+
|
7+
= note: this item must mention the opaque type in its signature in order to be able to register hidden types
8+
note: this item must mention the opaque type in its signature in order to be able to register hidden types
9+
--> $DIR/hidden_behind_struct_field3.rs:18:8
10+
|
11+
LL | fn foo() -> Self::Assoc {
12+
| ^^^
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)