Skip to content

Commit b16d659

Browse files
Add a test for generator discriminants
1 parent 8fba7fb commit b16d659

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

src/test/ui/generator/discriminant.rs

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are
2+
//! reflected in the output of `mem::discriminant`.
3+
4+
// run-pass
5+
6+
#![feature(generators, generator_trait, core_intrinsics)]
7+
8+
use std::intrinsics::discriminant_value;
9+
use std::marker::Unpin;
10+
use std::mem::size_of_val;
11+
use std::{cmp, ops::*};
12+
13+
macro_rules! yield25 {
14+
($e:expr) => {
15+
yield $e;
16+
yield $e;
17+
yield $e;
18+
yield $e;
19+
yield $e;
20+
21+
yield $e;
22+
yield $e;
23+
yield $e;
24+
yield $e;
25+
yield $e;
26+
27+
yield $e;
28+
yield $e;
29+
yield $e;
30+
yield $e;
31+
yield $e;
32+
33+
yield $e;
34+
yield $e;
35+
yield $e;
36+
yield $e;
37+
yield $e;
38+
39+
yield $e;
40+
yield $e;
41+
yield $e;
42+
yield $e;
43+
yield $e;
44+
};
45+
}
46+
47+
/// Yields 250 times.
48+
macro_rules! yield250 {
49+
() => {
50+
yield250!(())
51+
};
52+
53+
($e:expr) => {
54+
yield25!($e);
55+
yield25!($e);
56+
yield25!($e);
57+
yield25!($e);
58+
yield25!($e);
59+
60+
yield25!($e);
61+
yield25!($e);
62+
yield25!($e);
63+
yield25!($e);
64+
yield25!($e);
65+
};
66+
}
67+
68+
fn cycle(gen: impl Generator<()> + Unpin, expected_max_discr: u64) {
69+
let mut gen = Box::pin(gen);
70+
let mut max_discr = 0;
71+
loop {
72+
max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut()));
73+
match gen.as_mut().resume(()) {
74+
GeneratorState::Yielded(_) => {}
75+
GeneratorState::Complete(_) => {
76+
assert_eq!(max_discr, expected_max_discr);
77+
return;
78+
}
79+
}
80+
}
81+
}
82+
83+
fn main() {
84+
// Has only one invalid discr. value.
85+
let gen_u8_tiny_niche = || {
86+
|| {
87+
// 3 reserved variants
88+
89+
yield250!(); // 253 variants
90+
91+
yield; // 254
92+
yield; // 255
93+
}
94+
};
95+
96+
// Uses all values in the u8 discriminant.
97+
let gen_u8_full = || {
98+
|| {
99+
// 3 reserved variants
100+
101+
yield250!(); // 253 variants
102+
103+
yield; // 254
104+
yield; // 255
105+
yield; // 256
106+
}
107+
};
108+
109+
// Barely needs a u16 discriminant.
110+
let gen_u16 = || {
111+
|| {
112+
// 3 reserved variants
113+
114+
yield250!(); // 253 variants
115+
116+
yield; // 254
117+
yield; // 255
118+
yield; // 256
119+
yield; // 257
120+
}
121+
};
122+
123+
assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1);
124+
assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
125+
assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore
126+
assert_eq!(size_of_val(&gen_u8_full()), 1);
127+
assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche
128+
assert_eq!(size_of_val(&gen_u16()), 2);
129+
assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
130+
131+
cycle(gen_u8_tiny_niche(), 254);
132+
cycle(gen_u8_full(), 255);
133+
cycle(gen_u16(), 256);
134+
}

0 commit comments

Comments
 (0)