diff --git a/spec/compiler/semantic/block_spec.cr b/spec/compiler/semantic/block_spec.cr index a0e08f62a96f..d4f6199e2db0 100644 --- a/spec/compiler/semantic/block_spec.cr +++ b/spec/compiler/semantic/block_spec.cr @@ -1475,4 +1475,20 @@ describe "Block inference" do end )) { tuple_of([int32, int32]) } end + + it "allows underscore in block return type even if the return type can't be computed" do + semantic(%( + def foo(& : -> _) + yield + end + + def recursive + if true + foo { recursive } + end + end + + recursive + )) + end end diff --git a/src/compiler/crystal/semantic/call.cr b/src/compiler/crystal/semantic/call.cr index 2136e20a02e5..d481f273e28e 100644 --- a/src/compiler/crystal/semantic/call.cr +++ b/src/compiler/crystal/semantic/call.cr @@ -948,7 +948,8 @@ class Crystal::Call # Similar to above: we check that the block's type matches the block arg specification, # and we delay it if possible. - if output + # If the return type is an underscore, we just ignore any return type checking. + if output && !output.is_a?(Underscore) if !block.type? if !match.def.free_var?(output) && output.is_a?(ASTNode) && !output.is_a?(Underscore) begin @@ -983,8 +984,9 @@ class Crystal::Call end end end + + block.freeze_type = block_type end - block.freeze_type = block_type end end