-
Notifications
You must be signed in to change notification settings - Fork 328
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
Improve error reporting of named argument mismatch #12238
base: develop
Are you sure you want to change the base?
Improve error reporting of named argument mismatch #12238
Conversation
c71e95c
to
343673d
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.
- adventurous: I am afraid to touch
CurryNode
& co. myself - changing the type of thrown panic is an incompatible change
- better to keep the atom and add an
info
field to it
- better to keep the atom and add an
- are the benchmarks result OK?
- Probably they are (as these are just exceptional paths and they are unlikely tested).
- one minor
@CompilationFinal
note - otherwise looks decent
test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso
Show resolved
Hide resolved
@@ -78,7 +78,8 @@ private void initializeOversaturatedCallNode( | |||
InvokeCallableNodeGen.create( | |||
postApplicationSchema.getOversaturatedArguments(), | |||
defaultsExecutionMode, | |||
argumentsExecutionMode); | |||
argumentsExecutionMode, | |||
true); |
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 new boolean
argument? Isn't postApplicationSchema.getOversaturatedArguments()
good enough indicator that there are oversaturated arguments?
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.
But the create
method/constructor does not see postApplicationSchema
, it sees the result of postApplicationSchema.getOversaturatedArguments()
which is just a CallArgumentInfo[] schema
.
From inside of InvokeCallableNodeGen.create
you can no longer tell if the arguments being passed were 'oversaturated' or 'normal' - you just get some schema, that is the same kind as in all different places where InvokeCallableNode
is constructed.
That's why this argument is added to be able to distinguish the situations at call-site.
engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeCallableNode.java
Show resolved
Hide resolved
@@ -375,8 +381,17 @@ static Object doPolyglot( | |||
@Fallback | |||
public Object invokeGeneric( | |||
Object callable, VirtualFrame callerFrame, State state, Object[] arguments) { | |||
Atom error = EnsoContext.get(this).getBuiltins().error().makeNotInvokable(callable); | |||
throw new PanicException(error, this); | |||
if (isForOversaturatedArguments && schema.length >= 1 && schema[0].isNamed()) { |
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.
Is this a compilation constant? Try CompilerAsserts.partialEvaluationContant
or co.
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.
Tried in e645b05, is that how it is supposed to be used?
distribution/lib/Standard/Visualization/0.0.0-dev/src/Widgets.enso
Outdated
Show resolved
Hide resolved
I will schedule a run once I ensure that the tests are passing. |
|
||
Arguments: | ||
- argument_name: The name of the argument that was not found. | ||
Error argument_name |
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.
Remove ## PRIVATE
use:
Error argument_name | |
private Error argument_name |
possibly remove the documentation comment altogether.
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 is against the convention that we are using for all the errors.
I think changes in this PR should be consistent with the rest of the codebase - if we want to change the convention let's discuss and consider rewriting the whole Common.enso
file.
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.
We don't want the constructor to be private
, this breaks the very simple check I've implemented like payload.cause == (No_Such_Argument.Error "foo")
, at least outside of Base.
The PRIVATE
is to avoid cluttering Component Browser only, I guess at some point we may remove that tag from errors.
@@ -310,12 +310,32 @@ type Not_Invokable | |||
|
|||
Arguments: | |||
- target: The called object. | |||
Error target | |||
- cause: Additional information about what may have caused the error. | |||
Error target cause |
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 is still an incompatible change for the creators of this object. To make the change compatible use:
Error target cause | |
Error target cause=Nothing |
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
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've tried and unfortunately constructors of builtins do not like default arguments.
With the change above, the code
from Standard.Base import all
import Standard.Base.Errors.Common.Not_Invokable
main =
without_cause = Not_Invokable.Error "thing"
IO.println without_cause
still prints
Not_Invokable.Error target='thing' cause=_
I think the defaultness has to be handled in engine and we don't have capability to do that.
Technically, even with the default argument this change would still breaking as any pattern matching of Not_Invokable.Error _
also will now mismatch the amount of fields.
We could try to have 2 constructors for Not_Invokable
- the old one and the new one. But I think this is complicating stuff unnecessarily. Also not sure if the builtins machinery would currently allow this, as it would no longer be a UniquelyConstructibleBuiltin
.
## If the cache argument was not expected, we ignore the problem | ||
and return just the result of `f value` - held by | ||
the target of the Not_Invokable error. | ||
was_not_expecting_cache_argument = caught_panic.payload.cause == (No_Such_Argument.Error "cache") |
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.
Question to myself: Why do I find this unreadable? Would following be better?
f : Function ->
Panic.catch Not Invocable (f value cache=cache) caught_panic -> case caught.panic.payload.cause of
No_Such_Argument.Error "cache" -> caught_panic.payload.target
_ -> Panic.throw caught_panic
Maybe, but caught.panic.payload.cause
is still quite long...
f : Function -> | ||
# We pass the self value and the cache to the function. | ||
Panic.catch Not_Invokable (f value cache=cache) caught_panic-> | ||
## If the cache argument was not expected, we ignore the problem |
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 you use ##
instead of #
here?
## If the cache argument was not expected, we ignore the problem | |
# If the cache argument was not expected, we ignore the problem |
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.
Because the ##
allows to write a multi-line comment, and I don't want to create lines 300+ characters long.
@@ -375,7 +385,16 @@ static Object doPolyglot( | |||
@Fallback | |||
public Object invokeGeneric( | |||
Object callable, VirtualFrame callerFrame, State state, Object[] arguments) { | |||
Atom error = EnsoContext.get(this).getBuiltins().error().makeNotInvokable(callable); | |||
Atom cause = null; |
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 same code is already present in IndirectInvokeCallableNode
once. Can we refactor it to a single method?
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.
Hmmm, perhaps a good point.
Any suggestions where this common function could live? Put it as static
in InvokeCallableNode
and call from IndirectInvokeCallableNode
?
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.
Done in 97b7d27
This reverts commit 38ca032.
Running benchmarks:
|
Pull Request Description
Important Notes
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
TypeScript,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
or the Snowflake database integration, a run of the Extra Tests has been scheduled.