@@ -14,9 +14,7 @@ use middle::ty;
1414use util:: ppaux;
1515
1616use syntax:: ast;
17- use syntax:: ast_util;
18- use syntax:: visit:: Visitor ;
19- use syntax:: visit;
17+ use syntax:: visit:: { self , Visitor } ;
2018
2119struct CheckCrateVisitor < ' a , ' tcx : ' a > {
2220 tcx : & ' a ty:: ctxt < ' tcx > ,
@@ -37,24 +35,39 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
3735 {
3836 self . with_const ( true , f) ;
3937 }
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- }
4538}
4639
4740impl < ' a , ' tcx , ' v > Visitor < ' v > for CheckCrateVisitor < ' a , ' tcx > {
4841 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+ }
5058 }
5159 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) )
5365 }
5466 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) ;
5769 }
70+ visit:: walk_expr ( self , ex) ;
5871 }
5972}
6073
@@ -64,57 +77,13 @@ pub fn check_crate(tcx: &ty::ctxt) {
6477 tcx. sess . abort_if_errors ( ) ;
6578}
6679
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 ) {
11081 match e. node {
11182 ast:: ExprUnary ( ast:: UnDeref , _) => { }
11283 ast:: ExprUnary ( ast:: UnUniq , _) => {
11384 span_err ! ( v. tcx. sess, e. span, E0010 ,
11485 "cannot do allocations in constant expressions" ) ;
115- return false ;
11686 }
117- ast:: ExprLit ( ref lit) if ast_util:: lit_is_str ( & * * lit) => { }
11887 ast:: ExprBinary ( ..) | ast:: ExprUnary ( ..) => {
11988 let method_call = ty:: MethodCall :: expr ( e. id ) ;
12089 if v. tcx . method_map . borrow ( ) . contains_key ( & method_call) {
@@ -123,7 +92,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
12392 expressions") ;
12493 }
12594 }
126- ast:: ExprLit ( _) => ( ) ,
95+ ast:: ExprLit ( _) => { }
12796 ast:: ExprCast ( ref from, _) => {
12897 let toty = ty:: expr_ty ( v. tcx , e) ;
12998 let fromty = ty:: expr_ty ( v. tcx , & * * from) ;
@@ -142,39 +111,23 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
142111 expression") ;
143112 }
144113 }
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 ( _, _, _) => { }
161119
162- Some ( & def) => {
120+ def => {
163121 debug ! ( "(checking const) found bad def: {}" , def) ;
164122 span_err ! ( v. tcx. sess, e. span, E0014 ,
165123 "paths in constants may only refer to constants \
166124 or functions") ;
167125 }
168- None => {
169- v. tcx . sess . span_bug ( e. span , "unbound path in const?!" ) ;
170- }
171126 }
172127 }
173128 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.
178131 _ => {
179132 span_err ! ( v. tcx. sess, e. span, E0015 ,
180133 "function calls in constants are limited to \
@@ -190,9 +143,9 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
190143 "blocks in constants are limited to items and \
191144 tail expressions") ;
192145 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 ) ,
196149
197150 // Item statements are allowed
198151 ast:: DeclItem ( _) => { }
@@ -206,10 +159,6 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
206159 }
207160 }
208161 }
209- match block. expr {
210- Some ( ref expr) => { check_expr ( v, & * * expr) ; }
211- None => { }
212- }
213162 }
214163 ast:: ExprVec ( _) |
215164 ast:: ExprAddrOf ( ast:: MutImmutable , _) |
@@ -232,11 +181,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
232181 }
233182 }
234183
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" )
240186 }
241- true
242187}
0 commit comments