It would be nice of the front-end to not emit the following code to object file, especially so as.
1) Both functions share the same symbol (collision detection doesn't work in __traits code?)
2) Both functions failed semantic analysis.
---
module failsemantic;
template foo10083a(T)
{
int foo10083a(double) { return 1; }
int foo10083a(T) { return 2; }
}
static assert(!__traits(compiles, foo10083a!double(1)));
static assert(!__traits(compiles, foo10083a!double(1.0)));
---
Disassembly:
---
Disassembly of section .text._D12failsemantic16__T9foo10083aTdZ9foo10083aFNaNbNfdZi:
0000000000000000 <_D12failsemantic16__T9foo10083aTdZ9foo10083aFNaNbNfdZi>:
0: 55 push %rbp
1: 48 8b ec mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: b8 01 00 00 00 mov $0x1,%eax
d: c9 leaveq
e: c3 retq
f: 90 nop
0000000000000010 <_D12failsemantic16__T9foo10083aTdZ9foo10083aFNaNbNfdZi>:
10: 55 push %rbp
11: 48 8b ec mov %rsp,%rbp
14: 48 83 ec 10 sub $0x10,%rsp
18: b8 02 00 00 00 mov $0x2,%eax
1d: c9 leaveq
1e: c3 retq
1f: 90 nop
Comment #1 by yebblies — 2013-12-11T06:17:07Z
Actually, the functions pass semantic just fine.
Comment #2 by yebblies — 2013-12-11T07:24:33Z
The fix here is to not emit speculative templates, but unfortunately this will need some work in dmd.
void foo()() {}
void bar()() { foo(); }
static assert(is(typeof(bar()))); // marks foo!() and bar!() as speculative
void main()
{
bar(); // unmarks bar!()
// foo(); // without this line foo!() is still speculative.
}
So we need a way to detect speculativeness depending on another template instance.
Comment #3 by k.hara.pg — 2013-12-11T07:44:07Z
(In reply to comment #2)
> The fix here is to not emit speculative templates, but unfortunately this will
> need some work in dmd.
>
>
> void foo()() {}
> void bar()() { foo(); }
>
> static assert(is(typeof(bar()))); // marks foo!() and bar!() as speculative
>
> void main()
> {
> bar(); // unmarks bar!()
> // foo(); // without this line foo!() is still speculative.
> }
>
> So we need a way to detect speculativeness depending on another template
> instance.
Related: issue 10920
Calculating complete dependent graph between template instances during compilation, is the really needed feature in order to kill -allinst switch.
But, I'm still not sure how to do it efficiently...
Comment #4 by ibuclaw — 2013-12-11T08:10:23Z
(In reply to comment #1)
> Actually, the functions pass semantic just fine.
Yeah... I cracked open a debugger after raising this and realised the same. Fails compilation in CallExp::semantic, *after* it has been added to the module members list.
I poked about with omitting declared members when __traits(compiles) fails, then omitting from within SCOPEstaticassert - but it seems that in both cases causes *needed* symbols to be skipped leading to undefined symbol linker errors. Though I'm not immediately sure why symbols instantiated from static assert() or __traits(compiles) would be needed, unless of course my poking about was all wrong and had the adverse effect of:
static if (__traits(compiles, foo!double())) // instantiated and discarded.
{
return foo!double(); // instantiated, but not added to members.
}
Comment #5 by yebblies — 2013-12-11T09:16:13Z
(In reply to comment #4)
>
> I poked about with omitting declared members when __traits(compiles) fails,
> then omitting from within SCOPEstaticassert - but it seems that in both cases
> causes *needed* symbols to be skipped leading to undefined symbol linker
> errors. Though I'm not immediately sure why symbols instantiated from static
> assert() or __traits(compiles) would be needed, unless of course my poking
> about was all wrong and had the adverse effect of:
>
See my second comment for why you get linker errors when skipping toObjFile on speculative instances.
Comment #6 by robert.schadek — 2024-12-13T18:15:04Z