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

Inconsistent behaviour for .as(A), where A is either a class or a module #8334

Closed
lbarasti opened this issue Oct 15, 2019 · 4 comments · Fixed by #10760
Closed

Inconsistent behaviour for .as(A), where A is either a class or a module #8334

lbarasti opened this issue Oct 15, 2019 · 4 comments · Fixed by #10760

Comments

@lbarasti
Copy link
Contributor

lbarasti commented Oct 15, 2019

The following fails to compile with Error: undefined method 'f' for A (compile-time type is A+)

# snippet 1
class A; end
 
class B < A
  def f; 5; end
end
 
def g(x : A)
  x.f
end
 
a : A = B.new.as(A)
 
g(a)

On the other hand, turning A into a module leads to an error-free compilation:

# snippet 2
module A; end

class B; include A
  def f; 5; end
end
 
def g(x : A)
  x.f
end
 
a : A = B.new.as(A)
 
g(a)

I'd argue the two should behave in the same way - either way we pick - and mark this as a bug.
What are your thoughts?

@lbarasti
Copy link
Contributor Author

lbarasti commented Oct 15, 2019

Type parameters complicate things a bit. The following prints true

# snippet 3
module A
end
 
class B; include A
  def f
    5
  end
end
 
a : A = B.new.as(A)
 
puts a.responds_to?(:f) # prints true

whereas the following prints false

# snippet 4
module A(T)
end
 
class B(T); include A(T)
  def f
    5
  end
end
 
a : A(Nil) = B(Nil).new.as(A(Nil))
 
puts a.responds_to?(:f)

I'm compiling with crystal 0.31.1.

@lbarasti lbarasti changed the title Inconsistent behaviour on for .as(A), where A is either a class or a module Inconsistent behaviour for .as(A), where A is either a class or a module Oct 15, 2019
@asterite
Copy link
Member

So:

  • the first snippet fails to compile because A, which you can instantiate, doesn't define an f method.
  • the second snippet compiles because A is a module and can't be instantiated, and all of the types that include A (in this case just B) define f, so this is fine
  • the third snippet is similar to the second snippet
  • the fourth snippet is a compiler bug (it should print true)

@lbarasti
Copy link
Contributor Author

Makes sense. Shall I close this issue and open a tiny one for the compiler bug?

@asterite
Copy link
Member

We can use this issue. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants