@@ -61,9 +61,19 @@ import collect_locals::mk_f_to_fn_info;
61
61
import pre_post_conditions:: fn_pre_post;
62
62
import states:: find_pre_post_state_fn;
63
63
64
- fn check_states_expr ( & fn_ctxt fcx, @expr e ) {
64
+ fn check_states_expr ( & fn_ctxt fcx, & @expr e ) {
65
65
let precond prec = expr_precond ( fcx. ccx , e) ;
66
66
let prestate pres = expr_prestate ( fcx. ccx , e) ;
67
+
68
+ /*
69
+ log_err("check_states_expr:");
70
+ util::common::log_expr_err(*e);
71
+ log_err("prec = ");
72
+ log_bitv_err(fcx, prec);
73
+ log_err("pres = ");
74
+ log_bitv_err(fcx, pres);
75
+ */
76
+
67
77
if ( !implies ( pres, prec) ) {
68
78
auto s = "" ;
69
79
auto diff = first_difference_string ( fcx, prec, pres) ;
@@ -79,26 +89,27 @@ fn check_states_expr(&fn_ctxt fcx, @expr e) {
79
89
}
80
90
}
81
91
82
- fn check_states_stmt ( & fn_ctxt fcx, & stmt s) {
83
- auto a = stmt_to_ann ( fcx. ccx , s) ;
92
+ fn check_states_stmt ( & fn_ctxt fcx, & @ stmt s ) {
93
+ auto a = stmt_to_ann ( fcx. ccx , * s) ;
84
94
let precond prec = ann_precond ( a) ;
85
95
let prestate pres = ann_prestate ( a) ;
86
96
87
- /*
97
+ /*
88
98
log_err("check_states_stmt:");
89
- log_stmt_err(s);
99
+ log_stmt_err(* s);
90
100
log_err("prec = ");
91
- log_bitv_err(fcx.enclosing , prec);
101
+ log_bitv_err(fcx, prec);
92
102
log_err("pres = ");
93
- log_bitv_err(fcx.enclosing , pres);
103
+ log_bitv_err(fcx, pres);
94
104
*/
105
+
95
106
if ( !implies ( pres, prec) ) {
96
107
auto ss = "" ;
97
108
auto diff = first_difference_string ( fcx, prec, pres) ;
98
109
ss +=
99
110
"Unsatisfied precondition constraint (for example, " + diff +
100
111
") for statement:\n " ;
101
- ss += pretty:: pprust:: stmt_to_str ( s) ;
112
+ ss += pretty:: pprust:: stmt_to_str ( * s) ;
102
113
ss += "\n Precondition:\n " ;
103
114
ss += bitv_to_str ( fcx, prec) ;
104
115
ss += "\n Prestate: \n " ;
@@ -107,42 +118,50 @@ fn check_states_stmt(&fn_ctxt fcx, &stmt s) {
107
118
}
108
119
}
109
120
110
- fn check_states_against_conditions ( & fn_ctxt fcx, & _fn f, & ann a) {
111
- auto enclosing = fcx. enclosing ;
112
- auto nv = num_constraints ( enclosing) ;
113
- auto post = @mutable empty_poststate ( nv) ;
114
- fn do_one_ ( fn_ctxt fcx, & @stmt s , @mutable poststate post ) {
115
- check_states_stmt ( fcx, * s) ;
116
- * post = stmt_poststate ( fcx. ccx , * s) ;
121
+ fn check_states_against_conditions ( & fn_ctxt fcx, & _fn f, & ann a,
122
+ & span sp, & ident i, & def_id d) {
123
+ /* Postorder traversal instead of pre is important
124
+ because we want the smallest possible erroneous statement
125
+ or expression. */
126
+
127
+ let @mutable bool keepgoing = @mutable true ;
128
+
129
+ /* TODO probably should use visit instead */
130
+
131
+ fn quit ( @mutable bool keepgoing , & @ast:: item i) {
132
+ * keepgoing = false ;
117
133
}
118
- auto do_one = bind do_one_ ( fcx, _, post) ;
119
- vec:: map[ @stmt, ( ) ] ( do_one, f. body . node . stmts ) ;
120
- fn do_inner_ ( fn_ctxt fcx, & @expr e , @mutable poststate post ) {
121
- check_states_expr ( fcx, e) ;
122
- * post = expr_poststate ( fcx. ccx , e) ;
134
+ fn kg ( @mutable bool keepgoing ) -> bool {
135
+ ret * keepgoing;
123
136
}
124
- auto do_inner = bind do_inner_ ( fcx, _, post) ;
125
- option:: map[ @expr, ( ) ] ( do_inner, f. body . node . expr ) ;
126
- auto cf = fcx. enclosing . cf ;
127
- /* Finally, check that the return value is initialized */
128
137
138
+ auto v = rec ( visit_stmt_post=bind check_states_stmt ( fcx, _) ,
139
+ visit_expr_post=bind check_states_expr ( fcx, _) ,
140
+ visit_item_pre=bind quit ( keepgoing, _) ,
141
+ keep_going=bind kg( keepgoing)
142
+ with walk:: default_visitor ( ) ) ;
143
+
144
+ walk:: walk_fn ( v, f, sp, i, d, a) ;
145
+
146
+ /* Finally, check that the return value is initialized */
147
+ auto post = aux:: block_poststate ( fcx. ccx , f. body ) ;
129
148
let aux:: constr_ ret_c = rec ( id=fcx. id , c=aux:: ninit ( fcx. name ) ) ;
130
- if ( f. proto == ast:: proto_fn && !promises ( fcx, { * post } , ret_c) &&
149
+ if ( f. proto == ast:: proto_fn && !promises ( fcx, post, ret_c) &&
131
150
!type_is_nil ( fcx. ccx . tcx , ret_ty_of_fn ( fcx. ccx . tcx , a) ) &&
132
- cf == return ) {
151
+ f . decl . cf == return ) {
133
152
fcx. ccx . tcx . sess . span_note ( f. body . span ,
134
153
"In function " + fcx. name +
135
154
", not all control paths \
136
155
return a value") ;
137
156
fcx. ccx . tcx . sess . span_err ( f. decl . output . span ,
138
157
"see declared return type of '" +
139
158
ty_to_str ( * f. decl . output ) + "'" ) ;
140
- } else if ( cf == noreturn) {
159
+ } else if ( f . decl . cf == noreturn) {
141
160
142
161
// check that this really always fails
143
162
// the fcx.id bit means "returns" for a returning fn,
144
163
// "diverges" for a non-returning fn
145
- if ( !promises ( fcx, { * post } , ret_c) ) {
164
+ if ( !promises ( fcx, post, ret_c) ) {
146
165
fcx. ccx . tcx . sess . span_err ( f. body . span ,
147
166
"In non-returning function " + fcx. name
148
167
+
@@ -152,15 +171,16 @@ fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) {
152
171
}
153
172
}
154
173
155
- fn check_fn_states ( & fn_ctxt fcx, & _fn f, & ann a) {
174
+ fn check_fn_states ( & fn_ctxt fcx, & _fn f, & ann a, & span sp, & ident i,
175
+ & def_id d) {
156
176
/* Compute the pre- and post-states for this function */
157
177
158
178
auto g = find_pre_post_state_fn;
159
179
fixed_point_states ( fcx, g, f) ;
160
180
/* Now compare each expr's pre-state to its precondition
161
181
and post-state to its postcondition */
162
182
163
- check_states_against_conditions ( fcx, f, a) ;
183
+ check_states_against_conditions ( fcx, f, a, sp , i , d ) ;
164
184
}
165
185
166
186
fn fn_states ( & crate_ctxt ccx, & _fn f, & span sp, & ident i, & def_id id,
@@ -170,7 +190,7 @@ fn fn_states(&crate_ctxt ccx, &_fn f, &span sp, &ident i, &def_id id,
170
190
assert ( ccx. fm . contains_key ( id) ) ;
171
191
auto f_info = ccx. fm . get ( id) ;
172
192
auto fcx = rec ( enclosing=f_info, id=id, name=i, ccx=ccx) ;
173
- check_fn_states ( fcx, f, a) ;
193
+ check_fn_states ( fcx, f, a, sp , i , id ) ;
174
194
}
175
195
176
196
fn check_crate ( ty:: ctxt cx, @crate crate) {
@@ -185,15 +205,15 @@ fn check_crate(ty::ctxt cx, @crate crate) {
185
205
186
206
auto do_pre_post = walk:: default_visitor ( ) ;
187
207
do_pre_post =
188
- rec ( visit_fn_pre =bind fn_pre_post ( ccx, _, _, _, _, _)
208
+ rec ( visit_fn_post =bind fn_pre_post ( ccx, _, _, _, _, _)
189
209
with do_pre_post) ;
190
210
walk:: walk_crate ( do_pre_post, * crate ) ;
191
211
/* Check the pre- and postcondition against the pre- and poststate
192
212
for every expression */
193
213
194
214
auto do_states = walk:: default_visitor ( ) ;
195
215
do_states =
196
- rec ( visit_fn_pre =bind fn_states ( ccx, _, _, _, _, _) with do_states) ;
216
+ rec ( visit_fn_post =bind fn_states ( ccx, _, _, _, _, _) with do_states) ;
197
217
walk:: walk_crate ( do_states, * crate ) ;
198
218
}
199
219
//
0 commit comments