Auto merge of #70272 - eddyb:type-of-impl-trait, r=nikomatsakis

typeck/type_of: let wfcheck handle generics in opaque types' substs.

I was working on #70164, and `type_of`'s handling of opaque types seemed to be, by far, the trickiest use of `Ty::walk`, but I believe it wasn't doing anything (see https://github.com/rust-lang/rust/pull/57896#discussion_r396064431 - I suspect, based on glancing at the PR discussion, that an early attempt was kept in, despite becoming just an overcomplicated way to do exactly the same as the previous simple type equality check).

I would've loved to remove `ResolvedOpaqueTy` (keep the `Ty` and lose the `Substs`), but it looks like the MIR borrowck part of the process needs that now, so it would've been added anyway since #57896, even if that PR hadn't happened.

<hr/>

In the process, I've moved the remaining substitution validation to `wfcheck`, which was already handling lifetimes, and kept only `delay_span_bug`s in `type_of`, as an insurance policy.

I've added tests for lifetime and const cases, they seem to be checked correctly now.
(and more uniform than they were in https://github.com/rust-lang/rust/issues/63063#issuecomment-602162804)

However, the quality of the errors is maybe a bit worse, and they don't trigger when there are other errors (not sure if this is due to compilation stop points or something more specific to one opaque type).

r? @nikomatsakis cc @matthewjasper @oli-obk @Aaron1011
This commit is contained in:
bors 2020-04-04 09:16:19 +00:00
commit 49dc2f9f09
21 changed files with 281 additions and 316 deletions

View file

@ -8,13 +8,12 @@ trait TraitWithAssoc {
}
type Foo<V> = impl Trait<V>;
//~^ ERROR could not find defining uses
//~| ERROR the trait bound `T: TraitWithAssoc` is not satisfied
//~^ ERROR the trait bound `T: TraitWithAssoc` is not satisfied
trait Trait<U> {}
impl<W> Trait<W> for () {}
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
()
}

View file

@ -9,20 +9,6 @@ help: consider further restricting this bound
LL | fn foo_desugared<T: TraitWithAssoc + TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
| ^^^^^^^^^^^^^^^^
error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `<T as TraitWithAssoc>::Assoc`
--> $DIR/bound_reduction2.rs:18:1
|
LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
LL | | ()
LL | | }
| |_^
error: could not find defining uses
--> $DIR/bound_reduction2.rs:10:1
|
LL | type Foo<V> = impl Trait<V>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,14 +1,26 @@
#![feature(type_alias_impl_trait)]
#![feature(type_alias_impl_trait, const_generics)]
#![allow(incomplete_features)]
use std::fmt::Debug;
fn main() {}
// test that unused generic parameters are ok
type Two<T, U> = impl Debug;
//~^ could not find defining uses
type TwoTys<T, U> = impl Debug;
type TwoLifetimes<'a, 'b> = impl Debug;
type TwoConsts<const X: usize, const Y: usize> = impl Debug;
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ ERROR defining opaque type use restricts opaque type
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
//~^ ERROR non-defining opaque type use in defining scope
t
}
fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
//~^ ERROR non-defining opaque type use in defining scope
t
}
fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
//~^ ERROR non-defining opaque type use in defining scope
t
}

View file

@ -1,17 +1,38 @@
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
--> $DIR/generic_duplicate_param_use.rs:11:1
error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:13:30
|
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
LL | |
LL | | t
LL | | }
| |_^
error: could not find defining uses
--> $DIR/generic_duplicate_param_use.rs:8:1
LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
| ^^^^^^^^^^^^
|
LL | type Two<T, U> = impl Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: type used multiple times
--> $DIR/generic_duplicate_param_use.rs:9:13
|
LL | type TwoTys<T, U> = impl Debug;
| ^ ^
error: aborting due to 2 previous errors
error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:18:36
|
LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
| ^^^^^^^^^^^^^^^^^^^^
|
note: lifetime used multiple times
--> $DIR/generic_duplicate_param_use.rs:10:19
|
LL | type TwoLifetimes<'a, 'b> = impl Debug;
| ^^ ^^
error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:23:50
|
LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
| ^^^^^^^^^^^^^^^
|
note: constant used multiple times
--> $DIR/generic_duplicate_param_use.rs:11:22
|
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
| ^ ^
error: aborting due to 3 previous errors

View file

@ -8,10 +8,10 @@ fn main() {}
type Two<T, U> = impl Debug;
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ defining opaque type use restricts opaque type
t
}
fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
//~^ ERROR concrete type differs from previous defining opaque type use
t
}

View file

@ -1,8 +1,16 @@
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use2.rs:14:1
|
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
LL | |
LL | | t
LL | | }
| |_^ expected `U`, got `T`
|
note: previous use here
--> $DIR/generic_duplicate_param_use2.rs:10:1
|
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
LL | |
LL | | t
LL | | }
| |_^

View file

@ -8,15 +8,14 @@ fn main() {}
type Two<T, U> = impl Debug;
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ defining opaque type use restricts opaque type
t
}
fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
//~^ ERROR concrete type differs from previous defining opaque type use
t
}
fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
//~^ concrete type's generic parameters differ from previous defining use
u
}

View file

@ -1,28 +1,19 @@
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use3.rs:14:1
|
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
LL | |
LL | | t
LL | | }
| |_^ expected `U`, got `T`
|
note: previous use here
--> $DIR/generic_duplicate_param_use3.rs:10:1
|
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
LL | |
LL | | t
LL | | }
| |_^
error: concrete type's generic parameters differ from previous defining use
--> $DIR/generic_duplicate_param_use3.rs:19:1
|
LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
LL | |
LL | | u
LL | | }
| |_^ expected [`T`], got [`U`]
|
note: previous use here
--> $DIR/generic_duplicate_param_use3.rs:15:1
|
LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
LL | | t
LL | | }
| |_^
error: aborting due to 2 previous errors
error: aborting due to previous error

View file

@ -8,7 +8,7 @@ fn main() {}
type Two<T, U> = impl Debug;
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ ERROR defining opaque type use restricts opaque type
//~^ ERROR non-defining opaque type use in defining scope
t
}

View file

@ -1,11 +1,14 @@
error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
--> $DIR/generic_duplicate_param_use4.rs:10:1
error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use4.rs:10:27
|
LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
LL | |
LL | | t
LL | | }
| |_^
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
| ^^^^^^^^^
|
note: type used multiple times
--> $DIR/generic_duplicate_param_use4.rs:8:10
|
LL | type Two<T, U> = impl Debug;
| ^ ^
error: aborting due to previous error

View file

@ -1,13 +1,27 @@
#![feature(type_alias_impl_trait)]
#![feature(type_alias_impl_trait, const_generics)]
#![allow(incomplete_features)]
use std::fmt::Debug;
fn main() {}
type Cmp<T> = impl 'static;
//~^ ERROR could not find defining uses
//~^^ ERROR: at least one trait must be specified
type OneTy<T> = impl Debug;
type OneLifetime<'a> = impl Debug;
type OneConst<const X: usize> = impl Debug;
// Not defining uses, because they doesn't define *all* possible generics.
// not a defining use, because it doesn't define *all* possible generics
fn cmp() -> Cmp<u32> { //~ ERROR defining opaque type use does not fully define
fn concrete_ty() -> OneTy<u32> {
//~^ ERROR non-defining opaque type use in defining scope
5u32
}
fn concrete_lifetime() -> OneLifetime<'static> {
//~^ ERROR non-defining opaque type use in defining scope
6u32
}
fn concrete_const() -> OneConst<{123}> {
//~^ ERROR non-defining opaque type use in defining scope
7u32
}

View file

@ -1,22 +1,35 @@
error: at least one trait must be specified
--> $DIR/generic_nondefining_use.rs:5:15
error: non-defining opaque type use in defining scope
--> $DIR/generic_nondefining_use.rs:14:21
|
LL | type Cmp<T> = impl 'static;
| ^^^^^^^^^^^^
LL | fn concrete_ty() -> OneTy<u32> {
| ^^^^^^^^^^
|
note: used non-generic type `u32` for generic parameter
--> $DIR/generic_nondefining_use.rs:8:12
|
LL | type OneTy<T> = impl Debug;
| ^
error: defining opaque type use does not fully define opaque type: generic parameter `T` is specified as concrete type `u32`
--> $DIR/generic_nondefining_use.rs:11:1
error: non-defining opaque type use in defining scope
--> $DIR/generic_nondefining_use.rs:19:27
|
LL | / fn cmp() -> Cmp<u32> {
LL | | 5u32
LL | | }
| |_^
LL | type OneLifetime<'a> = impl Debug;
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
...
LL | fn concrete_lifetime() -> OneLifetime<'static> {
| ^^^^^^^^^^^^^^^^^^^^
error: could not find defining uses
--> $DIR/generic_nondefining_use.rs:5:1
error: non-defining opaque type use in defining scope
--> $DIR/generic_nondefining_use.rs:24:24
|
LL | type Cmp<T> = impl 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | fn concrete_const() -> OneConst<{123}> {
| ^^^^^^^^^^^^^^^
|
note: used non-generic constant `123usize` for generic parameter
--> $DIR/generic_nondefining_use.rs:10:21
|
LL | type OneConst<const X: usize> = impl Debug;
| ^
error: aborting due to 3 previous errors

View file

@ -6,7 +6,6 @@ trait IterBits {
}
type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
//~^ ERROR could not find defining uses
impl<T: Copy, E> IterBits for T
where
@ -18,7 +17,8 @@ where
{
type BitsIter = IterBitsIter<T, E, u8>;
fn iter_bits(self, n: u8) -> Self::BitsIter {
//~^ ERROR defining opaque type use does not fully define opaque type
//~^ ERROR non-defining opaque type use in defining scope
//~| ERROR non-defining opaque type use in defining scope
(0u8..n)
.rev()
.map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())

View file

@ -1,19 +1,26 @@
error: defining opaque type use does not fully define opaque type: generic parameter `I` is specified as concrete type `u8`
--> $DIR/issue-60564.rs:20:5
error: non-defining opaque type use in defining scope
--> $DIR/issue-60564.rs:19:34
|
LL | / fn iter_bits(self, n: u8) -> Self::BitsIter {
LL | |
LL | | (0u8..n)
LL | | .rev()
LL | | .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
LL | | }
| |_____^
error: could not find defining uses
--> $DIR/issue-60564.rs:8:1
LL | fn iter_bits(self, n: u8) -> Self::BitsIter {
| ^^^^^^^^^^^^^^
|
note: used non-generic type `_` for generic parameter
--> $DIR/issue-60564.rs:8:22
|
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^
error: non-defining opaque type use in defining scope
--> $DIR/issue-60564.rs:19:34
|
LL | fn iter_bits(self, n: u8) -> Self::BitsIter {
| ^^^^^^^^^^^^^^
|
note: used non-generic type `u8` for generic parameter
--> $DIR/issue-60564.rs:8:25
|
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
| ^
error: aborting due to 2 previous errors

View file

@ -4,9 +4,9 @@
#![feature(type_alias_impl_trait)]
trait Trait<T> {}
type Alias<'a, U> = impl Trait<U>; //~ ERROR could not find defining uses
type Alias<'a, U> = impl Trait<U>;
fn f<'a>() -> Alias<'a, ()> {}
//~^ ERROR defining opaque type use does not fully define opaque type: generic parameter `U`
//~^ ERROR non-defining opaque type use in defining scope
fn main() {}

View file

@ -1,14 +1,14 @@
error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `()`
--> $DIR/issue-68368-non-defining-use.rs:8:1
error: non-defining opaque type use in defining scope
--> $DIR/issue-68368-non-defining-use.rs:8:15
|
LL | fn f<'a>() -> Alias<'a, ()> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: could not find defining uses
--> $DIR/issue-68368-non-defining-use.rs:7:1
| ^^^^^^^^^^^^^
|
note: used non-generic type `()` for generic parameter
--> $DIR/issue-68368-non-defining-use.rs:7:16
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^
error: aborting due to 2 previous errors
error: aborting due to previous error

View file

@ -7,7 +7,6 @@ fn main() {}
type Two<T, U> = impl Debug;
fn two<T: Debug>(t: T) -> Two<T, u32> {
//~^ ERROR defining opaque type use does not fully define opaque type
(t, 4i8)
}

View file

@ -1,14 +1,5 @@
error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `u32`
--> $DIR/not_a_defining_use.rs:9:1
|
LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
LL | |
LL | | (t, 4i8)
LL | | }
| |_^
error: concrete type differs from previous defining opaque type use
--> $DIR/not_a_defining_use.rs:30:1
--> $DIR/not_a_defining_use.rs:29:1
|
LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
LL | | (t, <U as Bar>::FOO)
@ -16,12 +7,12 @@ LL | | }
| |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
|
note: previous use here
--> $DIR/not_a_defining_use.rs:14:1
--> $DIR/not_a_defining_use.rs:9:1
|
LL | / fn three<T: Debug, U>(t: T) -> Two<T, U> {
LL | | (t, 5i8)
LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
LL | | (t, 4i8)
LL | | }
| |_^
error: aborting due to 2 previous errors
error: aborting due to previous error