Skip to content

Commit ca6c57a

Browse files
Add some tests
1 parent fe2b33f commit ca6c57a

24 files changed

+399
-9
lines changed

compiler/rustc_hir_typeck/src/upvar.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,13 +394,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394394
coroutine_captures_by_ref_ty,
395395
);
396396

397-
let ty::Coroutine(_, args) = *self.typeck_results.borrow().expr_ty(body.value).kind()
397+
let ty::Coroutine(_, coroutine_args) =
398+
*self.typeck_results.borrow().expr_ty(body.value).kind()
398399
else {
399400
bug!();
400401
};
401402
self.demand_eqtype(
402403
span,
403-
args.as_coroutine().kind_ty(),
404+
coroutine_args.as_coroutine().kind_ty(),
404405
Ty::from_closure_kind(self.tcx, closure_kind),
405406
);
406407
}

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
371371
obligation: &PolyTraitObligation<'tcx>,
372372
candidates: &mut SelectionCandidateSet<'tcx>,
373373
) {
374-
if let Some(closure_kind) = obligation.self_ty().skip_binder().to_opt_closure_kind()
375-
&& let Some(goal_kind) =
376-
obligation.predicate.skip_binder().trait_ref.args.type_at(1).to_opt_closure_kind()
374+
let self_ty = obligation.self_ty().skip_binder();
375+
let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
376+
377+
// `to_opt_closure_kind` is kind of ICEy when it sees non-int types.
378+
if !(self_ty.is_integral() || self_ty.is_ty_var()) {
379+
return;
380+
}
381+
if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) {
382+
return;
383+
}
384+
385+
if let Some(closure_kind) = self_ty.to_opt_closure_kind()
386+
&& let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
377387
{
378388
if closure_kind.extends(goal_kind) {
379389
candidates.vec.push(AsyncFnKindHelperCandidate);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// aux-build:block-on.rs
2+
// edition:2021
3+
4+
#![feature(async_closure)]
5+
6+
extern crate block_on;
7+
8+
fn main() {
9+
block_on::block_on(async {
10+
let c = async |x| {};
11+
c(1i32).await;
12+
c(2usize).await;
13+
//~^ ERROR mismatched types
14+
});
15+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/arg-mismatch.rs:12:11
3+
|
4+
LL | c(2usize).await;
5+
| - ^^^^^^ expected `i32`, found `usize`
6+
| |
7+
| arguments to this function are incorrect
8+
|
9+
note: closure parameter defined here
10+
--> $DIR/arg-mismatch.rs:10:24
11+
|
12+
LL | let c = async |x| {};
13+
| ^
14+
help: change the type of the numeric literal from `usize` to `i32`
15+
|
16+
LL | c(2i32).await;
17+
| ~~~
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// aux-build:block-on.rs
2+
// edition:2021
3+
// run-pass
4+
5+
#![feature(async_closure, async_fn_traits)]
6+
7+
extern crate block_on;
8+
9+
use std::ops::AsyncFnOnce;
10+
11+
fn main() {
12+
block_on::block_on(async {
13+
let x = async || {};
14+
15+
async fn needs_async_fn_once(x: impl AsyncFnOnce()) {
16+
x().await;
17+
}
18+
needs_async_fn_once(x).await;
19+
});
20+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()])>.See <https://github.com/rust-lang/rust/issues/114858>.
2+
WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected *mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()]), found *mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()]).See <https://github.com/rust-lang/rust/issues/114858>.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// edition: 2021
2+
3+
#![feature(async_closure, noop_waker, async_fn_traits)]
4+
5+
use std::future::Future;
6+
use std::pin::pin;
7+
use std::task::*;
8+
9+
pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
10+
let mut fut = pin!(fut);
11+
// Poll loop, just to test the future...
12+
let ctx = &mut Context::from_waker(Waker::noop());
13+
14+
loop {
15+
match unsafe { fut.as_mut().poll(ctx) } {
16+
Poll::Pending => {}
17+
Poll::Ready(t) => break t,
18+
}
19+
}
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// aux-build:block-on.rs
2+
// edition:2021
3+
// run-pass
4+
5+
#![feature(async_closure)]
6+
7+
extern crate block_on;
8+
9+
fn main() {
10+
block_on::block_on(async {
11+
let x = async |x: &str| -> String { x.to_owned() };
12+
let mut s = x("hello, world").await;
13+
s.truncate(4);
14+
println!("{s}");
15+
});
16+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// aux-build:block-on.rs
2+
// edition:2021
3+
// build-pass
4+
5+
#![feature(async_closure, async_fn_traits)]
6+
7+
extern crate block_on;
8+
9+
use std::future::Future;
10+
use std::marker::PhantomData;
11+
use std::ops::AsyncFn;
12+
13+
struct S;
14+
struct B<'b>(PhantomData<&'b mut &'b mut ()>);
15+
16+
impl S {
17+
async fn q<F: AsyncFn(B<'_>)>(self, f: F) {
18+
f(B(PhantomData)).await;
19+
}
20+
}
21+
22+
fn main() {
23+
block_on::block_on(async {
24+
S.q(async |b: B<'_>| { println!("...") }).await;
25+
});
26+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// aux-build:block-on.rs
2+
// edition:2021
3+
4+
// known-bug: unknown
5+
// Borrow checking doesn't like that higher-ranked output...
6+
7+
#![feature(async_closure)]
8+
9+
extern crate block_on;
10+
11+
fn main() {
12+
block_on::block_on(async {
13+
let x = async move |x: &str| -> &str {
14+
x
15+
};
16+
let s = x("hello!").await;
17+
});
18+
}

0 commit comments

Comments
 (0)