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

C code generated for imported file that isn't used if generic types returned #19220

Open
Vindaar opened this issue Dec 6, 2021 · 0 comments
Open

Comments

@Vindaar
Copy link
Contributor

Vindaar commented Dec 6, 2021

Digging into why arraymancer in particular ends up producing a lot of C files that need to be compiled, despite the majority of arraymancer not being used reveals some weirdness with generics.

To give a short description in words:

Importing a module foo.nim defining a procedure bar in a test file test.nim that returns a generic of a type C[D], which is also, but independently, used in the test file will generate a C file for foo. This happens iff the compiler must automatically deduce the type to C[D] in the test file.

While the C compiler ends up eliminating most of that code, it still slows down compilation and I'm still not convinced this isn't also the reason for sometimes compiling in dynamic libraries that should not show up.

Example

Easier as code. The module we import:

foo.nim:

proc notUsed(): seq[float] =
  result = @[5.0, 5.0, 2.0]

Note how notUsed is not even exported, nor does this file define any globals.

and our test file:

import foo

# works
let bar: seq[float] = @[1.2.float, 3, 4]
var bar: seq[float]
let bar = @[1, 2, 3] # different type than `seq[float]` being returned in `foo`

# broken
let bar = @[2.float, 4, 10]
var bar = @[2.float, 4, 10]

Consider each line as a separate test file of course.

Meaning of works and broken

Works means the compiler does not produce a C file for foo. Broken means it does. So for the first 3 lines individually,
we end up with the following compilation output:

basti at voidRipper in ~/org/Misc/dead_code_elim_bug ツ nim c -f test.nim
Hint: used config file '/home/basti/src/nim/nim_git_repo/config/nim.cfg' [Conf]
Hint: used config file '/home/basti/src/nim/nim_git_repo/config/config.nims' [Conf]
..........................................................
/home/basti/org/Misc/dead_code_elim_bug/foo.nim(1, 6) Hint: 'notUsed' is declared but not used [XDeclaredButNotUsed]
/home/basti/org/Misc/dead_code_elim_bug/test.nim(9, 5) Hint: 'bar' is declared but not used [XDeclaredButNotUsed]
/home/basti/org/Misc/dead_code_elim_bug/test.nim(1, 8) Warning: imported and not used: 'foo' [UnusedImport]
CC: stdlib_digitsutils.nim
CC: stdlib_assertions.nim
CC: stdlib_dollars.nim
CC: stdlib_system.nim
CC: test.nim
Hint:  [Link]
Hint: gc: refc; opt: none (DEBUG BUILD, `-d:release` generates faster code)
26641 lines; 0.310s; 31.645MiB peakmem; proj: /home/basti/org/Misc/dead_code_elim_bug/test.nim; out: /home/basti/org/Misc/dead_code_elim_bug/test [SuccessX]

Note no CC: foo.nim.

Whereas the ones listed as broken:

basti at voidRipper in ~/org/Misc/dead_code_elim_bug ツ nim c -f test.nim
Hint: used config file '/home/basti/src/nim/nim_git_repo/config/nim.cfg' [Conf]
Hint: used config file '/home/basti/src/nim/nim_git_repo/config/config.nims' [Conf]
..........................................................
/home/basti/org/Misc/dead_code_elim_bug/foo.nim(1, 6) Hint: 'notUsed' is declared but not used [XDeclaredButNotUsed]
/home/basti/org/Misc/dead_code_elim_bug/test.nim(15, 5) Hint: 'bar' is declared but not used [XDeclaredButNotUsed]
/home/basti/org/Misc/dead_code_elim_bug/test.nim(1, 8) Warning: imported and not used: 'foo' [UnusedImport]
CC: stdlib_digitsutils.nim
CC: stdlib_assertions.nim
CC: stdlib_dollars.nim
CC: stdlib_system.nim
CC: foo.nim
CC: test.nim
Hint:  [Link]
Hint: gc: refc; opt: none (DEBUG BUILD, `-d:release` generates faster code)
26641 lines; 0.316s; 31.613MiB peakmem; proj: /home/basti/org/Misc/dead_code_elim_bug/test.nim; out: /home/basti/org/Misc/dead_code_elim_bug/test [SuccessX]

Note the line CC: foo.nim.

In larger code bases this leads to all sorts of C files being generated that aren't used anywhere unless one is very diligent in only importing the parts that are required (i.e. using import arraymancer / tensor instead of import arraymancer).

Possible Solution

Not enough understanding of how the compiler works to have any idea here.

Additional Information

Tested both on a devel from beginning of November, as well as todays:

Nim Compiler Version 1.7.1 [Linux: amd64]
Compiled at 2021-12-06
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: faacd63bf69561fe915f3651e6b917bb2c0e5bc2
active boot switches: -d:release -d:danger
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

No branches or pull requests

1 participant