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

[Playground] You've reached a bug in the playground #13470

Open
Vici37 opened this issue May 15, 2023 · 5 comments
Open

[Playground] You've reached a bug in the playground #13470

Vici37 opened this issue May 15, 2023 · 5 comments

Comments

@Vici37
Copy link

Vici37 commented May 15, 2023

I think I found a possible infinite loop in the standard library when implementing a new Int type, and while trying to minimally reproduce it, triggered a bug in the playground.

Code:

struct MyInt < Int
  def popcount; end
  def trailing_zeros_count; end
end

three = MyInt.new

Exception:

error in line 7
Error: instantiating 'Crystal::Playground::Agent#i(Int32)'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:25:5

 25 | send "value" do |json|
      ^---
Error: instantiating 'send(String)'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:62:20

 62 | message = JSON.build do |json|
                     ^----
Error: instantiating 'JSON:Module#build()'


In /usr/share/crystal/src/json/builder.cr:404:12

 404 | String.build do |str|
              ^----
Error: instantiating 'String.class#build()'


In /usr/share/crystal/src/string.cr:286:21

 286 | String::Builder.build(capacity) do |builder|
                       ^----
Error: instantiating 'String::Builder.class#build(Int32)'


In /usr/share/crystal/src/string.cr:286:21

 286 | String::Builder.build(capacity) do |builder|
                       ^----
Error: instantiating 'String::Builder.class#build(Int32)'


In /usr/share/crystal/src/json/builder.cr:404:12

 404 | String.build do |str|
              ^----
Error: instantiating 'String.class#build()'


In /usr/share/crystal/src/json/builder.cr:405:7

 405 | build(str, indent) do |json|
       ^----
Error: instantiating 'build(String::Builder, Nil)'


In /usr/share/crystal/src/json/builder.cr:415:13

 415 | builder.document do
               ^-------
Error: instantiating 'JSON::Builder#document()'


In /usr/share/crystal/src/json/builder.cr:415:13

 415 | builder.document do
               ^-------
Error: instantiating 'JSON::Builder#document()'


In /usr/share/crystal/src/json/builder.cr:405:7

 405 | build(str, indent) do |json|
       ^----
Error: instantiating 'build(String::Builder, Nil)'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:62:20

 62 | message = JSON.build do |json|
                     ^----
Error: instantiating 'JSON:Module#build()'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:63:12

 63 | json.object do
           ^-----
Error: instantiating 'JSON::Builder#object()'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:63:12

 63 | json.object do
           ^-----
Error: instantiating 'JSON::Builder#object()'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:25:5

 25 | send "value" do |json|
      ^---
Error: instantiating 'send(String)'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:27:27

 27 | json.field "value", safe_to_value(value)
                          ^------------
Error: instantiating 'safe_to_value(MyInt)'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:46:5

 46 | to_value(value) rescue "(error)"
      ^-------
Error: instantiating 'to_value(MyInt)'


In /usr/share/crystal/src/compiler/crystal/tools/playground/agent.cr:54:11

 54 | value.inspect
            ^------
Error: instantiating 'MyInt#inspect()'


In /usr/share/crystal/src/object.cr:129:12

 129 | String.build do |io|
              ^----
Error: instantiating 'String.class#build()'


In /usr/share/crystal/src/string.cr:286:21

 286 | String::Builder.build(capacity) do |builder|
                       ^----
Error: instantiating 'String::Builder.class#build(Int32)'


In /usr/share/crystal/src/string.cr:286:21

 286 | String::Builder.build(capacity) do |builder|
                       ^----
Error: instantiating 'String::Builder.class#build(Int32)'


In /usr/share/crystal/src/object.cr:129:12

 129 | String.build do |io|
              ^----
Error: instantiating 'String.class#build()'


In /usr/share/crystal/src/object.cr:130:7

 130 | inspect io
       ^------
Error: instantiating 'inspect(String::Builder)'


In /usr/share/crystal/src/object.cr:148:5

 148 | to_s io
       ^---
Error: instantiating 'to_s(String::Builder)'


In /usr/share/crystal/src/int.cr:737:7

 737 | internal_to_s(base, precision, upcase) do |ptr, count, negative|
       ^------------
Error: instantiating 'internal_to_s(Int32, Int32, Bool)'


In /usr/share/crystal/src/int.cr:762:30

 762 | ptr.value = digits[num.remainder(base).abs]
                              ^--------
Error: instantiating 'MyInt#remainder(Int32)'


In /usr/share/crystal/src/int.cr:185:5

 185 | {% begin %}
       ^
Error: expanding macro


There was a problem expanding macro 'macro_139643677739200'

Called macro defined in /usr/share/crystal/src/int.cr:185:5

 185 | {% begin %}

Which expanded to:

    1 | 
    2 |       if other == 0
    3 |         raise DivisionByZeroError.new
 >  4 |       elsif self < 0 && self == MyInt::MIN && other == -1
    5 |         self.class.new(0)
    6 |       else
    7 |         unsafe_mod other
    8 |       end
    9 |     
Error: undefined constant MyInt::MIN

The underlying error looks to be a compiler error due to macro expansion (trying to use the non-existent MIN constant on MyInt). This seems minor as the "bug in the playground" looks more like a bug in my code that the playground couldn't correctly parse.

@Blacksmoke16
Copy link
Member

Blacksmoke16 commented May 15, 2023

Pretty sure it's not really a good idea to extend stdlib types. But either way, somewhat interesting it doesn't error when not using the playground.

EDIT: This isn't really specific to the playground, so what is the actual bug here?

@Vici37
Copy link
Author

Vici37 commented May 15, 2023

Generally agreed :D I'm playing around implementing my own arbitrary arithmetic library written in native crystal (starting with essentially the same interface / specs as BigInt).

I think the above does error when not using the playground, I'm creating this issue as the popup appears in the playground requesting that an issue gets made for it:
image

@Vici37
Copy link
Author

Vici37 commented May 15, 2023

Regardless if it's not a bug in the playground (the bug is in my code for sure), there's another bug where the playground think this is it's bug.

@HertzDevil
Copy link
Contributor

HertzDevil commented May 15, 2023

BigInt < Int, so this use case is anticipated, unlike e.g. inheriting from Array. (The compiler does not declare BigInt as a built-in type using Crystal::Program.)

@HertzDevil
Copy link
Contributor

In general I don't think implementations for Int::Primitive should reside in Int itself. However Int::Primitive is a union so we have to either invent a new module or inline the defs in the individual integer types themselves.

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