@@ -47,7 +47,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
47
47
check_pat ( self , p) ;
48
48
}
49
49
fn visit_expr ( & mut self , ex : & Expr ) {
50
- check_expr ( self , ex) ;
50
+ if check_expr ( self , ex) {
51
+ visit:: walk_expr ( v, e) ;
52
+ }
51
53
}
52
54
}
53
55
@@ -96,73 +98,80 @@ fn check_pat(v: &mut CheckCrateVisitor, p: &Pat) {
96
98
}
97
99
}
98
100
99
- fn check_expr ( v : & mut CheckCrateVisitor , e : & Expr ) {
100
- if v. in_const {
101
- match e. node {
102
- ExprUnary ( UnDeref , _) => { }
103
- ExprUnary ( UnUniq , _) => {
104
- span_err ! ( v. tcx. sess, e. span, E0010 , "cannot do allocations in constant expressions" ) ;
105
- return ;
106
- }
107
- ExprLit ( ref lit) if ast_util:: lit_is_str ( & * * lit) => { }
108
- ExprBinary ( ..) | ExprUnary ( ..) => {
101
+ fn check_expr ( v : & mut CheckCrateVisitor , e : & Expr ) -> bool {
102
+ if !v. in_const { return true }
103
+
104
+ match e. node {
105
+ ExprUnary ( UnDeref , _) => { }
106
+ ExprUnary ( UnUniq , _) => {
107
+ span_err ! ( v. tcx. sess, e. span, E0010 ,
108
+ "cannot do allocations in constant expressions" ) ;
109
+ return false ;
110
+ }
111
+ ExprLit ( ref lit) if ast_util:: lit_is_str ( & * * lit) => { }
112
+ ExprBinary ( ..) | ExprUnary ( ..) => {
109
113
let method_call = typeck:: MethodCall :: expr ( e. id ) ;
110
114
if v. tcx . method_map . borrow ( ) . contains_key ( & method_call) {
111
115
span_err ! ( v. tcx. sess, e. span, E0011 ,
112
- "user-defined operators are not allowed in constant expressions" ) ;
116
+ "user-defined operators are not allowed in constant \
117
+ expressions") ;
113
118
}
114
- }
115
- ExprLit ( _) => ( ) ,
116
- ExprCast ( _, _) => {
119
+ }
120
+ ExprLit ( _) => ( ) ,
121
+ ExprCast ( _, _) => {
117
122
let ety = ty:: expr_ty ( v. tcx , e) ;
118
123
if !ty:: type_is_numeric ( ety) && !ty:: type_is_unsafe_ptr ( ety) {
119
124
span_err ! ( v. tcx. sess, e. span, E0012 ,
120
- "can not cast to `{}` in a constant expression" ,
121
- ppaux:: ty_to_string( v. tcx, ety)
122
- ) ;
125
+ "can not cast to `{}` in a constant expression" ,
126
+ ppaux:: ty_to_string( v. tcx, ety) ) ;
123
127
}
124
- }
125
- ExprPath ( ref pth) => {
128
+ }
129
+ ExprPath ( ref pth) => {
126
130
// NB: In the future you might wish to relax this slightly
127
131
// to handle on-demand instantiation of functions via
128
132
// foo::<bar> in a const. Currently that is only done on
129
133
// a path in trans::callee that only works in block contexts.
130
134
if !pth. segments . iter ( ) . all ( |segment| segment. types . is_empty ( ) ) {
131
135
span_err ! ( v. tcx. sess, e. span, E0013 ,
132
- "paths in constants may only refer to items without type parameters" ) ;
136
+ "paths in constants may only refer to items without \
137
+ type parameters") ;
133
138
}
134
139
match v. tcx . def_map . borrow ( ) . find ( & e. id ) {
135
- Some ( & DefStatic ( ..) ) |
136
- Some ( & DefFn ( ..) ) |
137
- Some ( & DefVariant ( _, _, _) ) |
138
- Some ( & DefStruct ( _) ) => { }
139
-
140
- Some ( & def) => {
141
- debug ! ( "(checking const) found bad def: {:?}" , def) ;
142
- span_err ! ( v. tcx. sess, e. span, E0014 ,
143
- "paths in constants may only refer to constants or functions" ) ;
144
- }
145
- None => {
146
- v. tcx . sess . span_bug ( e. span , "unbound path in const?!" ) ;
147
- }
140
+ Some ( & DefStatic ( ..) ) |
141
+ Some ( & DefFn ( ..) ) |
142
+ Some ( & DefVariant ( _, _, _) ) |
143
+ Some ( & DefStruct ( _) ) => { }
144
+
145
+ Some ( & def) => {
146
+ debug ! ( "(checking const) found bad def: {:?}" , def) ;
147
+ span_err ! ( v. tcx. sess, e. span, E0014 ,
148
+ "paths in constants may only refer to constants \
149
+ or functions") ;
150
+ }
151
+ None => {
152
+ v. tcx . sess . span_bug ( e. span , "unbound path in const?!" ) ;
153
+ }
148
154
}
149
- }
150
- ExprCall ( ref callee, _) => {
155
+ }
156
+ ExprCall ( ref callee, _) => {
151
157
match v. tcx . def_map . borrow ( ) . find ( & callee. id ) {
152
158
Some ( & DefStruct ( ..) ) |
153
159
Some ( & DefVariant ( ..) ) => { } // OK.
160
+
154
161
_ => {
155
162
span_err ! ( v. tcx. sess, e. span, E0015 ,
156
- "function calls in constants are limited to struct and enum constructors" ) ;
163
+ "function calls in constants are limited to \
164
+ struct and enum constructors") ;
157
165
}
158
166
}
159
- }
160
- ExprBlock ( ref block) => {
167
+ }
168
+ ExprBlock ( ref block) => {
161
169
// Check all statements in the block
162
170
for stmt in block. stmts . iter ( ) {
163
171
let block_span_err = |span|
164
172
span_err ! ( v. tcx. sess, span, E0016 ,
165
- "blocks in constants are limited to items and tail expressions" ) ;
173
+ "blocks in constants are limited to items and \
174
+ tail expressions") ;
166
175
match stmt. node {
167
176
StmtDecl ( ref span, _) => {
168
177
match span. node {
@@ -174,40 +183,43 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
174
183
}
175
184
StmtExpr ( ref expr, _) => block_span_err ( expr. span ) ,
176
185
StmtSemi ( ref semi, _) => block_span_err ( semi. span ) ,
177
- StmtMac ( ..) => v. tcx . sess . span_bug ( e. span ,
178
- "unexpanded statement macro in const?!" )
186
+ StmtMac ( ..) => {
187
+ v. tcx . sess . span_bug ( e. span , "unexpanded statement \
188
+ macro in const?!")
189
+ }
179
190
}
180
191
}
181
192
match block. expr {
182
193
Some ( ref expr) => check_expr ( v, & * * expr) ,
183
194
None => { }
184
195
}
185
- }
186
- ExprVec ( _) |
187
- ExprAddrOf ( MutImmutable , _) |
188
- ExprParen ( ..) |
189
- ExprField ( ..) |
190
- ExprTupField ( ..) |
191
- ExprIndex ( ..) |
192
- ExprTup ( ..) |
193
- ExprRepeat ( ..) |
194
- ExprStruct ( ..) => { }
195
- ExprAddrOf ( _, ref inner) => {
196
- match inner. node {
197
- // Mutable slices are allowed.
198
- ExprVec ( _) => { }
199
- _ => span_err ! ( v. tcx. sess, e. span, E0017 ,
200
- "references in constants may only refer to immutable values" )
196
+ }
197
+ ExprVec ( _) |
198
+ ExprAddrOf ( MutImmutable , _) |
199
+ ExprParen ( ..) |
200
+ ExprField ( ..) |
201
+ ExprTupField ( ..) |
202
+ ExprIndex ( ..) |
203
+ ExprTup ( ..) |
204
+ ExprRepeat ( ..) |
205
+ ExprStruct ( ..) => { }
201
206
202
- }
203
- } ,
207
+ ExprAddrOf ( _, ref inner) => {
208
+ match inner. node {
209
+ // Mutable slices are allowed.
210
+ ExprVec ( _) => { }
211
+ _ => span_err ! ( v. tcx. sess, e. span, E0017 ,
212
+ "references in constants may only refer \
213
+ to immutable values")
214
+
215
+ }
216
+ }
204
217
205
- _ => {
206
- span_err ! ( v. tcx. sess, e. span, E0019 ,
207
- "constant contains unimplemented expression type" ) ;
208
- return ;
209
- }
218
+ _ => {
219
+ span_err ! ( v. tcx. sess, e. span, E0019 ,
220
+ "constant contains unimplemented expression type" ) ;
221
+ return false ;
210
222
}
211
223
}
212
- visit :: walk_expr ( v , e ) ;
224
+ true
213
225
}
0 commit comments