@@ -6,6 +6,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
66 body : impl FnOnce ( & mut Self ) -> rustc_hir:: Expr < ' hir > ,
77 contract : & rustc_ast:: FnContract ,
88 ) -> 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+
914 match ( & contract. requires , & contract. ensures ) {
1015 ( Some ( req) , Some ( ens) ) => {
1116 // Lower the fn contract, which turns:
@@ -16,6 +21,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1621 //
1722 // {
1823 // let __postcond = if contracts_checks() {
24+ // CONTRACT_DECLARATIONS;
1925 // contract_check_requires(PRECOND);
2026 // Some(|ret_val| POSTCOND)
2127 // } else {
@@ -27,8 +33,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2733 let precond = self . lower_precond ( req) ;
2834 let postcond_checker = self . lower_postcond_checker ( ens) ;
2935
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+ ) ;
3241
3342 let wrapped_body =
3443 self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -43,16 +52,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
4352 //
4453 // {
4554 // let __postcond = if contracts_check() {
55+ // CONTRACT_DECLARATIONS;
4656 // Some(|ret_val| POSTCOND)
4757 // } else {
4858 // None
4959 // };
50- // __postcond({ body })
51- // }
52-
53- let postcond_checker = self . lower_postcond_checker ( ens) ;
5460 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) ;
5662
5763 let wrapped_body =
5864 self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -67,12 +73,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6773 //
6874 // {
6975 // if contracts_check() {
76+ // CONTRACT_DECLARATIONS;
7077 // contract_requires(PRECOND);
7178 // }
7279 // body
7380 // }
7481 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) ;
7683
7784 let body = self . arena . alloc ( body ( self ) ) ;
7885
@@ -121,9 +128,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
121128
122129 fn lower_contract_check_just_precond (
123130 & mut self ,
131+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
124132 precond : rustc_hir:: Stmt < ' hir > ,
125133 ) -> 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 ( ) ) ) ;
127137
128138 let then_block_stmts = self . block_all ( precond. span , stmts, None ) ;
129139 let then_block = self . arena . alloc ( self . expr_block ( & then_block_stmts) ) ;
@@ -144,10 +154,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
144154
145155 fn lower_contract_check_with_postcond (
146156 & mut self ,
157+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
147158 precond : Option < rustc_hir:: Stmt < ' hir > > ,
148159 postcond_checker : & ' hir rustc_hir:: Expr < ' hir > ,
149160 ) -> & ' 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 ( ) ) ) ;
151164 let span = match precond {
152165 Some ( precond) => precond. span ,
153166 None => postcond_checker. span ,
0 commit comments