Skip to content
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

implement genericsOpenSym for symchoices #23873

Merged
merged 7 commits into from
Jul 25, 2024
Merged

Conversation

metagn
Copy link
Collaborator

@metagn metagn commented Jul 21, 2024

fixes #23865

The node flag nfOpenSym implemented in #23091 for sym nodes is now also implemented for open symchoices. This means the intended behavior is still achieved when multiple overloads are in scope to be captured, so the issue is fixed. The code for the flag is documented and moved into a helper proc and the experimental switch is now enabled for the compiler test suite.

value

type
Result[T, E] = object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol we really need to stop copy-pasting this version of Result that has all the previous nim bug workarounds in it ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making the test cases reflect real world code has its advantages too.

@@ -331,6 +331,8 @@ type
nfHasComment # node has a comment
nfSkipFieldChecking # node skips field visable checking
nfOpenSym # node is a captured sym but can be overriden by local symbols
# ideally a unary node containing nkSym/nkOpenSymChoice or an
# extension over nkOpenSymChoice
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To elaborate on this (extension over nkOpenSymChoice):

If some version of #23104 is implemented (IMO the node flag for this instead is the lesser of 2 evils, but changing the representation for it is easier anyway), we could replace every nkSym instance of nfOpenSym with a unary nkOpenSymChoice that always prefers its first node, then add the symbol-replacing logic to nkOpenSymChoice in general, so we don't need nfOpenSym anymore. The condition for the new symbol replacing the symchoice would then become s2 != symChoice.preferredSym and s2 notin OverloadableSyms. The only problem is making sure the compiler can handle nkOpenSymChoice instead of nkSym in those spots.

The reason I couldn't implement these in a merged manner before is because I couldn't think of the symbol replacing logic we have now that only checks symbols in the generic proc instantiation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give a new node kind a try please, I consider every single flag a hack that lives on for far too long.

Copy link
Collaborator Author

@metagn metagn Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try it in another PR, I think the merging with nkOpenSymChoice should still eventually be done so we might end up deprecating the new node kind, at least maybe before the experimental switch is default.

I'm also not sure about the best representation for #23104, this seems wrong to me:

OpenSymChoice
  Preferred
    Sym "foo"
  Sym "foo"
  ...

Adding nkPreferredOpenSymChoice and nkPreferredClosedSymChoice seems kind of excessive too.

An option that isn't as intuitive but should be easier for the compiler/macros to deal with is to leave the first child of the symchoice empty/as an ident node if there isn't a preferred choice, and to make the preferred choice the first child if there is one.

# no preference:
OpenSymChoice
  Empty # or Ident "foo"
  Sym "foo"
  Sym "foo"

# first Sym "foo" is preferred:
OpenSymChoice
  Sym "foo"
  Sym "foo"
  ...

@metagn metagn marked this pull request as ready for review July 22, 2024 20:29
@Araq Araq merged commit 469a604 into nim-lang:devel Jul 25, 2024
18 checks passed
Copy link
Contributor

Thanks for your hard work on this PR!
The lines below are statistics of the Nim compiler built from 469a604

Hint: mm: orc; opt: speed; options: -d:release
173295 lines; 8.032s; 652.078MiB peakmem

let x = f().valueOr:
return $error
"ok"
doAssert g(int) == "error"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be f

@arnetheduck
Copy link
Contributor

arnetheduck commented Aug 6, 2024

Unfortunately, this PR does not fix the issue - the wrong test case was used so it merely shows that it is an issue :/

metagn added a commit to metagn/Nim that referenced this pull request Aug 11, 2024
Araq pushed a commit that referenced this pull request Aug 11, 2024
actually fixes #23865 following up #23873

In the handling of `nkIdent` in `semExpr`, the compiler looks for the
closest symbol with the name and [checks the symbol
kind](https://github.com/nim-lang/Nim/blob/6126a0bf46f4e29a368b8baefea69a2bcae54e93/compiler/semexprs.nim#L3171)
to also consider the overloads if the symbol kind is overloadable. But
it treats the normally overloadable template/macro/module sym kinds the
same as non-overloadable symbols, just calling `semSym` on it. We need
to mirror this behavior in `semOpenSym`; we treat the captured symchoice
as a fresh identifier, so if the symbol we find is a
template/macro/module, we use that symbol immediately as opposed to
waiting for overloads.
Araq pushed a commit that referenced this pull request Aug 12, 2024
refs #23873 (comment),
fixes #23386, fixes #23385, supersedes #23572

Turns the `nfOpenSym` node flag implemented in #23091 and extended in
#23102 and #23873, into a node kind `nkOpenSym` that forms a unary node
containing either `nkSym` or `nkOpenSymChoice`. Since this affects
macros working on generic proc AST, the node kind is now only generated
when the experimental switch `genericsOpenSym` is enabled, and a new
node flag `nfDisabledOpenSym` is set to the `nkSym` or `nkOpenSymChoice`
when the switch is not enabled so that we can give a warning.

Now that the experimental switch has more reasonable semantics, we
define `nimHasGenericsOpenSym2`.
arnetheduck added a commit to arnetheduck/nim-results that referenced this pull request Aug 13, 2024
This PR adds a workaround for the case where a global symbol is matched instead of the local `error`/`value` template in `valueOr` and friends, when `valueOr` is being used in a generic context.

Two options are added:
* when using Nim version supporting the experimental `genericsOpenSym` [feature](nim-lang/Nim#23873), we use it
* when not, a macro tries to replace all accesses in the given body with the correct symbol - this matching is done by name and some minimal heuristics which potentially could be wrong - the upstream solution is obviously preferable

Both solutions can be disabled via compile-time options to retain the old behavior of matching the global symbol.

See also nim-lang/Nim#22605

thanks to @Araq for the macro hack and @metagn for the language fix!
narimiran pushed a commit that referenced this pull request Aug 14, 2024
fixes #23865

The node flag `nfOpenSym` implemented in #23091 for sym nodes is now
also implemented for open symchoices. This means the intended behavior
is still achieved when multiple overloads are in scope to be captured,
so the issue is fixed. The code for the flag is documented and moved
into a helper proc and the experimental switch is now enabled for the
compiler test suite.

(cherry picked from commit 469a604)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
actually fixes #23865 following up #23873

In the handling of `nkIdent` in `semExpr`, the compiler looks for the
closest symbol with the name and [checks the symbol
kind](https://github.com/nim-lang/Nim/blob/6126a0bf46f4e29a368b8baefea69a2bcae54e93/compiler/semexprs.nim#L3171)
to also consider the overloads if the symbol kind is overloadable. But
it treats the normally overloadable template/macro/module sym kinds the
same as non-overloadable symbols, just calling `semSym` on it. We need
to mirror this behavior in `semOpenSym`; we treat the captured symchoice
as a fresh identifier, so if the symbol we find is a
template/macro/module, we use that symbol immediately as opposed to
waiting for overloads.

(cherry picked from commit a64aa51)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
refs #23873 (comment),
fixes #23386, fixes #23385, supersedes #23572

Turns the `nfOpenSym` node flag implemented in #23091 and extended in
containing either `nkSym` or `nkOpenSymChoice`. Since this affects
macros working on generic proc AST, the node kind is now only generated
when the experimental switch `genericsOpenSym` is enabled, and a new
node flag `nfDisabledOpenSym` is set to the `nkSym` or `nkOpenSymChoice`
when the switch is not enabled so that we can give a warning.

Now that the experimental switch has more reasonable semantics, we
define `nimHasGenericsOpenSym2`.

(cherry picked from commit 0c890ff)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
fixes #23865

The node flag `nfOpenSym` implemented in #23091 for sym nodes is now
also implemented for open symchoices. This means the intended behavior
is still achieved when multiple overloads are in scope to be captured,
so the issue is fixed. The code for the flag is documented and moved
into a helper proc and the experimental switch is now enabled for the
compiler test suite.

(cherry picked from commit 469a604)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
actually fixes #23865 following up #23873

In the handling of `nkIdent` in `semExpr`, the compiler looks for the
closest symbol with the name and [checks the symbol
kind](https://github.com/nim-lang/Nim/blob/6126a0bf46f4e29a368b8baefea69a2bcae54e93/compiler/semexprs.nim#L3171)
to also consider the overloads if the symbol kind is overloadable. But
it treats the normally overloadable template/macro/module sym kinds the
same as non-overloadable symbols, just calling `semSym` on it. We need
to mirror this behavior in `semOpenSym`; we treat the captured symchoice
as a fresh identifier, so if the symbol we find is a
template/macro/module, we use that symbol immediately as opposed to
waiting for overloads.

(cherry picked from commit a64aa51)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
refs #23873 (comment),
fixes #23386, fixes #23385, supersedes #23572

Turns the `nfOpenSym` node flag implemented in #23091 and extended in
containing either `nkSym` or `nkOpenSymChoice`. Since this affects
macros working on generic proc AST, the node kind is now only generated
when the experimental switch `genericsOpenSym` is enabled, and a new
node flag `nfDisabledOpenSym` is set to the `nkSym` or `nkOpenSymChoice`
when the switch is not enabled so that we can give a warning.

Now that the experimental switch has more reasonable semantics, we
define `nimHasGenericsOpenSym2`.

(cherry picked from commit 0c890ff)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
fixes #23865

The node flag `nfOpenSym` implemented in #23091 for sym nodes is now
also implemented for open symchoices. This means the intended behavior
is still achieved when multiple overloads are in scope to be captured,
so the issue is fixed. The code for the flag is documented and moved
into a helper proc and the experimental switch is now enabled for the
compiler test suite.

(cherry picked from commit 469a604)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
actually fixes #23865 following up #23873

In the handling of `nkIdent` in `semExpr`, the compiler looks for the
closest symbol with the name and [checks the symbol
kind](https://github.com/nim-lang/Nim/blob/6126a0bf46f4e29a368b8baefea69a2bcae54e93/compiler/semexprs.nim#L3171)
to also consider the overloads if the symbol kind is overloadable. But
it treats the normally overloadable template/macro/module sym kinds the
same as non-overloadable symbols, just calling `semSym` on it. We need
to mirror this behavior in `semOpenSym`; we treat the captured symchoice
as a fresh identifier, so if the symbol we find is a
template/macro/module, we use that symbol immediately as opposed to
waiting for overloads.

(cherry picked from commit a64aa51)
narimiran pushed a commit that referenced this pull request Aug 14, 2024
refs #23873 (comment),
fixes #23386, fixes #23385, supersedes #23572

Turns the `nfOpenSym` node flag implemented in #23091 and extended in
containing either `nkSym` or `nkOpenSymChoice`. Since this affects
macros working on generic proc AST, the node kind is now only generated
when the experimental switch `genericsOpenSym` is enabled, and a new
node flag `nfDisabledOpenSym` is set to the `nkSym` or `nkOpenSymChoice`
when the switch is not enabled so that we can give a warning.

Now that the experimental switch has more reasonable semantics, we
define `nimHasGenericsOpenSym2`.

(cherry picked from commit 0c890ff)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

genericsOpenSym not working when additional generally non-matching symbol with same name is present
3 participants