diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index f0e998b7a0032..dcb01a117b047 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -46,9 +46,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( for &assoc_id in tcx.associated_item_def_ids(impl_def_id) { let assoc = tcx.associated_item(assoc_id); match assoc.kind { - ty::AssocKind::Const | ty::AssocKind::Fn => { - locator.check(assoc_id.expect_local(), ImplTraitSource::AssocTy) - } + ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()), // Associated types don't have bodies, so they can't constrain hidden types ty::AssocKind::Type => {} } @@ -182,15 +180,9 @@ struct TaitConstraintLocator<'tcx> { typeck_types: Vec>, } -#[derive(Debug)] -enum ImplTraitSource { - AssocTy, - TyAlias, -} - impl TaitConstraintLocator<'_> { #[instrument(skip(self), level = "debug")] - fn check(&mut self, item_def_id: LocalDefId, source: ImplTraitSource) { + fn check(&mut self, item_def_id: LocalDefId) { // Don't try to check items that cannot possibly constrain the type. if !self.tcx.has_typeck_results(item_def_id) { debug!("no constraint: no typeck results"); @@ -242,12 +234,8 @@ impl TaitConstraintLocator<'_> { continue; } constrained = true; - let opaque_types_defined_by = match source { - ImplTraitSource::AssocTy => { - self.tcx.impl_trait_in_assoc_types_defined_by(item_def_id) - } - ImplTraitSource::TyAlias => self.tcx.opaque_types_defined_by(item_def_id), - }; + let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id); + if !opaque_types_defined_by.contains(&self.def_id) { self.tcx.dcx().emit_err(TaitForwardCompat { span: hidden_type.span, @@ -308,7 +296,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id, ImplTraitSource::TyAlias); + self.check(closure.def_id); } intravisit::walk_expr(self, ex); } @@ -316,7 +304,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. if it.owner_id.def_id != self.def_id { - self.check(it.owner_id.def_id, ImplTraitSource::TyAlias); + self.check(it.owner_id.def_id); intravisit::walk_item(self, it); } } @@ -324,13 +312,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. if it.owner_id.def_id != self.def_id { - self.check(it.owner_id.def_id, ImplTraitSource::TyAlias); + self.check(it.owner_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { trace!(?it.owner_id); - self.check(it.owner_id.def_id, ImplTraitSource::TyAlias); + self.check(it.owner_id.def_id); intravisit::walk_trait_item(self, it); } fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8357c21a3c2be..b0431ae05d395 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -344,15 +344,6 @@ rustc_queries! { } } - query impl_trait_in_assoc_types_defined_by( - key: LocalDefId - ) -> &'tcx ty::List { - desc { - |tcx| "computing the opaque types defined by `{}`", - tcx.def_path_str(key.to_def_id()) - } - } - /// Returns the list of bounds that can be used for /// `SelectionCandidate::ProjectionCandidate(_)` and /// `ProjectionTyCandidate::TraitDef`. diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index aaf968cbb7587..c6448b4f661d7 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -33,7 +33,11 @@ enum CollectionMode { } impl<'tcx> OpaqueTypeCollector<'tcx> { - fn new(tcx: TyCtxt<'tcx>, item: LocalDefId, mode: CollectionMode) -> Self { + fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { + let mode = match tcx.def_kind(tcx.local_parent(item)) { + DefKind::Impl { of_trait: true } => CollectionMode::ImplTraitInAssocTypes, + _ => CollectionMode::TypeAliasImplTraitTransition, + }; Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode } } @@ -284,23 +288,13 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } } -fn impl_trait_in_assoc_types_defined_by<'tcx>( - tcx: TyCtxt<'tcx>, - item: LocalDefId, -) -> &'tcx ty::List { - let mut collector = OpaqueTypeCollector::new(tcx, item, CollectionMode::ImplTraitInAssocTypes); - super::sig_types::walk_types(tcx, item, &mut collector); - tcx.mk_local_def_ids(&collector.opaques) -} - fn opaque_types_defined_by<'tcx>( tcx: TyCtxt<'tcx>, item: LocalDefId, ) -> &'tcx ty::List { let kind = tcx.def_kind(item); trace!(?kind); - let mut collector = - OpaqueTypeCollector::new(tcx, item, CollectionMode::TypeAliasImplTraitTransition); + let mut collector = OpaqueTypeCollector::new(tcx, item); super::sig_types::walk_types(tcx, item, &mut collector); match kind { DefKind::AssocFn @@ -343,6 +337,5 @@ fn opaque_types_defined_by<'tcx>( } pub(super) fn provide(providers: &mut Providers) { - *providers = - Providers { opaque_types_defined_by, impl_trait_in_assoc_types_defined_by, ..*providers }; + *providers = Providers { opaque_types_defined_by, ..*providers }; } diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs index 4c881dd133086..3117060cef0d2 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs @@ -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 } } diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr index 5c53dfa3a7500..4910e794e8d6e 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr @@ -1,11 +1,15 @@ -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 `::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 { @@ -13,3 +17,4 @@ LL | fn foo() -> Foo { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs index 1278563a92c46..c1f135994121e 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs @@ -17,7 +17,7 @@ impl Trait for Bar { type Assoc = impl Iterator; fn foo() -> Self::Assoc { vec![Foo { field: () }].into_iter() - //~^ ERROR item constrains opaque type that is not in its signature + //~^ ERROR mismatched types } } diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr index 0570e0303c633..f10ccc0029973 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr @@ -1,11 +1,15 @@ -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 `::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 { @@ -13,3 +17,4 @@ LL | fn foo() -> Self::Assoc { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0308`.