habitat icon indicating copy to clipboard operation
habitat copied to clipboard

Problem in macro create_settings_methods when global Nil class shadow by local with same name

Open dammer opened this issue 2 years ago • 2 comments
trafficstars

I came across a case where the name of the class Nil is contained in the module in which the class for which we create the settings is defined.

module A
  class Nil
  end

  class B
     Habiat.create do
        setting abc : Array(Something) = Array(Something)
     end
  end
end

In this case, the macro does not work correctly because it refers to a local A::Nil and not a global Nil class.

> 19 | # then raise a MissingSettingError
> 20 | @@abc : Array(Something.class) | Nil  = begin
> 21 |    Array(Something.class).new
          ^
Error: class variable '@@abc' of  A::B::HabitatSettings must be (Array(Something.class) | A::Nil), not (Array(Something.class) | Nil)

Without spoiling the idea of how smart it is to have a separate class Nil inside a local namespace, this can be fixed in code

  setting abc : Array(Something) | Nil | ::Nil  = Array(Something)

but I propose to explicitly specify the global ::Nil in this macro body if this possible.

https://github.com/luckyframework/habitat/blob/4d242eb524e00289fb5857ed1bd786ec96670a5d/src/habitat.cr#L239-L293

dammer avatar Jun 21 '23 11:06 dammer

That seems like a reasonable fix; however, I would suggest to not create a class called Nil. Crystal Nil is a struct https://github.com/crystal-lang/crystal/blob/739461fe78c6ce65033f009af3e360750d5b020d/src/nil.cr#L44 and I think having a type with the same name that's treated differently could lead to other issues within the code.

One thing we do in Avram to use an object that means "nothing" but isn't Nil is using a class called Nothing

https://github.com/luckyframework/avram/blob/main/src/avram/nothing.cr

jwoertink avatar Jun 21 '23 14:06 jwoertink

Thanks for the tip with Nothing, great solution, wonder if i can use it as it is a very big legacy shard(

dammer avatar Jun 21 '23 15:06 dammer