this is compiled, but should not:
require "json"
abstract class A
abstract def bla : String # <= expected to return string only
def show
p bla.to_json
end
end
class B < A
def bla
1 # <= Int32
end
end
B.new.show
in case when i change my api, but all code is compiled ok O_o, i want compiler to show this bugs
see also #160
Duplicate of #160
i not sure that this is #160, because this is about abstract defs(which is declare interfaces and restrictions), which compiler should checks to implement by it declaration.
OK, I'll reopen, but it's very similar
I recently was surprised by this myself.
After playing around a bit I'm starting to suspect that the return type on an abstract method has zero ramifications whatsoever. E.g.,
module Interface
abstract def foo : Zork
end
struct A
include Interface
def foo
3.14159
end
end
struct B
include Interface
def foo
"pi"
end
end
struct C
@x : Interface
def initialize(@x : Interface)
end
def foo
@x.foo
end
end
a = A.new
c = C.new(a)
typeof(c.foo) # => (Float64 | String)
The nonexistence of the type Zork is irrelevant, the code compiles, and the type Zork appears to have no effect on any real return type. I.e., : Zork at the end of the abstract method declaration seems to be a fancy form of whitespace.
If that's the case, maybe it would make sense for now to just outlaw return types on abstract methods. At least then there is then no surprise factor: the compiler tells you that it won't enforce restrictions on the return type, so don't even bother trying. Allowing return types on abstract methods could be restored in the future if they ever become meaningful.
Great. I think this is a pretty easy change, and would be happy to give it a shot, unless someone else (@RX14 ?) already plans to.
Just ran into this, and it was confusing. I understand, and agree with, the arguments from #160, but I think in the case for abstract methods is a little different, because I would like to enforce a return type of my subclasses. I'm not a fan of disallowing return types on abstract methods, as it feels like just a temporary band-aid.
Looks like this bug may still be active. This compiles on v0.30.1:
record ProductRequest, id : Int32
record ProductResponse, product : Product
record Product, id : Int32, name : String
abstract struct CatalogService
abstract def get_product(value : ProductRequest) : ProductResponse
end
struct CatalogHandler < CatalogService
# This should not compile since it does not return a `ProductResponse`
def get_product(request : ProductRequest)
"lol"
end
end
CatalogHandler.new.get_product(ProductRequest.new(id: 123))
In this example, CatalogHandler#get_product(ProductRequest) returns a string but the abstract method it's implementing specifies a return type of ProductResponse.
@jgaskins Pretty sure it's just a warning atm. Try running it with --warnings all
Ooh, okay. I didn't know warnings were opt-in. Thanks!
Most helpful comment
@jgaskins Pretty sure it's just a warning atm. Try running it with
--warnings all