1
+ import syntax:: ast:: * ;
2
+ import syntax:: visit;
3
+ import driver:: session:: session;
4
+
5
+ type ctx = { in_loop : bool , can_ret : bool } ;
6
+
7
+ fn check_crate ( sess : session , crate : @crate ) {
8
+ visit:: visit_crate ( * crate , { in_loop: false, can_ret: true} , visit:: mk_vt ( @{
9
+ visit_item : { |i, _cx, v |
10
+ visit:: visit_item ( i, { in_loop: false, can_ret: true } , v) ;
11
+ } ,
12
+ visit_expr : { |e: @expr, cx : ctx, v : visit:: vt<ctx>|
13
+ alt e. node {
14
+ expr_for ( _, e, b) | expr_while ( e, b) | expr_do_while ( b, e) {
15
+ v. visit_expr ( e, cx, v) ;
16
+ v. visit_block ( b, { in_loop: true with cx} , v) ;
17
+ }
18
+ expr_loop ( b) {
19
+ v. visit_block ( b, { in_loop: true with cx} , v) ;
20
+ }
21
+ expr_fn ( _, _, _, _) {
22
+ visit:: visit_expr ( e, { in_loop: false, can_ret: true } , v) ;
23
+ }
24
+ expr_fn_block ( fn_decl, blk) {
25
+ visit:: visit_expr ( e, { in_loop: false, can_ret: false } , v) ;
26
+ }
27
+ expr_break {
28
+ if !cx. in_loop {
29
+ sess. span_err ( e. span , "`break` outside of loop" ) ;
30
+ }
31
+ }
32
+ expr_cont {
33
+ if !cx. in_loop {
34
+ sess. span_err ( e. span , "`cont` outside of loop" ) ;
35
+ }
36
+ }
37
+ expr_ret( oe) {
38
+ if !cx. can_ret {
39
+ sess. span_err ( e. span , "`ret` in block function" ) ;
40
+ }
41
+ visit:: visit_expr_opt ( oe, cx, v) ;
42
+ }
43
+ expr_be ( re) {
44
+ if !cx. can_ret {
45
+ sess. span_err ( e. span , "`be` in block function" ) ;
46
+ }
47
+ v. visit_expr ( re, cx, v) ;
48
+ }
49
+ _ { visit:: visit_expr ( e, cx, v) ; }
50
+ }
51
+ }
52
+ with * visit:: default_visitor ( )
53
+ } ) ) ;
54
+ }
0 commit comments