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

compile-time type is mismatch on inherited generics #3509

Closed
maiha opened this issue Nov 6, 2016 · 3 comments
Closed

compile-time type is mismatch on inherited generics #3509

maiha opened this issue Nov 6, 2016 · 3 comments

Comments

@maiha
Copy link
Contributor

maiha commented Nov 6, 2016

I'm writing Try monad that inherits from generic class.
https://github.com/maiha/try.cr/blob/master/src/try.cr
This works on until 0.18.x but fails on 0.19.x.

Minimum reproducible code

class Try(T)
  def self.try : Success(T) | Failure(T)
    Success(T).new(yield)
  rescue err
    Failure(T).new(err)
  end
end

class Success(T) < Try(T)
  def initialize(@value : T); end
  def success?; true; end
end

class Failure(T) < Try(T)
  def initialize(@value : Exception); end
  def success?; false; end
end

i = Try(Int32).try { 1 }
p i.success?

0.18.7

% crystal -v
Crystal 0.18.7 [68783f1] (2016-07-03)
% crystal test.cr
true

0.19.4

% crystal -v
Crystal 0.19.4 [7f82f79] (2016-10-07)
% crystal test.cr
Error in ./test.cr:20: undefined method 'success?' for Try(Int32) (compile-time type is Try(Int32)+)

p i.success?
    ^~~~~~~~

It looks like #3423
but, failed on master branch too.

master(e019442)

% ./bin/crystal --version
Using compiled compiler at .build/crystal
Crystal 0.19.4+107 [e019442] (2016-11-06)

% ./bin/crystal test.cr
Error in ./test.cr:20: undefined method 'success?' for Try(Int32) (compile-time type is Try(Int32)+)

guess

When we directly specify the subclass, it works on 0.19.x.
Success(Int32).new(1).success? # => true

So, it would be a some problem on def self.try : Success(T) | Failure(T) about type inference.

Thanks.

@asterite
Copy link
Member

asterite commented Nov 6, 2016

This is actually an improvement over 0.18.7, so a fix. If you try it without generic types you'll see that you get a similar error. Whenever you mix two types in the same hierarchy you will get a "virtual type" of the base type. And there's no success? method on Try. You can make Try abstract to make it compile, which is also more correct code as you don't want Try to be instantiated by users.

@asterite
Copy link
Member

asterite commented Nov 6, 2016

Well, I don't know if an improvement, but it's consistent with how non-generic types work.

@maiha
Copy link
Contributor Author

maiha commented Nov 6, 2016

@asterite
I understood what was happening on virtual type. Thank you!
And it works with correct code as your advise, which provides good readability about the spec.
https://github.com/maiha/try.cr/blob/master/src/try.cr#L10-L15

Well, I agree that the compiler has same type inference logic for all cases. Improvement or not is a different problem. So, I'll comment it on another issue when I have a chance.

Thanks again!

@maiha maiha closed this as completed Nov 6, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants