Anyolite / anyolite

Embedded mruby/Ruby for Crystal
https://anyolite.github.io/anyolite
MIT License
162 stars 10 forks source link

Error: expected argument 'protection' to 'Mutex.new' to be Mutex::Protection, not (Mutex::Protection | Symbol) #30

Closed mistergibson closed 1 year ago

mistergibson commented 1 year ago

There was a problem expanding macro 'new_rb_func'

Code in macro 'wrap_constructor_function_with_keyword_args'

13 | __temp_81 = Anyolite::Macro.new_rb_func do ^ Called macro defined in lib/anyolite/src/implementations/mruby/Implementation.cr:7:5

7 | macro new_rb_func(&b)

Which expanded to:

5 | temp_85 = Anyolite::Macro.load_kw_args_into_vars(nil, [protection : Protection = :checked], __temp_84, temp_82) 6 | temp_86 = Anyolite::Macro.convert_regular_args(_rb, temp_82, nil, options: {:context => Mutex, :block_arg_number => nil, :block_return_type => nil, :store_block_arg => false, :type_vars => [] of ::NoReturn, :type_var_names_annotation => nil, :type_var_names => nil}) 7 | temp_87 = Mutex.new(protection: Anyolite::Macro.convert_from_ruby_to_crystal(_rb, temp_85.values[0], protection : Protection = :checked, options: {:context => Mutex, :block_arg_number => nil, :block_return_type => nil, :store_block_arg => false, :type_vars => [] of ::NoReturn, :type_var_names_annotation => nil, :type_var_names => nil}, debug_information: "Mutex.new - [protection : Protection = :checked]")) ^ Error: expected argument 'protection' to 'Mutex.new' to be Mutex::Protection, not (Mutex::Protection | Symbol)

Overloads are:

Hadeweka commented 1 year ago

Can you specify how exactly you encountered this error?

Based on the debug information from the error message it seams you wanted to wrap the Mutex class.

If this is the case, the problem results from the Crystal implementation, which uses def initialize(@protection : Protection = :checked) as the constructor for Mutex.

For some reason, Crystal accepts symbols as a default argument for the enum Protection, while the same syntax throws an error in Anyolite, when the symbol is passed as an argument to Mutex.new.

I don't think this can be fixed in Anyolite itself, but Anyolite supports a workaround for cases like this:

@[Anyolite::SpecializeInstanceMethod(initialize, [protection : Protection = :checked], [protection : Protection = Mutex::Protection::Checked])]
@[Anyolite::AddBlockArgInstanceMethod(synchronize, 0, Nil)]
class Mutex
end

This snippet essentially prepares the Mutex class for usage with Anyolite by internally changing the default argument of initialize to an actual instance of Protection (so the compiler does not complain about the symbol) and by informing Anyolite that the synchronize method requires a block as an argument.

Hadeweka commented 1 year ago

Generally related for cases, where a Crystal module or class requires modification to work with Anyolite:

https://github.com/Anyolite/anyolite/wiki/Code-guidelines-and-workarounds https://github.com/Anyolite/anyolite/wiki/Limitations-and-solutions https://github.com/Anyolite/anyolite/wiki/Passing-block-arguments

Hadeweka commented 1 year ago

Did the snippet fix the problem or is there still something not working?

Hadeweka commented 1 year ago

Closing this for now.

If the issue still arises despite of the given fix, just comment here again.