Skip to content

Commit

Permalink
Rollup merge of rust-lang#69340 - Centril:self-ctor-normalize, r=niko…
Browse files Browse the repository at this point in the history
…matsakis

instantiate_value_path: on `SelfCtor`, avoid unconstrained tyvars

Fixes rust-lang#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
  • Loading branch information
Centril committed Feb 28, 2020
2 parents bbf6eec + 6672a04 commit 76fe449
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 4 deletions.
6 changes: 2 additions & 4 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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?");
Expand Down
45 changes: 45 additions & 0 deletions src/test/ui/issues/issue-69306.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
115 changes: 115 additions & 0 deletions src/test/ui/issues/issue-69306.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 76fe449

Please sign in to comment.