about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-23 23:26:38 +0000
committerbors <bors@rust-lang.org>2023-06-23 23:26:38 +0000
commit1d67eba6873b1d551a259a0bbc1e2651b4443e12 (patch)
tree20a9937507ccd051ee0011e8b138eae2af9ba7a3
parent22e9fe644ea710eec50cb0aabcae7fa8dd9fd675 (diff)
parent27b386ad17720523ad7bc49e9cf481dd7f7d8da4 (diff)
downloadrust-1d67eba6873b1d551a259a0bbc1e2651b4443e12.tar.gz
rust-1d67eba6873b1d551a259a0bbc1e2651b4443e12.zip
Auto merge of #112891 - oli-obk:impl_trait_in_assoc_tys_cleanup, r=compiler-errors
Various impl trait in assoc tys cleanups

r? `@compiler-errors`

All commits except for the last are pure refactorings. 274dab5bd658c97886a8987340bf50ae57900c39 allows struct fields to participate in deciding whether a function has an opaque in its signature.

best reviewed commit by commit
-rw-r--r--compiler/rustc_hir/src/hir.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs3
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs2
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs2
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs130
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs14
-rw-r--r--tests/ui/generic-associated-types/issue-88595.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-88595.stderr26
-rw-r--r--tests/ui/impl-trait/in-assoc-type-unconstrained.stderr4
-rw-r--r--tests/ui/impl-trait/in-assoc-type.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs28
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs30
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs26
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.rs35
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/multi-error.rs23
-rw-r--r--tests/ui/type-alias-impl-trait/multi-error.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/non-defining-method.rs21
-rw-r--r--tests/ui/type-alias-impl-trait/non-defining-method.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.stderr5
29 files changed, 377 insertions, 109 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 70fc66947df..5e5001bc8b4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3743,6 +3743,29 @@ impl<'hir> Node<'hir> {
         }
     }
 
+    /// Get the type for constants, assoc types, type aliases and statics.
+    pub fn ty(self) -> Option<&'hir Ty<'hir>> {
+        match self {
+            Node::Item(it) => match it.kind {
+                ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
+                    Some(ty)
+                }
+                _ => None,
+            },
+            Node::TraitItem(it) => match it.kind {
+                TraitItemKind::Const(ty, _) => Some(ty),
+                TraitItemKind::Type(_, ty) => ty,
+                _ => None,
+            },
+            Node::ImplItem(it) => match it.kind {
+                ImplItemKind::Const(ty, _) => Some(ty),
+                ImplItemKind::Type(ty) => Some(ty),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+
     pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
         match self {
             Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 22aa3c7ff08..a7e81f41c69 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -563,8 +563,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             check_union(tcx, id.owner_id.def_id);
         }
         DefKind::OpaqueTy => {
-            let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
-            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+            let origin = tcx.opaque_type_origin(id.owner_id.def_id);
+            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
                 && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
                 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
             {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 814a290178e..744eb036933 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1543,8 +1543,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
         if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
             && self.seen.insert(unshifted_opaque_ty.def_id)
             && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
-            && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
-            && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+            && let origin = tcx.opaque_type_origin(opaque_def_id)
+            && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
             && source == self.fn_def_id
         {
             let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index a723dc3f079..2a32f0b5047 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -260,7 +260,8 @@ impl<T> Trait<T> for X {
                     (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
                         if tcx.is_type_alias_impl_trait(alias.def_id) {
                             if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
-                                diag.span_note(tcx.def_span(body_owner_def_id), "\
+                                let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id));
+                                diag.span_note(sp, "\
                                     this item must have the opaque type in its signature \
                                     in order to be able to register hidden types");
                             }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 0390c868c1b..3098b8bc2f9 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -378,7 +378,7 @@ impl<'tcx> InferCtxt<'tcx> {
             DefiningAnchor::Bind(bind) => bind,
         };
 
-        let origin = self.opaque_type_origin_unchecked(def_id);
+        let origin = self.tcx.opaque_type_origin(def_id);
         let in_definition_scope = match origin {
             // Async `impl Trait`
             hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
@@ -395,13 +395,6 @@ impl<'tcx> InferCtxt<'tcx> {
         };
         in_definition_scope.then_some(origin)
     }
-
-    /// Returns the origin of the opaque type `def_id` even if we are not in its
-    /// defining scope.
-    #[instrument(skip(self), level = "trace", ret)]
-    fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
-        self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
-    }
 }
 
 /// Visitor that requires that (almost) all regions in the type visited outlive
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 12f3a0fc2c2..eee29d2090a 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1138,8 +1138,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::InlineConst => true,
 
         DefKind::OpaqueTy => {
-            let opaque = tcx.hir().expect_item(def_id).expect_opaque_ty();
-            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+            let origin = tcx.opaque_type_origin(def_id);
+            if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
                 && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
                 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
             {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b2ada4882e1..1f9cf2c6448 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1192,6 +1192,12 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
         self.visibility(def_id).expect_local()
     }
+
+    /// Returns the origin of the opaque type `def_id`.
+    #[instrument(skip(self), level = "trace", ret)]
+    pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
+        self.hir().expect_item(def_id).expect_opaque_ty().origin
+    }
 }
 
 /// A trait implemented for all `X<'a>` types that can be safely and
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 658ab03c0f4..5b731641e9d 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -259,7 +259,7 @@ fn associated_type_for_impl_trait_in_trait(
     opaque_ty_def_id: LocalDefId,
 ) -> LocalDefId {
     let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
-        tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
+        tcx.opaque_type_origin(opaque_ty_def_id)
     else {
         bug!("expected opaque for {opaque_ty_def_id:?}");
     };
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 553bf40ef3a..947d4bbe86e 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -113,7 +113,7 @@ pub struct DuplicateArg<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils_impl_trait_not_param)]
+#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
 pub struct NotParam<'tcx> {
     pub arg: GenericArg<'tcx>,
     #[primary_span]
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 34c7b9f4451..29de8bf0e53 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,5 +1,4 @@
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
@@ -19,21 +18,26 @@ struct OpaqueTypeCollector<'tcx> {
 
     /// Avoid infinite recursion due to recursive declarations.
     seen: FxHashSet<LocalDefId>,
+
+    span: Option<Span>,
 }
 
 impl<'tcx> OpaqueTypeCollector<'tcx> {
-    fn collect(
-        tcx: TyCtxt<'tcx>,
-        item: LocalDefId,
-        val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
-    ) -> Vec<LocalDefId> {
-        let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
-        val.skip_binder().visit_with(&mut collector);
-        collector.opaques
+    fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
+        Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
     }
 
     fn span(&self) -> Span {
-        self.tcx.def_span(self.item)
+        self.span.unwrap_or_else(|| {
+            self.tcx.def_ident_span(self.item).unwrap_or_else(|| self.tcx.def_span(self.item))
+        })
+    }
+
+    fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) {
+        let old = self.span;
+        self.span = Some(span);
+        value.visit_with(self);
+        self.span = old;
     }
 
     fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
@@ -60,53 +64,57 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
-    type BreakTy = ErrorGuaranteed;
-
     #[instrument(skip(self), ret, level = "trace")]
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+        t.super_visit_with(self)?;
         match t.kind() {
             ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
                 if !self.seen.insert(alias_ty.def_id.expect_local()) {
                     return ControlFlow::Continue(());
                 }
+
+                self.opaques.push(alias_ty.def_id.expect_local());
+
                 match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
                     Ok(()) => {
                         // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
                         // supported at all, so this is sound to do, but once we want to support them, you'll
                         // start seeing the error below.
 
-                        self.opaques.push(alias_ty.def_id.expect_local());
-
                         // Collect opaque types nested within the associated type bounds of this opaque type.
-                        for (pred, _span) in self
+                        // We use identity substs here, because we already know that the opaque type uses
+                        // only generic parameters, and thus substituting would not give us more information.
+                        for (pred, span) in self
                             .tcx
                             .explicit_item_bounds(alias_ty.def_id)
-                            .subst_iter_copied(self.tcx, alias_ty.substs)
+                            .subst_identity_iter_copied()
                         {
                             trace!(?pred);
-                            pred.visit_with(self)?;
+                            self.visit_spanned(span, pred);
                         }
-
-                        ControlFlow::Continue(())
                     }
                     Err(NotUniqueParam::NotParam(arg)) => {
-                        let err = self.tcx.sess.emit_err(NotParam {
+                        self.tcx.sess.emit_err(NotParam {
                             arg,
                             span: self.span(),
                             opaque_span: self.tcx.def_span(alias_ty.def_id),
                         });
-                        ControlFlow::Break(err)
                     }
                     Err(NotUniqueParam::DuplicateParam(arg)) => {
-                        let err = self.tcx.sess.emit_err(DuplicateArg {
+                        self.tcx.sess.emit_err(DuplicateArg {
                             arg,
                             span: self.span(),
                             opaque_span: self.tcx.def_span(alias_ty.def_id),
                         });
-                        ControlFlow::Break(err)
                     }
                 }
             }
+            ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
+                self.tcx
+                    .type_of(alias_ty.def_id)
+                    .subst(self.tcx, alias_ty.substs)
+                    .visit_with(self)?;
+            }
             ty::Alias(ty::Projection, alias_ty) => {
                 // This avoids having to do normalization of `Self::AssocTy` by only
                 // supporting the case of a method defining opaque types from assoc types
@@ -136,26 +144,44 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                                 ty::InternalSubsts::identity_for_item(self.tcx, parent),
                             );
 
-                            if !check_substs_compatible(self.tcx, assoc, impl_substs) {
+                            if check_substs_compatible(self.tcx, assoc, impl_substs) {
+                                return self
+                                    .tcx
+                                    .type_of(assoc.def_id)
+                                    .subst(self.tcx, impl_substs)
+                                    .visit_with(self);
+                            } else {
                                 self.tcx.sess.delay_span_bug(
                                     self.tcx.def_span(assoc.def_id),
                                     "item had incorrect substs",
                                 );
-                                return ControlFlow::Continue(());
                             }
-
-                            return self
-                                .tcx
-                                .type_of(assoc.def_id)
-                                .subst(self.tcx, impl_substs)
-                                .visit_with(self);
                         }
                     }
                 }
-                t.super_visit_with(self)
             }
-            _ => t.super_visit_with(self),
+            ty::Adt(def, _) if def.did().is_local() => {
+                if !self.seen.insert(def.did().expect_local()) {
+                    return ControlFlow::Continue(());
+                }
+                for variant in def.variants().iter() {
+                    for field in variant.fields.iter() {
+                        // Don't use the `ty::Adt` substs, we either
+                        // * found the opaque in the substs
+                        // * will find the opaque in the unsubstituted fields
+                        // The only other situation that can occur is that after substituting,
+                        // some projection resolves to an opaque that we would have otherwise
+                        // not found. While we could substitute and walk those, that would mean we
+                        // would have to walk all substitutions of an Adt, which can quickly
+                        // degenerate into looking at an exponential number of types.
+                        let ty = self.tcx.type_of(field.did).subst_identity();
+                        self.visit_spanned(self.tcx.def_span(field.did), ty);
+                    }
+                }
+            }
+            _ => trace!(kind=?t.kind()),
         }
+        ControlFlow::Continue(())
     }
 }
 
@@ -166,21 +192,29 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
     match kind {
         // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
         DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
-            let defined_opaques = match kind {
-                DefKind::Fn => {
-                    OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
+            let mut collector = OpaqueTypeCollector::new(tcx, item);
+            match kind {
+                // Walk over the signature of the function-like to find the opaques.
+                DefKind::AssocFn | DefKind::Fn => {
+                    let ty_sig = tcx.fn_sig(item).subst_identity();
+                    let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
+                    // Walk over the inputs and outputs manually in order to get good spans for them.
+                    collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
+                    for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
+                        collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
+                    }
                 }
-                DefKind::AssocFn => {
-                    OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
+                // Walk over the type of the item to find opaques.
+                DefKind::AssocTy | DefKind::AssocConst => {
+                    let span = match tcx.hir().get_by_def_id(item).ty() {
+                        Some(ty) => ty.span,
+                        _ => tcx.def_span(item),
+                    };
+                    collector.visit_spanned(span, tcx.type_of(item).subst_identity());
                 }
-                DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
-                    tcx,
-                    item,
-                    ty::Binder::dummy(tcx.type_of(item).subst_identity()),
-                ),
                 _ => unreachable!(),
-            };
-            tcx.arena.alloc_from_iter(defined_opaques)
+            }
+            tcx.arena.alloc_from_iter(collector.opaques)
         }
         DefKind::Mod
         | DefKind::Struct
@@ -209,7 +243,9 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
         | DefKind::GlobalAsm
         | DefKind::Impl { .. }
         | DefKind::Closure
-        | DefKind::Generator => &[],
+        | DefKind::Generator => {
+            span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent")
+        }
     }
 }
 
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index 472d921ace0..63e63c5d4aa 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -61,7 +61,19 @@ pub type Type9 = impl Send;
 pub type Type10 = impl Send;
 pub type Type11 = impl Send;
 
-pub fn fn1<'a>() {
+pub fn fn1<'a>() where
+    Type1: 'static,
+    Type2: 'static,
+    Type3: 'static,
+    Type4: 'static,
+    Type5: 'static,
+    Type6: 'static,
+    Type7: 'static,
+    Type8: 'static,
+    Type9: 'static,
+    Type10: 'static,
+    Type11: 'static,
+{
     // Closure
     let closure1 = || { };
     let _: Type1 = closure1;
diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs
index 7de906e7ef3..5a40a612972 100644
--- a/tests/ui/generic-associated-types/issue-88595.rs
+++ b/tests/ui/generic-associated-types/issue-88595.rs
@@ -19,5 +19,4 @@ impl<'a> A<'a> for C {
     type B<'b> = impl Clone;
 
     fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
-    //~^ ERROR: mismatched types
 }
diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr
index d6caed85459..2b1a25acfa4 100644
--- a/tests/ui/generic-associated-types/issue-88595.stderr
+++ b/tests/ui/generic-associated-types/issue-88595.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-88595.rs:21:5
+  --> $DIR/issue-88595.rs:21:23
    |
 LL |     fn a(&'a self) -> Self::B<'a> {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
+   |                       ^^^^^^^^^^^ generic argument `'a` used twice
    |
 note: for this opaque type
   --> $DIR/issue-88595.rs:19:18
@@ -10,25 +10,5 @@ note: for this opaque type
 LL |     type B<'b> = impl Clone;
    |                  ^^^^^^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/issue-88595.rs:21:23
-   |
-LL |     type B<'b> = impl Clone;
-   |                  ---------- the expected opaque type
-LL |
-LL |     fn a(&'a self) -> Self::B<'a> {}
-   |        -              ^^^^^^^^^^^ expected opaque type, found `()`
-   |        |
-   |        implicitly returns `()` as its body has no tail or `return` expression
-   |
-   = note: expected opaque type `<C as A<'a>>::B<'a>`
-                found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-88595.rs:21:5
-   |
-LL |     fn a(&'a self) -> Self::B<'a> {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
index 1097cd0f452..8e61a65abe4 100644
--- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
+++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
@@ -40,10 +40,10 @@ LL |         fn method() -> Self::Ty;
    = note: expected signature `fn() -> <() as compare_method::Trait>::Ty`
               found signature `fn()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type-unconstrained.rs:22:9
+  --> $DIR/in-assoc-type-unconstrained.rs:22:12
    |
 LL |         fn method() -> () {}
-   |         ^^^^^^^^^^^^^^^^^
+   |            ^^^^^^
 
 error: unconstrained opaque type
   --> $DIR/in-assoc-type-unconstrained.rs:20:19
diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr
index f0a272dc2d5..ab3f3a14410 100644
--- a/tests/ui/impl-trait/in-assoc-type.stderr
+++ b/tests/ui/impl-trait/in-assoc-type.stderr
@@ -12,10 +12,10 @@ LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
    = note: expected opaque type `<() as Foo<()>>::Bar`
                 found unit type `()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type.rs:17:5
+  --> $DIR/in-assoc-type.rs:17:8
    |
 LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index bbd60d4398b..fe765271bd2 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -20,11 +20,6 @@ LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |
    = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
               found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9
-   |
-LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unconstrained opaque type
   --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
@@ -49,10 +44,10 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
               found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:9
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12
    |
 LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
new file mode 100644
index 00000000000..eb19b49c7e2
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
@@ -0,0 +1,28 @@
+//! This test shows that a field type that is a projection that resolves to an opaque,
+//! is not a defining use. While we could substitute the struct generics, that would
+//! mean we would have to walk all substitutions of an `Foo`, which can quickly
+//! degenerate into looking at an exponential number of types depending on the complexity
+//! of a program.
+
+#![feature(impl_trait_in_assoc_type)]
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> Foo<Self>;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo<Bar> {
+        Foo { field: () }
+        //~^ ERROR: mismatched types
+    }
+}
+
+struct Foo<T: Trait> {
+    field: <T as Trait>::Assoc,
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
new file mode 100644
index 00000000000..648efd1cbfe
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/hidden_behind_projection_behind_struct_field.rs:19:22
+   |
+LL |     type Assoc = impl std::fmt::Debug;
+   |                  -------------------- the expected opaque type
+LL |     fn foo() -> Foo<Bar> {
+LL |         Foo { field: () }
+   |                      ^^ expected opaque type, found `()`
+   |
+   = 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_projection_behind_struct_field.rs:18:8
+   |
+LL |     fn foo() -> Foo<Bar> {
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs
new file mode 100644
index 00000000000..58778702de6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs
@@ -0,0 +1,30 @@
+//! This test shows that the appearance of an opaque type
+//! in the substs of a struct are enough to make it count
+//! for making the function a defining use. It doesn't matter
+//! if the opaque type is actually used in the field.
+
+#![feature(impl_trait_in_assoc_type)]
+// check-pass
+
+use std::marker::PhantomData;
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> Foo<Self::Assoc>;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo<Self::Assoc> {
+        let foo: Foo<()> = Foo { field: PhantomData };
+        foo
+    }
+}
+
+struct Foo<T> {
+    field: PhantomData<T>,
+}
+
+fn main() {}
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
new file mode 100644
index 00000000000..e440dce5e51
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
@@ -0,0 +1,26 @@
+//! This test shows that we can even follow projections
+//! into associated types of the same impl if they are
+//! indirectly mentioned in a struct field.
+
+#![feature(impl_trait_in_assoc_type)]
+// check-pass
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> Foo;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo {
+        Foo { field: () }
+    }
+}
+
+struct Foo {
+    field: <Bar as Trait>::Assoc,
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
new file mode 100644
index 00000000000..839a611cb71
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
@@ -0,0 +1,35 @@
+//! This test checks that we can't actually have an opaque type behind
+//! a binder that references variables from that binder.
+
+// edition: 2021
+
+#![feature(type_alias_impl_trait)]
+
+trait B {
+    type C;
+}
+
+struct A;
+
+impl<'a> B for &'a A {
+    type C = Tait<'a>;
+}
+
+type Tait<'a> = impl std::fmt::Debug + 'a;
+
+struct Terminator;
+
+type Successors<'a> = impl std::fmt::Debug + 'a;
+
+impl Terminator {
+    fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
+        f = g;
+        //~^ ERROR: mismatched types
+    }
+}
+
+fn g(x: &()) -> &() {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
new file mode 100644
index 00000000000..aaba9ad5ca7
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/higher_kinded_params3.rs:26:9
+   |
+LL | type Tait<'a> = impl std::fmt::Debug + 'a;
+   |                 ------------------------- the expected opaque type
+...
+LL |         f = g;
+   |         ^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>`
+              found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
index 2beed73cb85..6ec5d13f812 100644
--- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
+++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
@@ -12,10 +12,10 @@ LL |         let x: Self::Foo = ();
    = note: expected opaque type `<() as Foo>::Foo`
                 found unit type `()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:5
+  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:8
    |
 LL |     fn bar() {
-   |     ^^^^^^^^
+   |        ^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs
new file mode 100644
index 00000000000..b5ff06572d0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/multi-error.rs
@@ -0,0 +1,23 @@
+//! This test checks that we don't follow up
+//! with type mismatch errors of opaque types
+//! with their hidden types if we failed the
+//! defining scope check at the signature level.
+
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo {
+    type Bar<T>;
+    type Baz;
+    fn foo() -> (Self::Bar<u32>, Self::Baz);
+}
+
+impl Foo for () {
+    type Bar<T> = impl Sized;
+    type Baz = impl Sized;
+    fn foo() -> (Self::Bar<u32>, Self::Baz) {
+        //~^ ERROR non-defining opaque type use
+        ((), ())
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr
new file mode 100644
index 00000000000..b2de2effea6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/multi-error.stderr
@@ -0,0 +1,15 @@
+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;
+   |                   ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.rs b/tests/ui/type-alias-impl-trait/non-defining-method.rs
new file mode 100644
index 00000000000..2f4a7052f72
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.rs
@@ -0,0 +1,21 @@
+//! This test checks that we don't follow up
+//! with type mismatch errors of opaque types
+//! with their hidden types if we failed the
+//! defining scope check at the signature level.
+
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo {
+    type Bar<T>;
+    fn foo() -> Self::Bar<u32>;
+    fn bar<T>() -> Self::Bar<T>;
+}
+
+impl Foo for () {
+    type Bar<T> = impl Sized;
+    fn foo() -> Self::Bar<u32> {}
+    //~^ ERROR non-defining opaque type use
+    fn bar<T>() -> Self::Bar<T> {}
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
new file mode 100644
index 00000000000..ed5590f9d71
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
@@ -0,0 +1,15 @@
+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;
+   |                   ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
index d2d00749091..a621bb519cd 100644
--- a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
+++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
@@ -12,10 +12,10 @@ LL |         let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
    = note: expected opaque type `<() as Foo<DefinesOpaque>>::Assoc`
                 found reference `&'static str`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/not-matching-trait-refs-isnt-defining.rs:16:5
+  --> $DIR/not-matching-trait-refs-isnt-defining.rs:16:8
    |
 LL |     fn test() -> <() as Foo<NoOpaques>>::Assoc {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
index 24f5cc8c733..e9032433494 100644
--- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
@@ -25,11 +25,6 @@ LL |         fn dont_define_this(_private: Private) {}
    |                                       ^^^^^^^
    = note: expected signature `fn(Private)`
               found signature `fn(MyPrivate)`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/unnameable_type.rs:20:5
-   |
-LL |     fn dont_define_this(_private: MyPrivate) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors