Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Captured block parameter not recognised when used inside macro #14727

Open
syalon opened this issue Jun 18, 2024 · 2 comments
Open

Captured block parameter not recognised when used inside macro #14727

syalon opened this issue Jun 18, 2024 · 2 comments

Comments

@syalon
Copy link

syalon commented Jun 18, 2024

my test code

def assert(cond, &err : -> String)
  {% if flag?(:debug) %}
    raise err.call unless cond
  {% end %}
end
 
assert(false) { "test error" }

compile result

Showing last frame. Use --error-trace for full trace.

There was a problem expanding macro 'macro_140633862877744'


Called macro defined in eval:2:3

Which expanded to:

 > 1 | 
 > 2 |     raise err.call unless cond
                 ^--
Error: undefined local variable or method 'err' for top-level

try online: https://play.crystal-lang.org/#/r/gxy9

@Blacksmoke16
Copy link
Member

You probably want to use a macro here:

macro assert(cond, &)
  {% if flag?(:debug) %}
    raise {{yield}} unless {{cond}}
  {% end %}
end

Related: #4263

Otherwise this is essentially a duplicate of #7975

@Blacksmoke16 Blacksmoke16 closed this as not planned Won't fix, can't repro, duplicate, stale Jun 18, 2024
@straight-shoota
Copy link
Member

straight-shoota commented Jun 18, 2024

This is not exacty #7975. The variable is not declared within the macro. It's only used there.

But it seems to be a similar issue. The compiler determines whether a block argument is a caputered block depending on whether the variable is referenced in the method body. Apparently it cannot recognise it when inside a macro.
So this relates to #8764.

It's easy to work around by inserting an explicit reference to the block variable outside the macro.

def assert(cond, &err : -> String)
  err
  {% if flag?(:debug) %}
    raise err.call unless cond
  {% end %}
end

@straight-shoota straight-shoota changed the title Compile error? Captured block parameter not recognised when used inside macro Jun 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants