@@ -18,6 +18,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1818 body : impl FnOnce ( & mut Self ) -> rustc_hir:: Expr < ' hir > ,
1919 contract : & rustc_ast:: FnContract ,
2020 ) -> rustc_hir:: Expr < ' hir > {
21+ // The order in which things are lowered is important! I.e to
22+ // refer to variables in contract_decls from postcond/precond,
23+ // we must lower it first!
24+ let contract_decls = self . lower_stmts ( & contract. declarations ) . 0 ;
25+
2126 match ( & contract. requires , & contract. ensures ) {
2227 ( Some ( req) , Some ( ens) ) => {
2328 // Lower the fn contract, which turns:
@@ -27,6 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2732 // into:
2833 //
2934 // let __postcond = if contract_checks {
35+ // CONTRACT_DECLARATIONS;
3036 // contract_check_requires(PRECOND);
3137 // Some(|ret_val| POSTCOND)
3238 // } else {
@@ -45,8 +51,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
4551 let precond = self . lower_precond ( req) ;
4652 let postcond_checker = self . lower_postcond_checker ( ens) ;
4753
48- let contract_check =
49- self . lower_contract_check_with_postcond ( Some ( precond) , postcond_checker) ;
54+ let contract_check = self . lower_contract_check_with_postcond (
55+ contract_decls,
56+ Some ( precond) ,
57+ postcond_checker,
58+ ) ;
5059
5160 let wrapped_body =
5261 self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -68,15 +77,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6877 // let ret = { body };
6978 //
7079 // if contract_checks {
80+ // CONTRACT_DECLARATIONS
7181 // contract_check_ensures(__postcond, ret)
7282 // } else {
7383 // ret
7484 // }
7585 // }
76-
7786 let postcond_checker = self . lower_postcond_checker ( ens) ;
7887 let contract_check =
79- self . lower_contract_check_with_postcond ( None , postcond_checker) ;
88+ self . lower_contract_check_with_postcond ( contract_decls , None , postcond_checker) ;
8089
8190 let wrapped_body =
8291 self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -91,12 +100,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
91100 //
92101 // {
93102 // if contracts_checks {
103+ // CONTRACT_DECLARATIONS;
94104 // contract_requires(PRECOND);
95105 // }
96106 // body
97107 // }
98108 let precond = self . lower_precond ( req) ;
99- let precond_check = self . lower_contract_check_just_precond ( precond) ;
109+ let precond_check = self . lower_contract_check_just_precond ( contract_decls , precond) ;
100110
101111 let body = self . arena . alloc ( body ( self ) ) ;
102112
@@ -145,9 +155,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
145155
146156 fn lower_contract_check_just_precond (
147157 & mut self ,
158+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
148159 precond : rustc_hir:: Stmt < ' hir > ,
149160 ) -> rustc_hir:: Stmt < ' 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 ( ) ) ) ;
151164
152165 let then_block_stmts = self . block_all ( precond. span , stmts, None ) ;
153166 let then_block = self . arena . alloc ( self . expr_block ( & then_block_stmts) ) ;
@@ -164,10 +177,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
164177
165178 fn lower_contract_check_with_postcond (
166179 & mut self ,
180+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
167181 precond : Option < rustc_hir:: Stmt < ' hir > > ,
168182 postcond_checker : & ' hir rustc_hir:: Expr < ' hir > ,
169183 ) -> & ' hir rustc_hir:: Expr < ' hir > {
170- let stmts = self . arena . alloc_from_iter ( precond. into_iter ( ) ) ;
184+ let stmts = self
185+ . arena
186+ . alloc_from_iter ( contract_decls. into_iter ( ) . map ( |d| * d) . chain ( precond. into_iter ( ) ) ) ;
171187 let span = match precond {
172188 Some ( precond) => precond. span ,
173189 None => postcond_checker. span ,
0 commit comments