-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Dotty does not yet implement the Kennedy and Pierce restriction #4805
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
Comments
Q: Should we implement the restriction or drop it?
|
I still have to see someone running into a recursion unintentionally because of this. Does anyone have a case where this happened and you were not trying to trick the compiler intentionally? If not, I would vote for not having a restriction - it's complicated code that might contain bugs,increases the complexity of the compiler, and might rule out sensible programs. |
I haven't searched for such natural examples and I'm not aware of any. And FWIW, if we decide against this, this should become a spec issue — should I add an |
I think allowing undecidable subtype checking is a bad idea: |
@JanBessai Looping types are still errors, but they're detected during compilation dynamically rather than statically. Unfortunately, subtyping in Scala and Dotty is also undecidable for a bunch of other reasons. See #4385 and #318. That goes back to DOT — type members can be defined using open mutual recursion, just like term members, and nobody knows how to get strong normalization there too (the published state of the art is https://www.cs.purdue.edu/homes/rompf/papers/wang-ecoop17.pdf, I'm actually exploring the topic).
#4385 turns the resulting stackoverflow into a log of the subtype checks done by the compiler.
Typechecking is still compositional in the appropriate sense — it doesn't depend on the bodies, only on their types — so the definition of
That's incorrect both because you can postulate excluded middle in Coq and because existing proofs of type soundness don't require "S <: T or not (S <: T)" — that's exactly decidability of subtyping, but is not required for proofs of soundness.
|
The question remains: will
That maybe a contentious issue in the presence of dependent types and macros, which both compute "behind the scene". Nothing enforces opaqueness (currently). However, libraries like scala-graph and shapeless are getting to the point where the details behind a type definition are not necessarily meant for public consumption.
That is not what I claimed. I've only claimed that no proof can ever use it in an intuitionistic setting, which remains true:
[1]: Barendregt, Henk, Mario Coppo, and Mariangiola Dezani-Ciancaglini. "A filter lambda model and the completeness of type assignment." The journal of symbolic logic 48.4 (1983): 931-940. |
First, fixing the OP issue does not make typechecking decidable, and this seems indeed an unlikely way to trigger the problem. Second, since we can as well finish the side discussion we started here rather than opening a new issue: Overall, Scala users suffer much bigger issues than decidability of typechecking — so worrying about this is a bit like optimizing something that is not the bottleneck. Then, this issue seems a non-bottleneck in a non-bottleneck. I'm not against decidable typechecking, but that seems hopeless without strong normalizations of types, which is already research for DOT even tho there are no F-Bounds there. If you're interested, we could talk about this elsewhere.
Ah, I misparsed "preventing it from ever being used in any proof about Scala", my bad. Still, this is likely to not be the 'bottleneck' for applying many of those theoretical projects to actual Scala. Relative to "the theorem is false", having to use the Delay monad (or similar mechanisms) to model a semi-decidable typechecker, though painful, is a smaller problem.
And instead of whitebox macros (which have no meaningful type signature), Dotty is adding typelevel programs to use in their type signatures (in #4616) — that will help adding an abstraction barrier there. For shapeless types, I see your concern, but I don't see a real abstraction barrier other than types.
That's implementation-defined — ideally all of those would loop, in practice some won't be detected. I agree this is annoying and unreliable in principle, I haven't seen complaints on this from actual users (including me), as opposed to PL researchers (a category which also includes me), mostly because they don't actually write such looping types, and certainly not in this way. |
Conclusion: for now typechecking is undecidable anyway, and issues are much easier to trigger. This check is also hard to implement. So it seems reasonable to let this unimplemented; if other sources of undecidability are ever fixed, we might want to reconsider. |
To remove one venue for undecidability, the SLS 5.1.5 mandates a restriction (implemented by scalac), which appears not implemented yet in Dotty.
Test
tests/untried/neg/t8146-non-finitary.scala
andtests/untried/neg/t8146-non-finitary-2.scala
trigger a "Recursion limit exceeded" exception, instead of triggering the SLS-mandated error.The Scalac implementation (which I haven't studied) starts at https://github.com/scala/scala/blob/9df13fd826bdf1c83cc701d1fa16e9ec729ab782/src/reflect/scala/reflect/internal/Types.scala#L1725-L1728.
The text was updated successfully, but these errors were encountered: