@@ -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,16 @@ 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 })
60
+ // contract_check_ensures(__postcond, { body })
51
61
// }
52
-
53
62
let postcond_checker = self . lower_postcond_checker ( ens) ;
54
63
let contract_check =
55
- self . lower_contract_check_with_postcond ( None , postcond_checker) ;
64
+ self . lower_contract_check_with_postcond ( contract_decls , None , postcond_checker) ;
56
65
57
66
let wrapped_body =
58
67
self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -67,12 +76,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
67
76
//
68
77
// {
69
78
// if contracts_check() {
79
+ // CONTRACT_DECLARATIONS;
70
80
// contract_requires(PRECOND);
71
81
// }
72
82
// body
73
83
// }
74
84
let precond = self . lower_precond ( req) ;
75
- let precond_check = self . lower_contract_check_just_precond ( precond) ;
85
+ let precond_check = self . lower_contract_check_just_precond ( contract_decls , precond) ;
76
86
77
87
let body = self . arena . alloc ( body ( self ) ) ;
78
88
@@ -121,9 +131,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
121
131
122
132
fn lower_contract_check_just_precond (
123
133
& mut self ,
134
+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
124
135
precond : rustc_hir:: Stmt < ' hir > ,
125
136
) -> rustc_hir:: Stmt < ' hir > {
126
- let stmts = self . arena . alloc_from_iter ( [ precond] . into_iter ( ) ) ;
137
+ let stmts = self
138
+ . arena
139
+ . alloc_from_iter ( contract_decls. into_iter ( ) . map ( |d| * d) . chain ( [ precond] . into_iter ( ) ) ) ;
127
140
128
141
let then_block_stmts = self . block_all ( precond. span , stmts, None ) ;
129
142
let then_block = self . arena . alloc ( self . expr_block ( & then_block_stmts) ) ;
@@ -144,10 +157,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
144
157
145
158
fn lower_contract_check_with_postcond (
146
159
& mut self ,
160
+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
147
161
precond : Option < rustc_hir:: Stmt < ' hir > > ,
148
162
postcond_checker : & ' hir rustc_hir:: Expr < ' hir > ,
149
163
) -> & ' hir rustc_hir:: Expr < ' hir > {
150
- let stmts = self . arena . alloc_from_iter ( precond. into_iter ( ) ) ;
164
+ let stmts = self
165
+ . arena
166
+ . alloc_from_iter ( contract_decls. into_iter ( ) . map ( |d| * d) . chain ( precond. into_iter ( ) ) ) ;
151
167
let span = match precond {
152
168
Some ( precond) => precond. span ,
153
169
None => postcond_checker. span ,
0 commit comments