diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-28 17:17:25 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-28 17:17:25 +0100 |
| commit | 76fe44928281ae6f1ffe881712e02fb2358a4883 (patch) | |
| tree | f3f229177d5a6e3cd1c0d31de5da10aa420853fb | |
| parent | bbf6eec2816d8ce34d2ae51b40e4bb9425b8f65e (diff) | |
| parent | 6672a047188c1590f13ec9b6dd1b00b35d2bd9c9 (diff) | |
| download | rust-76fe44928281ae6f1ffe881712e02fb2358a4883.tar.gz rust-76fe44928281ae6f1ffe881712e02fb2358a4883.zip | |
Rollup merge of #69340 - Centril:self-ctor-normalize, r=nikomatsakis
instantiate_value_path: on `SelfCtor`, avoid unconstrained tyvars Fixes https://github.com/rust-lang/rust/issues/69306. On `Self(...)` (that is, a `Res::SelfCtor`), do not use `self.impl_self_ty(...)`. The problem with that method is that it creates unconstrained inference variables for type parameters in the `impl` (e.g. `impl<T> S0<T>`). These variables then eventually get substituted for something else when they come in contact with the expected type (e.g. `S0<u8>`) or merely the arguments passed to the tuple constructor (e.g. the `0` in `Self(0)`). Instead of using `self.impl_self_ty(...)`, we instead merely use `let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id));` to get the rewritten `res`. r? @eddyb
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 6 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-69306.rs | 45 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-69306.stderr | 115 |
3 files changed, 162 insertions, 4 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3c71e8bf6b8..057d5510551 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5447,9 +5447,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(); @@ -5464,7 +5462,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 00000000000..85d60952ac8 --- /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 00000000000..a2a42739ca8 --- /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`. |
