Skip to content

Commit

Permalink
Handle impl-trait-in-assoc-types separately from type-alias-impl-trait
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Mar 1, 2024
1 parent d08b223 commit 73090ab
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 64 deletions.
10 changes: 6 additions & 4 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl<'tcx> InferCtxt<'tcx> {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local();
match self.defining_use_anchor {
DefiningAnchor::Bind(_) => {
DefiningAnchor::Bind { .. } => {
// Check that this is `impl Trait` type is
// declared by `parent_def_id` -- i.e., one whose
// value we are inferring. At present, this is
Expand Down Expand Up @@ -373,14 +373,16 @@ impl<'tcx> InferCtxt<'tcx> {
/// in its defining scope.
#[instrument(skip(self), level = "trace", ret)]
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
let defined_opaque_types = match self.defining_use_anchor {
let (rpit_and_tait, in_assoc_types) = match self.defining_use_anchor {
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
DefiningAnchor::Bind(bind) => bind,
DefiningAnchor::Bind { rpit_and_tait, in_assoc_types } => {
(rpit_and_tait, in_assoc_types)
}
};

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

defined_opaque_types.contains(&def_id).then_some(origin)
(rpit_and_tait.contains(&def_id) || in_assoc_types.contains(&def_id)).then_some(origin)
}
}

Expand Down
18 changes: 16 additions & 2 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::ty::abstract_const::NotConstEvaluatable;
use crate::ty::{self, AdtKind, Ty};
use crate::ty::{GenericArgsRef, TyCtxt};

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

impl<'tcx> DefiningAnchor<'tcx> {
pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
Self::Bind(tcx.opaque_types_defined_by(item))
Self::Bind {
rpit_and_tait: tcx.opaque_types_defined_by(item),
in_assoc_types: match tcx.def_kind(item) {
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy => {
let parent = tcx.local_parent(item);
if matches!(tcx.def_kind(parent), DefKind::Impl { of_trait: true }) {
tcx.impl_trait_in_assoc_types_defined_by(item)
} else {
&[]
}
}
_ => &[],
},
}
}
}
16 changes: 14 additions & 2 deletions compiler/rustc_ty_utils/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,19 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
t.super_visit_with(self)?;
match t.kind() {
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
self.visit_opaque_ty(alias_ty);
let mut parent = alias_ty.def_id.expect_local();
// Only collect opaque types that are not impl trait in associated types
loop {
match self.tcx.def_kind(parent) {
DefKind::OpaqueTy => {}
DefKind::AssocTy => break,
_ => {
self.visit_opaque_ty(alias_ty);
break;
}
}
parent = self.tcx.local_parent(parent);
}
}
// Skips type aliases, as they are meant to be transparent.
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
Expand Down Expand Up @@ -363,7 +375,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInAssocTypeCollector<'tcx> {
.instantiate(self.0.tcx, impl_args)
.visit_with(self);
} else {
self.0.tcx.dcx().span_bug(
self.0.tcx.dcx().span_delayed_bug(
self.0.tcx.def_span(assoc.def_id),
"item had incorrect args",
);
Expand Down
1 change: 0 additions & 1 deletion tests/ui/generic-associated-types/issue-88595.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ impl<'a> A<'a> for C {

fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
//~^ ERROR: non-defining opaque type use in defining scope
//~| ERROR: non-defining opaque type use in defining scope
}
15 changes: 1 addition & 14 deletions tests/ui/generic-associated-types/issue-88595.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,6 @@ note: for this opaque type
LL | type B<'b> = impl Clone;
| ^^^^^^^^^^

error: non-defining opaque type use in defining scope
--> $DIR/issue-88595.rs:21:23
|
LL | fn a(&'a self) -> Self::B<'a> {}
| ^^^^^^^^^^^ generic argument `'a` used twice
|
note: for this opaque type
--> $DIR/issue-88595.rs:19:18
|
LL | type B<'b> = impl Clone;
| ^^^^^^^^^^
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: non-defining opaque type use in defining scope
--> $DIR/issue-88595.rs:21:35
|
Expand All @@ -37,5 +24,5 @@ LL | impl<'a> A<'a> for C {
LL | type B<'b> = impl Clone;
| ^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Trait for Bar {
type Assoc = impl std::fmt::Debug;
fn foo() -> Foo {
Foo { field: () }
//~^ ERROR: item constrains opaque type that is not in its signature
//~^ ERROR: mismatched types
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
error: item constrains opaque type that is not in its signature
error[E0308]: mismatched types
--> $DIR/hidden_behind_struct_field2.rs:17:22
|
LL | type Assoc = impl std::fmt::Debug;
| -------------------- the expected opaque type
LL | fn foo() -> Foo {
LL | Foo { field: () }
| ^^
| ^^ expected opaque type, found `()`
|
= note: this item must mention the opaque type in its signature in order to be able to register hidden types
note: this item must mention the opaque type in its signature in order to be able to register hidden types
= note: expected opaque type `<Bar as Trait>::Assoc`
found unit type `()`
note: this item must have the opaque type in its signature in order to be able to register hidden types
--> $DIR/hidden_behind_struct_field2.rs:16:8
|
LL | fn foo() -> Foo {
| ^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Trait for Bar {
type Assoc = impl Iterator<Item = Foo>;
fn foo() -> Self::Assoc {
vec![Foo { field: () }].into_iter()
//~^ ERROR item constrains opaque type that is not in its signature
//~^ ERROR mismatched types
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
error: item constrains opaque type that is not in its signature
error[E0308]: mismatched types
--> $DIR/hidden_behind_struct_field3.rs:19:27
|
LL | type Assoc2 = impl std::fmt::Debug;
| -------------------- the expected opaque type
...
LL | vec![Foo { field: () }].into_iter()
| ^^
| ^^ expected opaque type, found `()`
|
= note: this item must mention the opaque type in its signature in order to be able to register hidden types
note: this item must mention the opaque type in its signature in order to be able to register hidden types
= note: expected opaque type `<Bar as Trait>::Assoc2`
found unit type `()`
note: this item must have the opaque type in its signature in order to be able to register hidden types
--> $DIR/hidden_behind_struct_field3.rs:18:8
|
LL | fn foo() -> Self::Assoc {
| ^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ LL | let _: i32 = closure();
| --- ^^^^^^^^^ expected `i32`, found opaque type
| |
| expected due to this
|
note: this item must have the opaque type in its signature in order to be able to register hidden types
--> $DIR/itiat-allow-nested-closures.rs:13:8
|
LL | fn bar() -> Self::Assoc {
| ^^^

error[E0308]: mismatched types
--> $DIR/itiat-allow-nested-closures.rs:22:9
Expand Down
1 change: 0 additions & 1 deletion tests/ui/type-alias-impl-trait/multi-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ impl Foo for () {
type Baz = impl Sized;
fn foo() -> (Self::Bar<u32>, Self::Baz) {
//~^ ERROR non-defining opaque type use
//~| ERROR non-defining opaque type use
((), ())
//~^ ERROR expected generic type parameter
}
Expand Down
17 changes: 2 additions & 15 deletions tests/ui/type-alias-impl-trait/multi-error.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,15 @@ note: for this opaque type
LL | type Bar<T> = impl Sized;
| ^^^^^^^^^^

error[E0792]: non-defining opaque type use in defining scope
--> $DIR/multi-error.rs:17:17
|
LL | fn foo() -> (Self::Bar<u32>, Self::Baz) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
|
note: for this opaque type
--> $DIR/multi-error.rs:15:19
|
LL | type Bar<T> = impl Sized;
| ^^^^^^^^^^
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0792]: expected generic type parameter, found `u32`
--> $DIR/multi-error.rs:20:9
--> $DIR/multi-error.rs:19:9
|
LL | type Bar<T> = impl Sized;
| - this generic parameter must be used with a generic type parameter
...
LL | ((), ())
| ^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0792`.
1 change: 0 additions & 1 deletion tests/ui/type-alias-impl-trait/non-defining-method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ impl Foo for () {
type Bar<T> = impl Sized;
fn foo() -> Self::Bar<u32> {}
//~^ ERROR non-defining opaque type use
//~| ERROR non-defining opaque type use
//~| ERROR expected generic type parameter, found `u32`
fn bar<T>() -> Self::Bar<T> {}
}
Expand Down
15 changes: 1 addition & 14 deletions tests/ui/type-alias-impl-trait/non-defining-method.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,6 @@ note: for this opaque type
LL | type Bar<T> = impl Sized;
| ^^^^^^^^^^

error[E0792]: non-defining opaque type use in defining scope
--> $DIR/non-defining-method.rs:16:17
|
LL | fn foo() -> Self::Bar<u32> {}
| ^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
|
note: for this opaque type
--> $DIR/non-defining-method.rs:15:19
|
LL | type Bar<T> = impl Sized;
| ^^^^^^^^^^
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0792]: expected generic type parameter, found `u32`
--> $DIR/non-defining-method.rs:16:32
|
Expand All @@ -31,6 +18,6 @@ LL | type Bar<T> = impl Sized;
LL | fn foo() -> Self::Bar<u32> {}
| ^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

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

0 comments on commit 73090ab

Please sign in to comment.