summaryrefslogtreecommitdiffstats
path: root/tests/ui/proc-macro/expand-expr.rs
blob: 700aac41c449a10890defc06ac3a17341ac3b100 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// aux-build:expand-expr.rs
// no-remap-src-base: check_expand_expr_file!() fails when enabled.

#![feature(concat_bytes)]
extern crate expand_expr;

use expand_expr::{
    check_expand_expr_file, echo_pm, expand_expr_fail, expand_expr_is, recursive_expand,
};

// Check builtin macros can be expanded.

expand_expr_is!(13u32, line!());
expand_expr_is!(24u32, column!());

expand_expr_is!("Hello, World!", concat!("Hello, ", "World", "!"));
expand_expr_is!("int10floats5.3booltrue", concat!("int", 10, "floats", 5.3, "bool", true));
expand_expr_is!("Hello", concat!(r##"Hello"##));

expand_expr_is!("Included file contents\n", include_str!("auxiliary/included-file.txt"));
expand_expr_is!(b"Included file contents\n", include_bytes!("auxiliary/included-file.txt"));

expand_expr_is!(
    "contents: Included file contents\n",
    concat!("contents: ", include_str!("auxiliary/included-file.txt"))
);

expand_expr_is!(
    b"contents: Included file contents\n",
    concat_bytes!(b"contents: ", include_bytes!("auxiliary/included-file.txt"))
);

// Correct value is checked for multiple sources.
check_expand_expr_file!(file!());

expand_expr_is!("hello", stringify!(hello));
expand_expr_is!("10 + 20", stringify!(10 + 20));

macro_rules! echo_tts {
    ($($t:tt)*) => { $($t)* };  //~ ERROR: expected expression, found `$`
}

macro_rules! echo_lit {
    ($l:literal) => {
        $l
    };
}

macro_rules! echo_expr {
    ($e:expr) => {
        $e
    };
}

macro_rules! simple_lit {
    ($l:literal) => {
        expand_expr_is!($l, $l);
        expand_expr_is!($l, echo_lit!($l));
        expand_expr_is!($l, echo_expr!($l));
        expand_expr_is!($l, echo_tts!($l));
        expand_expr_is!($l, echo_pm!($l));
        const _: () = {
            macro_rules! mac {
                () => {
                    $l
                };
            }
            expand_expr_is!($l, mac!());
            expand_expr_is!($l, echo_expr!(mac!()));
            expand_expr_is!($l, echo_tts!(mac!()));
            expand_expr_is!($l, echo_pm!(mac!()));
        };
    };
}

simple_lit!("Hello, World");
simple_lit!('c');
simple_lit!(b'c');
simple_lit!(10);
simple_lit!(10.0);
simple_lit!(10.0f64);
simple_lit!(-3.14159);
simple_lit!(-3.5e10);
simple_lit!(0xFEED);
simple_lit!(-0xFEED);
simple_lit!(0b0100);
simple_lit!(-0b0100);
simple_lit!("string");
simple_lit!(r##"raw string"##);
simple_lit!(b"byte string");
simple_lit!(br##"raw byte string"##);
simple_lit!(true);
simple_lit!(false);

// Ensure char escapes aren't normalized by expansion
simple_lit!("\u{0}");
simple_lit!("\0");
simple_lit!("\x00");
simple_lit!('\u{0}');
simple_lit!('\0');
simple_lit!('\x00');
simple_lit!(b"\x00");
simple_lit!(b"\0");
simple_lit!(b'\x00');
simple_lit!(b'\0');

// Extra tokens after the string literal aren't ignored
expand_expr_fail!("string"; hello); //~ ERROR: expected one of `.`, `?`, or an operator, found `;`

// Invalid expressions produce errors in addition to returning `Err(())`.
expand_expr_fail!($); //~ ERROR: expected expression, found `$`
expand_expr_fail!(echo_tts!($));
expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$`

// We get errors reported and recover during macro expansion if the macro
// doesn't produce a valid expression.
expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following
expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following

// For now, fail if a non-literal expression is expanded.
expand_expr_fail!(arbitrary_expression() + "etc");
expand_expr_fail!(echo_tts!(arbitrary_expression() + "etc"));
expand_expr_fail!(echo_expr!(arbitrary_expression() + "etc"));
expand_expr_fail!(echo_pm!(arbitrary_expression() + "etc"));

const _: u32 = recursive_expand!(); //~ ERROR: recursion limit reached while expanding `recursive_expand!`

fn main() {
    // https://github.com/rust-lang/rust/issues/104414
    match b"Included file contents\n" {
        include_bytes!("auxiliary/included-file.txt") => (),
        _ => panic!("include_bytes! in pattern"),
    }
}