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

Compiler assertion error: Crystal::Call#scope cannot be nil (NilAssertionError) #9749

Open
BrucePerens opened this issue Sep 15, 2020 · 2 comments

Comments

@BrucePerens
Copy link

BrucePerens commented Sep 15, 2020

This little ditty sets off Compiler assertion error: Crystal::Call#scope cannot be nil (NilAssertionError)

String.new.each do
  {% verbatim do %}
  p ""
  {% end %}
end

Compiler version:

Crystal 0.35.1 [5999ae29b] (2020-06-19)

LLVM: 8.0.0
Default target: x86_64-unknown-linux-gnu
@asterite
Copy link
Member

Reduced:

a do
  {% verbatim do %}
  b
  {% end %}
end

@BlobCodes
Copy link
Contributor

I accidentally created a duplicate issue of this, but I think my bug report could be useful for further investigation, so I'll paste it here.


Bug report

The following code raises a compile-time error (even with --prelude=empty):

def foo
end

{% verbatim do %}
  foo
{% end %}

This is the exception:

Crystal::Call#scope cannot be nil (NilAssertionError)
  from /crystal/src/compiler/crystal/program.cr:463:5 in 'lookup_macro'
  from /crystal/src/compiler/crystal/semantic/semantic_visitor.cr:301:19 in 'expand_macro:raise_on_missing_const'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/semantic/ast.cr:649:5 in 'expand_inline_macro'
[...]
Error: you've found a bug in the Crystal compiler. [...]

This only happens when there is no callee (A.foo() or 10.to_s do not raise).
This happens regardless of arguments to the method, other macro code inside the verbatim, other crystal code inside the macro, etc.
This only happens using verbatim. Using {% begin %}\{% if true %}\{% end %}{% end %} does not cause an error.
However, wrapping the verbatim code inside another macro works:

def foo
end

{% if true %}
  {% verbatim do %}
    foo
  {% end %}
{% end %}

In general, using verbatim at top-level behaves weirdly.
This code:

{% puts 1 %}
{% verbatim do %}
  {% puts 2 %}
{% end %}
{% puts 3 %}

..prints the numbers "1 2 3 2 2 2" (in this order).

When running the above code with crystal run --stats, I get this output:

Parse:                             00:00:00.000374521 (   0.76MB)
1emantic (top level):             
2
3
Semantic (top level):              00:00:00.337099992 ( 106.28MB)
Semantic (new):                    00:00:00.001081401 ( 106.28MB)
2emantic (type declarations):     
2
Semantic (type declarations):      00:00:00.019435251 ( 106.28MB)
Semantic (abstract def check):     00:00:00.007088344 ( 106.28MB)
Semantic (restrictions augmenter): 00:00:00.006305759 ( 106.28MB)
Semantic (ivars initializers):     00:00:00.060938856 ( 106.28MB)
Semantic (cvars initializers):     00:00:00.053511380 ( 122.28MB)
2emantic (main):                  
Semantic (main):                   00:00:00.035419036 ( 138.28MB)
Semantic (cleanup):                00:00:00.000240346 ( 138.28MB)
Semantic (recursive struct check): 00:00:00.000607983 ( 138.28MB)
Codegen (crystal):                 00:00:00.366583250 ( 138.34MB)
Codegen (bc+obj):                  00:00:00.038621489 ( 138.34MB)
Codegen (linking):                 00:00:00.200052298 ( 138.34MB)

We can see that everything is executed normally once inside the Semantic (top level) phase.
But for some reason, the macro is executed again twice inside the Semantic (type declarations) phase.
And later, it is called again inside the Semantic (main) phase.


Of course, using verbatim here makes no sense.
This issue was also not found during actual development but while researching the compiler internals.
Because of this, a potential fix could be to make using verbatim raise a proper error when there is no existing macro context.
Still, it should be investigated why all this happens.


$ crystal -v
Crystal 1.9.2 [1908c816f] (2023-07-19)

LLVM: 15.0.7
Default target: x86_64-unknown-linux-gnu

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