From fb9030d7ddf1fe8c9657af3f8361d38a1742a803 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Mon, 7 Aug 2023 19:05:59 +0000
Subject: [PATCH 1/2] Structurally normalize weak and inherent too

---
 compiler/rustc_hir_analysis/src/autoderef.rs                  | 2 +-
 compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs                | 2 +-
 .../rustc_trait_selection/src/traits/structural_normalize.rs  | 4 +++-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index c07ac35cba3..39db295044e 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -74,7 +74,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
             // we have some type like `&<Ty as Trait>::Assoc`, since users of
             // autoderef expect this type to have been structurally normalized.
             if self.infcx.next_trait_solver()
-                && let ty::Alias(ty::Projection, _) = ty.kind()
+                && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
             {
                 let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
                 self.state.obligations.extend(obligations);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 1433c67d55d..322d726a89d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1474,7 +1474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = self.resolve_vars_with_obligations(ty);
 
         if self.next_trait_solver()
-            && let ty::Alias(ty::Projection, _) = ty.kind()
+            && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
         {
             match self
                 .at(&self.misc(sp), self.param_env)
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index 84746eba3ec..d3c4dc45923 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -22,7 +22,9 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
         assert!(!ty.is_ty_var(), "should have resolved vars before calling");
 
         if self.infcx.next_trait_solver() {
-            while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
+            while let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, projection_ty) =
+                *ty.kind()
+            {
                 let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::NormalizeProjectionType,
                     span: self.cause.span,

From ba4a2f7cb72016613ac4b1fe66ee2f6704d9cd73 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Mon, 7 Aug 2023 18:51:38 +0000
Subject: [PATCH 2/2] Resolve target type of coercion

---
 compiler/rustc_hir_typeck/src/coercion.rs     |  8 +++-
 tests/ui/for/issue-20605.next.stderr          | 12 +++---
 .../coerce-behind-lazy.current.stderr         | 11 ++++++
 .../coerce-behind-lazy.next.stderr            | 11 ++++++
 .../ui/lazy-type-alias/coerce-behind-lazy.rs  | 16 ++++++++
 .../new-solver/lazy-nested-obligations-2.rs   |  2 +-
 .../lazy-nested-obligations-2.stderr          | 39 -------------------
 .../new-solver/more-object-bound.stderr       |  4 +-
 8 files changed, 53 insertions(+), 50 deletions(-)
 create mode 100644 tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
 create mode 100644 tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
 create mode 100644 tests/ui/lazy-type-alias/coerce-behind-lazy.rs
 delete mode 100644 tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr

diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index fa6bad84376..b2b3f435505 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1012,6 +1012,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         cause: Option<ObligationCause<'tcx>>,
     ) -> RelateResult<'tcx, Ty<'tcx>> {
         let source = self.try_structurally_resolve_type(expr.span, expr_ty);
+        let target = self.try_structurally_resolve_type(
+            cause.as_ref().map_or(expr.span, |cause| cause.span),
+            target,
+        );
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
         let cause =
@@ -1097,8 +1101,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     where
         E: AsCoercionSite,
     {
-        let prev_ty = self.resolve_vars_with_obligations(prev_ty);
-        let new_ty = self.resolve_vars_with_obligations(new_ty);
+        let prev_ty = self.try_structurally_resolve_type(cause.span, prev_ty);
+        let new_ty = self.try_structurally_resolve_type(new.span, new_ty);
         debug!(
             "coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)",
             prev_ty,
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index d55efedfcbe..0955efdbb73 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -34,12 +34,6 @@ error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIte
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^
 
-error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
-  --> $DIR/issue-20605.rs:5:27
-   |
-LL |     for item in *things { *item = 0 }
-   |                           ^^^^^
-
 error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
   --> $DIR/issue-20605.rs:5:9
    |
@@ -66,6 +60,12 @@ LL |     for item in *things { *item = 0 }
 note: required by a bound in `None`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
+error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
+  --> $DIR/issue-20605.rs:5:27
+   |
+LL |     for item in *things { *item = 0 }
+   |                           ^^^^^
+
 error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0277, E0614.
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr b/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
new file mode 100644
index 00000000000..98b3921dec4
--- /dev/null
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
@@ -0,0 +1,11 @@
+warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/coerce-behind-lazy.rs:5:12
+   |
+LL | #![feature(lazy_type_alias)]
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr b/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
new file mode 100644
index 00000000000..98b3921dec4
--- /dev/null
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/coerce-behind-lazy.rs:5:12
+   |
+LL | #![feature(lazy_type_alias)]
+   |            ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.rs b/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
new file mode 100644
index 00000000000..745eadb9625
--- /dev/null
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
@@ -0,0 +1,16 @@
+// check-pass
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
+#![feature(lazy_type_alias)]
+//~^ WARN the feature `lazy_type_alias` is incomplete
+
+use std::any::Any;
+
+type Coerce = Box<dyn Any>;
+
+fn test() -> Coerce {
+    Box::new(1)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs b/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs
index fd91d81cdf0..20f504928c7 100644
--- a/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs
+++ b/tests/ui/traits/new-solver/lazy-nested-obligations-2.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Ztrait-solver=next
-// known-bug: #95863
+// check-pass
 
 pub trait With {
     type F;
diff --git a/tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr b/tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr
deleted file mode 100644
index d0a4cd661b3..00000000000
--- a/tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/lazy-nested-obligations-2.rs:15:23
-   |
-LL |     let _: V<i32> = V(f);
-   |                     - ^ types differ
-   |                     |
-   |                     arguments to this struct are incorrect
-   |
-   = note: expected associated type `<i32 as With>::F`
-                      found fn item `for<'a> fn(&'a str) {f}`
-   = help: consider constraining the associated type `<i32 as With>::F` to `for<'a> fn(&'a str) {f}` or calling a method that returns `<i32 as With>::F`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-note: tuple struct defined here
-  --> $DIR/lazy-nested-obligations-2.rs:16:16
-   |
-LL |     pub struct V<T: With>(<T as With>::F);
-   |                ^
-
-error[E0308]: mismatched types
-  --> $DIR/lazy-nested-obligations-2.rs:21:30
-   |
-LL |     let _: E3<i32> = E3::Var(f);
-   |                      ------- ^ types differ
-   |                      |
-   |                      arguments to this enum variant are incorrect
-   |
-   = note: expected associated type `<i32 as With>::F`
-                      found fn item `for<'a> fn(&'a str) {f}`
-   = help: consider constraining the associated type `<i32 as With>::F` to `for<'a> fn(&'a str) {f}` or calling a method that returns `<i32 as With>::F`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-note: tuple variant defined here
-  --> $DIR/lazy-nested-obligations-2.rs:19:9
-   |
-LL |         Var(<T as With>::F),
-   |         ^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr
index 4554b8c7473..54965dee184 100644
--- a/tests/ui/traits/new-solver/more-object-bound.stderr
+++ b/tests/ui/traits/new-solver/more-object-bound.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied
-  --> $DIR/more-object-bound.rs:12:17
+  --> $DIR/more-object-bound.rs:12:5
    |
 LL |     foo::<A, B, dyn Trait<A = A, B = B>>(x)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait<A = A, B = B>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait<A = A, B = B>`
    |
 note: required by a bound in `foo`
   --> $DIR/more-object-bound.rs:18:8