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

fix #13443 Underscore cannot be defined more than once in proc #17581

Closed
wants to merge 8 commits into from

Conversation

ringabout
Copy link
Member

@ringabout ringabout commented Mar 30, 2021

fix #13443

future work

  • make it work for js+vm (see disabled test)
  • add test for:
template main =
  proc foo(_: int) =
    let a = _
doAssert not compiles(foo(1))
  • this doesn't work inside templates:
import std/sequtils

proc main() =
  iterator fn(_, _: int, c: int): int = yield c
  doAssert toSeq(fn(1,2,3)) == @[3]
static: main() # ok
main() # ok

template main2() =
  iterator fn(_, _: int, c: int): int = yield c
main2() # bug: Error: attempt to redefine: '_`gensym3'

ditto with procs:

when true:
  template main() =
    proc fn(_, _, a: int): auto =
      a
    echo fn(1,2,3) # Error: attempt to redefine: '_`gensym0'
  main()
  • this works but shouldn't:
when defined case5:
  template main() =
    proc fn(_, a: int): auto =
      echo _
      a
    echo fn(1,2)
  main()
  • this is a (desirable) breaking change but should be documented in changelog:
when defined case3:
  proc fn(_: int, a: int): auto =
    echo _
    a
  echo fn(1,2)

before PR: works
after PR: Error: undeclared identifier: '_'

  • see whether we should add __attribute__((unused)) in cgen for the corresponding parameters

@ringabout ringabout marked this pull request as draft March 30, 2021 06:17
@ringabout
Copy link
Member Author

It doesn't work with templates.
Hi @timotheecour do you think I should support it? Or some suggestions regarding it?

template main() =
  var x = 0
  proc foo(_, _: int) = x += 5

  foo(1, 2)
  doAssert x == 5

@timotheecour
Copy link
Member

timotheecour commented Mar 30, 2021

do you think I should support it?

yes i think that snippet should compile. can be done in subsequent PR though

@ringabout ringabout marked this pull request as ready for review March 30, 2021 06:29
compiler/semtypes.nim Outdated Show resolved Hide resolved
tests/proc/tunderscore.nim Outdated Show resolved Hide resolved
@@ -40,12 +40,6 @@ const
errNoGenericParamsAllowedForX = "no generic parameters allowed for $1"
errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types"


proc isDiscardUnderscoreV(v: PSym): bool =
Copy link
Member

Choose a reason for hiding this comment

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

i still don't like the duplication, instead just rename this to:

proc handleUnderscore(v: PSym): bool = ...

@@ -54,6 +54,9 @@ proc mangleParamName(m: BModule; s: PSym): Rope =
## we cannot use 'sigConflicts' here since we have a BModule, not a BProc.
## Fortunately C's scoping rules are sane enough so that that doesn't
## cause any trouble.
if s.name.s == "_":
Copy link
Member

Choose a reason for hiding this comment

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

can there be something similar for js? or what prevents this?

Copy link
Member Author

@ringabout ringabout Mar 31, 2021

Choose a reason for hiding this comment

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

It just didn't work for JS VM I guess a known bug

Copy link
Member Author

Choose a reason for hiding this comment

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

tunderscore.nim(9, 27) Error: cannot evaluate at compile time: x

Copy link
Member

Choose a reason for hiding this comment

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

in this case we should leave #13443 open (with a note) until we can address this :)

Copy link
Member Author

Choose a reason for hiding this comment

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

why, that's the bug of js vm, not related to my PR?

Copy link
Member

Choose a reason for hiding this comment

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

fine, I'll just open a new bug for js+vm then

Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be handled in the backend IMO.

Copy link
Member

@timotheecour timotheecour Mar 31, 2021

Choose a reason for hiding this comment

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

maybe, what do you suggest concretely?
(see also the items i added in future work)

Copy link
Collaborator

@metagn metagn Oct 28, 2022

Choose a reason for hiding this comment

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

Can't we just mangle if sfGensym in s.flags?

Suggested change
if s.name.s == "_":
if sfGensym in s.flags:

timotheecour
timotheecour previously approved these changes Mar 31, 2021
@timotheecour timotheecour added the TODO: followup needed remove tag once fixed or tracked elsewhere label Mar 31, 2021
@timotheecour timotheecour self-requested a review March 31, 2021 19:15
block:
proc ok(_, _, a: int): int = a
doassert ok(4, 2, 5) == 5

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
block:
iterator fn(_, _: int, c: int): int = yield c
doAssert toSeq(fn(1,2,3)) == @[3]

and add from std/sequtils import toSeq on top

@timotheecour timotheecour dismissed their stale review March 31, 2021 20:36

let's think a bit more

@ringabout ringabout closed this Sep 22, 2021
@metagn
Copy link
Collaborator

metagn commented Oct 28, 2022

This PR is needed to fix #13804 (which the checkboxes in the main post describe). There would only be a small patch in semtempl, namely putting these lines inside if param.name.s != "_":

Nim/compiler/semtempl.nim

Lines 645 to 646 in 779b1cc

param.flags.incl sfTemplateParam
param.flags.excl sfGenSym

If we don't want the backend mangling parameter names, we can whitelist the changes in semtypes to just templates.

As for the isDiscardUnderscore comments, we can just forward declare it in semtypes/move it there, or we can convert it to template ignoreUnderscore(v: PSym, body: untyped) which does if v.name.s == "_": v.flags.incl(sfGensym) else: body.

@metagn metagn removed the TODO: followup needed remove tag once fixed or tracked elsewhere label Jan 4, 2024
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.

Underscore cannot be defined more than once in proc
4 participants