Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5c363b1

Browse files
committedDec 2, 2024·
Adjust syntax
1 parent 1555074 commit 5c363b1

File tree

7 files changed

+557
-21
lines changed

7 files changed

+557
-21
lines changed
 

‎compiler/rustc_data_structures/src/flock.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! green/native threading. This is just a bare-bones enough solution for
55
//! librustdoc, it is not production quality at all.
66
7+
#[cfg(bootstrap)]
78
cfg_match! {
89
cfg(target_os = "linux") => {
910
mod linux;
@@ -27,4 +28,28 @@ cfg_match! {
2728
}
2829
}
2930

31+
#[cfg(not(bootstrap))]
32+
cfg_match! {
33+
(target_os = "linux") => {
34+
mod linux;
35+
use linux as imp;
36+
}
37+
(target_os = "redox") => {
38+
mod linux;
39+
use linux as imp;
40+
}
41+
(unix) => {
42+
mod unix;
43+
use unix as imp;
44+
}
45+
(windows) => {
46+
mod windows;
47+
use self::windows as imp;
48+
}
49+
_ => {
50+
mod unsupported;
51+
use unsupported as imp;
52+
}
53+
}
54+
3055
pub use imp::Lock;

‎compiler/rustc_data_structures/src/profiling.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ fn get_thread_id() -> u32 {
860860
}
861861

862862
// Memory reporting
863+
#[cfg(bootstrap)]
863864
cfg_match! {
864865
cfg(windows) => {
865866
pub fn get_resident_set_size() -> Option<usize> {
@@ -921,5 +922,67 @@ cfg_match! {
921922
}
922923
}
923924

925+
#[cfg(not(bootstrap))]
926+
cfg_match! {
927+
(windows) => {
928+
pub fn get_resident_set_size() -> Option<usize> {
929+
use std::mem;
930+
931+
use windows::{
932+
Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
933+
Win32::System::Threading::GetCurrentProcess,
934+
};
935+
936+
let mut pmc = PROCESS_MEMORY_COUNTERS::default();
937+
let pmc_size = mem::size_of_val(&pmc);
938+
unsafe {
939+
K32GetProcessMemoryInfo(
940+
GetCurrentProcess(),
941+
&mut pmc,
942+
pmc_size as u32,
943+
)
944+
}
945+
.ok()
946+
.ok()?;
947+
948+
Some(pmc.WorkingSetSize)
949+
}
950+
}
951+
(target_os = "macos") => {
952+
pub fn get_resident_set_size() -> Option<usize> {
953+
use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
954+
use std::mem;
955+
const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int;
956+
957+
unsafe {
958+
let mut info: proc_taskinfo = mem::zeroed();
959+
let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
960+
let pid = getpid() as c_int;
961+
let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
962+
if ret == PROC_TASKINFO_SIZE {
963+
Some(info.pti_resident_size as usize)
964+
} else {
965+
None
966+
}
967+
}
968+
}
969+
}
970+
(unix) => {
971+
pub fn get_resident_set_size() -> Option<usize> {
972+
let field = 1;
973+
let contents = fs::read("/proc/self/statm").ok()?;
974+
let contents = String::from_utf8(contents).ok()?;
975+
let s = contents.split_whitespace().nth(field)?;
976+
let npages = s.parse::<usize>().ok()?;
977+
Some(npages * 4096)
978+
}
979+
}
980+
_ => {
981+
pub fn get_resident_set_size() -> Option<usize> {
982+
None
983+
}
984+
}
985+
}
986+
924987
#[cfg(test)]
925988
mod tests;

‎compiler/rustc_span/src/analyze_source_file.rs

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub(crate) fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<Multi
2929
(lines, multi_byte_chars)
3030
}
3131

32+
#[cfg(bootstrap)]
3233
cfg_match! {
3334
cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
3435
fn analyze_source_file_dispatch(
@@ -185,6 +186,165 @@ cfg_match! {
185186
}
186187
}
187188
}
189+
190+
#[cfg(not(bootstrap))]
191+
cfg_match! {
192+
(any(target_arch = "x86", target_arch = "x86_64")) => {
193+
fn analyze_source_file_dispatch(
194+
src: &str,
195+
lines: &mut Vec<RelativeBytePos>,
196+
multi_byte_chars: &mut Vec<MultiByteChar>,
197+
) {
198+
if is_x86_feature_detected!("sse2") {
199+
unsafe {
200+
analyze_source_file_sse2(src, lines, multi_byte_chars);
201+
}
202+
} else {
203+
analyze_source_file_generic(
204+
src,
205+
src.len(),
206+
RelativeBytePos::from_u32(0),
207+
lines,
208+
multi_byte_chars,
209+
);
210+
}
211+
}
212+
213+
/// Checks 16 byte chunks of text at a time. If the chunk contains
214+
/// something other than printable ASCII characters and newlines, the
215+
/// function falls back to the generic implementation. Otherwise it uses
216+
/// SSE2 intrinsics to quickly find all newlines.
217+
#[target_feature(enable = "sse2")]
218+
unsafe fn analyze_source_file_sse2(
219+
src: &str,
220+
lines: &mut Vec<RelativeBytePos>,
221+
multi_byte_chars: &mut Vec<MultiByteChar>,
222+
) {
223+
#[cfg(target_arch = "x86")]
224+
use std::arch::x86::*;
225+
#[cfg(target_arch = "x86_64")]
226+
use std::arch::x86_64::*;
227+
228+
const CHUNK_SIZE: usize = 16;
229+
230+
let src_bytes = src.as_bytes();
231+
232+
let chunk_count = src.len() / CHUNK_SIZE;
233+
234+
// This variable keeps track of where we should start decoding a
235+
// chunk. If a multi-byte character spans across chunk boundaries,
236+
// we need to skip that part in the next chunk because we already
237+
// handled it.
238+
let mut intra_chunk_offset = 0;
239+
240+
for chunk_index in 0..chunk_count {
241+
let ptr = src_bytes.as_ptr() as *const __m128i;
242+
// We don't know if the pointer is aligned to 16 bytes, so we
243+
// use `loadu`, which supports unaligned loading.
244+
let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };
245+
246+
// For character in the chunk, see if its byte value is < 0, which
247+
// indicates that it's part of a UTF-8 char.
248+
let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) };
249+
// Create a bit mask from the comparison results.
250+
let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) };
251+
252+
// If the bit mask is all zero, we only have ASCII chars here:
253+
if multibyte_mask == 0 {
254+
assert!(intra_chunk_offset == 0);
255+
256+
// Check if there are any control characters in the chunk. All
257+
// control characters that we can encounter at this point have a
258+
// byte value less than 32 or ...
259+
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
260+
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };
261+
262+
// ... it's the ASCII 'DEL' character with a value of 127.
263+
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
264+
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };
265+
266+
let control_char_mask = control_char_mask0 | control_char_mask1;
267+
268+
if control_char_mask != 0 {
269+
// Check for newlines in the chunk
270+
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
271+
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
272+
273+
if control_char_mask == newlines_mask {
274+
// All control characters are newlines, record them
275+
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
276+
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
277+
278+
loop {
279+
let index = newlines_mask.trailing_zeros();
280+
281+
if index >= CHUNK_SIZE as u32 {
282+
// We have arrived at the end of the chunk.
283+
break;
284+
}
285+
286+
lines.push(RelativeBytePos(index) + output_offset);
287+
288+
// Clear the bit, so we can find the next one.
289+
newlines_mask &= (!1) << index;
290+
}
291+
292+
// We are done for this chunk. All control characters were
293+
// newlines and we took care of those.
294+
continue;
295+
} else {
296+
// Some of the control characters are not newlines,
297+
// fall through to the slow path below.
298+
}
299+
} else {
300+
// No control characters, nothing to record for this chunk
301+
continue;
302+
}
303+
}
304+
305+
// The slow path.
306+
// There are control chars in here, fallback to generic decoding.
307+
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
308+
intra_chunk_offset = analyze_source_file_generic(
309+
&src[scan_start..],
310+
CHUNK_SIZE - intra_chunk_offset,
311+
RelativeBytePos::from_usize(scan_start),
312+
lines,
313+
multi_byte_chars,
314+
);
315+
}
316+
317+
// There might still be a tail left to analyze
318+
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
319+
if tail_start < src.len() {
320+
analyze_source_file_generic(
321+
&src[tail_start..],
322+
src.len() - tail_start,
323+
RelativeBytePos::from_usize(tail_start),
324+
lines,
325+
multi_byte_chars,
326+
);
327+
}
328+
}
329+
}
330+
_ => {
331+
// The target (or compiler version) does not support SSE2 ...
332+
fn analyze_source_file_dispatch(
333+
src: &str,
334+
lines: &mut Vec<RelativeBytePos>,
335+
multi_byte_chars: &mut Vec<MultiByteChar>,
336+
) {
337+
analyze_source_file_generic(
338+
src,
339+
src.len(),
340+
RelativeBytePos::from_u32(0),
341+
lines,
342+
multi_byte_chars,
343+
);
344+
}
345+
}
346+
}
347+
188348
// `scan_len` determines the number of bytes in `src` to scan. Note that the
189349
// function can read past `scan_len` if a multi-byte character start within the
190350
// range but extends past it. The overflow is returned by the function.

‎library/core/src/macros/mod.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ pub macro assert_matches {
224224
/// }
225225
/// }
226226
/// ```
227+
#[cfg(bootstrap)]
227228
#[unstable(feature = "cfg_match", issue = "115585")]
228229
#[rustc_diagnostic_item = "cfg_match"]
229230
pub macro cfg_match {
@@ -284,6 +285,95 @@ pub macro cfg_match {
284285
}
285286
}
286287

288+
/// A macro for defining `#[cfg]` match-like statements.
289+
///
290+
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
291+
/// `#[cfg]` cases, emitting the implementation which matches first.
292+
///
293+
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
294+
/// without having to rewrite each clause multiple times.
295+
///
296+
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
297+
/// all previous declarations do not evaluate to true.
298+
///
299+
/// # Example
300+
///
301+
/// ```
302+
/// #![feature(cfg_match)]
303+
///
304+
/// cfg_match! {
305+
/// (unix) => {
306+
/// fn foo() { /* unix specific functionality */ }
307+
/// }
308+
/// (target_pointer_width = "32") => {
309+
/// fn foo() { /* non-unix, 32-bit functionality */ }
310+
/// }
311+
/// _ => {
312+
/// fn foo() { /* fallback implementation */ }
313+
/// }
314+
/// }
315+
/// ```
316+
#[cfg(not(bootstrap))]
317+
#[unstable(feature = "cfg_match", issue = "115585")]
318+
#[rustc_diagnostic_item = "cfg_match"]
319+
pub macro cfg_match {
320+
// with a final wildcard
321+
(
322+
$(($initial_meta:meta) => { $($initial_tokens:tt)* })+
323+
_ => { $($extra_tokens:tt)* }
324+
) => {
325+
cfg_match! {
326+
@__items ();
327+
$((($initial_meta) ($($initial_tokens)*)),)+
328+
(() ($($extra_tokens)*)),
329+
}
330+
},
331+
332+
// without a final wildcard
333+
(
334+
$(($extra_meta:meta) => { $($extra_tokens:tt)* })*
335+
) => {
336+
cfg_match! {
337+
@__items ();
338+
$((($extra_meta) ($($extra_tokens)*)),)*
339+
}
340+
},
341+
342+
// Internal and recursive macro to emit all the items
343+
//
344+
// Collects all the previous cfgs in a list at the beginning, so they can be
345+
// negated. After the semicolon is all the remaining items.
346+
(@__items ($($_:meta,)*);) => {},
347+
(
348+
@__items ($($no:meta,)*);
349+
(($($yes:meta)?) ($($tokens:tt)*)),
350+
$($rest:tt,)*
351+
) => {
352+
// Emit all items within one block, applying an appropriate #[cfg]. The
353+
// #[cfg] will require all `$yes` matchers specified and must also negate
354+
// all previous matchers.
355+
#[cfg(all(
356+
$($yes,)?
357+
not(any($($no),*))
358+
))]
359+
cfg_match! { @__identity $($tokens)* }
360+
361+
// Recurse to emit all other items in `$rest`, and when we do so add all
362+
// our `$yes` matchers to the list of `$no` matchers as future emissions
363+
// will have to negate everything we just matched as well.
364+
cfg_match! {
365+
@__items ($($no,)* $($yes,)?);
366+
$($rest,)*
367+
}
368+
},
369+
370+
// Internal macro to make __apply work out right for different match types,
371+
// because of how macros match/expand stuff.
372+
(@__identity $($tokens:tt)*) => {
373+
$($tokens)*
374+
}
375+
}
376+
287377
/// Asserts that a boolean expression is `true` at runtime.
288378
///
289379
/// This will invoke the [`panic!`] macro if the provided expression cannot be

‎library/core/tests/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ mod intrinsics;
151151
mod io;
152152
mod iter;
153153
mod lazy;
154+
#[cfg(not(bootstrap))]
154155
mod macros;
156+
#[cfg(bootstrap)]
157+
mod macros_bootstrap;
155158
mod manually_drop;
156159
mod mem;
157160
mod net;

‎library/core/tests/macros.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ struct Struct;
1010

1111
impl Trait for Struct {
1212
cfg_match! {
13-
cfg(feature = "blah") => {
13+
(feature = "blah") => {
1414
fn blah(&self) {
1515
unimplemented!();
1616
}
@@ -47,21 +47,21 @@ fn matches_leading_pipe() {
4747
#[test]
4848
fn cfg_match_basic() {
4949
cfg_match! {
50-
cfg(target_pointer_width = "64") => { fn f0_() -> bool { true }}
50+
(target_pointer_width = "64") => { fn f0_() -> bool { true }}
5151
}
5252

5353
cfg_match! {
54-
cfg(unix) => { fn f1_() -> bool { true }}
55-
cfg(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }}
54+
(unix) => { fn f1_() -> bool { true }}
55+
(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }}
5656
}
5757

5858
cfg_match! {
59-
cfg(target_pointer_width = "32") => { fn f2_() -> bool { false }}
60-
cfg(target_pointer_width = "64") => { fn f2_() -> bool { true }}
59+
(target_pointer_width = "32") => { fn f2_() -> bool { false }}
60+
(target_pointer_width = "64") => { fn f2_() -> bool { true }}
6161
}
6262

6363
cfg_match! {
64-
cfg(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }}
64+
(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }}
6565
_ => { fn f3_() -> i32 { 2 }}
6666
}
6767

@@ -83,7 +83,7 @@ fn cfg_match_basic() {
8383
#[test]
8484
fn cfg_match_debug_assertions() {
8585
cfg_match! {
86-
cfg(debug_assertions) => {
86+
(debug_assertions) => {
8787
assert!(cfg!(debug_assertions));
8888
assert_eq!(4, 2+2);
8989
}
@@ -98,13 +98,13 @@ fn cfg_match_debug_assertions() {
9898
#[test]
9999
fn cfg_match_no_duplication_on_64() {
100100
cfg_match! {
101-
cfg(windows) => {
101+
(windows) => {
102102
fn foo() {}
103103
}
104-
cfg(unix) => {
104+
(unix) => {
105105
fn foo() {}
106106
}
107-
cfg(target_pointer_width = "64") => {
107+
(target_pointer_width = "64") => {
108108
fn foo() {}
109109
}
110110
}
@@ -114,34 +114,34 @@ fn cfg_match_no_duplication_on_64() {
114114
#[test]
115115
fn cfg_match_options() {
116116
cfg_match! {
117-
cfg(test) => {
117+
(test) => {
118118
use core::option::Option as Option2;
119119
fn works1() -> Option2<u32> { Some(1) }
120120
}
121121
_ => { fn works1() -> Option<u32> { None } }
122122
}
123123

124124
cfg_match! {
125-
cfg(feature = "foo") => { fn works2() -> bool { false } }
126-
cfg(test) => { fn works2() -> bool { true } }
125+
(feature = "foo") => { fn works2() -> bool { false } }
126+
(test) => { fn works2() -> bool { true } }
127127
_ => { fn works2() -> bool { false } }
128128
}
129129

130130
cfg_match! {
131-
cfg(feature = "foo") => { fn works3() -> bool { false } }
131+
(feature = "foo") => { fn works3() -> bool { false } }
132132
_ => { fn works3() -> bool { true } }
133133
}
134134

135135
cfg_match! {
136-
cfg(test) => {
136+
(test) => {
137137
use core::option::Option as Option3;
138138
fn works4() -> Option3<u32> { Some(1) }
139139
}
140140
}
141141

142142
cfg_match! {
143-
cfg(feature = "foo") => { fn works5() -> bool { false } }
144-
cfg(test) => { fn works5() -> bool { true } }
143+
(feature = "foo") => { fn works5() -> bool { false } }
144+
(test) => { fn works5() -> bool { true } }
145145
}
146146

147147
assert!(works1().is_some());
@@ -154,7 +154,7 @@ fn cfg_match_options() {
154154
#[test]
155155
fn cfg_match_two_functions() {
156156
cfg_match! {
157-
cfg(target_pointer_width = "64") => {
157+
(target_pointer_width = "64") => {
158158
fn foo1() {}
159159
fn bar1() {}
160160
}
@@ -178,7 +178,7 @@ fn cfg_match_two_functions() {
178178

179179
fn _accepts_expressions() -> i32 {
180180
cfg_match! {
181-
cfg(unix) => { 1 }
181+
(unix) => { 1 }
182182
_ => { 2 }
183183
}
184184
}
@@ -189,7 +189,7 @@ fn _allows_stmt_expr_attributes() {
189189
let one = 1;
190190
let two = 2;
191191
cfg_match! {
192-
cfg(unix) => { one * two; }
192+
(unix) => { one * two; }
193193
_ => { one + two; }
194194
}
195195
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#![allow(unused_must_use)]
2+
3+
#[allow(dead_code)]
4+
trait Trait {
5+
fn blah(&self);
6+
}
7+
8+
#[allow(dead_code)]
9+
struct Struct;
10+
11+
impl Trait for Struct {
12+
cfg_match! {
13+
cfg(feature = "blah") => {
14+
fn blah(&self) {
15+
unimplemented!();
16+
}
17+
}
18+
_ => {
19+
fn blah(&self) {
20+
unimplemented!();
21+
}
22+
}
23+
}
24+
}
25+
26+
#[test]
27+
fn assert_eq_trailing_comma() {
28+
assert_eq!(1, 1,);
29+
}
30+
31+
#[test]
32+
fn assert_escape() {
33+
assert!(r#"☃\backslash"#.contains("\\"));
34+
}
35+
36+
#[test]
37+
fn assert_ne_trailing_comma() {
38+
assert_ne!(1, 2,);
39+
}
40+
41+
#[rustfmt::skip]
42+
#[test]
43+
fn matches_leading_pipe() {
44+
matches!(1, | 1 | 2 | 3);
45+
}
46+
47+
#[test]
48+
fn cfg_match_basic() {
49+
cfg_match! {
50+
cfg(target_pointer_width = "64") => { fn f0_() -> bool { true }}
51+
}
52+
53+
cfg_match! {
54+
cfg(unix) => { fn f1_() -> bool { true }}
55+
cfg(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }}
56+
}
57+
58+
cfg_match! {
59+
cfg(target_pointer_width = "32") => { fn f2_() -> bool { false }}
60+
cfg(target_pointer_width = "64") => { fn f2_() -> bool { true }}
61+
}
62+
63+
cfg_match! {
64+
cfg(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }}
65+
_ => { fn f3_() -> i32 { 2 }}
66+
}
67+
68+
#[cfg(target_pointer_width = "64")]
69+
assert!(f0_());
70+
71+
#[cfg(unix)]
72+
assert!(f1_());
73+
74+
#[cfg(target_pointer_width = "32")]
75+
assert!(!f2_());
76+
#[cfg(target_pointer_width = "64")]
77+
assert!(f2_());
78+
79+
#[cfg(not(target_pointer_width = "16"))]
80+
assert_eq!(f3_(), 2);
81+
}
82+
83+
#[test]
84+
fn cfg_match_debug_assertions() {
85+
cfg_match! {
86+
cfg(debug_assertions) => {
87+
assert!(cfg!(debug_assertions));
88+
assert_eq!(4, 2+2);
89+
}
90+
_ => {
91+
assert!(cfg!(not(debug_assertions)));
92+
assert_eq!(10, 5+5);
93+
}
94+
}
95+
}
96+
97+
#[cfg(target_pointer_width = "64")]
98+
#[test]
99+
fn cfg_match_no_duplication_on_64() {
100+
cfg_match! {
101+
cfg(windows) => {
102+
fn foo() {}
103+
}
104+
cfg(unix) => {
105+
fn foo() {}
106+
}
107+
cfg(target_pointer_width = "64") => {
108+
fn foo() {}
109+
}
110+
}
111+
foo();
112+
}
113+
114+
#[test]
115+
fn cfg_match_options() {
116+
cfg_match! {
117+
cfg(test) => {
118+
use core::option::Option as Option2;
119+
fn works1() -> Option2<u32> { Some(1) }
120+
}
121+
_ => { fn works1() -> Option<u32> { None } }
122+
}
123+
124+
cfg_match! {
125+
cfg(feature = "foo") => { fn works2() -> bool { false } }
126+
cfg(test) => { fn works2() -> bool { true } }
127+
_ => { fn works2() -> bool { false } }
128+
}
129+
130+
cfg_match! {
131+
cfg(feature = "foo") => { fn works3() -> bool { false } }
132+
_ => { fn works3() -> bool { true } }
133+
}
134+
135+
cfg_match! {
136+
cfg(test) => {
137+
use core::option::Option as Option3;
138+
fn works4() -> Option3<u32> { Some(1) }
139+
}
140+
}
141+
142+
cfg_match! {
143+
cfg(feature = "foo") => { fn works5() -> bool { false } }
144+
cfg(test) => { fn works5() -> bool { true } }
145+
}
146+
147+
assert!(works1().is_some());
148+
assert!(works2());
149+
assert!(works3());
150+
assert!(works4().is_some());
151+
assert!(works5());
152+
}
153+
154+
#[test]
155+
fn cfg_match_two_functions() {
156+
cfg_match! {
157+
cfg(target_pointer_width = "64") => {
158+
fn foo1() {}
159+
fn bar1() {}
160+
}
161+
_ => {
162+
fn foo2() {}
163+
fn bar2() {}
164+
}
165+
}
166+
167+
#[cfg(target_pointer_width = "64")]
168+
{
169+
foo1();
170+
bar1();
171+
}
172+
#[cfg(not(target_pointer_width = "64"))]
173+
{
174+
foo2();
175+
bar2();
176+
}
177+
}
178+
179+
fn _accepts_expressions() -> i32 {
180+
cfg_match! {
181+
cfg(unix) => { 1 }
182+
_ => { 2 }
183+
}
184+
}
185+
186+
// The current implementation expands to a macro call, which allows the use of expression
187+
// statements.
188+
fn _allows_stmt_expr_attributes() {
189+
let one = 1;
190+
let two = 2;
191+
cfg_match! {
192+
cfg(unix) => { one * two; }
193+
_ => { one + two; }
194+
}
195+
}

0 commit comments

Comments
 (0)
Please sign in to comment.