-
Notifications
You must be signed in to change notification settings - Fork 63
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
Check return types #615
Check return types #615
Conversation
spec/index.html
Outdated
@@ -212,6 +212,7 @@ <h1>Structured Headers</h1> | |||
<li><b>for:</b> The type of value to which a clause of type "concrete method" or "internal method" applies.</li> | |||
<li><b>redefinition:</b> If "true", the name of the operation will not automatically link (i.e., it will not automatically be given an aoid).</li> | |||
<li><b>skip global checks:</b> If "true", disables consistency checks for this AO which require knowing every callsite.</li> | |||
<li><b>skip return checks:</b> If "true", disables checking that the returned values from this AO correspond to its declared return type.</li> |
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.
Instead of skipping return checks, shouldn't we be asserting that the return check fails? That way if it is later changed in such a way that it passes, we know we can remove the annotation.
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.
That would probably be better but I don't want to do the work to implement it. PRs welcome.
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.
OK actually that was trivial, done.
src/typechecker.ts
Outdated
@@ -179,6 +185,37 @@ const getExpressionVisitor = | |||
} | |||
}; | |||
|
|||
type ErrorForUsingTypeXAsTypeY = | |||
| null | |||
| 'number-to-math' |
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.
For completion's sake, shouldn't we have bigint-to-real
?
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.
Sure I guess. That's not related to this PR but I can fold it in.
'\nhint: you passed a mathematical value, but this position takes an ES language BigInt'; | ||
break; | ||
} | ||
case 'other': { |
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.
Instead of testing for null
above, either use a default
or (if you're looking to get an exhaustivity check from TS), fallthrough with case null:
here.
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.
The test for null
guards the whole error-producing logic, not just this switch case.
@@ -332,6 +435,152 @@ function isConsumedAsCompletion(expr: Expr, path: PathItem[]) { | |||
return false; | |||
} | |||
|
|||
// returns a boolean to indicate whether this line can return an abrupt completion, or null to indicate we should stop caring |
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 don't really like that. Can't we make an enum for it?
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.
Then we couldn't use ||=
.
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.
just implement Functor
😛
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.
no
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 think we're missing tests where the completiony-ness of an Abstract Closure doesn't match that of the containing algorithm (in both ways).
We have an assertion that this is not an error:
What else are you looking for? |
Ah that's right, I misread this test and thought they were both returning completion records. Then the only one we're missing is one where the algorithm returns a completion but the AC returns a non-completion. |
That wouldn't be an error even with no handling of ACs because values returned from AOs which return completions are automatically boxed into NormalCompletion. |
I wouldn't expect the Return steps inside an AC to auto-wrap in NormalCompletion just because the containing algorithm is declared to return a completion. If that's how it currently works, it shouldn't be. |
5a93027
to
53462ac
Compare
It's not, but ACs don't have return types. The bodies of ACs are exempt from the return type analysis entirely. My point is that if the body incorrectly weren't exempt from the analysis, such that a So there's no test you could write here which would fail under any code we could have written. So there's no reason to have a test. |
36b9f1c
to
a805c61
Compare
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 might call this something else now, but LGTM either way.
The spec isn't entirely clear on this point. 5.2.3.5 "Implicit Normal Completion" says "In algorithms within abstract operations which are declared to return a Completion Record, ..." which would seem to include an AC within such an AO. Maybe that section should carve out an exception for ACs. But then the question might arise as to whether ACs have their own rule for implicit (Tangent: maybe ACs should explicitly state their return type.) |
795a6dd
to
5741bfc
Compare
Based on #613.
This will give errors for cases like
such as
Fixes #609 by moving the logic for checking for returned abrupt completions out of an ad-hoc bit of
Algorithm.ts
and into the typechecker as part of a more general facility for checking the return types from algorithms.This also drops the special handling for
GeneratorYield
and instead adds a new attribute, "skip return checks", which will need to be added to it as well asCompletion
andNormalCompletion
and any other algorithms which are doing weird stuff in the future. As such, this is a breaking change (but only very slightly).This introduces no new errors on ecma262, ecma402, or proposal-temporal except for the three algorithms called out in the previous paragraph, which will be fixed by adding the new attribute when upstreaming this change.
The actual logic, in
inspectReturns
, is pleasingly simple: we just look forReturn Foo.
, parseFoo
the same way we parse arguments to AO calls, and compare its type to the algorithm's return type the same way we'd compare a call argument to the corresponding AO's corresponding parameter type. We also look for?
andThrow
and etc so we can ensure the containing algorithm returns an abrupt completion.