@@ -6,6 +6,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6
6
body : impl FnOnce ( & mut Self ) -> rustc_hir:: Expr < ' hir > ,
7
7
contract : & rustc_ast:: FnContract ,
8
8
) -> rustc_hir:: Expr < ' hir > {
9
+ // The order in which things are lowered is important! I.e to
10
+ // refer to variables in contract_decls from postcond/precond,
11
+ // we must lower it first!
12
+ let contract_decls = self . lower_stmts ( & contract. declarations ) . 0 ;
13
+
9
14
match ( & contract. requires , & contract. ensures ) {
10
15
( Some ( req) , Some ( ens) ) => {
11
16
// Lower the fn contract, which turns:
@@ -16,6 +21,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16
21
//
17
22
// {
18
23
// let __postcond = if contracts_checks() {
24
+ // CONTRACT_DECLARATIONS;
19
25
// contract_check_requires(PRECOND);
20
26
// Some(|ret_val| POSTCOND)
21
27
// } else {
@@ -27,8 +33,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
27
33
let precond = self . lower_precond ( req) ;
28
34
let postcond_checker = self . lower_postcond_checker ( ens) ;
29
35
30
- let contract_check =
31
- self . lower_contract_check_with_postcond ( Some ( precond) , postcond_checker) ;
36
+ let contract_check = self . lower_contract_check_with_postcond (
37
+ contract_decls,
38
+ Some ( precond) ,
39
+ postcond_checker,
40
+ ) ;
32
41
33
42
let wrapped_body =
34
43
self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -43,16 +52,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
43
52
//
44
53
// {
45
54
// let __postcond = if contracts_check() {
55
+ // CONTRACT_DECLARATIONS;
46
56
// Some(|ret_val| POSTCOND)
47
57
// } else {
48
58
// None
49
59
// };
50
- // __postcond({ body })
51
- // }
52
-
53
- let postcond_checker = self . lower_postcond_checker ( ens) ;
54
60
let contract_check =
55
- self . lower_contract_check_with_postcond ( None , postcond_checker) ;
61
+ self . lower_contract_check_with_postcond ( contract_decls , None , postcond_checker) ;
56
62
57
63
let wrapped_body =
58
64
self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -67,12 +73,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
67
73
//
68
74
// {
69
75
// if contracts_check() {
76
+ // CONTRACT_DECLARATIONS;
70
77
// contract_requires(PRECOND);
71
78
// }
72
79
// body
73
80
// }
74
81
let precond = self . lower_precond ( req) ;
75
- let precond_check = self . lower_contract_check_just_precond ( precond) ;
82
+ let precond_check = self . lower_contract_check_just_precond ( contract_decls , precond) ;
76
83
77
84
let body = self . arena . alloc ( body ( self ) ) ;
78
85
@@ -121,9 +128,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
121
128
122
129
fn lower_contract_check_just_precond (
123
130
& mut self ,
131
+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
124
132
precond : rustc_hir:: Stmt < ' hir > ,
125
133
) -> rustc_hir:: Stmt < ' hir > {
126
- let stmts = self . arena . alloc_from_iter ( [ precond] . into_iter ( ) ) ;
134
+ let stmts = self
135
+ . arena
136
+ . alloc_from_iter ( contract_decls. into_iter ( ) . map ( |d| * d) . chain ( [ precond] . into_iter ( ) ) ) ;
127
137
128
138
let then_block_stmts = self . block_all ( precond. span , stmts, None ) ;
129
139
let then_block = self . arena . alloc ( self . expr_block ( & then_block_stmts) ) ;
@@ -144,10 +154,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
144
154
145
155
fn lower_contract_check_with_postcond (
146
156
& mut self ,
157
+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
147
158
precond : Option < rustc_hir:: Stmt < ' hir > > ,
148
159
postcond_checker : & ' hir rustc_hir:: Expr < ' hir > ,
149
160
) -> & ' hir rustc_hir:: Expr < ' hir > {
150
- let stmts = self . arena . alloc_from_iter ( precond. into_iter ( ) ) ;
161
+ let stmts = self
162
+ . arena
163
+ . alloc_from_iter ( contract_decls. into_iter ( ) . map ( |d| * d) . chain ( precond. into_iter ( ) ) ) ;
151
164
let span = match precond {
152
165
Some ( precond) => precond. span ,
153
166
None => postcond_checker. span ,
0 commit comments