about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-23 09:59:40 +0000
committerbors <bors@rust-lang.org>2023-10-23 09:59:40 +0000
commita56bd2b944aed6b4a0507cc1870fb4c86d08e48e (patch)
tree93fef0ff5217a7dc9b4c2d90affc5e1510c5427c
parent6bb4ad6dfb7d373c2f19b6cc8c0f05bd73f6d3cc (diff)
parentfe8ebb1890574a713bc8ee7cd5cc6cde54989b55 (diff)
downloadrust-a56bd2b944aed6b4a0507cc1870fb4c86d08e48e.tar.gz
rust-a56bd2b944aed6b4a0507cc1870fb4c86d08e48e.zip
Auto merge of #116849 - oli-obk:error_shenanigans, r=cjgillot
Avoid a `track_errors` by bubbling up most errors from `check_well_formed`

I believe `track_errors` is mostly papering over issues that a sufficiently convoluted query graph can hit. I made this change, while the actual change I want to do is to stop bailing out early on errors, and instead use this new `ErrorGuaranteed` to invoke `check_well_formed` for individual items before doing all the `typeck` logic on them.

This works towards resolving https://github.com/rust-lang/rust/issues/97477 and various other ICEs, as well as allowing us to use parallel rustc more (which is currently rather limited/bottlenecked due to the very sequential nature in which we do `rustc_hir_analysis::check_crate`)

cc `@SparrowLii` `@Zoxc` for the new `try_par_for_each_in` function
-rw-r--r--compiler/rustc_data_structures/src/sync.rs2
-rw-r--r--compiler/rustc_data_structures/src/sync/parallel.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs230
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs6
-rw-r--r--compiler/rustc_macros/src/query.rs10
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs15
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs32
-rw-r--r--compiler/rustc_middle/src/query/mod.rs10
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs58
-rw-r--r--compiler/rustc_span/src/lib.rs19
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6252.stderr14
-rw-r--r--tests/ui/associated-consts/issue-105330.rs9
-rw-r--r--tests/ui/associated-consts/issue-105330.stderr86
-rw-r--r--tests/ui/associated-consts/issue-58022.rs1
-rw-r--r--tests/ui/associated-consts/issue-58022.stderr22
-rw-r--r--tests/ui/async-await/issue-66312.rs2
-rw-r--r--tests/ui/async-await/issue-66312.stderr11
-rw-r--r--tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs2
-rw-r--r--tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr19
-rw-r--r--tests/ui/consts/issue-39974.rs1
-rw-r--r--tests/ui/consts/issue-39974.stderr13
-rw-r--r--tests/ui/generic-associated-types/issue-86787.rs4
-rw-r--r--tests/ui/generic-associated-types/issue-86787.stderr21
-rw-r--r--tests/ui/inference/issue-107090.rs6
-rw-r--r--tests/ui/inference/issue-107090.stderr17
-rw-r--r--tests/ui/infinite/infinite-struct.stderr6
-rw-r--r--tests/ui/issues/issue-77919.rs1
-rw-r--r--tests/ui/issues/issue-77919.stderr14
-rw-r--r--tests/ui/layout/cannot-transmute-unnormalizable-type.rs3
-rw-r--r--tests/ui/layout/cannot-transmute-unnormalizable-type.stderr14
-rw-r--r--tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs6
-rw-r--r--tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr13
-rw-r--r--tests/ui/self/self_type_keyword.rs2
-rw-r--r--tests/ui/self/self_type_keyword.stderr27
-rw-r--r--tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs2
-rw-r--r--tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr8
36 files changed, 425 insertions, 310 deletions
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 62fff604f81..f957734b04d 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -54,7 +54,7 @@ pub use worker_local::{Registry, WorkerLocal};
 mod parallel;
 #[cfg(parallel_compiler)]
 pub use parallel::scope;
-pub use parallel::{join, par_for_each_in, par_map, parallel_guard};
+pub use parallel::{join, par_for_each_in, par_map, parallel_guard, try_par_for_each_in};
 
 pub use std::sync::atomic::Ordering;
 pub use std::sync::atomic::Ordering::SeqCst;
diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs
index 1944ddfb710..39dddb59569 100644
--- a/compiler/rustc_data_structures/src/sync/parallel.rs
+++ b/compiler/rustc_data_structures/src/sync/parallel.rs
@@ -77,6 +77,15 @@ mod disabled {
         })
     }
 
+    pub fn try_par_for_each_in<T: IntoIterator, E: Copy>(
+        t: T,
+        mut for_each: impl FnMut(T::Item) -> Result<(), E>,
+    ) -> Result<(), E> {
+        parallel_guard(|guard| {
+            t.into_iter().fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret))
+        })
+    }
+
     pub fn par_map<T: IntoIterator, R, C: FromIterator<R>>(
         t: T,
         mut map: impl FnMut(<<T as IntoIterator>::IntoIter as Iterator>::Item) -> R,
@@ -167,6 +176,26 @@ mod enabled {
         });
     }
 
+    pub fn try_par_for_each_in<
+        T: IntoIterator + IntoParallelIterator<Item = <T as IntoIterator>::Item>,
+        E: Copy + Send,
+    >(
+        t: T,
+        for_each: impl Fn(<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend,
+    ) -> Result<(), E> {
+        parallel_guard(|guard| {
+            if mode::is_dyn_thread_safe() {
+                let for_each = FromDyn::from(for_each);
+                t.into_par_iter()
+                    .fold_with(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret))
+                    .reduce(|| Ok(()), |a, b| a.and(b))
+            } else {
+                t.into_iter()
+                    .fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret))
+            }
+        })
+    }
+
     pub fn par_map<
         I,
         T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 34c28bce5d8..3f31ce7aa58 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -92,7 +92,8 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     span: Span,
     body_def_id: LocalDefId,
     f: F,
-) where
+) -> Result<(), ErrorGuaranteed>
+where
     F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
 {
     let param_env = tcx.param_env(body_def_id);
@@ -106,40 +107,46 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     }
     f(&mut wfcx);
 
-    let assumed_wf_types = match wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)
-    {
-        Ok(wf_types) => wf_types,
-        Err(_guar) => return,
-    };
+    let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
 
     let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
 
     let errors = wfcx.select_all_or_error();
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(errors);
-        return;
+        let err = infcx.err_ctxt().report_fulfillment_errors(errors);
+        if tcx.sess.err_count() > 0 {
+            return Err(err);
+        } else {
+            // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs causes an
+            // error (delay_span_bug) during normalization, without reporting an error, so we need to act as if
+            // no error happened, in order to let our callers continue and report an error later in
+            // check_impl_items_against_trait.
+            return Ok(());
+        }
     }
 
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
 
-    let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env);
+    wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env)?;
+    infcx.tainted_by_errors().error_reported()
 }
 
-fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
+fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> {
     let node = tcx.hir().owner(def_id);
-    match node {
-        hir::OwnerNode::Crate(_) => {}
+    let mut res = match node {
+        hir::OwnerNode::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
         hir::OwnerNode::Item(item) => check_item(tcx, item),
         hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
         hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
         hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
-    }
+    };
 
     if let Some(generics) = node.generics() {
         for param in generics.params {
-            check_param_wf(tcx, param)
+            res = res.and(check_param_wf(tcx, param));
         }
     }
+    res
 }
 
 /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
@@ -156,7 +163,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
 #[instrument(skip(tcx), level = "debug")]
-fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
+fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<(), ErrorGuaranteed> {
     let def_id = item.owner_id.def_id;
 
     debug!(
@@ -186,31 +193,32 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
             let is_auto = tcx
                 .impl_trait_ref(def_id)
                 .is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
+            let mut res = Ok(());
             if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
                 let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
                 let mut err =
                     tcx.sess.struct_span_err(sp, "impls of auto traits cannot be default");
                 err.span_labels(impl_.defaultness_span, "default because of this");
                 err.span_label(sp, "auto trait");
-                err.emit();
+                res = Err(err.emit());
             }
             // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
             match (tcx.impl_polarity(def_id), impl_.polarity) {
                 (ty::ImplPolarity::Positive, _) => {
-                    check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
+                    res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
                 }
                 (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
                     if let hir::Defaultness::Default { .. } = impl_.defaultness {
                         let mut spans = vec![span];
                         spans.extend(impl_.defaultness_span);
-                        struct_span_err!(
+                        res = Err(struct_span_err!(
                             tcx.sess,
                             spans,
                             E0750,
                             "negative impls cannot be default impls"
                         )
-                        .emit();
+                        .emit());
                     }
                 }
                 (ty::ImplPolarity::Reservation, _) => {
@@ -218,49 +226,52 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
                 }
                 _ => unreachable!(),
             }
+            res
         }
         hir::ItemKind::Fn(ref sig, ..) => {
-            check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
+            check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
         }
         hir::ItemKind::Static(ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
+            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
         }
         hir::ItemKind::Const(ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
+            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
         }
         hir::ItemKind::Struct(_, ast_generics) => {
-            check_type_defn(tcx, item, false);
+            let res = check_type_defn(tcx, item, false);
             check_variances_for_type_defn(tcx, item, ast_generics);
+            res
         }
         hir::ItemKind::Union(_, ast_generics) => {
-            check_type_defn(tcx, item, true);
+            let res = check_type_defn(tcx, item, true);
             check_variances_for_type_defn(tcx, item, ast_generics);
+            res
         }
         hir::ItemKind::Enum(_, ast_generics) => {
-            check_type_defn(tcx, item, true);
+            let res = check_type_defn(tcx, item, true);
             check_variances_for_type_defn(tcx, item, ast_generics);
+            res
         }
-        hir::ItemKind::Trait(..) => {
-            check_trait(tcx, item);
-        }
-        hir::ItemKind::TraitAlias(..) => {
-            check_trait(tcx, item);
-        }
+        hir::ItemKind::Trait(..) => check_trait(tcx, item),
+        hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
         // `ForeignItem`s are handled separately.
-        hir::ItemKind::ForeignMod { .. } => {}
+        hir::ItemKind::ForeignMod { .. } => Ok(()),
         hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
             if tcx.type_alias_is_lazy(item.owner_id) {
                 // Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
                 // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
-                check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+                let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
                 check_variances_for_type_defn(tcx, item, ast_generics);
+                res
+            } else {
+                Ok(())
             }
         }
-        _ => {}
+        _ => Ok(()),
     }
 }
 
-fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
+fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<(), ErrorGuaranteed> {
     let def_id = item.owner_id.def_id;
 
     debug!(
@@ -275,11 +286,14 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
         hir::ForeignItemKind::Static(ty, ..) => {
             check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
         }
-        hir::ForeignItemKind::Type => (),
+        hir::ForeignItemKind::Type => Ok(()),
     }
 }
 
-fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
+fn check_trait_item(
+    tcx: TyCtxt<'_>,
+    trait_item: &hir::TraitItem<'_>,
+) -> Result<(), ErrorGuaranteed> {
     let def_id = trait_item.owner_id.def_id;
 
     let (method_sig, span) = match trait_item.kind {
@@ -288,18 +302,19 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
         _ => (None, trait_item.span),
     };
     check_object_unsafe_self_trait_by_name(tcx, trait_item);
-    check_associated_item(tcx, def_id, span, method_sig);
+    let mut res = check_associated_item(tcx, def_id, span, method_sig);
 
     if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
         for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
-            check_associated_item(
+            res = res.and(check_associated_item(
                 tcx,
                 assoc_ty_def_id.expect_local(),
                 tcx.def_span(assoc_ty_def_id),
                 None,
-            );
+            ));
         }
     }
+    res
 }
 
 /// Require that the user writes where clauses on GATs for the implicit
@@ -826,7 +841,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
     }
 }
 
-fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
+fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> Result<(), ErrorGuaranteed> {
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
         // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
@@ -834,13 +849,13 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
         _ => (None, impl_item.span),
     };
 
-    check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig);
+    check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
 }
 
-fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
+fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ErrorGuaranteed> {
     match param.kind {
         // We currently only check wf of const params here.
-        hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),
+        hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
 
         // Const parameters are well formed if their type is structural match.
         hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
@@ -860,68 +875,66 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                         ty,
                         trait_def_id,
                     );
-                });
+                })
             } else {
-                let diag = match ty.kind() {
-                    ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
-                    ty::FnPtr(_) => Some(tcx.sess.struct_span_err(
+                let mut diag = match ty.kind() {
+                    ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
+                    ty::FnPtr(_) => tcx.sess.struct_span_err(
                         hir_ty.span,
                         "using function pointers as const generic parameters is forbidden",
-                    )),
-                    ty::RawPtr(_) => Some(tcx.sess.struct_span_err(
+                    ),
+                    ty::RawPtr(_) => tcx.sess.struct_span_err(
                         hir_ty.span,
                         "using raw pointers as const generic parameters is forbidden",
-                    )),
-                    _ => Some(tcx.sess.struct_span_err(
+                    ),
+                    _ => tcx.sess.struct_span_err(
                         hir_ty.span,
                         format!("`{}` is forbidden as the type of a const generic parameter", ty),
-                    )),
+                    ),
                 };
 
-                if let Some(mut diag) = diag {
-                    diag.note("the only supported types are integers, `bool` and `char`");
+                diag.note("the only supported types are integers, `bool` and `char`");
 
-                    let cause = ObligationCause::misc(hir_ty.span, param.def_id);
-                    let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
-                        tcx,
-                        tcx.param_env(param.def_id),
-                        ty,
-                        cause,
-                    ) {
-                        // Can never implement `ConstParamTy`, don't suggest anything.
-                        Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
-                        // May be able to implement `ConstParamTy`. Only emit the feature help
-                        // if the type is local, since the user may be able to fix the local type.
-                        Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
-                            fn ty_is_local(ty: Ty<'_>) -> bool {
-                                match ty.kind() {
-                                    ty::Adt(adt_def, ..) => adt_def.did().is_local(),
-                                    // Arrays and slices use the inner type's `ConstParamTy`.
-                                    ty::Array(ty, ..) => ty_is_local(*ty),
-                                    ty::Slice(ty) => ty_is_local(*ty),
-                                    // `&` references use the inner type's `ConstParamTy`.
-                                    // `&mut` are not supported.
-                                    ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
-                                    // Say that a tuple is local if any of its components are local.
-                                    // This is not strictly correct, but it's likely that the user can fix the local component.
-                                    ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
-                                    _ => false,
-                                }
+                let cause = ObligationCause::misc(hir_ty.span, param.def_id);
+                let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
+                    tcx,
+                    tcx.param_env(param.def_id),
+                    ty,
+                    cause,
+                ) {
+                    // Can never implement `ConstParamTy`, don't suggest anything.
+                    Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
+                    // May be able to implement `ConstParamTy`. Only emit the feature help
+                    // if the type is local, since the user may be able to fix the local type.
+                    Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
+                        fn ty_is_local(ty: Ty<'_>) -> bool {
+                            match ty.kind() {
+                                ty::Adt(adt_def, ..) => adt_def.did().is_local(),
+                                // Arrays and slices use the inner type's `ConstParamTy`.
+                                ty::Array(ty, ..) => ty_is_local(*ty),
+                                ty::Slice(ty) => ty_is_local(*ty),
+                                // `&` references use the inner type's `ConstParamTy`.
+                                // `&mut` are not supported.
+                                ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
+                                // Say that a tuple is local if any of its components are local.
+                                // This is not strictly correct, but it's likely that the user can fix the local component.
+                                ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
+                                _ => false,
                             }
-
-                            ty_is_local(ty)
                         }
-                        // Implments `ConstParamTy`, suggest adding the feature to enable.
-                        Ok(..) => true,
-                    };
-                    if may_suggest_feature && tcx.sess.is_nightly_build() {
-                        diag.help(
+
+                        ty_is_local(ty)
+                    }
+                    // Implments `ConstParamTy`, suggest adding the feature to enable.
+                    Ok(..) => true,
+                };
+                if may_suggest_feature && tcx.sess.is_nightly_build() {
+                    diag.help(
                             "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
                         );
-                    }
-
-                    diag.emit();
                 }
+
+                Err(diag.emit())
             }
         }
     }
@@ -933,7 +946,7 @@ fn check_associated_item(
     item_id: LocalDefId,
     span: Span,
     sig_if_method: Option<&hir::FnSig<'_>>,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let loc = Some(WellFormedLoc::Ty(item_id));
     enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
         let item = tcx.associated_item(item_id);
@@ -985,7 +998,11 @@ fn item_adt_kind(kind: &ItemKind<'_>) -> Option<AdtKind> {
 }
 
 /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: bool) {
+fn check_type_defn<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item: &hir::Item<'tcx>,
+    all_sized: bool,
+) -> Result<(), ErrorGuaranteed> {
     let _ = tcx.representability(item.owner_id.def_id);
     let adt_def = tcx.adt_def(item.owner_id);
 
@@ -1080,11 +1097,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
         }
 
         check_where_clauses(wfcx, item.span, item.owner_id.def_id);
-    });
+    })
 }
 
 #[instrument(skip(tcx, item))]
-fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
+fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuaranteed> {
     debug!(?item.owner_id);
 
     let def_id = item.owner_id.def_id;
@@ -1103,7 +1120,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
         }
     }
 
-    enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
+    let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
         check_where_clauses(wfcx, item.span, def_id)
     });
 
@@ -1111,6 +1128,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     if let hir::ItemKind::Trait(..) = item.kind {
         check_gat_where_clauses(tcx, item.owner_id.def_id);
     }
+    res
 }
 
 /// Checks all associated type defaults of trait `trait_def_id`.
@@ -1142,7 +1160,7 @@ fn check_item_fn(
     ident: Ident,
     span: Span,
     decl: &hir::FnDecl<'_>,
-) {
+) -> Result<(), ErrorGuaranteed> {
     enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
         let sig = tcx.fn_sig(def_id).instantiate_identity();
         check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
@@ -1160,7 +1178,7 @@ fn check_item_type(
     item_id: LocalDefId,
     ty_span: Span,
     unsized_handling: UnsizedHandling,
-) {
+) -> Result<(), ErrorGuaranteed> {
     debug!("check_item_type: {:?}", item_id);
 
     enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
@@ -1200,7 +1218,7 @@ fn check_item_type(
                 tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
             );
         }
-    });
+    })
 }
 
 #[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
@@ -1209,7 +1227,7 @@ fn check_impl<'tcx>(
     item: &'tcx hir::Item<'tcx>,
     ast_self_ty: &hir::Ty<'_>,
     ast_trait_ref: &Option<hir::TraitRef<'_>>,
-) {
+) -> Result<(), ErrorGuaranteed> {
     enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
         match ast_trait_ref {
             Some(ast_trait_ref) => {
@@ -1258,7 +1276,7 @@ fn check_impl<'tcx>(
         }
 
         check_where_clauses(wfcx, item.span, item.owner_id.def_id);
-    });
+    })
 }
 
 /// Checks where-clauses and inline bounds that are declared on `def_id`.
@@ -1879,12 +1897,12 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
     }
 }
 
-fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) {
+fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
     let items = tcx.hir_module_items(module);
-    items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
-    items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));
-    items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id));
-    items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+    let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+    res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
+    res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
+    res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)))
 }
 
 fn error_392(
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index c7b3648099c..88f3db03a4e 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -205,10 +205,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         })?;
     }
 
-    tcx.sess.track_errors(|| {
-        tcx.sess.time("wf_checking", || {
-            tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
-        });
+    tcx.sess.time("wf_checking", || {
+        tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
     })?;
 
     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index d0d41c614d6..d8a695b131b 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -114,6 +114,11 @@ struct QueryModifiers {
 
     /// Generate a `feed` method to set the query's value from another query.
     feedable: Option<Ident>,
+
+    /// Forward the result on ensure if the query gets recomputed, and
+    /// return `Ok(())` otherwise. Only applicable to queries returning
+    /// `Result<(), ErrorGuaranteed>`
+    ensure_forwards_result_if_red: Option<Ident>,
 }
 
 fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
@@ -128,6 +133,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
     let mut depth_limit = None;
     let mut separate_provide_extern = None;
     let mut feedable = None;
+    let mut ensure_forwards_result_if_red = None;
 
     while !input.is_empty() {
         let modifier: Ident = input.parse()?;
@@ -187,6 +193,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
             try_insert!(separate_provide_extern = modifier);
         } else if modifier == "feedable" {
             try_insert!(feedable = modifier);
+        } else if modifier == "ensure_forwards_result_if_red" {
+            try_insert!(ensure_forwards_result_if_red = modifier);
         } else {
             return Err(Error::new(modifier.span(), "unknown query modifier"));
         }
@@ -206,6 +214,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
         depth_limit,
         separate_provide_extern,
         feedable,
+        ensure_forwards_result_if_red,
     })
 }
 
@@ -325,6 +334,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             eval_always,
             depth_limit,
             separate_provide_extern,
+            ensure_forwards_result_if_red,
         );
 
         if modifiers.cache.is_some() {
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 3ca26ec98c6..58c0c6bab49 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -6,7 +6,7 @@ use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
+use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
@@ -16,7 +16,7 @@ use rustc_index::Idx;
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{ErrorGuaranteed, Span};
 use rustc_target::spec::abi::Abi;
 
 #[inline]
@@ -632,6 +632,17 @@ impl<'hir> Map<'hir> {
         })
     }
 
+    #[inline]
+    pub fn try_par_for_each_module(
+        self,
+        f: impl Fn(LocalModDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
+    ) -> Result<(), ErrorGuaranteed> {
+        let crate_items = self.tcx.hir_crate_items(());
+        try_par_for_each_in(&crate_items.submodules[..], |module| {
+            f(LocalModDefId::new_unchecked(module.def_id))
+        })
+    }
+
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
     /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 0da8fe9cca7..f28ec771169 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -9,12 +9,12 @@ pub mod place;
 use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
+use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
-use rustc_span::{ExpnId, DUMMY_SP};
+use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP};
 
 /// Top-level HIR node for current owner. This only contains the node for which
 /// `HirId::local_id == 0`, and excludes bodies.
@@ -78,20 +78,32 @@ impl ModuleItems {
         self.owners().map(|id| id.def_id)
     }
 
-    pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
-        par_for_each_in(&self.items[..], |&id| f(id))
+    pub fn par_items(
+        &self,
+        f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
+    ) -> Result<(), ErrorGuaranteed> {
+        try_par_for_each_in(&self.items[..], |&id| f(id))
     }
 
-    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) {
-        par_for_each_in(&self.trait_items[..], |&id| f(id))
+    pub fn par_trait_items(
+        &self,
+        f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
+    ) -> Result<(), ErrorGuaranteed> {
+        try_par_for_each_in(&self.trait_items[..], |&id| f(id))
     }
 
-    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) {
-        par_for_each_in(&self.impl_items[..], |&id| f(id))
+    pub fn par_impl_items(
+        &self,
+        f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
+    ) -> Result<(), ErrorGuaranteed> {
+        try_par_for_each_in(&self.impl_items[..], |&id| f(id))
     }
 
-    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) {
-        par_for_each_in(&self.foreign_items[..], |&id| f(id))
+    pub fn par_foreign_items(
+        &self,
+        f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
+    ) -> Result<(), ErrorGuaranteed> {
+        try_par_for_each_in(&self.foreign_items[..], |&id| f(id))
     }
 }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index cd5206a837f..23d77a1ebe4 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -25,7 +25,9 @@ use crate::mir::interpret::{
 use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
 use crate::query::erase::{erase, restore, Erase};
-use crate::query::plumbing::{query_ensure, query_get_at, CyclePlaceholder, DynamicQuery};
+use crate::query::plumbing::{
+    query_ensure, query_ensure_error_guaranteed, query_get_at, CyclePlaceholder, DynamicQuery,
+};
 use crate::thir;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -965,8 +967,9 @@ rustc_queries! {
         desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
     }
 
-    query check_mod_type_wf(key: LocalModDefId) -> () {
+    query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
+        ensure_forwards_result_if_red
     }
 
     query collect_mod_item_types(key: LocalModDefId) -> () {
@@ -1499,8 +1502,9 @@ rustc_queries! {
         feedable
     }
 
-    query check_well_formed(key: hir::OwnerId) -> () {
+    query check_well_formed(key: hir::OwnerId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) }
+        ensure_forwards_result_if_red
     }
 
     // The `DefId`s of all non-generic functions and statics in the given crate
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 34e5b02ba5b..f4a8ada8f68 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -173,6 +173,45 @@ pub fn query_ensure<'tcx, Cache>(
     }
 }
 
+#[inline]
+pub fn query_ensure_error_guaranteed<'tcx, Cache>(
+    tcx: TyCtxt<'tcx>,
+    execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
+    query_cache: &Cache,
+    key: Cache::Key,
+    check_cache: bool,
+) -> Result<(), ErrorGuaranteed>
+where
+    Cache: QueryCache<Value = super::erase::Erase<Result<(), ErrorGuaranteed>>>,
+{
+    let key = key.into_query_param();
+    if let Some(res) = try_get_cached(tcx, query_cache, &key) {
+        super::erase::restore(res)
+    } else {
+        execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache })
+            .map(super::erase::restore)
+            // Either we actually executed the query, which means we got a full `Result`,
+            // or we can just assume the query succeeded, because it was green in the
+            // incremental cache. If it is green, that means that the previous compilation
+            // that wrote to the incremental cache compiles successfully. That is only
+            // possible if the cache entry was `Ok(())`, so we emit that here, without
+            // actually encoding the `Result` in the cache or loading it from there.
+            .unwrap_or(Ok(()))
+    }
+}
+
+macro_rules! query_ensure {
+    ([]$($args:tt)*) => {
+        query_ensure($($args)*)
+    };
+    ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => {
+        query_ensure_error_guaranteed($($args)*)
+    };
+    ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
+        query_ensure!([$($modifiers)*]$($args)*)
+    };
+}
+
 macro_rules! query_helper_param_ty {
     (DefId) => { impl IntoQueryParam<DefId> };
     (LocalDefId) => { impl IntoQueryParam<LocalDefId> };
@@ -220,6 +259,18 @@ macro_rules! separate_provide_extern_decl {
     };
 }
 
+macro_rules! ensure_result {
+    ([][$ty:ty]) => {
+        ()
+    };
+    ([(ensure_forwards_result_if_red) $($rest:tt)*][$ty:ty]) => {
+        Result<(), ErrorGuaranteed>
+    };
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        ensure_result!([$($modifiers)*][$($args)*])
+    };
+}
+
 macro_rules! separate_provide_extern_default {
     ([][$name:ident]) => {
         ()
@@ -343,14 +394,15 @@ macro_rules! define_callbacks {
         impl<'tcx> TyCtxtEnsure<'tcx> {
             $($(#[$attr])*
             #[inline(always)]
-            pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
-                query_ensure(
+            pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> ensure_result!([$($modifiers)*][$V]) {
+                query_ensure!(
+                    [$($modifiers)*]
                     self.tcx,
                     self.tcx.query_system.fns.engine.$name,
                     &self.tcx.query_system.caches.$name,
                     key.into_query_param(),
                     false,
-                );
+                )
             })*
         }
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 8bb64aa5f12..1a94b7e98fd 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -2247,7 +2247,7 @@ where
 
 /// Useful type to use with `Result<>` indicate that an error has already
 /// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
 #[derive(HashStable_Generic)]
 pub struct ErrorGuaranteed(());
 
@@ -2259,3 +2259,20 @@ impl ErrorGuaranteed {
         ErrorGuaranteed(())
     }
 }
+
+impl<E: rustc_serialize::Encoder> Encodable<E> for ErrorGuaranteed {
+    #[inline]
+    fn encode(&self, _e: &mut E) {
+        panic!(
+            "should never serialize an `ErrorGuaranteed`, as we do not write metadata or incremental caches in case errors occurred"
+        )
+    }
+}
+impl<D: rustc_serialize::Decoder> Decodable<D> for ErrorGuaranteed {
+    #[inline]
+    fn decode(_d: &mut D) -> ErrorGuaranteed {
+        panic!(
+            "`ErrorGuaranteed` should never have been serialized to metadata or incremental caches"
+        )
+    }
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
index f929bec9583..30be9dde73c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
@@ -24,16 +24,6 @@ help: you might be missing a type parameter
 LL | impl<N, M, VAL> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          +++++
 
-error[E0046]: not all trait items implemented, missing: `VAL`
-  --> $DIR/ice-6252.rs:11:1
-   |
-LL |     const VAL: T;
-   |     ------------ `VAL` from trait
-...
-LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0046, E0412.
-For more information about an error, try `rustc --explain E0046`.
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs
index 86e45f10b0e..285e89cce49 100644
--- a/tests/ui/associated-consts/issue-105330.rs
+++ b/tests/ui/associated-consts/issue-105330.rs
@@ -9,13 +9,10 @@ impl TraitWAssocConst for impl Demo { //~ ERROR E0404
 }
 
 fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658
-    foo::<Demo>()(); //~ ERROR E0271
-    //~^ ERROR E0618
-    //~| ERROR E0277
+    foo::<Demo>()();
 }
 
-fn main<A: TraitWAssocConst<A=32>>() { //~ ERROR E0131
+fn main<A: TraitWAssocConst<A=32>>() {
     //~^ ERROR E0658
-    foo::<Demo>(); //~ ERROR E0277
-    //~^ ERROR E0271
+    foo::<Demo>();
 }
diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr
index 200856caa25..55207909f7a 100644
--- a/tests/ui/associated-consts/issue-105330.stderr
+++ b/tests/ui/associated-consts/issue-105330.stderr
@@ -25,7 +25,7 @@ LL | fn foo<A: TraitWAssocConst<A=32>>() {
    = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
 
 error[E0658]: associated const equality is incomplete
-  --> $DIR/issue-105330.rs:17:29
+  --> $DIR/issue-105330.rs:15:29
    |
 LL | fn main<A: TraitWAssocConst<A=32>>() {
    |                             ^^^^
@@ -39,85 +39,7 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument
 LL | impl TraitWAssocConst for impl Demo {
    |                           ^^^^^^^^^
 
-error[E0131]: `main` function is not allowed to have generic parameters
-  --> $DIR/issue-105330.rs:17:8
-   |
-LL | fn main<A: TraitWAssocConst<A=32>>() {
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters
-
-error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
-  --> $DIR/issue-105330.rs:12:11
-   |
-LL |     foo::<Demo>()();
-   |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
-   |
-help: this trait has no implementations, consider adding one
-  --> $DIR/issue-105330.rs:1:1
-   |
-LL | pub trait TraitWAssocConst {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `foo`
-  --> $DIR/issue-105330.rs:11:11
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   |           ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
-  --> $DIR/issue-105330.rs:12:11
-   |
-LL |     foo::<Demo>()();
-   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
-   |
-   = note: expected constant `32`
-              found constant `<Demo as TraitWAssocConst>::A`
-note: required by a bound in `foo`
-  --> $DIR/issue-105330.rs:11:28
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   |                            ^^^^ required by this bound in `foo`
-
-error[E0618]: expected function, found `()`
-  --> $DIR/issue-105330.rs:12:5
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   | ----------------------------------- `foo::<Demo>` defined here returns `()`
-LL |     foo::<Demo>()();
-   |     ^^^^^^^^^^^^^--
-   |     |
-   |     call expression requires function
-
-error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
-  --> $DIR/issue-105330.rs:19:11
-   |
-LL |     foo::<Demo>();
-   |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
-   |
-help: this trait has no implementations, consider adding one
-  --> $DIR/issue-105330.rs:1:1
-   |
-LL | pub trait TraitWAssocConst {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `foo`
-  --> $DIR/issue-105330.rs:11:11
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   |           ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
-  --> $DIR/issue-105330.rs:19:11
-   |
-LL |     foo::<Demo>();
-   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
-   |
-   = note: expected constant `32`
-              found constant `<Demo as TraitWAssocConst>::A`
-note: required by a bound in `foo`
-  --> $DIR/issue-105330.rs:11:28
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   |                            ^^^^ required by this bound in `foo`
-
-error: aborting due to 11 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658.
-For more information about an error, try `rustc --explain E0131`.
+Some errors have detailed explanations: E0404, E0562, E0658.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/associated-consts/issue-58022.rs b/tests/ui/associated-consts/issue-58022.rs
index 2a8a1eaa6d3..8e2a441f239 100644
--- a/tests/ui/associated-consts/issue-58022.rs
+++ b/tests/ui/associated-consts/issue-58022.rs
@@ -11,6 +11,7 @@ impl Bar<[u8]> {
     const SIZE: usize = 32;
 
     fn new(slice: &[u8; Self::SIZE]) -> Self {
+        //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time
         Foo(Box::new(*slice))
         //~^ ERROR: expected function, tuple struct or tuple variant, found trait `Foo`
     }
diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr
index 56d85c066a8..82cbc9ed3b0 100644
--- a/tests/ui/associated-consts/issue-58022.stderr
+++ b/tests/ui/associated-consts/issue-58022.stderr
@@ -7,13 +7,27 @@ LL |
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
    |                         ^^^^^^^^^ cannot refer to the associated constant of trait
 
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-58022.rs:13:41
+   |
+LL |     fn new(slice: &[u8; Self::SIZE]) -> Self {
+   |                                         ^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `Bar<[u8]>`
+  --> $DIR/issue-58022.rs:8:12
+   |
+LL | pub struct Bar<T: ?Sized>(T);
+   |            ^^^
+   = note: the return type of a function must have a statically known size
+
 error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo`
-  --> $DIR/issue-58022.rs:14:9
+  --> $DIR/issue-58022.rs:15:9
    |
 LL |         Foo(Box::new(*slice))
    |         ^^^ not a function, tuple struct or tuple variant
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0423, E0790.
-For more information about an error, try `rustc --explain E0423`.
+Some errors have detailed explanations: E0277, E0423, E0790.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-66312.rs b/tests/ui/async-await/issue-66312.rs
index 9224971ecb1..fbc58697d48 100644
--- a/tests/ui/async-await/issue-66312.rs
+++ b/tests/ui/async-await/issue-66312.rs
@@ -6,7 +6,7 @@ trait Test<T> {
 
 async fn f() {
     let x = Some(2);
-    if x.is_some() {
+    if x.is_some() { //~ ERROR mismatched types
         println!("Some");
     }
 }
diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr
index 80d294a10a0..dad5807cb50 100644
--- a/tests/ui/async-await/issue-66312.stderr
+++ b/tests/ui/async-await/issue-66312.stderr
@@ -7,6 +7,13 @@ LL |     fn is_some(self: T);
    = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-66312.rs:9:8
+   |
+LL |     if x.is_some() {
+   |        ^^^^^^^^^^^ expected `bool`, found `()`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0307`.
+Some errors have detailed explanations: E0307, E0308.
+For more information about an error, try `rustc --explain E0307`.
diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs
index 29aa0f59d74..c254b4ee09d 100644
--- a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs
+++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs
@@ -15,7 +15,7 @@ fn bad_infer_fn<_>() {}
 
 
 fn main() {
-  let a: All<_, _, _>;
+  let a: All<_, _, _>; //~ ERROR struct takes 2 generic arguments but 3
   all_fn();
   let v: [u8; _];
   let v: [u8; 10] = [0; _];
diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr
index e6d0c743d01..a6b736261e0 100644
--- a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr
+++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr
@@ -19,6 +19,21 @@ LL | struct BadInfer<_>;
    = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
    = help: if you intended `_` to be a const parameter, use `const _: usize` instead
 
-error: aborting due to 3 previous errors
+error[E0107]: struct takes 2 generic arguments but 3 generic arguments were supplied
+  --> $DIR/infer-arg-test.rs:18:10
+   |
+LL |   let a: All<_, _, _>;
+   |          ^^^       - help: remove this generic argument
+   |          |
+   |          expected 2 generic arguments
+   |
+note: struct defined here, with 2 generic parameters: `T`, `N`
+  --> $DIR/infer-arg-test.rs:3:8
+   |
+LL | struct All<'a, T, const N: usize> {
+   |        ^^^     -  --------------
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0392`.
+Some errors have detailed explanations: E0107, E0392.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/consts/issue-39974.rs b/tests/ui/consts/issue-39974.rs
index 503647ef4a8..9cb180014b8 100644
--- a/tests/ui/consts/issue-39974.rs
+++ b/tests/ui/consts/issue-39974.rs
@@ -1,4 +1,5 @@
 const LENGTH: f64 = 2;
+//~^ ERROR mismatched types
 
 struct Thing {
     f: [[f64; 2]; LENGTH],
diff --git a/tests/ui/consts/issue-39974.stderr b/tests/ui/consts/issue-39974.stderr
index 56365e51e0a..4bde599039e 100644
--- a/tests/ui/consts/issue-39974.stderr
+++ b/tests/ui/consts/issue-39974.stderr
@@ -1,9 +1,18 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-39974.rs:4:19
+  --> $DIR/issue-39974.rs:5:19
    |
 LL |     f: [[f64; 2]; LENGTH],
    |                   ^^^^^^ expected `usize`, found `f64`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-39974.rs:1:21
+   |
+LL | const LENGTH: f64 = 2;
+   |                     ^
+   |                     |
+   |                     expected `f64`, found integer
+   |                     help: use a float literal: `2.0`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/generic-associated-types/issue-86787.rs b/tests/ui/generic-associated-types/issue-86787.rs
index 96075ca503d..5edd0a9f02f 100644
--- a/tests/ui/generic-associated-types/issue-86787.rs
+++ b/tests/ui/generic-associated-types/issue-86787.rs
@@ -22,8 +22,8 @@ where
     type T = Either<Left::T, Right::T>;
     type TRef<'a> = Either<&'a Left::T, &'a Right::T>
     where
-        <Left as HasChildrenOf>::T: 'a,
-        <Right as HasChildrenOf>::T: 'a;
+        <Left as HasChildrenOf>::T: 'a, //~ ERROR impl has stricter requirements than trait
+        <Right as HasChildrenOf>::T: 'a; //~ ERROR impl has stricter requirements than trait
 
     fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>> {
         todo!()
diff --git a/tests/ui/generic-associated-types/issue-86787.stderr b/tests/ui/generic-associated-types/issue-86787.stderr
index f34c63cf72e..00795abbd05 100644
--- a/tests/ui/generic-associated-types/issue-86787.stderr
+++ b/tests/ui/generic-associated-types/issue-86787.stderr
@@ -9,5 +9,24 @@ LL |     type TRef<'a>;
    = note: this bound is currently required to ensure that impls have maximum flexibility
    = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: aborting due to previous error
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/issue-86787.rs:25:37
+   |
+LL |     type TRef<'a>;
+   |     ------------- definition of `TRef` from trait
+...
+LL |         <Left as HasChildrenOf>::T: 'a,
+   |                                     ^^ impl has extra requirement `<Left as HasChildrenOf>::T: 'a`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/issue-86787.rs:26:38
+   |
+LL |     type TRef<'a>;
+   |     ------------- definition of `TRef` from trait
+...
+LL |         <Right as HasChildrenOf>::T: 'a;
+   |                                      ^^ impl has extra requirement `<Right as HasChildrenOf>::T: 'a`
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0276`.
diff --git a/tests/ui/inference/issue-107090.rs b/tests/ui/inference/issue-107090.rs
index a22e12c6d88..799c3641833 100644
--- a/tests/ui/inference/issue-107090.rs
+++ b/tests/ui/inference/issue-107090.rs
@@ -2,8 +2,8 @@ use std::marker::PhantomData;
 struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
 where
     Foo<'short, 'out, T>: Convert<'a, 'b>;
-    //~^ ERROR use of undeclared lifetime name
-    //~| ERROR use of undeclared lifetime name `'out`
+//~^ ERROR use of undeclared lifetime name
+//~| ERROR use of undeclared lifetime name `'out`
 
 trait Convert<'a, 'b>: Sized {
     fn cast(&'a self) -> &'b Self;
@@ -19,7 +19,7 @@ impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
 
 fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
     //~^ ERROR use of undeclared lifetime name
-    sadness.cast() //~ ERROR mismatched types
+    sadness.cast()
 }
 
 fn main() {}
diff --git a/tests/ui/inference/issue-107090.stderr b/tests/ui/inference/issue-107090.stderr
index 55825f7765b..e509e262fb1 100644
--- a/tests/ui/inference/issue-107090.stderr
+++ b/tests/ui/inference/issue-107090.stderr
@@ -66,19 +66,6 @@ LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short,
    |           |
    |           help: consider introducing lifetime `'short` here: `'short,`
 
-error[E0308]: mismatched types
-  --> $DIR/issue-107090.rs:22:5
-   |
-LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
-   |                       - expected this type parameter                                    ------- expected `&'out T` because of return type
-LL |
-LL |     sadness.cast()
-   |     ^^^^^^^^^^^^^^ expected `&T`, found `&Foo<'_, '_, T>`
-   |
-   = note: expected reference `&'out T`
-              found reference `&Foo<'_, '_, T>`
-
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0261, E0308.
-For more information about an error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/infinite/infinite-struct.stderr b/tests/ui/infinite/infinite-struct.stderr
index b6c72b1de46..82d147b63cd 100644
--- a/tests/ui/infinite/infinite-struct.stderr
+++ b/tests/ui/infinite/infinite-struct.stderr
@@ -22,6 +22,10 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
 LL |     x: Bar<Box<Foo>>,
    |            ++++   +
 
-error: aborting due to 2 previous errors
+error: reached the recursion limit finding the struct tail for `Take`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/ui/issues/issue-77919.rs b/tests/ui/issues/issue-77919.rs
index 966d76d148a..3cbf493afb8 100644
--- a/tests/ui/issues/issue-77919.rs
+++ b/tests/ui/issues/issue-77919.rs
@@ -10,4 +10,3 @@ struct Multiply<N, M> {
 }
 impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
 //~^ ERROR cannot find type `VAL` in this scope
-//~| ERROR not all trait items implemented, missing: `VAL`
diff --git a/tests/ui/issues/issue-77919.stderr b/tests/ui/issues/issue-77919.stderr
index dbbe70ff069..9d2f859e05a 100644
--- a/tests/ui/issues/issue-77919.stderr
+++ b/tests/ui/issues/issue-77919.stderr
@@ -20,16 +20,6 @@ help: you might be missing a type parameter
 LL | impl<N, M, VAL> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          +++++
 
-error[E0046]: not all trait items implemented, missing: `VAL`
-  --> $DIR/issue-77919.rs:11:1
-   |
-LL |     const VAL: T;
-   |     ------------ `VAL` from trait
-...
-LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0046, E0412.
-For more information about an error, try `rustc --explain E0046`.
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.rs b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs
index d2b6e1d8eba..1a2ff8c4705 100644
--- a/tests/ui/layout/cannot-transmute-unnormalizable-type.rs
+++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs
@@ -16,7 +16,8 @@ struct Other {
 
 fn main() {
     unsafe {
+        // FIXME(oli-obk): make this report a transmute error again.
         std::mem::transmute::<Option<()>, Option<&Other>>(None);
-        //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+        //^ ERROR cannot transmute between types of different sizes, or dependently-sized types
     }
 }
diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
index dd5119318ff..ee2c5ab7e39 100644
--- a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
+++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
@@ -4,16 +4,6 @@ error[E0412]: cannot find type `Missing` in this scope
 LL |     Missing: Trait,
    |     ^^^^^^^ not found in this scope
 
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/cannot-transmute-unnormalizable-type.rs:19:9
-   |
-LL |         std::mem::transmute::<Option<()>, Option<&Other>>(None);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: source type: `Option<()>` (8 bits)
-   = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized)
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0412, E0512.
-For more information about an error, try `rustc --explain E0412`.
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs
index 9eeee195e56..f1238ec240f 100644
--- a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs
+++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs
@@ -5,5 +5,9 @@ fn f2<'a>(x: u8, y: Vec<&'a ...>) {}
 //~^ ERROR C-variadic type `...` may not be nested inside another type
 
 fn main() {
-    let _recovery_witness: () = 0; //~ ERROR mismatched types
+    // While this is an error, wf-checks happen before typeck, and if any wf-checks
+    // encountered errors, we do not continue to typeck, even if the items are
+    // unrelated.
+    // FIXME(oli-obk): make this report a type mismatch again.
+    let _recovery_witness: () = 0;
 }
diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
index 8b9d676a45d..7ca6a6d1bbf 100644
--- a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
+++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
@@ -10,15 +10,6 @@ error[E0743]: C-variadic type `...` may not be nested inside another type
 LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {}
    |                             ^^^
 
-error[E0308]: mismatched types
-  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33
-   |
-LL |     let _recovery_witness: () = 0;
-   |                            --   ^ expected `()`, found integer
-   |                            |
-   |                            expected due to this
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0743.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0743`.
diff --git a/tests/ui/self/self_type_keyword.rs b/tests/ui/self/self_type_keyword.rs
index b42bf8eea1a..96d24715edb 100644
--- a/tests/ui/self/self_type_keyword.rs
+++ b/tests/ui/self/self_type_keyword.rs
@@ -22,6 +22,8 @@ pub fn main() {
         //~^ ERROR cannot find macro `Self` in this scope
         Foo { Self } => (),
         //~^ ERROR expected identifier, found keyword `Self`
+        //~| ERROR mismatched types
+        //~| ERROR `Foo` does not have a field named `Self`
     }
 }
 
diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr
index aca08d81163..6e65fae808d 100644
--- a/tests/ui/self/self_type_keyword.stderr
+++ b/tests/ui/self/self_type_keyword.stderr
@@ -31,19 +31,19 @@ LL |         Foo { Self } => (),
    |               ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:29:26
+  --> $DIR/self_type_keyword.rs:31:26
    |
 LL |     extern crate core as Self;
    |                          ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:34:32
+  --> $DIR/self_type_keyword.rs:36:32
    |
 LL |     use std::option::Option as Self;
    |                                ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:39:11
+  --> $DIR/self_type_keyword.rs:41:11
    |
 LL |     trait Self {}
    |           ^^^^ expected identifier, found keyword
@@ -80,7 +80,22 @@ LL | struct Bar<'Self>;
    |
    = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData`
 
-error: aborting due to 12 previous errors
+error[E0308]: mismatched types
+  --> $DIR/self_type_keyword.rs:23:9
+   |
+LL |     match 15 {
+   |           -- this expression has type `{integer}`
+...
+LL |         Foo { Self } => (),
+   |         ^^^^^^^^^^^^ expected integer, found `Foo`
+
+error[E0026]: struct `Foo` does not have a field named `Self`
+  --> $DIR/self_type_keyword.rs:23:15
+   |
+LL |         Foo { Self } => (),
+   |               ^^^^ struct `Foo` does not have this field
+
+error: aborting due to 14 previous errors
 
-Some errors have detailed explanations: E0392, E0531.
-For more information about an error, try `rustc --explain E0392`.
+Some errors have detailed explanations: E0026, E0308, E0392, E0531.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
index a1b9a7eba4d..193544ebd3f 100644
--- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
+++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
@@ -5,7 +5,7 @@
 
 
 trait Trait {
-    fn func<const N: u32>() -> [ (); N ];
+    fn func<const N: u32>() -> [ (); N ]; //~ ERROR mismatched types
 }
 
 struct S {}
diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr
index 9843651b1e6..16aaf0615ed 100644
--- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr
+++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr
@@ -4,6 +4,12 @@ error[E0308]: mismatched types
 LL |     fn func<const N: u32>() -> [ (); { () }] {
    |                                        ^^ expected `usize`, found `()`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/const-in-impl-fn-return-type.rs:8:38
+   |
+LL |     fn func<const N: u32>() -> [ (); N ];
+   |                                      ^ expected `usize`, found `u32`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.