From 6672a047188c1590f13ec9b6dd1b00b35d2bd9c9 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Fri, 21 Feb 2020 04:53:32 +0100
Subject: [PATCH] instantiate_value_path: .impl_self_ty -> .type_of

---
 src/librustc_typeck/check/mod.rs      |   6 +-
 src/test/ui/issues/issue-69306.rs     |  45 ++++++++++
 src/test/ui/issues/issue-69306.stderr | 115 ++++++++++++++++++++++++++
 3 files changed, 162 insertions(+), 4 deletions(-)
 create mode 100644 src/test/ui/issues/issue-69306.rs
 create mode 100644 src/test/ui/issues/issue-69306.stderr

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4ab5d8f9ad3f6..698b0e9bfcb87 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5446,9 +5446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .unwrap_or(false);
 
         let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
-            let ty = self.impl_self_ty(span, impl_def_id).ty;
-            let adt_def = ty.ty_adt_def();
-
+            let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id));
             match ty.kind {
                 ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
                     let variant = adt_def.non_enum_variant();
@@ -5463,7 +5461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         span,
                         "the `Self` constructor can only be used with tuple or unit structs",
                     );
-                    if let Some(adt_def) = adt_def {
+                    if let Some(adt_def) = ty.ty_adt_def() {
                         match adt_def.adt_kind() {
                             AdtKind::Enum => {
                                 err.help("did you mean to use one of the enum's variants?");
diff --git a/src/test/ui/issues/issue-69306.rs b/src/test/ui/issues/issue-69306.rs
new file mode 100644
index 0000000000000..85d60952ac823
--- /dev/null
+++ b/src/test/ui/issues/issue-69306.rs
@@ -0,0 +1,45 @@
+fn main() {}
+
+struct S0<T>(T);
+impl<T> S0<T> {
+    const C: S0<u8> = Self(0);
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+
+    fn foo() {
+        Self(0);
+        //~^ ERROR mismatched types
+    }
+}
+
+// Testing normalization.
+trait Fun {
+    type Out;
+}
+impl<T> Fun for S0<T> {
+    type Out = Self;
+}
+trait Foo<T> {
+    fn foo();
+}
+impl<T> Foo<T> for <S0<T> as Fun>::Out {
+    fn foo() {
+        Self(0); //~ ERROR mismatched types
+    }
+}
+
+struct S1<T, U>(T, U);
+impl<T> S1<T, u8> {
+    const C: S1<u8, u8> = Self(0, 1);
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+struct S2<T>(T);
+impl<T> S2<T> {
+    fn map<U>(x: U) -> S2<U> {
+        Self(x)
+        //~^ ERROR mismatched types
+        //~| ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/issues/issue-69306.stderr b/src/test/ui/issues/issue-69306.stderr
new file mode 100644
index 0000000000000..a2a42739ca8be
--- /dev/null
+++ b/src/test/ui/issues/issue-69306.stderr
@@ -0,0 +1,115 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:5:28
+   |
+LL | impl<T> S0<T> {
+   |      - this type parameter
+LL |     const C: S0<u8> = Self(0);
+   |                            ^ expected type parameter `T`, found integer
+   |
+   = note: expected type parameter `T`
+                        found type `{integer}`
+   = help: type parameters must be constrained to match other types
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:5:23
+   |
+LL | impl<T> S0<T> {
+   |      - this type parameter
+LL |     const C: S0<u8> = Self(0);
+   |                       ^^^^^^^ expected `u8`, found type parameter `T`
+   |
+   = note: expected struct `S0<u8>`
+              found struct `S0<T>`
+   = help: type parameters must be constrained to match other types
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:10:14
+   |
+LL | impl<T> S0<T> {
+   |      - this type parameter
+...
+LL |         Self(0);
+   |              ^ expected type parameter `T`, found integer
+   |
+   = note: expected type parameter `T`
+                        found type `{integer}`
+   = help: type parameters must be constrained to match other types
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:27:14
+   |
+LL | impl<T> Foo<T> for <S0<T> as Fun>::Out {
+   |      - this type parameter
+LL |     fn foo() {
+LL |         Self(0);
+   |              ^ expected type parameter `T`, found integer
+   |
+   = note: expected type parameter `T`
+                        found type `{integer}`
+   = help: type parameters must be constrained to match other types
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:33:32
+   |
+LL | impl<T> S1<T, u8> {
+   |      - this type parameter
+LL |     const C: S1<u8, u8> = Self(0, 1);
+   |                                ^ expected type parameter `T`, found integer
+   |
+   = note: expected type parameter `T`
+                        found type `{integer}`
+   = help: type parameters must be constrained to match other types
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:33:27
+   |
+LL | impl<T> S1<T, u8> {
+   |      - this type parameter
+LL |     const C: S1<u8, u8> = Self(0, 1);
+   |                           ^^^^^^^^^^ expected `u8`, found type parameter `T`
+   |
+   = note: expected struct `S1<u8, _>`
+              found struct `S1<T, _>`
+   = help: type parameters must be constrained to match other types
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:41:14
+   |
+LL | impl<T> S2<T> {
+   |      - expected type parameter
+LL |     fn map<U>(x: U) -> S2<U> {
+   |            - found type parameter
+LL |         Self(x)
+   |              ^ expected type parameter `T`, found type parameter `U`
+   |
+   = note: expected type parameter `T`
+              found type parameter `U`
+   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69306.rs:41:9
+   |
+LL | impl<T> S2<T> {
+   |      - found type parameter
+LL |     fn map<U>(x: U) -> S2<U> {
+   |            -           ----- expected `S2<U>` because of return type
+   |            |
+   |            expected type parameter
+LL |         Self(x)
+   |         ^^^^^^^ expected type parameter `U`, found type parameter `T`
+   |
+   = note: expected struct `S2<U>`
+              found struct `S2<T>`
+   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.