bon_macros/parsing/
const_.rs1use super::reject_attrs;
2use crate::util::prelude::*;
3
4pub(crate) fn require_embeddable_const_expr(expr: &syn::Expr) -> Result {
20 use require_embeddable_const_expr as recurse;
21
22 fn recurse_block(block: &syn::Block) -> Result {
23 let stmt = match block.stmts.as_slice() {
24 [stmt] => stmt,
25 [] => return Ok(()),
26 _ => bail!(
27 &block,
28 "only a single expression in a block is allowed in this position"
29 ),
30 };
31
32 match stmt {
33 syn::Stmt::Expr(expr, None) => recurse(expr),
34 _ => bail!(
35 &stmt,
36 "this kind of statement is not allowed in this position; \
37 only a single expression is allowed in a block is allowed here"
38 ),
39 }
40 }
41
42 use syn::Expr::*;
43
44 match expr {
45 Array(arr) => {
46 reject_attrs(&arr.attrs)?;
47 arr.elems.iter().try_for_each(recurse)?;
48 }
49 Binary(binary) => {
50 reject_attrs(&binary.attrs)?;
51 recurse(&binary.left)?;
52 recurse(&binary.right)?;
53 }
54 Block(block) => {
55 reject_attrs(&block.attrs)?;
56 recurse_block(&block.block)?;
57 }
58 Call(call) => {
59 reject_attrs(&call.attrs)?;
60 recurse(&call.func)?;
61 call.args.iter().try_for_each(recurse)?;
62 }
63 Cast(cast) => {
64 reject_attrs(&cast.attrs)?;
65 recurse(&cast.expr)?;
66 }
67 Field(field) => {
68 reject_attrs(&field.attrs)?;
69 recurse(&field.base)?;
70 }
71 Group(group) => {
72 reject_attrs(&group.attrs)?;
73 recurse(&group.expr)?;
74 }
75 If(if_expr) => {
76 reject_attrs(&if_expr.attrs)?;
77 recurse(&if_expr.cond)?;
78 recurse_block(&if_expr.then_branch)?;
79 if let Some((_else, else_branch)) = &if_expr.else_branch {
80 recurse(else_branch)?;
81 }
82 }
83 Const(const_block) => {
84 reject_attrs(&const_block.attrs)?;
85 recurse_block(&const_block.block)?;
86 }
87 Index(index) => {
88 reject_attrs(&index.attrs)?;
89 recurse(&index.expr)?;
90 recurse(&index.index)?;
91 }
92 Infer(infer) => reject_attrs(&infer.attrs)?,
93 Lit(lit) => reject_attrs(&lit.attrs)?,
94 Loop(loop_expr) => {
95 reject_attrs(&loop_expr.attrs)?;
96 recurse_block(&loop_expr.body)?;
97 }
98 Match(expr_match) => {
99 reject_attrs(&expr_match.attrs)?;
100 recurse(&expr_match.expr)?;
101 expr_match.arms.iter().try_for_each(|arm| {
102 reject_attrs(&arm.attrs)?;
103
104 if let Some((_if, guard)) = &arm.guard {
105 recurse(guard)?;
106 }
107
108 recurse(&arm.body)
109 })?;
110 }
111 MethodCall(method_call) => {
112 reject_attrs(&method_call.attrs)?;
113 recurse(&method_call.receiver)?;
114 method_call.args.iter().try_for_each(recurse)?;
115 }
116 Paren(paren) => {
117 reject_attrs(&paren.attrs)?;
118 recurse(&paren.expr)?;
119 }
120 Path(path) => reject_attrs(&path.attrs)?,
121 Range(range) => {
122 reject_attrs(&range.attrs)?;
123 if let Some(start) = &range.start {
124 recurse(start)?;
125 }
126 if let Some(end) = &range.end {
127 recurse(end)?;
128 }
129 }
130
131 Reference(reference) => {
132 reject_attrs(&reference.attrs)?;
133 recurse(&reference.expr)?;
134 }
135 Repeat(repeat) => {
136 reject_attrs(&repeat.attrs)?;
137 recurse(&repeat.expr)?;
138 recurse(&repeat.len)?;
139 }
140 Struct(struct_expr) => {
141 reject_attrs(&struct_expr.attrs)?;
142 struct_expr.fields.iter().try_for_each(|field| {
143 reject_attrs(&field.attrs)?;
144 recurse(&field.expr)
145 })?;
146 if let Some(rest) = &struct_expr.rest {
147 recurse(rest)?;
148 }
149 }
150 Tuple(tuple) => {
151 reject_attrs(&tuple.attrs)?;
152 tuple.elems.iter().try_for_each(recurse)?;
153 }
154 Unary(unary) => {
155 reject_attrs(&unary.attrs)?;
156 recurse(&unary.expr)?;
157 }
158 Unsafe(unsafe_expr) => {
159 reject_attrs(&unsafe_expr.attrs)?;
160 recurse_block(&unsafe_expr.block)?;
161 }
162 While(while_expr) => {
163 reject_attrs(&while_expr.attrs)?;
164 recurse(&while_expr.cond)?;
165 recurse_block(&while_expr.body)?;
166 }
167 _ => {
168 bail!(
169 &expr,
170 "this kind of expression is not allowed in this position; \
171 if you need to use a complex expression such as this then \
172 move it into a separate `const fn` and call that function \
173 here instead"
174 )
175 }
176 }
177
178 Ok(())
179}