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

strformat doesn't work properly inside generics #7632

Closed
mratsim opened this issue Apr 16, 2018 · 13 comments · Fixed by #10927
Closed

strformat doesn't work properly inside generics #7632

mratsim opened this issue Apr 16, 2018 · 13 comments · Fixed by #10927

Comments

@mratsim
Copy link
Collaborator

mratsim commented Apr 16, 2018

This needs 2 files

File 1

# Name: test_format
import strformat

proc fails*(a: static[int]) =
  echo &"formatted {a:2}"

proc fails2*[N: static[int]](a: int) =
  echo &"formatted {a:2}"

proc works*(a: int) =
  echo &"formatted {a:2}"

proc fails0*(a: int or uint) =
  echo &"formatted {a:2}"

File 2

import test_format

works(5)

fails0(6)

fails(7)

fails2[0](8)

lib/pure/strformat.nim(276, 5) Error: undeclared identifier: 'format'

It seems like within a generic or static proc the compiler tries to resolve the identifier 'format' earlier than expected as format is declared after the macros that calls it here on line 489.

This seems related to #6387 (Generics proc + macros: identifier resolution happens before macro)

@mratsim mratsim changed the title Static + strformat: Error undeclared identifier format Generic or Static + strformat: Error undeclared identifier format Apr 16, 2018
@mratsim
Copy link
Collaborator Author

mratsim commented Apr 16, 2018

I suspect it's related to #5053 as well.

@zah zah added the Generics label Apr 17, 2018
@zah
Copy link
Member

zah commented Apr 29, 2018

strformat doesn't work in templates too:

import strformat

template formatMsg(s: string): string =
  &"test {s}"

echo formatMsg("x")

@zah zah changed the title Generic or Static + strformat: Error undeclared identifier format strformat doesn't work properly inside generics and templates Apr 29, 2018
@zah zah added the Templates label Apr 29, 2018
@bluenote10
Copy link
Contributor

I have observed/reported this issue for other string interpolations before (my own outdated and nimboost). In these cases the underlying issue was the behavior of parseExpr. I had opened this issue to discuss if this can be fixed, but it turned out to be unsolvable.

@zah
Copy link
Member

zah commented May 11, 2018

We have a plan how to fix it. Templates expecting untyped params will be expanded earlier while the body of another template or generic is being read. Thus, the interpolation will produce AST nodes that will bind properly to the template parameters.

@timotheecour
Copy link
Member

timotheecour commented Oct 17, 2018

ping on this issue as it causes non-ideal bug-fixing workarounds like #9417 /cc @zah

Araq pushed a commit that referenced this issue Oct 18, 2018
* fix #9394 by replacing `fmt` with normal string append

Until issue #7632 is fixed, use string append.

* use `strutils.%` instead of normal string add
@Araq
Copy link
Member

Araq commented Oct 18, 2018

I spent some time fixing/chaning this part of the language and it's not trivial, some other complex tests fail then...

narimiran pushed a commit to narimiran/Nim that referenced this issue Oct 31, 2018
* fix nim-lang#9394 by replacing `fmt` with normal string append

Until issue nim-lang#7632 is fixed, use string append.

* use `strutils.%` instead of normal string add
narimiran pushed a commit to narimiran/Nim that referenced this issue Nov 1, 2018
* fix nim-lang#9394 by replacing `fmt` with normal string append

Until issue nim-lang#7632 is fixed, use string append.

* use `strutils.%` instead of normal string add
narimiran pushed a commit that referenced this issue Nov 1, 2018
* fix #9394 by replacing `fmt` with normal string append

Until issue #7632 is fixed, use string append.

* use `strutils.%` instead of normal string add
narimiran pushed a commit that referenced this issue Nov 1, 2018
* fix #9394 by replacing `fmt` with normal string append

Until issue #7632 is fixed, use string append.

* use `strutils.%` instead of normal string add

(cherry picked from commit 82a1576)
@bluenote10
Copy link
Contributor

@krux02 In general, could you write a quick comment when you close an issue like that? When I saw that this issue was closed I spend an hour trying to figure out why I still cannot get strformat to work in a template (I was going over the changes in the PR to see how they relate to the discussion here. Only when someone else posted that it is still not working I realized that it isn't a problem on my end). Since it still doesn't work, the issue should either stay open or say "won't fix" to avoid confusion. In any case, I like your workaround, reposting it here for other users:

template t(s): untyped =
  block:
    let x {.inject.} = s
    &"test {x}"

@krux02
Copy link
Contributor

krux02 commented Apr 11, 2019

This issue is fixed. The example from this issue has been added to the test case. Your problem is an entirely different problem. By now that example has been added to the documentation of strformat including an explanation why it can't work. It is a structural problem that can't simply be "fixed". In other languages that support string interpolation this problem does not occur because these other languages don't have nim like templates.

@bluenote10
Copy link
Contributor

bluenote10 commented Apr 11, 2019

  • The issue name is strformat doesn't work properly inside generics and templates and that is literally not fixed.
  • It's the first thing users will discover when googling "nim strformat template not working" or so.
  • So far it was the place to discuss the strformat inside templates issue and I was tracking it for that reason.

Let's remove the "and template" and track the remaining issue in #10977 ?

@krux02 krux02 changed the title strformat doesn't work properly inside generics and templates strformat doesn't work properly inside generics Apr 11, 2019
@jcosborn
Copy link
Contributor

This hasn't really been fixed for generics. The test case in git only works because the main test file tstrformat.nim imports strformat. If you run the original test case where the import strformat is not present, it still fails.

@krux02
Copy link
Contributor

krux02 commented May 17, 2019

@jcosborn I just tested it again on development branch of Nim. The example from the issue works.

@narimiran
Copy link
Member

The test case in git only works because the main test file tstrformat.nim imports strformat. If you run the original test case where the import strformat is not present, it still fails.

Using Nim devel (v0.19.9) with the original test case (with two separate files), it works correctly.

Using Nim stable (v0.19.6 or older) it fails with lib/pure/strformat.nim(278, 5) Error: undeclared identifier: 'format', but that is expected as the fix hasn't been backported to the stable version.
You can either use the devel version or wait for v0.20.

jcosborn added a commit to jcosborn/Nim that referenced this issue May 17, 2019
@jcosborn
Copy link
Contributor

Yes, sorry, I was looking at the newer devel tests, but running an older version and 0.19.6.
I've submitted a PR to move the test above the import just in case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants