-
Notifications
You must be signed in to change notification settings - Fork 272
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
bugfix: don't prefer the unison file for name suffixes #5276
Conversation
00367ba
to
84b45c6
Compare
Hey this looks good. If we're changing the name resolution rules though, I would want to update them for both terms and types equally in any release of ucm. Are they split up just to avoid merge conflicts, or is there a reason to wait hold off on the terms piece? |
@aryairani agreed – this part is ready for review but shouldn't be merged before the term half is done and reviewed, too |
Ok sounds good! |
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'm good with this, but also think that terms should work the same way as types here. So once that's ready, I'm good with merging.
…es from the namespace
Converting this to draft until it's ready for further review. |
I'm not sure I understand what the change here is; how does it handle things like this?
E.g. does it resolve I think we really don't want the latter for a bunch of UX reasons Also, I know Paul and Fabio really want things to pretty print without full qualification whenever possible, e.g. the following is undesirable:
|
@ChrisPenner in this example
|
Forgive me, but even with the explanation I'm still a bit confused;
This is the part that keeps confusing me, you say that |
Is it that the suffix |
Correct.
No, when resolving a name to a definition, there's no preferential treatment to anything in the file over the namespace. Does all that make sense @aryairani / @ChrisPenner? |
I'm not clear just from this example about what it means to not have preferential treatment, but I'll read through the transcripts and report back. |
It means the same thing as "supersede" from your question. A suffix (non-exact match) that could refer to something in the file or the namespace will not resolve to the thing in the file, it will instead be ambiguous. That's the trunk behavior that this PR changes. |
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.
Looks good. Do we need some kind of test to make sure that this change doesn't introduce round-trip errors, or do the existing transcripts cover that?
@@ -62,14 +62,17 @@ type Baz = { qux : Nat } | |||
type RefersToFoo = RefersToFoo Foo | |||
|
|||
refersToBar = cases | |||
Bar -> 17 | |||
Foo.Bar -> 17 |
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 was ambiguous because it could have been [ns.]longer.foo.Foo.Bar or [file.]Foo.Bar, TDNR doesn't help, and so you have to expand it until it's unambiguous or an exact match?
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.
Correct. TDNR doesn't apply here – it's not used for patterns.
Spelling out Foo.Bar
would even be necessary if there was an explicit type signature on refersToBar
.
In principle a type checker could of course help in that case; only a unique suffix among all the constructors of the known type should be required. But we don't make it to the type checker because we eagerly resolve all constructor references in patterns during parsing.
@aryairani I'm not sure any existing test covers this change well. A few broke incidentally because they were using suffixes that are now considered ambiguous. The pretty-printer didn't match this feature of the parser: it would sometimes print more segments than necessary because file suffixes shadowed namespace names (which was the bug this fixes). So, now the parser and pretty-printer are in sync wrt. suffixification. I believe the new transcript that demonstrates the new behavior is the main bug-catching test, do you see something that it's missing? |
👍
I thought the transcript was excellent; I didn't notice anything missing.
I guess what might be missing, though it doesn't necessarily belong in this PR, is an equivalent sort of behavior demo for the printer; or even putting the printer and parser together in interesting cases like you've laid out here, as a round-trip test. I want to keep the known round-trip error list up to date if possible; and any time there's a change to either the parser or the printer there could possibly be an impact to round-trips. Once we have a passing round-trip test I guess it'll be easier to detect when the property breaks. |
Overview
This PR changes the parse-time name resolution logic. Previously, a locally-bound name ("file name")
X.Y.Z
would shadow namesX.Y.Z
,Y.Z
, andZ
in the namespace ("namespace names").That feature was implemented in the following PRs:
The situation prior to the two PRs above was not good: suffixes such as
Y.Z
orZ
(continuing the example above) would not refer to any file name, and would resolve to (if anything) a namespace name.But the situation after the two PRs above (trunk today) is not good either: it means there is no syntax whatsoever to refer to namespace names
Y.Z
orZ
, ifX.Y.Z
is a file name. That means we cannot properly render some names, which meansupdate
,upgrade
,merge
, and evenedit
all have buggy corner cases: #5268The fix implemented here is to make file names and namespace names exist at the same precedence level (except that file names still shadow namespace names, it's just suffixes of file names that no longer shadow).
Along the way, I discovered a bunch of weird stuff and did my best to either preserve existing behavior or clean up / fix bugs – whichever was easier.
For example, one thing I stumbled upon that I'm particularly happy about: the error message you get when you've typed in an ambiguous pattern actually makes sense now. I'm not sure if there is a ticket about this, but if you had:
in your namespace and tried to write a function
you'd get the baffling error message
Now, you'll get one that looks like the other "ambiguous name" errors:
I also discovered a couple bugs in the recently-implemented namespace directive feature (#5285) that I fixed. The term parser previously did not account for any namespace directive, which it needs to, in order to properly resolve constructor references and type links.
Another bug:
Names.shadowing
was callingNames.unionLeft
, but that's not correct, and neither wasNames.unionLeftName
, turns out. I removed both of those broken union functions in favor of the one we want and now use:Names.shadowing
, which combines two names with a left bias: if a name is related to a set of referencesr1
from the left argument andr2
from the right argument, then user1
and dropr2
.Test coverage
I've included a transcript that demonstrates the new behavior. I also deleted a couple old irrelevant transcripts that demonstrated the old behavior.