@@ -284,9 +284,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
284284 ExprKind :: Index ( el, er, brackets_span) => {
285285 hir:: ExprKind :: Index ( self . lower_expr ( el) , self . lower_expr ( er) , * brackets_span)
286286 }
287- ExprKind :: Range ( Some ( e1) , Some ( e2) , RangeLimits :: Closed ) => {
288- self . lower_expr_range_closed ( e. span , e1, e2)
289- }
290287 ExprKind :: Range ( e1, e2, lims) => {
291288 self . lower_expr_range ( e. span , e1. as_deref ( ) , e2. as_deref ( ) , * lims)
292289 }
@@ -314,8 +311,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
314311 hir:: ExprKind :: Continue ( self . lower_jump_destination ( e. id , * opt_label) )
315312 }
316313 ExprKind :: Ret ( e) => {
317- let e = e. as_ref ( ) . map ( |x| self . lower_expr ( x) ) ;
318- hir :: ExprKind :: Ret ( e )
314+ let expr = e. as_ref ( ) . map ( |x| self . lower_expr ( x) ) ;
315+ self . checked_return ( expr )
319316 }
320317 ExprKind :: Yeet ( sub_expr) => self . lower_expr_yeet ( e. span , sub_expr. as_deref ( ) ) ,
321318 ExprKind :: Become ( sub_expr) => {
@@ -382,6 +379,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
382379 } )
383380 }
384381
382+ /// Create an `ExprKind::Ret` that is preceded by a call to check contract ensures clause.
383+ fn checked_return ( & mut self , opt_expr : Option < & ' hir hir:: Expr < ' hir > > ) -> hir:: ExprKind < ' hir > {
384+ let checked_ret = if let Some ( Some ( ( span, fresh_ident) ) ) =
385+ self . contract . as_ref ( ) . map ( |c| c. ensures . as_ref ( ) . map ( |e| ( e. expr . span , e. fresh_ident ) ) )
386+ {
387+ let expr = opt_expr. unwrap_or_else ( || self . expr_unit ( span) ) ;
388+ Some ( self . inject_ensures_check ( expr, span, fresh_ident. 0 , fresh_ident. 2 ) )
389+ } else {
390+ opt_expr
391+ } ;
392+ hir:: ExprKind :: Ret ( checked_ret)
393+ }
394+
395+ /// Wraps an expression with a call to the ensures check before it gets returned.
396+ pub ( crate ) fn inject_ensures_check (
397+ & mut self ,
398+ expr : & ' hir hir:: Expr < ' hir > ,
399+ span : Span ,
400+ check_ident : Ident ,
401+ check_hir_id : HirId ,
402+ ) -> & ' hir hir:: Expr < ' hir > {
403+ let checker_fn = self . expr_ident ( span, check_ident, check_hir_id) ;
404+ let span = self . mark_span_with_reason ( DesugaringKind :: Contract , span, None ) ;
405+ self . expr_call ( span, checker_fn, std:: slice:: from_ref ( expr) )
406+ }
407+
385408 pub ( crate ) fn lower_const_block ( & mut self , c : & AnonConst ) -> hir:: ConstBlock {
386409 self . with_new_scopes ( c. value . span , |this| {
387410 let def_id = this. local_def_id ( c. id ) ;
@@ -1512,15 +1535,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
15121535
15131536 let lang_item = match ( e1, e2, lims) {
15141537 ( None , None , HalfOpen ) => hir:: LangItem :: RangeFull ,
1515- ( Some ( ..) , None , HalfOpen ) => hir:: LangItem :: RangeFrom ,
1538+ ( Some ( ..) , None , HalfOpen ) => {
1539+ if self . tcx . features ( ) . new_range ( ) {
1540+ hir:: LangItem :: RangeFromCopy
1541+ } else {
1542+ hir:: LangItem :: RangeFrom
1543+ }
1544+ }
15161545 ( None , Some ( ..) , HalfOpen ) => hir:: LangItem :: RangeTo ,
1517- ( Some ( ..) , Some ( ..) , HalfOpen ) => hir:: LangItem :: Range ,
1546+ ( Some ( ..) , Some ( ..) , HalfOpen ) => {
1547+ if self . tcx . features ( ) . new_range ( ) {
1548+ hir:: LangItem :: RangeCopy
1549+ } else {
1550+ hir:: LangItem :: Range
1551+ }
1552+ }
15181553 ( None , Some ( ..) , Closed ) => hir:: LangItem :: RangeToInclusive ,
1519- ( Some ( ..) , Some ( ..) , Closed ) => unreachable ! ( ) ,
1554+ ( Some ( e1) , Some ( e2) , Closed ) => {
1555+ if self . tcx . features ( ) . new_range ( ) {
1556+ hir:: LangItem :: RangeInclusiveCopy
1557+ } else {
1558+ return self . lower_expr_range_closed ( span, e1, e2) ;
1559+ }
1560+ }
15201561 ( start, None , Closed ) => {
15211562 self . dcx ( ) . emit_err ( InclusiveRangeWithNoEnd { span } ) ;
15221563 match start {
1523- Some ( ..) => hir:: LangItem :: RangeFrom ,
1564+ Some ( ..) => {
1565+ if self . tcx . features ( ) . new_range ( ) {
1566+ hir:: LangItem :: RangeFromCopy
1567+ } else {
1568+ hir:: LangItem :: RangeFrom
1569+ }
1570+ }
15241571 None => hir:: LangItem :: RangeFull ,
15251572 }
15261573 }
@@ -1970,7 +2017,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
19702017 ) ,
19712018 ) )
19722019 } else {
1973- self . arena . alloc ( self . expr ( try_span, hir:: ExprKind :: Ret ( Some ( from_residual_expr) ) ) )
2020+ let ret_expr = self . checked_return ( Some ( from_residual_expr) ) ;
2021+ self . arena . alloc ( self . expr ( try_span, ret_expr) )
19742022 } ;
19752023 self . lower_attrs ( ret_expr. hir_id , & attrs) ;
19762024
@@ -2019,7 +2067,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
20192067 let target_id = Ok ( catch_id) ;
20202068 hir:: ExprKind :: Break ( hir:: Destination { label : None , target_id } , Some ( from_yeet_expr) )
20212069 } else {
2022- hir :: ExprKind :: Ret ( Some ( from_yeet_expr) )
2070+ self . checked_return ( Some ( from_yeet_expr) )
20232071 }
20242072 }
20252073
0 commit comments