Skip to content

Commit 8364a06

Browse files
committed
Merge the impl trait in assoc type collector into the opaque type collector and use a runtime switch instead
1 parent f5f11e1 commit 8364a06

File tree

3 files changed

+34
-82
lines changed

3 files changed

+34
-82
lines changed

compiler/rustc_ty_utils/src/opaque_types.rs

+18-81
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,20 @@ struct OpaqueTypeCollector<'tcx> {
2222
seen: FxHashSet<LocalDefId>,
2323

2424
span: Option<Span>,
25+
26+
mode: CollectionMode,
27+
}
28+
29+
enum CollectionMode {
30+
/// For impl trait in assoc types we only permit collecting them from
31+
/// associated types of the same impl block.
32+
ImplTraitInAssocTypes,
33+
TypeAliasImplTraitTransition,
2534
}
2635

2736
impl<'tcx> OpaqueTypeCollector<'tcx> {
28-
fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
29-
Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
37+
fn new(tcx: TyCtxt<'tcx>, item: LocalDefId, mode: CollectionMode) -> Self {
38+
Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode }
3039
}
3140

3241
fn span(&self) -> Span {
@@ -251,6 +260,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
251260
}
252261
}
253262
ty::Adt(def, _) if def.did().is_local() => {
263+
if let CollectionMode::ImplTraitInAssocTypes = self.mode {
264+
return ControlFlow::Continue(());
265+
}
254266
if !self.seen.insert(def.did().expect_local()) {
255267
return ControlFlow::Continue(());
256268
}
@@ -275,89 +287,13 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
275287
}
276288
}
277289

278-
struct ImplTraitInAssocTypeCollector<'tcx>(OpaqueTypeCollector<'tcx>);
279-
280-
impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> {
281-
#[instrument(skip(self), ret, level = "trace")]
282-
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
283-
let old = self.0.span;
284-
self.0.span = Some(span);
285-
value.visit_with(self);
286-
self.0.span = old;
287-
288-
ControlFlow::Continue(())
289-
}
290-
}
291-
292-
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInAssocTypeCollector<'tcx> {
293-
#[instrument(skip(self), ret, level = "trace")]
294-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
295-
t.super_visit_with(self)?;
296-
match t.kind() {
297-
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
298-
self.0.visit_opaque_ty(alias_ty);
299-
}
300-
ty::Alias(ty::Projection, alias_ty) => {
301-
// This avoids having to do normalization of `Self::AssocTy` by only
302-
// supporting the case of a method defining opaque types from assoc types
303-
// in the same impl block.
304-
let parent_trait_ref = self
305-
.0
306-
.parent_trait_ref()
307-
.expect("impl trait in assoc type collector used on non-assoc item");
308-
// If the trait ref of the associated item and the impl differs,
309-
// then we can't use the impl's identity args below, so
310-
// just skip.
311-
if alias_ty.trait_ref(self.0.tcx) == parent_trait_ref {
312-
let parent = self.0.parent().expect("we should have a parent here");
313-
314-
for &assoc in self.0.tcx.associated_items(parent).in_definition_order() {
315-
trace!(?assoc);
316-
if assoc.trait_item_def_id != Some(alias_ty.def_id) {
317-
continue;
318-
}
319-
320-
// If the type is further specializable, then the type_of
321-
// is not actually correct below.
322-
if !assoc.defaultness(self.0.tcx).is_final() {
323-
continue;
324-
}
325-
326-
let impl_args = alias_ty.args.rebase_onto(
327-
self.0.tcx,
328-
parent_trait_ref.def_id,
329-
ty::GenericArgs::identity_for_item(self.0.tcx, parent),
330-
);
331-
332-
if check_args_compatible(self.0.tcx, assoc, impl_args) {
333-
return self
334-
.0
335-
.tcx
336-
.type_of(assoc.def_id)
337-
.instantiate(self.0.tcx, impl_args)
338-
.visit_with(self);
339-
} else {
340-
self.0.tcx.dcx().span_bug(
341-
self.0.tcx.def_span(assoc.def_id),
342-
"item had incorrect args",
343-
);
344-
}
345-
}
346-
}
347-
}
348-
_ => trace!(kind=?t.kind()),
349-
}
350-
ControlFlow::Continue(())
351-
}
352-
}
353-
354290
fn impl_trait_in_assoc_types_defined_by<'tcx>(
355291
tcx: TyCtxt<'tcx>,
356292
item: LocalDefId,
357293
) -> &'tcx ty::List<LocalDefId> {
358-
let mut collector = ImplTraitInAssocTypeCollector(OpaqueTypeCollector::new(tcx, item));
294+
let mut collector = OpaqueTypeCollector::new(tcx, item, CollectionMode::ImplTraitInAssocTypes);
359295
super::sig_types::walk_types(tcx, item, &mut collector);
360-
tcx.mk_local_def_ids(&collector.0.opaques)
296+
tcx.mk_local_def_ids(&collector.opaques)
361297
}
362298

363299
fn opaque_types_defined_by<'tcx>(
@@ -366,7 +302,8 @@ fn opaque_types_defined_by<'tcx>(
366302
) -> &'tcx ty::List<LocalDefId> {
367303
let kind = tcx.def_kind(item);
368304
trace!(?kind);
369-
let mut collector = OpaqueTypeCollector::new(tcx, item);
305+
let mut collector =
306+
OpaqueTypeCollector::new(tcx, item, CollectionMode::TypeAliasImplTraitTransition);
370307
super::sig_types::walk_types(tcx, item, &mut collector);
371308
match kind {
372309
DefKind::AssocFn

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)