@@ -14,9 +14,7 @@ use middle::ty;
14
14
use util:: ppaux;
15
15
16
16
use syntax:: ast;
17
- use syntax:: ast_util;
18
- use syntax:: visit:: Visitor ;
19
- use syntax:: visit;
17
+ use syntax:: visit:: { self , Visitor } ;
20
18
21
19
struct CheckCrateVisitor < ' a , ' tcx : ' a > {
22
20
tcx : & ' a ty:: ctxt < ' tcx > ,
@@ -37,24 +35,39 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
37
35
{
38
36
self . with_const ( true , f) ;
39
37
}
40
- fn outside_const < F > ( & mut self , f : F ) where
41
- F : FnOnce ( & mut CheckCrateVisitor < ' a , ' tcx > ) ,
42
- {
43
- self . with_const ( false , f) ;
44
- }
45
38
}
46
39
47
40
impl < ' a , ' tcx , ' v > Visitor < ' v > for CheckCrateVisitor < ' a , ' tcx > {
48
41
fn visit_item ( & mut self , i : & ast:: Item ) {
49
- check_item ( self , i) ;
42
+ match i. node {
43
+ ast:: ItemStatic ( _, _, ref ex) |
44
+ ast:: ItemConst ( _, ref ex) => {
45
+ self . inside_const ( |v| v. visit_expr ( & * * ex) ) ;
46
+ }
47
+ ast:: ItemEnum ( ref enum_definition, _) => {
48
+ self . inside_const ( |v| {
49
+ for var in enum_definition. variants . iter ( ) {
50
+ if let Some ( ref ex) = var. node . disr_expr {
51
+ v. visit_expr ( & * * ex) ;
52
+ }
53
+ }
54
+ } ) ;
55
+ }
56
+ _ => self . with_const ( false , |v| visit:: walk_item ( v, i) )
57
+ }
50
58
}
51
59
fn visit_pat ( & mut self , p : & ast:: Pat ) {
52
- check_pat ( self , p) ;
60
+ let is_const = match p. node {
61
+ ast:: PatLit ( _) | ast:: PatRange ( ..) => true ,
62
+ _ => false
63
+ } ;
64
+ self . with_const ( is_const, |v| visit:: walk_pat ( v, p) )
53
65
}
54
66
fn visit_expr ( & mut self , ex : & ast:: Expr ) {
55
- if check_expr ( self , ex ) {
56
- visit :: walk_expr ( self , ex) ;
67
+ if self . in_const {
68
+ check_expr ( self , ex) ;
57
69
}
70
+ visit:: walk_expr ( self , ex) ;
58
71
}
59
72
}
60
73
@@ -64,57 +77,13 @@ pub fn check_crate(tcx: &ty::ctxt) {
64
77
tcx. sess . abort_if_errors ( ) ;
65
78
}
66
79
67
- fn check_item ( v : & mut CheckCrateVisitor , it : & ast:: Item ) {
68
- match it. node {
69
- ast:: ItemStatic ( _, _, ref ex) |
70
- ast:: ItemConst ( _, ref ex) => {
71
- v. inside_const ( |v| v. visit_expr ( & * * ex) ) ;
72
- }
73
- ast:: ItemEnum ( ref enum_definition, _) => {
74
- for var in ( * enum_definition) . variants . iter ( ) {
75
- for ex in var. node . disr_expr . iter ( ) {
76
- v. inside_const ( |v| v. visit_expr ( & * * ex) ) ;
77
- }
78
- }
79
- }
80
- _ => v. outside_const ( |v| visit:: walk_item ( v, it) )
81
- }
82
- }
83
-
84
- fn check_pat ( v : & mut CheckCrateVisitor , p : & ast:: Pat ) {
85
- fn is_str ( e : & ast:: Expr ) -> bool {
86
- match e. node {
87
- ast:: ExprBox ( _, ref expr) => {
88
- match expr. node {
89
- ast:: ExprLit ( ref lit) => ast_util:: lit_is_str ( & * * lit) ,
90
- _ => false ,
91
- }
92
- }
93
- _ => false ,
94
- }
95
- }
96
- match p. node {
97
- // Let through plain ~-string literals here
98
- ast:: PatLit ( ref a) => if !is_str ( & * * a) { v. inside_const ( |v| v. visit_expr ( & * * a) ) ; } ,
99
- ast:: PatRange ( ref a, ref b) => {
100
- if !is_str ( & * * a) { v. inside_const ( |v| v. visit_expr ( & * * a) ) ; }
101
- if !is_str ( & * * b) { v. inside_const ( |v| v. visit_expr ( & * * b) ) ; }
102
- }
103
- _ => v. outside_const ( |v| visit:: walk_pat ( v, p) )
104
- }
105
- }
106
-
107
- fn check_expr ( v : & mut CheckCrateVisitor , e : & ast:: Expr ) -> bool {
108
- if !v. in_const { return true }
109
-
80
+ fn check_expr ( v : & mut CheckCrateVisitor , e : & ast:: Expr ) {
110
81
match e. node {
111
82
ast:: ExprUnary ( ast:: UnDeref , _) => { }
112
83
ast:: ExprUnary ( ast:: UnUniq , _) => {
113
84
span_err ! ( v. tcx. sess, e. span, E0010 ,
114
85
"cannot do allocations in constant expressions" ) ;
115
- return false ;
116
86
}
117
- ast:: ExprLit ( ref lit) if ast_util:: lit_is_str ( & * * lit) => { }
118
87
ast:: ExprBinary ( ..) | ast:: ExprUnary ( ..) => {
119
88
let method_call = ty:: MethodCall :: expr ( e. id ) ;
120
89
if v. tcx . method_map . borrow ( ) . contains_key ( & method_call) {
@@ -123,7 +92,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
123
92
expressions") ;
124
93
}
125
94
}
126
- ast:: ExprLit ( _) => ( ) ,
95
+ ast:: ExprLit ( _) => { }
127
96
ast:: ExprCast ( ref from, _) => {
128
97
let toty = ty:: expr_ty ( v. tcx , e) ;
129
98
let fromty = ty:: expr_ty ( v. tcx , & * * from) ;
@@ -142,39 +111,23 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
142
111
expression") ;
143
112
}
144
113
}
145
- ast:: ExprPath ( ref pth) => {
146
- // NB: In the future you might wish to relax this slightly
147
- // to handle on-demand instantiation of functions via
148
- // foo::<bar> in a const. Currently that is only done on
149
- // a path in trans::callee that only works in block contexts.
150
- if !pth. segments . iter ( ) . all ( |segment| segment. parameters . is_empty ( ) ) {
151
- span_err ! ( v. tcx. sess, e. span, E0013 ,
152
- "paths in constants may only refer to items without \
153
- type parameters") ;
154
- }
155
- match v. tcx . def_map . borrow ( ) . get ( & e. id ) {
156
- Some ( & DefStatic ( ..) ) |
157
- Some ( & DefConst ( ..) ) |
158
- Some ( & DefFn ( ..) ) |
159
- Some ( & DefVariant ( _, _, _) ) |
160
- Some ( & DefStruct ( _) ) => { }
114
+ ast:: ExprPath ( _) => {
115
+ match v. tcx . def_map . borrow ( ) [ e. id ] {
116
+ DefStatic ( ..) | DefConst ( ..) |
117
+ DefFn ( ..) | DefStaticMethod ( ..) | DefMethod ( ..) |
118
+ DefStruct ( _) | DefVariant ( _, _, _) => { }
161
119
162
- Some ( & def) => {
120
+ def => {
163
121
debug ! ( "(checking const) found bad def: {}" , def) ;
164
122
span_err ! ( v. tcx. sess, e. span, E0014 ,
165
123
"paths in constants may only refer to constants \
166
124
or functions") ;
167
125
}
168
- None => {
169
- v. tcx . sess . span_bug ( e. span , "unbound path in const?!" ) ;
170
- }
171
126
}
172
127
}
173
128
ast:: ExprCall ( ref callee, _) => {
174
- match v. tcx . def_map . borrow ( ) . get ( & callee. id ) {
175
- Some ( & DefStruct ( ..) ) |
176
- Some ( & DefVariant ( ..) ) => { } // OK.
177
-
129
+ match v. tcx . def_map . borrow ( ) [ callee. id ] {
130
+ DefStruct ( ..) | DefVariant ( ..) => { } // OK.
178
131
_ => {
179
132
span_err ! ( v. tcx. sess, e. span, E0015 ,
180
133
"function calls in constants are limited to \
@@ -190,9 +143,9 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
190
143
"blocks in constants are limited to items and \
191
144
tail expressions") ;
192
145
match stmt. node {
193
- ast:: StmtDecl ( ref span , _) => {
194
- match span . node {
195
- ast:: DeclLocal ( _) => block_span_err ( span . span ) ,
146
+ ast:: StmtDecl ( ref decl , _) => {
147
+ match decl . node {
148
+ ast:: DeclLocal ( _) => block_span_err ( decl . span ) ,
196
149
197
150
// Item statements are allowed
198
151
ast:: DeclItem ( _) => { }
@@ -206,10 +159,6 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
206
159
}
207
160
}
208
161
}
209
- match block. expr {
210
- Some ( ref expr) => { check_expr ( v, & * * expr) ; }
211
- None => { }
212
- }
213
162
}
214
163
ast:: ExprVec ( _) |
215
164
ast:: ExprAddrOf ( ast:: MutImmutable , _) |
@@ -232,11 +181,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
232
181
}
233
182
}
234
183
235
- _ => {
236
- span_err ! ( v. tcx. sess, e. span, E0019 ,
237
- "constant contains unimplemented expression type" ) ;
238
- return false ;
239
- }
184
+ _ => span_err ! ( v. tcx. sess, e. span, E0019 ,
185
+ "constant contains unimplemented expression type" )
240
186
}
241
- true
242
187
}
0 commit comments