Skip to content

Commit 87d1317

Browse files
Fixup and add new tests for generator auto-trait
1 parent cdb1f13 commit 87d1317

File tree

7 files changed

+198
-65
lines changed

7 files changed

+198
-65
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// run-pass
2+
// edition:2018
3+
4+
#![allow(unused)]
5+
6+
use core::future::Future;
7+
use core::pin::Pin;
8+
use core::task::{Poll, Context};
9+
10+
struct Map<Fut, F>(Fut, F);
11+
12+
impl<Fut, F, S> Future for Map<Fut, F> where Fut: Future, F: FnOnce(Fut::Output) -> S {
13+
type Output = S;
14+
15+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
16+
todo!()
17+
}
18+
}
19+
20+
enum MaybeDone<Fut: Future> {
21+
Maybe(Fut),
22+
Done(Fut::Output),
23+
}
24+
25+
impl<Fut: Future> Future for MaybeDone<Fut> {
26+
type Output = ();
27+
28+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
29+
todo!()
30+
}
31+
}
32+
33+
fn drop_static(s: &'static str) {}
34+
35+
async fn foo() {
36+
let a = async { "hello" as &'static str};
37+
let b = Map(a, drop_static);
38+
let c = MaybeDone::Maybe(b);
39+
c.await
40+
}
41+
42+
fn needs_send<T: Send>(t: T) {}
43+
44+
fn main() {
45+
needs_send(foo());
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// run-pass
2+
// edition:2018
3+
4+
#![allow(unused)]
5+
6+
use std::marker::PhantomData;
7+
8+
pub struct One<T>(PhantomData<T>);
9+
pub struct Two<T, U>(PhantomData<(T, U)>);
10+
11+
unsafe impl<T, U> Send for Two<T, U> where U: IsOne<T> {}
12+
13+
pub trait IsOne<T> {}
14+
impl<T> IsOne<T> for One<T> {}
15+
16+
fn main() {
17+
fn assert_send(_: impl Send) {}
18+
assert_send(async {
19+
type T = Box<dyn Send + Sync + 'static>;
20+
let _value = Two::<T, One<T>>(PhantomData);
21+
async {}.await;
22+
});
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// run-pass
2+
// edition:2018
3+
4+
#![allow(unused)]
5+
6+
use core::future::Future;
7+
use core::marker::PhantomData;
8+
use core::pin::Pin;
9+
use core::task::{Context, Poll};
10+
11+
async fn f() {}
12+
13+
pub fn fail<'a>() -> Box<dyn Future<Output = ()> + Send + 'a> {
14+
Box::new(async { new(|| async { f().await }).await })
15+
}
16+
17+
fn new<A, B>(_a: A) -> F<A, B>
18+
where
19+
A: Fn() -> B,
20+
{
21+
F { _i: PhantomData }
22+
}
23+
24+
trait Stream {
25+
type Item;
26+
}
27+
28+
struct T<A, B> {
29+
_a: PhantomData<A>,
30+
_b: PhantomData<B>,
31+
}
32+
33+
impl<A, B> Stream for T<A, B>
34+
where
35+
A: Fn() -> B,
36+
{
37+
type Item = B;
38+
}
39+
40+
struct F<A, B>
41+
where
42+
A: Fn() -> B,
43+
{
44+
_i: PhantomData<<T<A, B> as Stream>::Item>,
45+
}
46+
47+
impl<A, B> Future for F<A, B>
48+
where
49+
A: Fn() -> B,
50+
{
51+
type Output = ();
52+
fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
53+
unimplemented!()
54+
}
55+
}
56+
57+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// run-pass
2+
// edition:2018
3+
4+
#![allow(unused)]
5+
6+
use std::future::Future;
7+
use std::marker::PhantomData;
8+
9+
trait Stream {
10+
type Item;
11+
}
12+
13+
struct Filter<St: Stream> {
14+
pending_item: St::Item,
15+
}
16+
17+
fn filter<St: Stream>(_: St) -> Filter<St> {
18+
unimplemented!();
19+
}
20+
21+
struct FilterMap<Fut, F> {
22+
f: F,
23+
pending: PhantomData<Fut>,
24+
}
25+
26+
impl<Fut, F> Stream for FilterMap<Fut, F>
27+
where
28+
F: FnMut() -> Fut,
29+
Fut: Future,
30+
{
31+
type Item = ();
32+
}
33+
34+
pub fn get_foo() -> impl Future + Send {
35+
async {
36+
let _y = &();
37+
let _x = filter(FilterMap {
38+
f: || async move { *_y },
39+
pending: PhantomData,
40+
});
41+
async {}.await;
42+
}
43+
}
44+
45+
fn main() {}

src/test/ui/generator/auto-trait-regions.nll.stderr

-47
This file was deleted.

src/test/ui/generator/auto-trait-regions.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22
#![feature(auto_traits)]
33
#![feature(negative_impls)]
44

5+
use std::cell::Cell;
6+
57
auto trait Foo {}
68

79
struct No;
810

911
impl !Foo for No {}
1012

11-
struct A<'a, 'b>(&'a mut bool, &'b mut bool, No);
13+
struct A<'a, 'b>(Cell<&'a bool>, Cell<&'b mut bool>, No);
14+
15+
impl<'a, 'b> Drop for A<'a, 'b> {
16+
fn drop(&mut self) {}
17+
}
1218

1319
impl<'a, 'b: 'a> Foo for A<'a, 'b> {}
1420

@@ -18,36 +24,39 @@ impl Foo for &'static OnlyFooIfStaticRef {}
1824
struct OnlyFooIfRef(No);
1925
impl<'a> Foo for &'a OnlyFooIfRef {}
2026

21-
fn assert_foo<T: Foo>(f: T) {}
27+
fn assert_foo<T: Foo>(_f: T) {}
2228

2329
fn main() {
24-
// Make sure 'static is erased for generator interiors so we can't match it in trait selection
25-
let x: &'static _ = &OnlyFooIfStaticRef(No);
30+
let z = OnlyFooIfStaticRef(No);
31+
let x = &z;
2632
let gen = || {
2733
let x = x;
2834
yield;
2935
assert_foo(x);
3036
};
31-
assert_foo(gen);
37+
assert_foo(gen); // bad
3238
//~^ ERROR implementation of `Foo` is not general enough
3339
//~| ERROR implementation of `Foo` is not general enough
40+
drop(z);
3441

3542
// Allow impls which matches any lifetime
36-
let x = &OnlyFooIfRef(No);
43+
let z = OnlyFooIfRef(No);
44+
let x = &z;
3745
let gen = || {
3846
let x = x;
3947
yield;
4048
assert_foo(x);
4149
};
4250
assert_foo(gen); // ok
51+
drop(z);
4352

44-
// Disallow impls which relates lifetimes in the generator interior
45-
let gen = || {
46-
let a = A(&mut true, &mut true, No);
53+
let gen = static || {
54+
let mut y = true;
55+
let a = A::<'static, '_>(Cell::new(&true), Cell::new(&mut y), No);
4756
yield;
48-
assert_foo(a);
57+
drop(a);
4958
};
5059
assert_foo(gen);
51-
//~^ ERROR not general enough
52-
//~| ERROR not general enough
60+
//~^ ERROR implementation of `Foo` is not general enough
61+
//~| ERROR implementation of `Foo` is not general enough
5362
}

src/test/ui/generator/auto-trait-regions.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
error: implementation of `Foo` is not general enough
2-
--> $DIR/auto-trait-regions.rs:31:5
2+
--> $DIR/auto-trait-regions.rs:37:5
33
|
4-
LL | assert_foo(gen);
4+
LL | assert_foo(gen); // bad
55
| ^^^^^^^^^^ implementation of `Foo` is not general enough
66
|
77
= note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
88
= note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
99

1010
error: implementation of `Foo` is not general enough
11-
--> $DIR/auto-trait-regions.rs:31:5
11+
--> $DIR/auto-trait-regions.rs:37:5
1212
|
13-
LL | assert_foo(gen);
13+
LL | assert_foo(gen); // bad
1414
| ^^^^^^^^^^ implementation of `Foo` is not general enough
1515
|
1616
= note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
1717
= note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
1818

1919
error: implementation of `Foo` is not general enough
20-
--> $DIR/auto-trait-regions.rs:50:5
20+
--> $DIR/auto-trait-regions.rs:59:5
2121
|
2222
LL | assert_foo(gen);
2323
| ^^^^^^^^^^ implementation of `Foo` is not general enough
@@ -26,7 +26,7 @@ LL | assert_foo(gen);
2626
= note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
2727

2828
error: implementation of `Foo` is not general enough
29-
--> $DIR/auto-trait-regions.rs:50:5
29+
--> $DIR/auto-trait-regions.rs:59:5
3030
|
3131
LL | assert_foo(gen);
3232
| ^^^^^^^^^^ implementation of `Foo` is not general enough

0 commit comments

Comments
 (0)