enum Foo
Bar
def type
case value
when 0 then Int32
else
raise "BUG"
end
end
end
def foo(foo : Foo, type : T.class = foo.type) forall T
{% pp! T %}
end
foo(:bar)
# Expected:
T # => Int32
# Got (as expected):
T # => Int32
enum Foo
Bar
Baz
def type
case value
when 0 then Int32
when 1 then String
else
raise "BUG"
end
end
end
def foo(foo : Foo, type : T.class = foo.type) forall T
{% pp! T %}
end
foo(:bar)
# Expected:
T # => Int32
T # => String
# Got:
T # => Int32
enum Foo
Bab
Bar
Baz
def type
case value
when 0 then Float32
when 1 then Int32
when 2 then String
else
raise "BUG"
end
end
end
def foo(foo : Foo, type : T.class = foo.type) forall T
{% pp! T %}
end
foo(:bar)
# Expected:
T # => Float32
T # => Int32
T # => String
# Got:
T # => Float32
As @asterite mentioned in #7533,
Arguments are solved first. The compiler doesn't know what T is in the restriction for y.
But looks like the compiler actually _knows_ the restriction and it does it wrong. I expect either of these:
undefined constant T in all casesOkay, this is actually a bug. Please rename the issue, I don't know how to name it :thinking:
It should work with the Edit button next to New issue (in the top right).
I'm sorry but it's not clear to me what the issue is. Bug reports shouldn't include what the compiler does right now. You should explain how it behaves now, how's that's wrong, and what's your expected behaviour.
@asterite I've updated the issue
I still don't get it. You expect the method to be invoked or instantiated multiple times?
I expect it to either do not instantiate at all (raising undefined constant T) or instantiate multiple times (which is preferable).
I don't get it, how could it instantiate multiple times? you only call foo once..
Also, typeof(Foo::Bar.type) is the union of all the return values, how could it return only one since Foo::Bar.type is 'evaluated' at runtime only?
I'm guessing you want something like:
enum Foo
Bar
Bazzz
def type
{% if @enum_instance.value == 0 %} # or {% if @enum_instance.member_name.id == "Bar".id %}
Int32
{% elsif @enum_instance.value == 1 %}
String
{% end %}
end
end
typeof(Foo::Bar.type) # => Int32.class
typeof(Foo::Bazzz.type) # => String.class
Where @enum_instance would be available in an enum' instance method, and represent the current instance of the enum, with its value / member' name / ...
So, I think there might be a bug with a type restriction against a default value (that has a special logic, which I didn't code). But what you want is impossible. You seem to want a runtime type at compile time.
@asterite wanna open a new issue about the bug you mention?
In any case I think there's no action for this issue and would vote to close it.
No, sorry, I'm taking some vacations from Crystal.
Most helpful comment
It should work with the Edit button next to New issue (in the top right).