Skip to content

Commit 4b5a66e

Browse files
committed
Add tests for type inference for generators
1 parent 447596c commit 4b5a66e

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

crates/hir-ty/src/tests/coercion.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,24 @@ fn foo() {
294294
);
295295
}
296296

297+
#[test]
298+
fn generator_yield_return_coerce() {
299+
check_no_mismatches(
300+
r#"
301+
fn test() {
302+
let g = || {
303+
yield &1u32;
304+
yield &&1u32;
305+
if true {
306+
return &1u32;
307+
}
308+
&&1u32
309+
};
310+
}
311+
"#,
312+
);
313+
}
314+
297315
#[test]
298316
fn assign_coerce() {
299317
check_no_mismatches(

crates/hir-ty/src/tests/simple.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,88 @@ fn closure_return_inferred() {
19171917
);
19181918
}
19191919

1920+
#[test]
1921+
fn generator_types_inferred() {
1922+
check_infer(
1923+
r#"
1924+
//- minicore: generator, deref
1925+
use core::ops::{Generator, GeneratorState};
1926+
use core::pin::Pin;
1927+
1928+
fn f(v: i64) {}
1929+
fn test() {
1930+
let mut g = |r| {
1931+
let a = yield 0;
1932+
let a = yield 1;
1933+
let a = yield 2;
1934+
"return value"
1935+
};
1936+
1937+
match Pin::new(&mut g).resume(0usize) {
1938+
GeneratorState::Yielded(y) => { f(y); }
1939+
GeneratorState::Complete(r) => {}
1940+
}
1941+
}
1942+
"#,
1943+
expect![[r#"
1944+
70..71 'v': i64
1945+
78..80 '{}': ()
1946+
91..362 '{ ... } }': ()
1947+
101..106 'mut g': {generator}
1948+
109..218 '|r| { ... }': {generator}
1949+
110..111 'r': usize
1950+
113..218 '{ ... }': &str
1951+
127..128 'a': usize
1952+
131..138 'yield 0': usize
1953+
137..138 '0': i64
1954+
152..153 'a': usize
1955+
156..163 'yield 1': usize
1956+
162..163 '1': i64
1957+
177..178 'a': usize
1958+
181..188 'yield 2': usize
1959+
187..188 '2': i64
1960+
198..212 '"return value"': &str
1961+
225..360 'match ... }': ()
1962+
231..239 'Pin::new': fn new<&mut {generator}>(&mut {generator}) -> Pin<&mut {generator}>
1963+
231..247 'Pin::n...mut g)': Pin<&mut {generator}>
1964+
231..262 'Pin::n...usize)': GeneratorState<i64, &str>
1965+
240..246 '&mut g': &mut {generator}
1966+
245..246 'g': {generator}
1967+
255..261 '0usize': usize
1968+
273..299 'Genera...ded(y)': GeneratorState<i64, &str>
1969+
297..298 'y': i64
1970+
303..312 '{ f(y); }': ()
1971+
305..306 'f': fn f(i64)
1972+
305..309 'f(y)': ()
1973+
307..308 'y': i64
1974+
321..348 'Genera...ete(r)': GeneratorState<i64, &str>
1975+
346..347 'r': &str
1976+
352..354 '{}': ()
1977+
"#]],
1978+
);
1979+
}
1980+
1981+
#[test]
1982+
fn generator_resume_yield_return_unit() {
1983+
check_no_mismatches(
1984+
r#"
1985+
//- minicore: generator, deref
1986+
use core::ops::{Generator, GeneratorState};
1987+
use core::pin::Pin;
1988+
fn test() {
1989+
let mut g = || {
1990+
let () = yield;
1991+
};
1992+
1993+
match Pin::new(&mut g).resume(()) {
1994+
GeneratorState::Yielded(()) => {}
1995+
GeneratorState::Complete(()) => {}
1996+
}
1997+
}
1998+
"#,
1999+
);
2000+
}
2001+
19202002
#[test]
19212003
fn fn_pointer_return() {
19222004
check_infer(

crates/test-utils/src/minicore.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
//! add:
3838
//! as_ref: sized
3939
//! drop:
40+
//! generator: pin
4041
4142
pub mod marker {
4243
// region:sized
@@ -182,6 +183,19 @@ pub mod ops {
182183
type Target: ?Sized;
183184
fn deref(&self) -> &Self::Target;
184185
}
186+
187+
impl<T: ?Sized> Deref for &T {
188+
type Target = T;
189+
fn deref(&self) -> &T {
190+
loop {}
191+
}
192+
}
193+
impl<T: ?Sized> Deref for &mut T {
194+
type Target = T;
195+
fn deref(&self) -> &T {
196+
loop {}
197+
}
198+
}
185199
// region:deref_mut
186200
#[lang = "deref_mut"]
187201
pub trait DerefMut: Deref {
@@ -347,6 +361,27 @@ pub mod ops {
347361
fn add(self, rhs: Rhs) -> Self::Output;
348362
}
349363
// endregion:add
364+
365+
// region:generator
366+
mod generator {
367+
use crate::pin::Pin;
368+
369+
#[lang = "generator"]
370+
pub trait Generator<R = ()> {
371+
type Yield;
372+
#[lang = "generator_return"]
373+
type Return;
374+
fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
375+
}
376+
377+
#[lang = "generator_state"]
378+
pub enum GeneratorState<Y, R> {
379+
Yielded(Y),
380+
Complete(R),
381+
}
382+
}
383+
pub use self::generator::{Generator, GeneratorState};
384+
// endregion:generator
350385
}
351386

352387
// region:eq
@@ -455,6 +490,19 @@ pub mod pin {
455490
pub struct Pin<P> {
456491
pointer: P,
457492
}
493+
impl<P> Pin<P> {
494+
pub fn new(pointer: P) -> Pin<P> {
495+
loop {}
496+
}
497+
}
498+
// region:deref
499+
impl<P: crate::ops::Deref> crate::ops::Deref for Pin<P> {
500+
type Target = P::Target;
501+
fn deref(&self) -> &P::Target {
502+
loop {}
503+
}
504+
}
505+
// endregion:deref
458506
}
459507
// endregion:pin
460508

0 commit comments

Comments
 (0)