Bug 16481 – invalid code accepted leading to linker error

Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-09-09T13:40:47Z
Last change time
2022-11-10T14:24:02Z
Keywords
accepts-invalid
Assigned to
No Owner
Creator
John Colvin

Comments

Comment #0 by john.loughran.colvin — 2016-09-09T13:40:47Z
% cat mod.d void blah() { import std.algorithm; import std.conv; int[][] a; a.map!(x => x.map!to); } % dmd mod.d Undefined symbols for architecture x86_64: "_D3std9algorithm9iteration32__T9MapResultS123std4conv2toTAiZ9MapResult6__ctorMFNaNbNcNiNfAiZS3std9algorithm9iteration32__T9MapResultS123std4conv2toTAiZ9MapResult", referenced from: _D3std9algorithm9iteration23__T3mapS123std4conv2toZ11__T3mapTAiZ3mapFNaNbNiNfAiZS3std9algorithm9iteration32__T9MapResultS123std4conv2toTAiZ9MapResult in mod.o "_main", referenced from: implicit entry/start for main executable (maybe you meant: __d_main_args, _D4core6thread6Thread7sm_mainC4core6thread6Thread ) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) --- errorlevel 1 That code shouldn't compile (because of using std.conv.to without a target type), so it should never hit the linker at all.
Comment #1 by john.loughran.colvin — 2016-09-09T14:03:40Z
Reduced version without phobos imports: void blah() { int[] a; a.map!(x => x.map!to); } template to() { } template map(fun...) { auto map(Range)(Range r) { alias RE = Range; alias _fun = unaryFun!fun; assert(!is(typeof(_fun(RE.init)))); MapResult!(_fun, Range)(r); } } struct MapResult(alias fun, Range) { alias R = Range; R _input; this(R) { } @property front() { fun(_input); } } template unaryFun(alias fun) { alias unaryFun = fun; } Undefined symbols for architecture x86_64: "_D3mod26__T9MapResultS73mod2toTAiZ9MapResult6__ctorMFNaNbNcNiNfAiZS3mod26__T9MapResultS73mod2toTAiZ9MapResult", referenced from: _D3mod17__T3mapS73mod2toZ11__T3mapTAiZ3mapFNaNbNiNfAiZv in mod.o If you comment out the assert then you get this error instead: mod.d(34): Error: template mod.to cannot deduce function from argument types !()(int[]), candidates are: mod.d(8): mod.to() mod.d(19): Error: template instance mod.MapResult!(to, int[]) error instantiating mod.d(5): instantiated from here: map!(int[]) mod.d(34): instantiated from here: __lambda1!(int[]) mod.d(19): instantiated from here: MapResult!(__lambda1, int[]) mod.d(5): instantiated from here: map!(int[]) which is what I expect and looks ok.
Comment #2 by ag0aep6g — 2016-09-09T14:50:27Z
Reduced further: ---- enum e = is(typeof(fun!())); void fun()() { auto m = MapResult!()(0); } alias f = fun!(); struct MapResult() { this(int) {} void front() { undefined(); } } ---- Looks similar to issue 16239. When the 0 in `MapResult!()(0)` is removed, the program compiles and links (with -main). => accepts-invalid
Comment #3 by john.loughran.colvin — 2020-12-14T13:58:31Z
(In reply to ag0aep6g from comment #2) > Reduced further: > > ---- > enum e = is(typeof(fun!())); > void fun()() { auto m = MapResult!()(0); } > alias f = fun!(); > > struct MapResult() > { > this(int) {} > void front() { undefined(); } > } > ---- > > Looks similar to issue 16239. > > When the 0 in `MapResult!()(0)` is removed, the program compiles and links > (with -main). => accepts-invalid A little further info: if you remove the enum e line, then compilation fails as expected, complaining about undefined. If you change alias f = fun!() to void bar() { fun!(); } then there is no change (confirming that it's not a question of whether the unused fun instantiation needs to be emitted)
Comment #4 by razvan.nitu1305 — 2022-11-10T14:24:02Z
*** This issue has been marked as a duplicate of issue 15459 ***