Thread overview
std.traits functions causing the compiler to crash
Jun 07, 2013
Eric
Jun 07, 2013
bearophile
Jun 08, 2013
Eric
Jun 08, 2013
bearophile
Jun 08, 2013
Eric
Jun 11, 2013
Regan Heath
June 07, 2013
mport std.traits;

interface Xidentity(V, K) {
    static if (hasMember!(V, "k")) static assert(0);
    public int getInstanceCount();
}

class X(K) : Xidentity!(X!(K), K) {
    private K k;

    X newInstance(K k) { return(new X(k)); }

    private this(K k) { this.k = k; }
    public int getInstanceCount() { return(5); }
}

void main() {
    auto x = new X!(double)(6.0);
}

If I compile the above code, the static if statement in the interface
declaration causes the compiler to segfault without any other information.
gdb give the following stacktrace:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xf75106c0 (LWP 30889)]
0x08170d26 in TraitsExp::semantic ()
Current language:  auto; currently asm
(gdb) backtrace
#0  0x08170d26 in TraitsExp::semantic ()
#1  0x0809a51a in Expression::ctfeSemantic ()
#2  0x081446da in TemplateInstance::semanticTiargs ()
#3  0x08145035 in TemplateInstance::semanticTiargs ()
#4  0x08148f04 in TemplateInstance::semantic ()
#5  0x08149470 in TemplateInstance::semantic ()
#6  0x0809feae in ScopeExp::semantic ()
#7  0x0809fcfd in BinExp::semantic ()
#8  0x080ac66e in BinExp::semanticp ()
#9  0x080ac7bc in EqualExp::semantic ()
#10 0x080aa75e in OrOrExp::semantic ()
#11 0x0809a51a in Expression::ctfeSemantic ()
#12 0x08077bee in VarDeclaration::semantic ()
#13 0x0804ccc5 in StaticIfDeclaration::semantic ()
#14 0x0813fc49 in TemplateInstance::expandMembers ()
#15 0x0813fc8c in TemplateInstance::tryExpandMembers ()
#16 0x08148ce0 in TemplateInstance::semantic ()
#17 0x08149470 in TemplateInstance::semantic ()
#18 0x0809feae in ScopeExp::semantic ()
#19 0x0809a51a in Expression::ctfeSemantic ()
#20 0x080713c4 in StaticIfCondition::include ()
#21 0x0804b443 in ConditionalDeclaration::include ()
#22 0x0804cd40 in StaticIfDeclaration::include ()
#23 0x0804cc95 in StaticIfDeclaration::semantic ()
#24 0x0806a0f0 in InterfaceDeclaration::semantic ()
#25 0x0813fc49 in TemplateInstance::expandMembers ()
#26 0x0813fc8c in TemplateInstance::tryExpandMembers ()
#27 0x08148ce0 in TemplateInstance::semantic ()
#28 0x08149470 in TemplateInstance::semantic ()
#29 0x080fcd13 in TypeInstance::resolve ()
#30 0x080f9a4d in TypeInstance::semantic ()
#31 0x080685b0 in ClassDeclaration::semantic ()
#32 0x0813fc49 in TemplateInstance::expandMembers ()
#33 0x0813fc8c in TemplateInstance::tryExpandMembers ()
#34 0x08148ce0 in TemplateInstance::semantic ()
#35 0x08149470 in TemplateInstance::semantic ()
#36 0x080fcd13 in TypeInstance::resolve ()
#37 0x080f9a4d in TypeInstance::semantic ()
#38 0x080af314 in NewExp::semantic ()
#39 0x080deaf4 in ExpInitializer::inferType ()
#40 0x08077560 in VarDeclaration::semantic ()
#41 0x080a3ea1 in DeclarationExp::semantic ()
#42 0x0812cc41 in ExpStatement::semantic ()
#43 0x08138c91 in CompoundStatement::semantic ()
#44 0x080c0cf5 in FuncDeclaration::semantic3 ()
#45 0x080f16bb in Module::semantic3 ()
#46 0x080edf5c in tryMain ()
#47 0x080efab2 in main ()

I'm using compiler version v2.063-devel-53aa503.
Is this a known problem, or is there a work-around?

Thanks,

Eric
June 07, 2013
Eric:

> Is this a known problem, or is there a work-around?

This is your code reduced a little:

import std.traits: hasMember;
interface Xidentity(V, K) if (!hasMember!(V, "x")) {
}
class Foo(K): Xidentity!(Foo!K, K) {
    K x;
}
void main() {
    new Foo!double;
}


I think it contains a loop at the level of types. In theory the compiler should catch them and give a nice error message.

You probably want to use the template constraint syntax, as I have used.

In D return is not a function, so don't use the ( ).

Bye,
bearophile
June 08, 2013
O
> import std.traits: hasMember;
> interface Xidentity(V, K) if (!hasMember!(V, "x")) {
> }
> class Foo(K): Xidentity!(Foo!K, K) {
>     K x;
> }
> void main() {
>     new Foo!double;
> }
>
>
> I think it contains a loop at the level of types. In theory the compiler should catch them and give a nice error message.
>
> You probably want to use the template constraint syntax, as I have used.

Yes, the template constraint is much better.  However, the compiler
still crashes, even with the new code:

import std.traits: hasMember;

interface Identity(V, K) if (!hasMember!(V, "k")) {
}

class Foo(K): Identity!(Foo!K, K) {
    K k;
}

void main() {
    new Foo!double;
}

(dmd7) mrbig:~/tp/d_test2/dlib>dmd Test.d
Segmentation fault (core dumped)


> In D return is not a function, so don't use the ( ).
Yeah, I know.  return returns an expression, and parenthesis
are legal expression syntax:)
-Eric

June 08, 2013
Eric:

> Yes, the template constraint is much better.  However, the compiler still crashes, even with the new code:

Because there's a type definition loop, regardless. Using a constraint doesn't change that situation.

Bye,
bearophile
June 08, 2013
On Saturday, 8 June 2013 at 02:32:57 UTC, bearophile wrote:
> Eric:
>
>> Yes, the template constraint is much better.  However, the compiler still crashes, even with the new code:
>
> Because there's a type definition loop, regardless. Using a constraint doesn't change that situation.
>
> Bye,
> bearophile

How is there a type definition loop?  I'm just trying to constrain
the interface.  At a minimum this should be a compiler bug, but
I would hope that dimple constraints would work.

-Eric
June 11, 2013
On Sat, 08 Jun 2013 05:52:49 +0100, Eric <eric@makechip.com> wrote:

> On Saturday, 8 June 2013 at 02:32:57 UTC, bearophile wrote:
>> Eric:
>>
>>> Yes, the template constraint is much better.  However, the compiler still crashes, even with the new code:
>>
>> Because there's a type definition loop, regardless. Using a constraint doesn't change that situation.
>>
>> Bye,
>> bearophile
>
> How is there a type definition loop?  I'm just trying to constrain
> the interface.  At a minimum this should be a compiler bug, but
> I would hope that dimple constraints would work.

There is a type loop but I agree the compiler should really be able to catch it.

Using bearophile's short example..

import std.traits: hasMember;
interface Xidentity(V, K) if (!hasMember!(V, "x")) {
}
class Foo(K): Xidentity!(Foo!K, K) {
    K x;
}
void main() {
    new Foo!double;
}

The compiler starts by generating the template for Foo(double), requiring Xidentity(Foo!double,.. requiring Foo(double), requiring Xidentity(Foo!double,.., and so on..

It should really be able to detect that it is re-generating the original Foo(double) and simply re-use/terminate the loop there, I think. (I am no compiler expert however)

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/