Open toddsundsted opened 4 years ago
investigating whether this is related to https://github.com/crystal-lang/crystal/pull/8426
In Digest::Base
, change the type restrictions that look like & : Digest::Base -> _
to be & : self -> _
to fix the problem. That's the actual type that's yielded. It's definitely a compiler bug, but change that to fix the regression.
In my opinion that PR refactor was a huge mistake. The core devs should pay more attention to what code they accept from external contributors. Such sensitive code like that shouldn't be handled to external contributors. There's inheritance there which is not needed at all. And macro inherited
which is a big smell (I think @asterite said that too).
thanks @HankAnderson with that guidance I created a test case that doesn't depend on Digest
but recreates the error:
class Base
def self.digest(& : Base -> _)
yield new
end
def update
end
end
class Extended < Base
end
Extended.digest do |digest|
while rand > 0.5
digest.update
end
end
It's even shorter:
def foo(& : Base ->)
yield Extended.new
end
class Base
end
class Extended < Base
end
foo do |digest|
while true
digest
end
end
Thanks @toddsundsted / @HankAnderson for reducing this. It seems that this is not a regression but something wrongly handled since the beginning of #8117 in 0.31.0. https://github.com/crystal-lang/crystal/issues/9483#issuecomment-644423912 can be reproduced in 0.31 ... 0.35.
I seems unintuitive that a downcast is been made instead of an upcast.
def m(& : T -> R)
s : S
yield s
end
Should type iff S < T
, so as long as the yielded expressing can be upcast to the type argument of the block it should be sound. I didn't investigate further.
I will send a PR to workaround this issue in the context of Digest for now and include that in 0.35.1.
Regarding the refactors in digest, @HankAnderson I disagree that they should've been done only by maintainers. Reviews are part of the process and having a variety of authors encourage discovering and deciding best approaches and idioms within the language. Maybe reviewers overlooked something, I doubt the reviews were an unconscious approval.
This does not mean that the design can't be iterated and improved. I believe in partial/iterative progress. Other parts of the std-lib and compiler might require more trust, of course.
thanks @bcardiff
I fully support the latter remark of @bcardiff. Approving and merging code is really not about trusting the individual who wrote it. I personally know I can put trust in many contributors, both inside and outside the core team. But trusting the author doesn't mean their code is flawless. And for that it also doesn't make a difference whether you're on the core team. I'm sure every core member could name a few of their code changes that needed to be fixed later. That's just how things work. There's a review process to reduce the amount of mistakes getting merged. But it can't be eliminated. And instead of having fewer people (i.e. the core members) involved with writing and reviewing sensitive code, I'd like to encourage more people to do that. More minds on the same piece of code means less opportunities for bugs to hide.
@bcardiff This shouldn't be closed as the root cause of the OP's issue is still standing.
You're right.
Code like the following worked prior to 0.35:
The error I get is:
Link to playground reproducing the error: https://play.crystal-lang.org/#/r/99si
I am testing with 0.35 on OSX 10.14.6 (it works on 0.34 and earlier).