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
replace unknown names with holes in name desugaring #3619
base: master
Are you sure you want to change the base?
replace unknown names with holes in name desugaring #3619
Conversation
I'm not sure about the "you could subsitute with one of these values" section; usually, when I encounter an UnknownName error, it's because I:
In each case I know what I want to put there, so having a list of other things I could put there is unlikely to be helpful, especially because we already have holes for asking the compiler "what can I put here". I would prefer either having a "did you mean: something" section based mostly on edit distance for misspellings, or not having it at all. |
The "has the inferred type" section above seems to cover this case
Perhaps a "did you mean to import [something] from one of these modules?" message is also displayed when the name is an exact match for an existing unimported function
If there are functions within a small edit distance list these as "did you mean...", possibly prioritizing functions which also appear in the list of matches for the type hole |
Just to clarify: yes, I think suggesting values of the unknown name which haven't been imported or suggesting values a small edit distance away from that name would both be fantastic, but both of these are probably best tackled separately; for now, just adding the inferred type would probably be best. |
@hdgarrood I agree that the plain type search results without some sort of edit distance comparison isn't the most helpful. I've taken it out, and the error message is now a lot more readable. @spicydonuts I think there is a lot we can do with edit distance comparison, and I really like the idea of suggesting possibly forgotten imports. I agree with Harry that this could be done in a follow up PR. For now, I have updated this PR to:
Here is an updated example:
Previously, this would fail with an
|
I just realized a problem with the current implementation - the holes created by an unknown value (or just a plain Hole) can spuriously cause
And
Both fail with
While the real error in both of them is that there is a Hole or an unknown value. This is because the I'm not sure how big of a deal this is with Holes (or if it can even be helped), but for I'm thinking of ways to remedy this. One idea that I have is to modify some of the |
You could wrap the original |
…or caused by trying to infer the type of a hole
This comment has been minimized.
This comment has been minimized.
…or rendering function to handle UnknownName and HoleInferredType errors specially
This comment has been minimized.
This comment has been minimized.
… Expr AST into separate data type. Add explicit traversal collecting Holes
…re caused by holes
I wasn't satisfied with the stateful approach I originally took, so I have created an explicit AST traversal that takes an Other than the problems with unknown name holes causing Let me know of any feedback, and I'd be happy to address it and try to get this over the line! I'm going to address the duplicated error code tomorrow when I get a chance. |
I have made a few changes that hopefully make this PR more focused/easier to review. At first I started to make possible improvements to errors messages for errors that are possibly caused by the existence of typed holes. However, in favor of having this PR be smaller and easier to review, I have reverted those changes and only included changes pertaining to the original issue. I can do follow up work on the other issues in subsequent PRs, if wanted. The main change since @hdgarrood's last review adds a mechanism to avoid unknown name holes from causing spurious |
Has anyone had a chance to look over this? I'm happy to change my approach with a little guidance, if needed! |
Can you give me an example that triggers this case? |
renderSimpleErrorMessage (UnknownName name (Just (ty, ctx))) = | ||
paras $ [ line $ "Unknown " <> printName name <> " has the inferred type " | ||
, markCodeBox (indent (typeAsBox maxBound ty)) | ||
] ++ renderContext ctx |
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.
Something about this error message isn't right to me. I know it was just "Unknown foo" before which is also terrible, but adding "has the inferred type" makes it seem less like an error.
Maybe something like for unqualified
The name foo is not in scope.
The name foo is not in scope. It has the inferred type ...
And for qualified:
The name foo is not exported by module Foo.
The name foo is not exported by module Foo. It has the inferred type ...
@hdgarrood @colinwahl What do you think?
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 like the idea of having different errors depending on whether or not the name is qualified! This particular error did seem very terse - I think this is a improvement
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.
@natefaubion Actually, now that I think about it, this may be missing a couple of cases. You could have some declaration
baz :: Effect Int
baz = do
Bar.bar
Where the module Bar
does export a value bar
, but there just isn't an import for it. In this case, I don't think that the error The name bar is not exported by module Foo.
Is an appropriate error.
Maybe something like The name bar is not imported from module Bar. ...
Would be more accurate. What do you think?
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 one has actually bitten me one more than one occasion - not very serious - but it can just nudge you into haring off looking for the export in the imported file instead of fixing the import. If you have any kind of doubts about your build system integrity (as seems to be too often the case) it can pitch you into a worse yak-shaving-wild-goose-chase digression there too.
Sure, something like this:
Will fail with one |
@natefaubion I pushed a proposed update to the typechecking logic for the cases where there is an unknown name in a expression. It alleviates the problem of throwing a spurious (
But at least we have given some indication of what the type should be, and we have also prevented the spurious errors that were previously caused. This has the added benefit of not reporting the wrong source spans, like my previous attempt did. What do you think? Is it OK to report unknown types for unknown name errors? |
@natefaubion bumping this PR. I still am unsure of the best way to resolve the Thanks! |
Replaces unknown names with holes in name desugaring
This intends to close #3619
UnknownName
error to support reporting inferred type and contextUnknownValue
case toExpr
updateValue
phase) to replace unknown names withUnknownValue
UnknownValue
intoUnknownName
warningstypeCheckModule
to escalateUnknownName
warnings produced during typechecking into errorsUnknownName
errors before reporting errors which may have been caused by tried to infer the type for theUnknownValue
node in the ASTHere is an example:
The
UnknownName
error now reports the inferred type of the unknown value, as well as the local context at the unknown value.