diff --git a/src/implementation/codegen.rs b/src/implementation/codegen.rs index e94956f..34dcb1d 100644 --- a/src/implementation/codegen.rs +++ b/src/implementation/codegen.rs @@ -8,7 +8,7 @@ use syn::{ spanned::Spanned, visit::{visit_return_type, Visit}, visit_mut::{self as visitor, visit_block_mut, visit_expr_mut, VisitMut}, - Attribute, Expr, ExprCall, ReturnType, TypeImplTrait, + Attribute, Expr, ExprCall, ExprClosure, ReturnType, TypeImplTrait, }; use crate::implementation::{Contract, ContractMode, ContractType, FuncWithContracts}; @@ -379,6 +379,10 @@ impl VisitMut for ReturnReplacer { visit_expr_mut(self, node); } + + fn visit_expr_closure_mut(&mut self, _node: &mut ExprClosure) { + // Do not replace return statements inside closures. Skip calling the base visitor. + } } struct ImplDetector { diff --git a/tests/issues.rs b/tests/issues.rs index 043cac2..36449f1 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -96,3 +96,25 @@ fn gl_issue_18() { assert_eq!(1, euclidean(3, 4)); } + +#[allow(unused)] // compile-only test +#[test] +fn gl_issue_41() { + use contracts::requires; + + fn foo(f: impl Fn(i32) -> i32) -> i32 { + // no-op + f(-10) + } + + #[requires(true)] + fn bar() { + let y = foo(|x: i32| { + if x < 0 { + return 0; + } + x + }); + assert_eq!(y, 0); + } +}