@@ -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,16 @@ 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 })
60+ // contract_check_ensures(__postcond, { body })
5161 // }
52-
5362 let postcond_checker = self . lower_postcond_checker ( ens) ;
5463 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) ;
5665
5766 let wrapped_body =
5867 self . wrap_body_with_contract_check ( body, contract_check, postcond_checker. span ) ;
@@ -67,12 +76,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6776 //
6877 // {
6978 // if contracts_check() {
79+ // CONTRACT_DECLARATIONS;
7080 // contract_requires(PRECOND);
7181 // }
7282 // body
7383 // }
7484 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) ;
7686
7787 let body = self . arena . alloc ( body ( self ) ) ;
7888
@@ -121,9 +131,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
121131
122132 fn lower_contract_check_just_precond (
123133 & mut self ,
134+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
124135 precond : rustc_hir:: Stmt < ' hir > ,
125136 ) -> 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 ( ) ) ) ;
127140
128141 let then_block_stmts = self . block_all ( precond. span , stmts, None ) ;
129142 let then_block = self . arena . alloc ( self . expr_block ( & then_block_stmts) ) ;
@@ -144,10 +157,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
144157
145158 fn lower_contract_check_with_postcond (
146159 & mut self ,
160+ contract_decls : & ' hir [ rustc_hir:: Stmt < ' hir > ] ,
147161 precond : Option < rustc_hir:: Stmt < ' hir > > ,
148162 postcond_checker : & ' hir rustc_hir:: Expr < ' hir > ,
149163 ) -> & ' 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 ( ) ) ) ;
151167 let span = match precond {
152168 Some ( precond) => precond. span ,
153169 None => postcond_checker. span ,
0 commit comments