Skip to content

Commit 8e6bf3c

Browse files
authored
Unrolled build for rust-lang#121838
Rollup merge of rust-lang#121838 - oli-obk:impl_trait_in_assoc_tys_fix, r=compiler-errors Use the correct logic for nested impl trait in assoc types Previously we accidentally continued with the TAIT visitor, which allowed more than we wanted to. r? ```@compiler-errors```
2 parents 5a1e544 + 8364a06 commit 8e6bf3c

File tree

3 files changed

+61
-81
lines changed

3 files changed

+61
-81
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//! This test demonstrates a bug where we accidentally
2+
//! detected opaque types in struct fields, but only if nested
3+
//! in projections of another opaque type.
4+
5+
#![feature(impl_trait_in_assoc_type)]
6+
7+
struct Bar;
8+
9+
trait Trait: Sized {
10+
type Assoc2;
11+
type Assoc;
12+
fn foo() -> Self::Assoc;
13+
}
14+
15+
impl Trait for Bar {
16+
type Assoc2 = impl std::fmt::Debug;
17+
type Assoc = impl Iterator<Item = Foo>;
18+
fn foo() -> Self::Assoc {
19+
vec![Foo { field: () }].into_iter()
20+
//~^ ERROR item constrains opaque type that is not in its signature
21+
}
22+
}
23+
24+
struct Foo {
25+
field: <Bar as Trait>::Assoc2,
26+
}
27+
28+
fn main() {}
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)