]> git.lizzy.rs Git - rust.git/blob - src/test/ui/generator/discriminant.rs
Add a test for generator discriminants
[rust.git] / src / test / ui / generator / discriminant.rs
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 }