|
12 | 12 | #![allow(unsigned_negation)]
|
13 | 13 |
|
14 | 14 | pub use self::const_val::*;
|
15 |
| -pub use self::constness::*; |
16 | 15 |
|
17 | 16 | use metadata::csearch;
|
18 | 17 | use middle::{astencode, def};
|
19 | 18 | use middle::pat_util::def_to_path;
|
20 | 19 | use middle::ty::{self};
|
21 | 20 | use middle::astconv_util::{ast_ty_to_prim_ty};
|
22 |
| -use util::nodemap::DefIdMap; |
23 | 21 |
|
24 | 22 | use syntax::ast::{self, Expr};
|
25 | 23 | use syntax::parse::token::InternedString;
|
26 | 24 | use syntax::ptr::P;
|
27 |
| -use syntax::visit::{self, Visitor}; |
28 | 25 | use syntax::{ast_map, ast_util, codemap};
|
29 | 26 |
|
30 | 27 | use std::collections::hash_map::Entry::Vacant;
|
31 | 28 | use std::rc::Rc;
|
32 | 29 |
|
33 |
| -// |
34 |
| -// This pass classifies expressions by their constant-ness. |
35 |
| -// |
36 |
| -// Constant-ness comes in 3 flavours: |
37 |
| -// |
38 |
| -// - Integer-constants: can be evaluated by the frontend all the way down |
39 |
| -// to their actual value. They are used in a few places (enum |
40 |
| -// discriminants, switch arms) and are a subset of |
41 |
| -// general-constants. They cover all the integer and integer-ish |
42 |
| -// literals (nil, bool, int, uint, char, iNN, uNN) and all integer |
43 |
| -// operators and copies applied to them. |
44 |
| -// |
45 |
| -// - General-constants: can be evaluated by LLVM but not necessarily by |
46 |
| -// the frontend; usually due to reliance on target-specific stuff such |
47 |
| -// as "where in memory the value goes" or "what floating point mode the |
48 |
| -// target uses". This _includes_ integer-constants, plus the following |
49 |
| -// constructors: |
50 |
| -// |
51 |
| -// fixed-size vectors and strings: [] and ""/_ |
52 |
| -// vector and string slices: &[] and &"" |
53 |
| -// tuples: (,) |
54 |
| -// enums: foo(...) |
55 |
| -// floating point literals and operators |
56 |
| -// & and * pointers |
57 |
| -// copies of general constants |
58 |
| -// |
59 |
| -// (in theory, probably not at first: if/match on integer-const |
60 |
| -// conditions / discriminants) |
61 |
| -// |
62 |
| -// - Non-constants: everything else. |
63 |
| -// |
64 |
| - |
65 |
| -#[derive(Copy)] |
66 |
| -pub enum constness { |
67 |
| - integral_const, |
68 |
| - general_const, |
69 |
| - non_const |
70 |
| -} |
71 |
| - |
72 |
| -type constness_cache = DefIdMap<constness>; |
73 |
| - |
74 |
| -pub fn join(a: constness, b: constness) -> constness { |
75 |
| - match (a, b) { |
76 |
| - (integral_const, integral_const) => integral_const, |
77 |
| - (integral_const, general_const) |
78 |
| - | (general_const, integral_const) |
79 |
| - | (general_const, general_const) => general_const, |
80 |
| - _ => non_const |
81 |
| - } |
82 |
| -} |
83 |
| - |
84 |
| -pub fn join_all<It: Iterator<Item=constness>>(cs: It) -> constness { |
85 |
| - cs.fold(integral_const, |a, b| join(a, b)) |
86 |
| -} |
87 |
| - |
88 | 30 | fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
|
89 | 31 | let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
|
90 | 32 | match opt_def {
|
@@ -185,113 +127,6 @@ pub fn lookup_const_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
|
185 | 127 | }
|
186 | 128 | }
|
187 | 129 |
|
188 |
| -struct ConstEvalVisitor<'a, 'tcx: 'a> { |
189 |
| - tcx: &'a ty::ctxt<'tcx>, |
190 |
| - ccache: constness_cache, |
191 |
| -} |
192 |
| - |
193 |
| -impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> { |
194 |
| - fn classify(&mut self, e: &Expr) -> constness { |
195 |
| - let did = ast_util::local_def(e.id); |
196 |
| - match self.ccache.get(&did) { |
197 |
| - Some(&x) => return x, |
198 |
| - None => {} |
199 |
| - } |
200 |
| - let cn = match e.node { |
201 |
| - ast::ExprLit(ref lit) => { |
202 |
| - match lit.node { |
203 |
| - ast::LitStr(..) | ast::LitFloat(..) => general_const, |
204 |
| - _ => integral_const |
205 |
| - } |
206 |
| - } |
207 |
| - |
208 |
| - ast::ExprUnary(_, ref inner) | ast::ExprParen(ref inner) => |
209 |
| - self.classify(&**inner), |
210 |
| - |
211 |
| - ast::ExprBinary(_, ref a, ref b) => |
212 |
| - join(self.classify(&**a), self.classify(&**b)), |
213 |
| - |
214 |
| - ast::ExprTup(ref es) | |
215 |
| - ast::ExprVec(ref es) => |
216 |
| - join_all(es.iter().map(|e| self.classify(&**e))), |
217 |
| - |
218 |
| - ast::ExprStruct(_, ref fs, None) => { |
219 |
| - let cs = fs.iter().map(|f| self.classify(&*f.expr)); |
220 |
| - join_all(cs) |
221 |
| - } |
222 |
| - |
223 |
| - ast::ExprCast(ref base, _) => { |
224 |
| - let ty = ty::expr_ty(self.tcx, e); |
225 |
| - let base = self.classify(&**base); |
226 |
| - if ty::type_is_integral(ty) { |
227 |
| - join(integral_const, base) |
228 |
| - } else if ty::type_is_fp(ty) { |
229 |
| - join(general_const, base) |
230 |
| - } else { |
231 |
| - non_const |
232 |
| - } |
233 |
| - } |
234 |
| - |
235 |
| - ast::ExprField(ref base, _) => self.classify(&**base), |
236 |
| - |
237 |
| - ast::ExprTupField(ref base, _) => self.classify(&**base), |
238 |
| - |
239 |
| - ast::ExprIndex(ref base, ref idx) => |
240 |
| - join(self.classify(&**base), self.classify(&**idx)), |
241 |
| - |
242 |
| - ast::ExprAddrOf(ast::MutImmutable, ref base) => |
243 |
| - self.classify(&**base), |
244 |
| - |
245 |
| - // FIXME: (#3728) we can probably do something CCI-ish |
246 |
| - // surrounding nonlocal constants. But we don't yet. |
247 |
| - ast::ExprPath(_) | ast::ExprQPath(_) => self.lookup_constness(e), |
248 |
| - |
249 |
| - ast::ExprRepeat(..) => general_const, |
250 |
| - |
251 |
| - ast::ExprBlock(ref block) => { |
252 |
| - match block.expr { |
253 |
| - Some(ref e) => self.classify(&**e), |
254 |
| - None => integral_const |
255 |
| - } |
256 |
| - } |
257 |
| - |
258 |
| - _ => non_const |
259 |
| - }; |
260 |
| - self.ccache.insert(did, cn); |
261 |
| - cn |
262 |
| - } |
263 |
| - |
264 |
| - fn lookup_constness(&self, e: &Expr) -> constness { |
265 |
| - match lookup_const(self.tcx, e) { |
266 |
| - Some(rhs) => { |
267 |
| - let ty = ty::expr_ty(self.tcx, &*rhs); |
268 |
| - if ty::type_is_integral(ty) { |
269 |
| - integral_const |
270 |
| - } else { |
271 |
| - general_const |
272 |
| - } |
273 |
| - } |
274 |
| - None => non_const |
275 |
| - } |
276 |
| - } |
277 |
| - |
278 |
| -} |
279 |
| - |
280 |
| -impl<'a, 'tcx, 'v> Visitor<'v> for ConstEvalVisitor<'a, 'tcx> { |
281 |
| - fn visit_expr_post(&mut self, e: &Expr) { |
282 |
| - self.classify(e); |
283 |
| - } |
284 |
| -} |
285 |
| - |
286 |
| -pub fn process_crate(tcx: &ty::ctxt) { |
287 |
| - visit::walk_crate(&mut ConstEvalVisitor { |
288 |
| - tcx: tcx, |
289 |
| - ccache: DefIdMap(), |
290 |
| - }, tcx.map.krate()); |
291 |
| - tcx.sess.abort_if_errors(); |
292 |
| -} |
293 |
| - |
294 |
| - |
295 | 130 | // FIXME (#33): this doesn't handle big integer/float literals correctly
|
296 | 131 | // (nor does the rest of our literal handling).
|
297 | 132 | #[derive(Clone, PartialEq)]
|
|
0 commit comments