Skip to content

Capture all lifetimes for TAITs and impl trait in associated types #114616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 30, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion compiler/rustc_hir_analysis/src/variance/mod.rs
Original file line number Diff line number Diff line change
@@ -129,7 +129,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc

// By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
// lifetime generics.
let mut variances: Vec<_> = std::iter::repeat(ty::Invariant).take(generics.count()).collect();
let variances = std::iter::repeat(ty::Invariant).take(generics.count());

let mut variances: Vec<_> = match tcx.opaque_type_origin(item_def_id) {
rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {
variances.collect()
}
// But TAIT are invariant for all generics
rustc_hir::OpaqueTyOrigin::TyAlias { .. } => return tcx.arena.alloc_from_iter(variances),
};

// Mark all lifetimes from parent generics as unused (Bivariant).
// This will be overridden later if required.
3 changes: 2 additions & 1 deletion tests/ui/impl-trait/issue-108591.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,8 @@ impl MyTy<'_> {
}
}

type Opaque<'a> = impl Sized;
type Opaque2 = impl Sized;
type Opaque<'a> = Opaque2;
fn define<'a>() -> Opaque<'a> {}

fn test<'a>() {
3 changes: 2 additions & 1 deletion tests/ui/impl-trait/issue-108592.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,8 @@ fn test_closure() {
closure(&opaque());
}

type Opaque<'a> = impl Sized;
type Opaque2 = impl Sized;
type Opaque<'a> = Opaque2;
fn define<'a>() -> Opaque<'a> {}

fn test_tait(_: &Opaque<'_>) {
6 changes: 1 addition & 5 deletions tests/ui/impl-trait/issue-86465.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
#![feature(type_alias_impl_trait)]

pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

type X<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
type X<'a, 'b> = impl std::fmt::Debug;

fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
(a, a)
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/issue-86465.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: concrete type differs from previous defining opaque type use
--> $DIR/issue-86465.rs:10:5
--> $DIR/issue-86465.rs:6:5
|
LL | (a, a)
| ^^^^^^
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#![feature(type_alias_impl_trait)]
#![allow(dead_code)]

pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

type OneLifetime<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
type OneLifetime<'a, 'b> = impl std::fmt::Debug;

fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
a
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: concrete type differs from previous defining opaque type use
--> $DIR/different_lifetimes_defining_uses.rs:15:5
--> $DIR/different_lifetimes_defining_uses.rs:11:5
|
LL | b
| ^ expected `&'a u32`, got `&'b u32`
|
note: previous use here
--> $DIR/different_lifetimes_defining_uses.rs:11:5
--> $DIR/different_lifetimes_defining_uses.rs:7:5
|
LL | a
| ^
Original file line number Diff line number Diff line change
@@ -2,11 +2,7 @@

fn main() {}

pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
type Two<'a, 'b> = impl std::fmt::Debug;

fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
//~^ ERROR non-defining opaque type use
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_lifetime_param.rs:11:26
--> $DIR/generic_duplicate_lifetime_param.rs:7:26
|
LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
| ^^^^^^^^^^^ generic argument `'a` used twice
|
note: for this opaque type
--> $DIR/generic_duplicate_lifetime_param.rs:9:20
--> $DIR/generic_duplicate_lifetime_param.rs:5:20
|
LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | type Two<'a, 'b> = impl std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^

error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_lifetime_param.rs:13:5
--> $DIR/generic_duplicate_lifetime_param.rs:9:5
|
LL | t
| ^
|
note: lifetime used multiple times
--> $DIR/generic_duplicate_lifetime_param.rs:9:10
--> $DIR/generic_duplicate_lifetime_param.rs:5:10
|
LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
LL | type Two<'a, 'b> = impl std::fmt::Debug;
| ^^ ^^

error: aborting due to 2 previous errors
Original file line number Diff line number Diff line change
@@ -14,11 +14,7 @@ fn main() {}
// test that unused generic parameters are ok
type TwoTys<T, U> = impl Debug;

pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
type TwoLifetimes<'a, 'b> = impl Debug;

type TwoConsts<const X: usize, const Y: usize> = impl Debug;

26 changes: 13 additions & 13 deletions tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:25:30
--> $DIR/generic_duplicate_param_use.rs:21:30
|
LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
| ^^^^^^^^^^^^ generic argument `T` used twice
@@ -11,7 +11,7 @@ LL | type TwoTys<T, U> = impl Debug;
| ^^^^^^^^^^

error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:27:5
--> $DIR/generic_duplicate_param_use.rs:23:5
|
LL | t
| ^
@@ -23,49 +23,49 @@ LL | type TwoTys<T, U> = impl Debug;
| ^ ^

error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:31:36
--> $DIR/generic_duplicate_param_use.rs:27:36
|
LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
| ^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
|
note: for this opaque type
--> $DIR/generic_duplicate_param_use.rs:21:29
--> $DIR/generic_duplicate_param_use.rs:17:29
|
LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | type TwoLifetimes<'a, 'b> = impl Debug;
| ^^^^^^^^^^

error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:33:5
--> $DIR/generic_duplicate_param_use.rs:29:5
|
LL | t
| ^
|
note: lifetime used multiple times
--> $DIR/generic_duplicate_param_use.rs:21:19
--> $DIR/generic_duplicate_param_use.rs:17:19
|
LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
LL | type TwoLifetimes<'a, 'b> = impl Debug;
| ^^ ^^

error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:37:50
--> $DIR/generic_duplicate_param_use.rs:33:50
|
LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
| ^^^^^^^^^^^^^^^ generic argument `N` used twice
|
note: for this opaque type
--> $DIR/generic_duplicate_param_use.rs:23:50
--> $DIR/generic_duplicate_param_use.rs:19:50
|
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
| ^^^^^^^^^^

error: non-defining opaque type use in defining scope
--> $DIR/generic_duplicate_param_use.rs:39:5
--> $DIR/generic_duplicate_param_use.rs:35:5
|
LL | t
| ^
|
note: constant used multiple times
--> $DIR/generic_duplicate_param_use.rs:23:16
--> $DIR/generic_duplicate_param_use.rs:19:16
|
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
5 changes: 2 additions & 3 deletions tests/ui/type-alias-impl-trait/generic_lifetime_param.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// check-pass
// build-pass (FIXME(62277): could be check-pass?)

#![feature(type_alias_impl_trait)]

fn main() {}

type Region<'a> = impl std::fmt::Debug + 'a;

type Region<'a> = impl std::fmt::Debug;

fn region<'b>(a: &'b ()) -> Region<'b> {
a
4 changes: 2 additions & 2 deletions tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#![feature(type_alias_impl_trait)]

mod test_lifetime_param {
type Ty<'a> = impl Sized + 'a;
type Ty<'a> = impl Sized;
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}

mod test_higher_kinded_lifetime_param {
type Ty<'a> = impl Sized + 'a;
type Ty<'a> = impl Sized;
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
20 changes: 12 additions & 8 deletions tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
// check-pass

#![feature(impl_trait_in_assoc_type)]
#![feature(impl_trait_in_assoc_type, type_alias_impl_trait)]

trait Callable {
type Output;
fn call() -> Self::Output;
}
mod foo {
pub trait Callable {
type Output;
fn call() -> Self::Output;
}

impl<'a> Callable for &'a () {
type Output = impl Sized;
fn call() -> Self::Output {}
pub type OutputHelper = impl Sized;
impl<'a> Callable for &'a () {
type Output = OutputHelper;
fn call() -> Self::Output {}
}
}
use foo::*;

fn test<'a>() -> impl Sized {
<&'a () as Callable>::call()
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/issue-89686.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

use std::future::Future;

type G<'a, T> = impl Future<Output = ()> + 'a;
type G<'a, T> = impl Future<Output = ()>;

trait Trait {
type F: Future<Output = ()>;
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/issue-89686.stderr
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ LL | async move { self.f().await }
|
help: consider restricting type parameter `T`
|
LL | type G<'a, T: Trait> = impl Future<Output = ()> + 'a;
LL | type G<'a, T: Trait> = impl Future<Output = ()>;
| +++++++

error: aborting due to previous error
5 changes: 3 additions & 2 deletions tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#![feature(type_alias_impl_trait)]

type Opaque<'a, T> = impl Sized;
type Opaque2<T> = impl Sized;
type Opaque<'a, T> = Opaque2<T>;
fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
//~^ ERROR: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds
//~^ ERROR: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds

fn main() {}
9 changes: 5 additions & 4 deletions tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds
--> $DIR/missing_lifetime_bound.rs:4:47
error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds
--> $DIR/missing_lifetime_bound.rs:5:47
|
LL | type Opaque<'a, T> = impl Sized;
| ---------- opaque type defined here
LL | type Opaque2<T> = impl Sized;
| ---------- opaque type defined here
LL | type Opaque<'a, T> = Opaque2<T>;
LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
| -- ^
| |
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
#![feature(type_alias_impl_trait)]

pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
type Foo<'a, 'b> = impl std::fmt::Debug;

fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
(i, i) //~ ERROR concrete type differs from previous
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: concrete type differs from previous defining opaque type use
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
LL | (i, i)
| ^^^^^^
Original file line number Diff line number Diff line change
@@ -7,11 +7,7 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>)
(a.clone(), a)
}

pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
type Foo<'a, 'b> = impl std::fmt::Debug;

fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
(i, j)
4 changes: 2 additions & 2 deletions tests/ui/type-alias-impl-trait/self_implication.rs
Original file line number Diff line number Diff line change
@@ -22,9 +22,9 @@ fn bar() {
}

// desugared
type FooX<'a> = impl Sized;
type FooX = impl Sized;
impl<'a> Foo<'a> {
fn foo(&self) -> FooX<'a> {}
fn foo(&self) -> FooX {}
}

// use site
50 changes: 50 additions & 0 deletions tests/ui/type-alias-impl-trait/variance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#![feature(rustc_attrs, type_alias_impl_trait, impl_trait_in_assoc_type)]
#![allow(internal_features)]
#![rustc_variance_of_opaques]

trait Captures<'a> {}
impl<T> Captures<'_> for T {}

type NotCapturedEarly<'a> = impl Sized; //~ [o]

type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o]

type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [o]

type CapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'b>>; //~ [o]

type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a> + Captures<'b>>; //~ [o]

type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [o, o, o]

trait Foo<'i> {
type ImplicitCapturedEarly<'a>;

type ExplicitCaptureEarly<'a>;

type ImplicitCaptureLate<'a>;

type ExplicitCaptureLate<'a>;
}

impl<'i> Foo<'i> for &'i () {
type ImplicitCapturedEarly<'a> = impl Sized; //~ [o, o]

type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>; //~ [o, o]

type ImplicitCaptureLate<'a> = impl Sized; //~ [o, o]

type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>; //~ [o, o]
}

impl<'i> Foo<'i> for () {
type ImplicitCapturedEarly<'a> = impl Sized; //~ [o, o]

type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>; //~ [o, o]

type ImplicitCaptureLate<'a> = impl Sized; //~ [o, o]

type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>; //~ [o, o]
}

fn main() {}
86 changes: 86 additions & 0 deletions tests/ui/type-alias-impl-trait/variance.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
error: [o]
--> $DIR/variance.rs:8:29
|
LL | type NotCapturedEarly<'a> = impl Sized;
| ^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:10:26
|
LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:12:56
|
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
| ^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:14:53
|
LL | type CapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'b>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o]
--> $DIR/variance.rs:16:49
|
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a> + Captures<'b>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o, o, o]
--> $DIR/variance.rs:18:27
|
LL | type Bar<'a, 'b: 'b, T> = impl Sized;
| ^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:31:38
|
LL | type ImplicitCapturedEarly<'a> = impl Sized;
| ^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:33:37
|
LL | type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:35:36
|
LL | type ImplicitCaptureLate<'a> = impl Sized;
| ^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:37:36
|
LL | type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:41:38
|
LL | type ImplicitCapturedEarly<'a> = impl Sized;
| ^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:43:37
|
LL | type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:45:36
|
LL | type ImplicitCaptureLate<'a> = impl Sized;
| ^^^^^^^^^^

error: [o, o]
--> $DIR/variance.rs:47:36
|
LL | type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 14 previous errors