Skip to content

Commit 73090ab

Browse files
committed
Handle impl-trait-in-assoc-types separately from type-alias-impl-trait
1 parent d08b223 commit 73090ab

14 files changed

+66
-64
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl<'tcx> InferCtxt<'tcx> {
106106
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
107107
let def_id = def_id.expect_local();
108108
match self.defining_use_anchor {
109-
DefiningAnchor::Bind(_) => {
109+
DefiningAnchor::Bind { .. } => {
110110
// Check that this is `impl Trait` type is
111111
// declared by `parent_def_id` -- i.e., one whose
112112
// value we are inferring. At present, this is
@@ -373,14 +373,16 @@ impl<'tcx> InferCtxt<'tcx> {
373373
/// in its defining scope.
374374
#[instrument(skip(self), level = "trace", ret)]
375375
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
376-
let defined_opaque_types = match self.defining_use_anchor {
376+
let (rpit_and_tait, in_assoc_types) = match self.defining_use_anchor {
377377
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
378-
DefiningAnchor::Bind(bind) => bind,
378+
DefiningAnchor::Bind { rpit_and_tait, in_assoc_types } => {
379+
(rpit_and_tait, in_assoc_types)
380+
}
379381
};
380382

381383
let origin = self.tcx.opaque_type_origin(def_id);
382384

383-
defined_opaque_types.contains(&def_id).then_some(origin)
385+
(rpit_and_tait.contains(&def_id) || in_assoc_types.contains(&def_id)).then_some(origin)
384386
}
385387
}
386388

compiler/rustc_middle/src/traits/mod.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::ty::abstract_const::NotConstEvaluatable;
1515
use crate::ty::{self, AdtKind, Ty};
1616
use crate::ty::{GenericArgsRef, TyCtxt};
1717

18+
use hir::def::DefKind;
1819
use rustc_data_structures::sync::Lrc;
1920
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
2021
use rustc_hir as hir;
@@ -1004,7 +1005,7 @@ pub enum CodegenObligationError {
10041005
pub enum DefiningAnchor<'tcx> {
10051006
/// Define opaques which are in-scope of the current item being analyzed.
10061007
/// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`.
1007-
Bind(&'tcx [LocalDefId]),
1008+
Bind { rpit_and_tait: &'tcx [LocalDefId], in_assoc_types: &'tcx [LocalDefId] },
10081009
/// In contexts where we don't currently know what opaques are allowed to be
10091010
/// defined, such as (old solver) canonical queries, we will simply allow
10101011
/// opaques to be defined, but "bubble" them up in the canonical response or
@@ -1021,6 +1022,19 @@ pub enum DefiningAnchor<'tcx> {
10211022

10221023
impl<'tcx> DefiningAnchor<'tcx> {
10231024
pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
1024-
Self::Bind(tcx.opaque_types_defined_by(item))
1025+
Self::Bind {
1026+
rpit_and_tait: tcx.opaque_types_defined_by(item),
1027+
in_assoc_types: match tcx.def_kind(item) {
1028+
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy => {
1029+
let parent = tcx.local_parent(item);
1030+
if matches!(tcx.def_kind(parent), DefKind::Impl { of_trait: true }) {
1031+
tcx.impl_trait_in_assoc_types_defined_by(item)
1032+
} else {
1033+
&[]
1034+
}
1035+
}
1036+
_ => &[],
1037+
},
1038+
}
10251039
}
10261040
}

compiler/rustc_ty_utils/src/opaque_types.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,19 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
205205
t.super_visit_with(self)?;
206206
match t.kind() {
207207
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
208-
self.visit_opaque_ty(alias_ty);
208+
let mut parent = alias_ty.def_id.expect_local();
209+
// Only collect opaque types that are not impl trait in associated types
210+
loop {
211+
match self.tcx.def_kind(parent) {
212+
DefKind::OpaqueTy => {}
213+
DefKind::AssocTy => break,
214+
_ => {
215+
self.visit_opaque_ty(alias_ty);
216+
break;
217+
}
218+
}
219+
parent = self.tcx.local_parent(parent);
220+
}
209221
}
210222
// Skips type aliases, as they are meant to be transparent.
211223
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
@@ -363,7 +375,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInAssocTypeCollector<'tcx> {
363375
.instantiate(self.0.tcx, impl_args)
364376
.visit_with(self);
365377
} else {
366-
self.0.tcx.dcx().span_bug(
378+
self.0.tcx.dcx().span_delayed_bug(
367379
self.0.tcx.def_span(assoc.def_id),
368380
"item had incorrect args",
369381
);

tests/ui/generic-associated-types/issue-88595.rs

-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,4 @@ impl<'a> A<'a> for C {
2020

2121
fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
2222
//~^ ERROR: non-defining opaque type use in defining scope
23-
//~| ERROR: non-defining opaque type use in defining scope
2423
}

tests/ui/generic-associated-types/issue-88595.stderr

+1-14
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,6 @@ note: for this opaque type
1010
LL | type B<'b> = impl Clone;
1111
| ^^^^^^^^^^
1212

13-
error: non-defining opaque type use in defining scope
14-
--> $DIR/issue-88595.rs:21:23
15-
|
16-
LL | fn a(&'a self) -> Self::B<'a> {}
17-
| ^^^^^^^^^^^ generic argument `'a` used twice
18-
|
19-
note: for this opaque type
20-
--> $DIR/issue-88595.rs:19:18
21-
|
22-
LL | type B<'b> = impl Clone;
23-
| ^^^^^^^^^^
24-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25-
2613
error: non-defining opaque type use in defining scope
2714
--> $DIR/issue-88595.rs:21:35
2815
|
@@ -37,5 +24,5 @@ LL | impl<'a> A<'a> for C {
3724
LL | type B<'b> = impl Clone;
3825
| ^^
3926

40-
error: aborting due to 3 previous errors
27+
error: aborting due to 2 previous errors
4128

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Trait for Bar {
1515
type Assoc = impl std::fmt::Debug;
1616
fn foo() -> Foo {
1717
Foo { field: () }
18-
//~^ ERROR: item constrains opaque type that is not in its signature
18+
//~^ ERROR: mismatched types
1919
}
2020
}
2121

Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
error: item constrains opaque type that is not in its signature
1+
error[E0308]: mismatched types
22
--> $DIR/hidden_behind_struct_field2.rs:17:22
33
|
4+
LL | type Assoc = impl std::fmt::Debug;
5+
| -------------------- the expected opaque type
6+
LL | fn foo() -> Foo {
47
LL | Foo { field: () }
5-
| ^^
8+
| ^^ expected opaque type, found `()`
69
|
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
10+
= note: expected opaque type `<Bar as Trait>::Assoc`
11+
found unit type `()`
12+
note: this item must have the opaque type in its signature in order to be able to register hidden types
913
--> $DIR/hidden_behind_struct_field2.rs:16:8
1014
|
1115
LL | fn foo() -> Foo {
1216
| ^^^
1317

1418
error: aborting due to 1 previous error
1519

20+
For more information about this error, try `rustc --explain E0308`.

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Trait for Bar {
1717
type Assoc = impl Iterator<Item = Foo>;
1818
fn foo() -> Self::Assoc {
1919
vec![Foo { field: () }].into_iter()
20-
//~^ ERROR item constrains opaque type that is not in its signature
20+
//~^ ERROR mismatched types
2121
}
2222
}
2323

Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
error: item constrains opaque type that is not in its signature
1+
error[E0308]: mismatched types
22
--> $DIR/hidden_behind_struct_field3.rs:19:27
33
|
4+
LL | type Assoc2 = impl std::fmt::Debug;
5+
| -------------------- the expected opaque type
6+
...
47
LL | vec![Foo { field: () }].into_iter()
5-
| ^^
8+
| ^^ expected opaque type, found `()`
69
|
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
10+
= note: expected opaque type `<Bar as Trait>::Assoc2`
11+
found unit type `()`
12+
note: this item must have the opaque type in its signature in order to be able to register hidden types
913
--> $DIR/hidden_behind_struct_field3.rs:18:8
1014
|
1115
LL | fn foo() -> Self::Assoc {
1216
| ^^^
1317

1418
error: aborting due to 1 previous error
1519

20+
For more information about this error, try `rustc --explain E0308`.

tests/ui/type-alias-impl-trait/itiat-allow-nested-closures.bad.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ LL | let _: i32 = closure();
88
| --- ^^^^^^^^^ expected `i32`, found opaque type
99
| |
1010
| expected due to this
11+
|
12+
note: this item must have the opaque type in its signature in order to be able to register hidden types
13+
--> $DIR/itiat-allow-nested-closures.rs:13:8
14+
|
15+
LL | fn bar() -> Self::Assoc {
16+
| ^^^
1117

1218
error[E0308]: mismatched types
1319
--> $DIR/itiat-allow-nested-closures.rs:22:9

tests/ui/type-alias-impl-trait/multi-error.rs

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ impl Foo for () {
1616
type Baz = impl Sized;
1717
fn foo() -> (Self::Bar<u32>, Self::Baz) {
1818
//~^ ERROR non-defining opaque type use
19-
//~| ERROR non-defining opaque type use
2019
((), ())
2120
//~^ ERROR expected generic type parameter
2221
}

tests/ui/type-alias-impl-trait/multi-error.stderr

+2-15
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,15 @@ note: for this opaque type
1010
LL | type Bar<T> = impl Sized;
1111
| ^^^^^^^^^^
1212

13-
error[E0792]: non-defining opaque type use in defining scope
14-
--> $DIR/multi-error.rs:17:17
15-
|
16-
LL | fn foo() -> (Self::Bar<u32>, Self::Baz) {
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
18-
|
19-
note: for this opaque type
20-
--> $DIR/multi-error.rs:15:19
21-
|
22-
LL | type Bar<T> = impl Sized;
23-
| ^^^^^^^^^^
24-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25-
2613
error[E0792]: expected generic type parameter, found `u32`
27-
--> $DIR/multi-error.rs:20:9
14+
--> $DIR/multi-error.rs:19:9
2815
|
2916
LL | type Bar<T> = impl Sized;
3017
| - this generic parameter must be used with a generic type parameter
3118
...
3219
LL | ((), ())
3320
| ^^^^^^^^
3421

35-
error: aborting due to 3 previous errors
22+
error: aborting due to 2 previous errors
3623

3724
For more information about this error, try `rustc --explain E0792`.

tests/ui/type-alias-impl-trait/non-defining-method.rs

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ impl Foo for () {
1515
type Bar<T> = impl Sized;
1616
fn foo() -> Self::Bar<u32> {}
1717
//~^ ERROR non-defining opaque type use
18-
//~| ERROR non-defining opaque type use
1918
//~| ERROR expected generic type parameter, found `u32`
2019
fn bar<T>() -> Self::Bar<T> {}
2120
}

tests/ui/type-alias-impl-trait/non-defining-method.stderr

+1-14
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,6 @@ note: for this opaque type
1010
LL | type Bar<T> = impl Sized;
1111
| ^^^^^^^^^^
1212

13-
error[E0792]: non-defining opaque type use in defining scope
14-
--> $DIR/non-defining-method.rs:16:17
15-
|
16-
LL | fn foo() -> Self::Bar<u32> {}
17-
| ^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
18-
|
19-
note: for this opaque type
20-
--> $DIR/non-defining-method.rs:15:19
21-
|
22-
LL | type Bar<T> = impl Sized;
23-
| ^^^^^^^^^^
24-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25-
2613
error[E0792]: expected generic type parameter, found `u32`
2714
--> $DIR/non-defining-method.rs:16:32
2815
|
@@ -31,6 +18,6 @@ LL | type Bar<T> = impl Sized;
3118
LL | fn foo() -> Self::Bar<u32> {}
3219
| ^^
3320

34-
error: aborting due to 3 previous errors
21+
error: aborting due to 2 previous errors
3522

3623
For more information about this error, try `rustc --explain E0792`.

0 commit comments

Comments
 (0)