about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs57
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs69
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs11
-rw-r--r--tests/crashes/103899.rs27
-rw-r--r--tests/crashes/105299.rs19
-rw-r--r--tests/ui/dropck/dropck-only-error-ambiguity.rs23
-rw-r--r--tests/ui/dropck/dropck-only-error-ambiguity.stderr11
-rw-r--r--tests/ui/dropck/dropck-only-error-async.rs (renamed from tests/crashes/135039.rs)13
-rw-r--r--tests/ui/dropck/dropck-only-error-async.stderr15
-rw-r--r--tests/ui/dropck/dropck-only-error-gat.rs (renamed from tests/crashes/91985.rs)9
-rw-r--r--tests/ui/dropck/dropck-only-error-gat.stderr15
-rw-r--r--tests/ui/dropck/dropck-only-error.rs23
-rw-r--r--tests/ui/dropck/dropck-only-error.stderr9
-rw-r--r--tests/ui/typeck/issue-103899.current.stderr15
-rw-r--r--tests/ui/typeck/issue-103899.next.stderr15
-rw-r--r--tests/ui/typeck/issue-103899.rs5
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.rs4
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.stderr12
20 files changed, 262 insertions, 109 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 62d49a62744..148e75aa84c 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,7 +3,8 @@ use rustc_index::bit_set::DenseBitSet;
 use rustc_index::interval::IntervalSet;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::for_liveness;
-use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
+use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
+use rustc_middle::span_bug;
 use rustc_middle::traits::query::DropckOutlivesResult;
 use rustc_middle::ty::relate::Relate;
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
@@ -11,7 +12,10 @@ use rustc_mir_dataflow::ResultsCursor;
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
 use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
-use rustc_span::DUMMY_SP;
+use rustc_span::{DUMMY_SP, Span};
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
+use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::traits::query::dropck_outlives;
 use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
 use tracing::debug;
 
@@ -162,9 +166,10 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
     fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
         for local in boring_locals {
             let local_ty = self.cx.body.local_decls[local].ty;
+            let local_span = self.cx.body.local_decls[local].source_info.span;
             let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
                 let typeck = &self.cx.typeck;
-                move || LivenessContext::compute_drop_data(typeck, local_ty)
+                move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
             });
 
             drop_data.dropck_result.report_overflows(
@@ -522,9 +527,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             values::pretty_print_points(self.location_map, live_at.iter()),
         );
 
+        let local_span = self.body.local_decls()[dropped_local].source_info.span;
         let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
             let typeck = &self.typeck;
-            move || Self::compute_drop_data(typeck, dropped_ty)
+            move || Self::compute_drop_data(typeck, dropped_ty, local_span)
         });
 
         if let Some(data) = &drop_data.region_constraint_data {
@@ -589,19 +595,44 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         }
     }
 
-    fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> {
-        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
+    fn compute_drop_data(
+        typeck: &TypeChecker<'_, 'tcx>,
+        dropped_ty: Ty<'tcx>,
+        span: Span,
+    ) -> DropData<'tcx> {
+        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty);
+
+        let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
 
-        match typeck
-            .infcx
-            .param_env
-            .and(DropckOutlives { dropped_ty })
-            .fully_perform(typeck.infcx, DUMMY_SP)
-        {
+        match op.fully_perform(typeck.infcx, DUMMY_SP) {
             Ok(TypeOpOutput { output, constraints, .. }) => {
                 DropData { dropck_result: output, region_constraint_data: constraints }
             }
-            Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+            Err(_) => {
+                // We don't run dropck on HIR, and dropck looks inside fields of
+                // types, so there's no guarantee that it succeeds. We also
+                // can't rely on the the `ErrorGuaranteed` from `fully_perform` here
+                // because it comes from delay_span_bug.
+                let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
+                let errors =
+                    match dropck_outlives::compute_dropck_outlives_with_errors(&ocx, op, span) {
+                        Ok(_) => ocx.select_all_or_error(),
+                        Err(e) => {
+                            if e.is_empty() {
+                                ocx.select_all_or_error()
+                            } else {
+                                e
+                            }
+                        }
+                    };
+
+                if !errors.is_empty() {
+                    typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
+                } else {
+                    span_bug!(span, "Rerunning drop data query produced no error.");
+                }
+                DropData { dropck_result: Default::default(), region_constraint_data: None }
+            }
         }
     }
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 693823b4af4..7c4ea06a746 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -802,7 +802,7 @@ rustc_queries! {
 
     query adt_dtorck_constraint(
         key: DefId
-    ) -> Result<&'tcx DropckConstraint<'tcx>, NoSolution> {
+    ) -> &'tcx DropckConstraint<'tcx> {
         desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
     }
 
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 9330a9481f5..0d8cf524661 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -266,8 +266,21 @@ where
                 let tcx = self.tcx();
 
                 assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
-                let field_ty =
-                    tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args));
+                // The type error for normalization may have been in dropck: see
+                // `compute_drop_data` in rustc_borrowck, in which case we wouldn't have
+                // deleted the MIR body and could have an error here as well.
+                let field_ty = match tcx
+                    .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args))
+                {
+                    Ok(t) => t,
+                    Err(_) => Ty::new_error(
+                        self.tcx(),
+                        self.elaborator
+                            .body()
+                            .tainted_by_errors
+                            .expect("Error in drop elaboration not found by dropck."),
+                    ),
+                };
 
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 92098e20448..f04a5feba30 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_infer::traits::query::type_op::DropckOutlives;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::Span;
 use tracing::{debug, instrument};
 
+use crate::solve::NextSolverError;
 use crate::traits::query::NoSolution;
 use crate::traits::query::normalize::QueryNormalizeExt;
-use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
+use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt};
 
 /// This returns true if the type `ty` is "trivial" for
 /// dropck-outlives -- that is, if it doesn't require any types to
@@ -93,6 +94,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
     goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
     span: Span,
 ) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
+    match compute_dropck_outlives_with_errors(ocx, goal, span) {
+        Ok(r) => Ok(r),
+        Err(_) => Err(NoSolution),
+    }
+}
+
+pub fn compute_dropck_outlives_with_errors<'tcx, E>(
+    ocx: &ObligationCtxt<'_, 'tcx, E>,
+    goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
+    span: Span,
+) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     let tcx = ocx.infcx.tcx;
     let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
 
@@ -149,11 +164,11 @@ pub fn compute_dropck_outlives_inner<'tcx>(
         dtorck_constraint_for_ty_inner(
             tcx,
             ocx.infcx.typing_env(param_env),
-            DUMMY_SP,
+            span,
             depth,
             ty,
             &mut constraints,
-        )?;
+        );
 
         // "outlives" represent types/regions that may be touched
         // by a destructor.
@@ -173,11 +188,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
         // do not themselves define a destructor", more or less. We have
         // to push them onto the stack to be expanded.
         for ty in constraints.dtorck_types.drain(..) {
-            let Normalized { value: ty, obligations } =
-                ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
-            ocx.register_obligations(obligations);
+            let ty = if let Ok(Normalized { value: ty, obligations }) =
+                ocx.infcx.at(&cause, param_env).query_normalize(ty)
+            {
+                ocx.register_obligations(obligations);
+
+                debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+                ty
+            } else {
+                ocx.deeply_normalize(&cause, param_env, ty)?;
 
-            debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+                let errors = ocx.select_where_possible();
+                debug!("normalize errors: {ty} ~> {errors:#?}");
+                return Err(errors);
+            };
 
             match ty.kind() {
                 // All parameters live for the duration of the
@@ -213,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
     depth: usize,
     ty: Ty<'tcx>,
     constraints: &mut DropckConstraint<'tcx>,
-) -> Result<(), NoSolution> {
+) {
     if !tcx.recursion_limit().value_within_limit(depth) {
         constraints.overflows.push(ty);
-        return Ok(());
+        return;
     }
 
     if trivial_dropck_outlives(tcx, ty) {
-        return Ok(());
+        return;
     }
 
     match ty.kind() {
@@ -244,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // single-element containers, behave like their element
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
                 dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
-            })?;
+            });
         }
 
         ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in tys.iter() {
-                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
             }
-            Ok::<_, NoSolution>(())
-        })?,
+        }),
 
         ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in args.as_closure().upvar_tys() {
-                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
             }
-            Ok::<_, NoSolution>(())
-        })?,
+        }),
 
         ty::CoroutineClosure(_, args) => {
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
@@ -271,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
                         depth + 1,
                         ty,
                         constraints,
-                    )?;
+                    );
                 }
-                Ok::<_, NoSolution>(())
-            })?
+            })
         }
 
         ty::Coroutine(_, args) => {
@@ -313,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
 
         ty::Adt(def, args) => {
             let DropckConstraint { dtorck_types, outlives, overflows } =
-                tcx.at(span).adt_dtorck_constraint(def.did())?;
+                tcx.at(span).adt_dtorck_constraint(def.did());
             // FIXME: we can try to recursively `dtorck_constraint_on_ty`
             // there, but that needs some way to handle cycles.
             constraints
@@ -346,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
         ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
-            return Err(NoSolution);
+            tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty));
         }
     }
-
-    Ok(())
 }
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index b3377e15aa7..5eddad39e2b 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -30,10 +30,7 @@ fn dropck_outlives<'tcx>(
 }
 
 /// Calculates the dtorck constraint for a type.
-pub(crate) fn adt_dtorck_constraint(
-    tcx: TyCtxt<'_>,
-    def_id: DefId,
-) -> Result<&DropckConstraint<'_>, NoSolution> {
+pub(crate) fn adt_dtorck_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &DropckConstraint<'_> {
     let def = tcx.adt_def(def_id);
     let span = tcx.def_span(def_id);
     let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
@@ -52,20 +49,20 @@ pub(crate) fn adt_dtorck_constraint(
             overflows: vec![],
         };
         debug!("dtorck_constraint: {:?} => {:?}", def, result);
-        return Ok(tcx.arena.alloc(result));
+        return tcx.arena.alloc(result);
     }
 
     let mut result = DropckConstraint::empty();
     for field in def.all_fields() {
         let fty = tcx.type_of(field.did).instantiate_identity();
-        dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?;
+        dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result);
     }
     result.outlives.extend(tcx.destructor_constraints(def));
     dedup_dtorck_constraint(&mut result);
 
     debug!("dtorck_constraint: {:?} => {:?}", def, result);
 
-    Ok(tcx.arena.alloc(result))
+    tcx.arena.alloc(result)
 }
 
 fn dedup_dtorck_constraint(c: &mut DropckConstraint<'_>) {
diff --git a/tests/crashes/103899.rs b/tests/crashes/103899.rs
deleted file mode 100644
index 39c2d72bd35..00000000000
--- a/tests/crashes/103899.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//@ known-bug: #103899
-
-trait BaseWithAssoc {
-    type Assoc;
-}
-
-trait WrapperWithAssoc {
-    type BaseAssoc: BaseWithAssoc;
-}
-
-struct Wrapper<B> {
-    inner: B,
-}
-
-struct ProjectToBase<T: BaseWithAssoc> {
-    data_type_h: T::Assoc,
-}
-
-struct DoubleProject<L: WrapperWithAssoc> {
-    buffer: Wrapper<ProjectToBase<L::BaseAssoc>>,
-}
-
-fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
-    loop {}
-}
-
-fn main() {}
diff --git a/tests/crashes/105299.rs b/tests/crashes/105299.rs
deleted file mode 100644
index 8e3aafa47bc..00000000000
--- a/tests/crashes/105299.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//@ known-bug: #105299
-
-pub trait Foo: Clone {}
-
-pub struct Bar<'a, T: Clone> {
-    pub cow: std::borrow::Cow<'a, [T]>,
-
-    pub THIS_CAUSES_ICE: (), // #1
-}
-
-impl<T> Bar<'_, T>
-where
-    T: Clone,
-    [T]: Foo,
-{
-    pub fn MOVES_SELF(self) {} // #2
-}
-
-pub fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error-ambiguity.rs b/tests/ui/dropck/dropck-only-error-ambiguity.rs
new file mode 100644
index 00000000000..ddba2af7070
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-ambiguity.rs
@@ -0,0 +1,23 @@
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// Version where the normalization error is an ambiguous trait implementation.
+// <[T] as ToOwned>::Owned is ambiguous on whether to use T: Clone or [T]::Clone.
+// Regression test for #105299
+
+pub trait Foo: Clone {}
+
+pub struct Bar<'a, T: Clone> {
+    pub cow: std::borrow::Cow<'a, [T]>,
+
+    pub THIS_CAUSES_ICE: (),
+}
+
+impl<T> Bar<'_, T>
+where
+    T: Clone,
+    [T]: Foo,
+{
+    pub fn MOVES_SELF(self) {}
+    //~^ ERROR type annotations needed
+}
+
+pub fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error-ambiguity.stderr b/tests/ui/dropck/dropck-only-error-ambiguity.stderr
new file mode 100644
index 00000000000..de19bd49f4e
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-ambiguity.stderr
@@ -0,0 +1,11 @@
+error[E0284]: type annotations needed
+  --> $DIR/dropck-only-error-ambiguity.rs:19:23
+   |
+LL |     pub fn MOVES_SELF(self) {}
+   |                       ^^^^ cannot infer type
+   |
+   = note: cannot satisfy `<[T] as ToOwned>::Owned == _`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/crashes/135039.rs b/tests/ui/dropck/dropck-only-error-async.rs
index c4c5336fd4f..71158e3c6ef 100644
--- a/tests/crashes/135039.rs
+++ b/tests/ui/dropck/dropck-only-error-async.rs
@@ -1,7 +1,6 @@
-//@ known-bug: #135039
-//@ edition:2021
-
-pub type UserId<Backend> = <<Backend as AuthnBackend>::User as AuthUser>::Id;
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// issue #135039
+//@ edition:2018
 
 pub trait AuthUser {
     type Id;
@@ -13,7 +12,7 @@ pub trait AuthnBackend {
 
 pub struct AuthSession<Backend: AuthnBackend> {
     user: Option<Backend::User>,
-    data: Option<UserId<Backend>>,
+    data: Option<<<Backend as AuthnBackend>::User as AuthUser>::Id>,
 }
 
 pub trait Authz: Sized {
@@ -27,8 +26,12 @@ pub trait Query<User: Authz> {
 
 pub async fn run_query<User: Authz, Q: Query<User> + 'static>(
     auth: AuthSession<User::AuthnBackend>,
+    //~^ ERROR the trait bound `User: AuthUser` is not satisfied [E0277]
+    //~| ERROR the trait bound `User: AuthUser` is not satisfied [E0277]
     query: Q,
 ) -> Result<Q::Output, ()> {
     let user = auth.user;
     query.run().await
 }
+
+fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error-async.stderr b/tests/ui/dropck/dropck-only-error-async.stderr
new file mode 100644
index 00000000000..4a069c8ac33
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-async.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `User: AuthUser` is not satisfied
+  --> $DIR/dropck-only-error-async.rs:28:5
+   |
+LL |     auth: AuthSession<User::AuthnBackend>,
+   |     ^^^^ the trait `AuthUser` is not implemented for `User`
+
+error[E0277]: the trait bound `User: AuthUser` is not satisfied
+  --> $DIR/dropck-only-error-async.rs:28:5
+   |
+LL |     auth: AuthSession<User::AuthnBackend>,
+   |     ^^^^ the trait `AuthUser` is not implemented for `User`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/crashes/91985.rs b/tests/ui/dropck/dropck-only-error-gat.rs
index 338550430e1..dadcf76a43f 100644
--- a/tests/crashes/91985.rs
+++ b/tests/ui/dropck/dropck-only-error-gat.rs
@@ -1,6 +1,6 @@
-//@ known-bug: #91985
-
-#![feature(generic_associated_types)]
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// Version that uses a generic associated type
+// Regression test for #91985
 
 pub trait Trait1 {
     type Associated: Ord;
@@ -22,7 +22,7 @@ impl GatTrait for GatStruct {
 
 pub struct OuterStruct<T1: Trait1, T2: Trait2> {
     inner: InnerStruct<T2, GatStruct>,
-    t1:    T1,
+    t1: T1,
 }
 
 pub struct InnerStruct<T: Trait2, G: GatTrait> {
@@ -35,6 +35,7 @@ where
     T2: Trait2<Associated = T1::Associated>,
 {
     pub fn new() -> Self {
+        //~^ ERROR the trait bound `<T1 as Trait1>::Associated: Clone` is not satisfied
         todo!()
     }
 }
diff --git a/tests/ui/dropck/dropck-only-error-gat.stderr b/tests/ui/dropck/dropck-only-error-gat.stderr
new file mode 100644
index 00000000000..53982c0826a
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error-gat.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `<T1 as Trait1>::Associated: Clone` is not satisfied
+  --> $DIR/dropck-only-error-gat.rs:37:21
+   |
+LL |     pub fn new() -> Self {
+   |                     ^^^^ the trait `Clone` is not implemented for `<T1 as Trait1>::Associated`
+   |
+note: required by a bound in `GatTrait::Gat`
+  --> $DIR/dropck-only-error-gat.rs:14:17
+   |
+LL |     type Gat<T: Clone>;
+   |                 ^^^^^ required by this bound in `GatTrait::Gat`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dropck/dropck-only-error.rs b/tests/ui/dropck/dropck-only-error.rs
new file mode 100644
index 00000000000..e85eeb82e00
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error.rs
@@ -0,0 +1,23 @@
+// Test that we don't ICE for a typeck error that only shows up in dropck
+// issue #135039
+
+pub trait AuthUser {
+    type Id;
+}
+
+pub trait AuthnBackend {
+    type User: AuthUser;
+}
+
+pub struct AuthSession<Backend: AuthnBackend> {
+    data: Option<<<Backend as AuthnBackend>::User as AuthUser>::Id>,
+}
+
+pub trait Authz: Sized {
+    type AuthnBackend: AuthnBackend<User = Self>;
+}
+
+pub fn run_query<User: Authz>(auth: AuthSession<User::AuthnBackend>) {}
+//~^ ERROR the trait bound `User: AuthUser` is not satisfied [E0277]
+
+fn main() {}
diff --git a/tests/ui/dropck/dropck-only-error.stderr b/tests/ui/dropck/dropck-only-error.stderr
new file mode 100644
index 00000000000..6c7cd5d296c
--- /dev/null
+++ b/tests/ui/dropck/dropck-only-error.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `User: AuthUser` is not satisfied
+  --> $DIR/dropck-only-error.rs:20:31
+   |
+LL | pub fn run_query<User: Authz>(auth: AuthSession<User::AuthnBackend>) {}
+   |                               ^^^^ the trait `AuthUser` is not implemented for `User`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/typeck/issue-103899.current.stderr b/tests/ui/typeck/issue-103899.current.stderr
new file mode 100644
index 00000000000..a3a164907be
--- /dev/null
+++ b/tests/ui/typeck/issue-103899.current.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied
+  --> $DIR/issue-103899.rs:24:54
+   |
+LL | fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
+   |                                                      ^^^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-103899.rs:4:1
+   |
+LL | trait BaseWithAssoc {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/typeck/issue-103899.next.stderr b/tests/ui/typeck/issue-103899.next.stderr
new file mode 100644
index 00000000000..a3a164907be
--- /dev/null
+++ b/tests/ui/typeck/issue-103899.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied
+  --> $DIR/issue-103899.rs:24:54
+   |
+LL | fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
+   |                                                      ^^^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-103899.rs:4:1
+   |
+LL | trait BaseWithAssoc {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs
index 81ab92a8994..92356ecf288 100644
--- a/tests/ui/typeck/issue-103899.rs
+++ b/tests/ui/typeck/issue-103899.rs
@@ -1,9 +1,5 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
-//@ check-fail
-//@ failure-status: 101
-//@ dont-check-compiler-stderr
-//@ known-bug: #103899
 
 trait BaseWithAssoc {
     type Assoc;
@@ -26,6 +22,7 @@ struct DoubleProject<L: WrapperWithAssoc> {
 }
 
 fn trigger<L: WrapperWithAssoc<BaseAssoc = ()>>() -> DoubleProject<L> {
+    //~^ ERROR the trait bound `(): BaseWithAssoc` is not satisfied [E0277]
     loop {}
 }
 
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs
index 01893044c27..20cc1cfe730 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.rs
+++ b/tests/ui/wf/hir-wf-check-erase-regions.rs
@@ -8,7 +8,9 @@ impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
     //~^ ERROR `&'a T` is not an iterator
     type Item = &'a T;
 
-    fn into_iter(self) -> Self::IntoIter { //~ ERROR `&'a T` is not an iterator
+    fn into_iter(self) -> Self::IntoIter {
+        //~^ ERROR `&'a T` is not an iterator
+        //~| ERROR `&T` is not an iterator
         unimplemented!()
     }
 }
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr
index 4b696dc1d1d..e4d48bf82c0 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr
@@ -34,6 +34,16 @@ LL |     fn into_iter(self) -> Self::IntoIter {
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: `&T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:11:27
+   |
+LL |     fn into_iter(self) -> Self::IntoIter {
+   |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `&T` to implement `IntoIterator`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.