@@ -314,21 +314,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
314
314
hir:: ExprKind :: Continue ( self . lower_jump_destination ( e. id , * opt_label) )
315
315
}
316
316
ExprKind :: Ret ( e) => {
317
- let mut e = e. as_ref ( ) . map ( |x| self . lower_expr ( x) ) ;
318
- if let Some ( Some ( ( span, fresh_ident) ) ) = self
319
- . contract
320
- . as_ref ( )
321
- . map ( |c| c. ensures . as_ref ( ) . map ( |e| ( e. expr . span , e. fresh_ident ) ) )
322
- {
323
- let checker_fn = self . expr_ident ( span, fresh_ident. 0 , fresh_ident. 2 ) ;
324
- let args = if let Some ( e) = e {
325
- std:: slice:: from_ref ( e)
326
- } else {
327
- std:: slice:: from_ref ( self . expr_unit ( span) )
328
- } ;
329
- e = Some ( self . expr_call ( span, checker_fn, args) ) ;
330
- }
331
- hir:: ExprKind :: Ret ( e)
317
+ let expr = e. as_ref ( ) . map ( |x| self . lower_expr ( x) ) ;
318
+ self . checked_return ( expr)
332
319
}
333
320
ExprKind :: Yeet ( sub_expr) => self . lower_expr_yeet ( e. span , sub_expr. as_deref ( ) ) ,
334
321
ExprKind :: Become ( sub_expr) => {
@@ -395,6 +382,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
395
382
} )
396
383
}
397
384
385
+ /// Create an `ExprKind::Ret` that is preceded by a call to check contract ensures clause.
386
+ fn checked_return ( & mut self , opt_expr : Option < & ' hir hir:: Expr < ' hir > > ) -> hir:: ExprKind < ' hir > {
387
+ let checked_ret = if let Some ( Some ( ( span, fresh_ident) ) ) =
388
+ self . contract . as_ref ( ) . map ( |c| c. ensures . as_ref ( ) . map ( |e| ( e. expr . span , e. fresh_ident ) ) )
389
+ {
390
+ let expr = opt_expr. unwrap_or_else ( || self . expr_unit ( span) ) ;
391
+ Some ( self . inject_ensures_check ( expr, span, fresh_ident. 0 , fresh_ident. 2 ) )
392
+ } else {
393
+ opt_expr
394
+ } ;
395
+ hir:: ExprKind :: Ret ( checked_ret)
396
+ }
397
+
398
+ /// Wraps an expression with a call to the ensures check before it gets returned.
399
+ pub ( crate ) fn inject_ensures_check (
400
+ & mut self ,
401
+ expr : & ' hir hir:: Expr < ' hir > ,
402
+ span : Span ,
403
+ check_ident : Ident ,
404
+ check_hir_id : HirId ,
405
+ ) -> & ' hir hir:: Expr < ' hir > {
406
+ let checker_fn = self . expr_ident ( span, check_ident, check_hir_id) ;
407
+ let span = self . mark_span_with_reason ( DesugaringKind :: Contract , span, None ) ;
408
+ self . expr_call ( span, checker_fn, std:: slice:: from_ref ( expr) )
409
+ }
410
+
398
411
pub ( crate ) fn lower_const_block ( & mut self , c : & AnonConst ) -> hir:: ConstBlock {
399
412
self . with_new_scopes ( c. value . span , |this| {
400
413
let def_id = this. local_def_id ( c. id ) ;
@@ -1983,7 +1996,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
1983
1996
) ,
1984
1997
) )
1985
1998
} else {
1986
- self . arena . alloc ( self . expr ( try_span, hir:: ExprKind :: Ret ( Some ( from_residual_expr) ) ) )
1999
+ let ret_expr = self . checked_return ( Some ( from_residual_expr) ) ;
2000
+ self . arena . alloc ( self . expr ( try_span, ret_expr) )
1987
2001
} ;
1988
2002
self . lower_attrs ( ret_expr. hir_id , & attrs) ;
1989
2003
@@ -2032,7 +2046,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
2032
2046
let target_id = Ok ( catch_id) ;
2033
2047
hir:: ExprKind :: Break ( hir:: Destination { label : None , target_id } , Some ( from_yeet_expr) )
2034
2048
} else {
2035
- hir :: ExprKind :: Ret ( Some ( from_yeet_expr) )
2049
+ self . checked_return ( Some ( from_yeet_expr) )
2036
2050
}
2037
2051
}
2038
2052
0 commit comments