-
Notifications
You must be signed in to change notification settings - Fork 323
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
Opt-in return type checks #8502
Conversation
The first approach implements the checks with a simple 'trick' - I 'just' wrap the body of a function that has the return type check with a type ascription (when creating the IR). This then ensures that the type is checked. At first I thought that this will break TCO (since technically the ascription is an additional operation, so the tail-call would no longer be the last operation in a branch - but apparently this is ignored so TCO still works - I added test cases to verify it). However, I'm not sure if this is the right solution. We still need to somehow pass the information about the return type signature into our IR. One way is as implemented in this PR, another one that I considered (and briefly started implementing) is extending the family of IR nodes With the latter approach, the return type is specified more 'directly' and then we can perform an IR transformation adding the ascriptions or do the translation slightly differently. For example this could allow us to add better error messages for when the type is wrong (currently it is ' It also seems that the latter approach may be more friendly to other IR passes that perform any kind of type inference - the type check is part of the function definition so it should then be easier to turn this information into type inference metadata associated with that function. Whereas with the current approach, we'd need to match the body of the function for such ascriptions (but that is still certainly doable and may actually be preferred for more advanced cases (example below)). Example where actually analyzing such ascriptions is more flexible:
technically code that is able to analyze the kind of ascriptions, with some additional extensions, should also be able to infer that |
Added the ascriptions to Sieve benchmarks and scheduled a run of benchmarks: https://github.com/enso-org/enso/actions/runs/7195218562 |
c0877f8
to
74aac1a
Compare
f8e03ac
to
578ade0
Compare
The CI did not run my added benchmark (perhaps I need to try again), but I've ran them on my PC. JMH
Enso Runner
Interestingly the JMH and Enso Runner results differ a bit - Enso Runner seems to favor the type checks more while on JMH they get worse results relative to the one without. Looking at the graph with marked std-dev we can see that all tests have similar performance - if we want to get any more detailed results we may need to increase the warmup time/iterations. Within the current setting it seems that the overhead is rather small, if any. |
I did one more run with extended warmup and measurement iterations and times: -options = Bench.options . set_warmup (Bench.phase_conf 3 5) . set_measure (Bench.phase_conf 3 3)
+options = Bench.options . set_warmup (Bench.phase_conf 3 7) . set_measure (Bench.phase_conf 5 7)
Here we can see that the variants without type checks are slightly faster, even including the variance of measurements, the difference is by about 8%. |
@@ -322,7 +322,7 @@ case object TypeSignatures extends IRPass { | |||
* | |||
* @param signature the expression for the type signature | |||
*/ | |||
case class Signature(signature: Expression) extends IRPass.IRMetadata { | |||
case class Signature(signature: Expression, comment: Option[String] = None) extends IRPass.IRMetadata { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will likely change the cache serialization format - you'd rather assign new number for the @Persistable(Signature.class)
definition.
@@ -322,7 +322,7 @@ case object TypeSignatures extends IRPass { | |||
* | |||
* @param signature the expression for the type signature | |||
*/ | |||
case class Signature(signature: Expression) extends IRPass.IRMetadata { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need comment
now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed if for now.
...runtime/src/main/java/org/enso/interpreter/node/callable/argument/ReadArgumentCheckNode.java
Outdated
Show resolved
Hide resolved
engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala
Outdated
Show resolved
Hide resolved
* 2. for `foo a : Integer -> Integer`, this results in a compile error currently. | ||
*/ | ||
@Test | ||
public void weirdReturnTypeSignature1() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the test called weird
? I'd expect that something fails then, but apparently it works. Calling nonIntuitiveForRadek
;-)
engine/runtime/src/test/java/org/enso/interpreter/test/SignatureTest.java
Show resolved
Hide resolved
acceptAndAdd : Integer | ||
acceptAndAdd self n = | ||
iterate f = case f of | ||
acceptAndAdd : Integer -> Filter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are supposed to be some changes in https://github.com/enso-org/enso/pull/7882/files#diff-f318804809286bb567f4076547fa2ed5455b0662960e4c9c295287582b5bc9daR30 because of interaction with JavaScript.
next : Gen | ||
next self -> Gen = Gen.Generator self.n+1 | ||
|
||
natural : Gen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can remove the natural : Gen
definition now.
98457d7
to
78efd1f
Compare
I decided to scratch the better error messages for now, and try to get this PR merged with the current state - return type mismatch resulting in:
I will create a second followup PR where I will try to improve it to be:
I decided to keep the PRs separate, as I see 2 possible approaches for implementing the error messages and I feel like at least one of them may be controversial - so I want to discuss it in a separate PR, without blocking merging of the basic feature that already works. |
Pull Request Description
Important Notes
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
./run ide build
.