Bug 16994 – Apparently faulty symbol resolution in some cases

Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-12-20T16:20:00Z
Last change time
2017-01-08T22:13:12Z
Assigned to
nobody
Creator
meapineapple

Comments

Comment #0 by meapineapple — 2016-12-20T16:20:25Z
This error is occurring in a large project I'm working on as of this commit: https://github.com/pineapplemachine/mach.d/commit/e1f7f91db0293ef24a974398fb598bbba3e9f336 These tests can be reproduced by running the following command: rdmd -I"path/to/cloned/repo/mach.d" -debug -g -unittest --main "path/to/module.d" When this module is compiled using rdmd, dmd v2.072.0 on OSX Mavericks, unit tests pass: https://github.com/pineapplemachine/mach.d/blob/e1f7f91db0293ef24a974398fb598bbba3e9f336/mach/range/map/plural.d When this module, which imports the above plural.d, is compiled by the same means, the unit tests for that module, mach/range/map/plural.d, fail: https://github.com/pineapplemachine/mach.d/blob/e1f7f91db0293ef24a974398fb598bbba3e9f336/mach/range/readme.d When this module, which imports the above mach/range/readme.d, is compiled by the same means, the unit tests for all modules - including mach/range/map/plural.d - pass. Same goes for every other module that I have tried compiling and running tests for, which also import the above modules: https://github.com/pineapplemachine/mach.d/blob/e1f7f91db0293ef24a974398fb598bbba3e9f336/mach/range/package.d I have verified that in all the above cases, the unit tests are indeed being evaluated; the apparent success of the tests cannot be due to the tests simply being skipped. One of the dependencies of mach/range/map/plural.d is mach/meta/varreduce.d as seen here: https://github.com/pineapplemachine/mach.d/blob/e1f7f91db0293ef24a974398fb598bbba3e9f336/mach/meta/varreduce.d varreduce.d defines `varreduce`, which performs a reduce HOF upon a sequence of variadic arguments. It also defines a number of functions abstracting and calling `varreduce`, including `varmin`, which finds the minimum, and `varsum`, which calculates the sum. For example, `varmin(4, 2, 5) == 2` and `varsum(4, 2, 5) == 11`. The `length` property of `MapPluralRange` defined in plural.d uses `varmin` to calculate the minimum length of several constituent ranges. (It may help to think of this range as a sort of `zip`, where the length of the resulting range is equivalent to the length of its shortest input.) Except for when these tests are performed as a result of compiling the aforementioned readme.d, this property behaves as expected and does in fact return the shortest length. When tests are performed as a result of compiling readme.d, the shortest length is returned when there are two or fewer member ranges. (i.e. `varmin` receives two or fewer arguments.) When there are three or more member ranges, the `length` property returns the sum of the lengths instead of the minimum, as though symbol lookup were causing the implementation of `varsum` to be evaluated instead of `varmin`. This behavior has remained consistent across a number of different test cases. I have been unable to reproduce it in any case except for the compilation and testing of mach/range/readme.d. All of the dependencies of that `length` property, including `varmin`, are thoroughly unit tested and the level of verification makes it very unlikely that this issue could result from an incorrect implementation of any of those dependencies.
Comment #1 by code — 2017-01-08T18:11:14Z
Indeed changing the implementation of varsum to return the minimum length fixes the issue. This could be a bug in dmd's template instantiation cache. Note that the issue vanishes with 2.072.2, but likely just as a side effect of some other rearrangements.
Comment #2 by code — 2017-01-08T20:43:07Z
Only happens with rdmd's double compilation mode, https://github.com/dlang/tools/pull/194, which firsts builds object for the root module, then builds another (single) object for all dependencies. That PR caused a number of issues and was reverted for 2.072.2 https://github.com/dlang/tools/commit/8a5b9d6224eec712d3d6ce533b426a194848c77c.
Comment #3 by code — 2017-01-08T22:11:55Z
Seems to be a duplicate of issue 14894, only in this case the 2 compilations produce different functions with the same mangling instead of causing a linker error. It just happens that in both compilations a lambda with the same number (__lambda21) is passed to varreduce paired with the same argument types, the linker will just pick the implementation that occurs first. A workaround is to convert the lambdas alias VarReduceMin = (a, b) => (a < b ? a : b); to template functions. auto VarReduceMin(A, B)(A a, B b) { return (a < b ? a : b); }
Comment #4 by code — 2017-01-08T22:13:12Z
*** This issue has been marked as a duplicate of issue 14894 ***