www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2484] New: Templated classes have no moduleinfo

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484

           Summary: Templated classes have no moduleinfo
           Product: D
           Version: 2.019
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: simen.kjaras gmail.com


import std.stdio;
class c() {}
void main() {
        auto a = new c!();
        auto t = Object.factory(a.classinfo.name);
}

Here, Object.factory return null, because c!() has no information in
ModuleInfo.


-- 
Dec 02 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484





------- Comment #1 from dhasenan gmail.com  2009-02-15 10:07 -------
This is actually an interesting situation.

Most nested types should be fine. Templates are difficult. The ClassInfo is
generated at each instantiation, and the linker takes care of duplicates. But
the compiler can't. So the ClassInfo would have to appear in multiple
ModuleInfos. This isn't a very good situation, and besides, the name of the
variable is localClasses -- the template isn't necessarily instantiated in the
same module in which it is defined. And you can't patch up the object file for
that module to include the generated ClassInfo for the instantiation.

You could have each module have a list of templated classes instantiated in
that module. That seems a bit ugly. You could have that list stored privately
and patch up ModuleInfo.localClasses at runtime, but that could be expensive.


-- 
Feb 15 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484


Justin <mrjnewt gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mrjnewt gmail.com




--- Comment #2 from Justin <mrjnewt gmail.com>  2009-07-01 10:56:19 PDT ---
Following Chris Wright's suggestion, I can confirm that this works (dmd.1.045):

import std.stdio,
    std.moduleinit;

void main() {

    auto foo = new Container!(int)();
    foo.thingy = 3;
    assert(foo.thingy == 3);
    writefln("foo Classinfo.name : ", foo.classinfo.name);

    // Patch ModuleInfo
    foreach (mod; ModuleInfo.modules)
    {
        if (mod.name == "factory")
        {
            mod.localClasses ~= [foo.classinfo];
            break;
        }
    }

    auto bar = Object.factory(foo.classinfo.name);
    assert(bar !is null);
    writefln("bar Classinfo.name : ", bar.classinfo.name);
}
class Container(T) { T thingy; }

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 01 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484





--- Comment #3 from Justin <mrjnewt gmail.com>  2009-07-01 11:31:25 PDT ---
Ok, with a bit of work, I thing I've improved on this technique a bit.
Here's factory.d:

module factory;

import std.stdio;
import container;

void main() {    
    auto foo = new Container!(int)();
    foo.thingy = 3;
    assert(foo.thingy == 3);
    writefln("foo Classinfo.name : ", foo.classinfo.name);

    auto bar = Object.factory(foo.classinfo.name);
    assert(bar !is null);
    writefln("bar Classinfo.name : ", bar.classinfo.name);
}

And container.d uses a template to insert the patching work:
module container;

import std.moduleinit;

const char[] CURRENT_MODULE = "container";

class Container(T) { 
    T thingy; 

    mixin registerTemplatedClass;
}

public template registerTemplatedClass() {
    static this() {
        // Patch ModuleInfo
        foreach (mod; ModuleInfo.modules)
        {
            if (mod.name == CURRENT_MODULE)
            {
                mod.localClasses ~= [this.classinfo];
                break;
            }
        }
    }
}

This could be improved if there's a way of getting the current module; I
couldn't find anything, so I created the constant CURRENT_MODULE which will
have to be placed in each module which uses the template.

Output is the expected:
foo Classinfo.name : container.Container!(int).Container
bar Classinfo.name : container.Container!(int).Container

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 01 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484


nfxjfg gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nfxjfg gmail.com


--- Comment #4 from nfxjfg gmail.com 2010-04-23 16:23:51 PDT ---
This has absolutely nothing to do with templates. It's because dmd does a very
crappy job when finding classes of a module and adding them into
ModuleInfo.localClasses. For example, this doesn't work either:

struct X {
    class Y {
    }
}

assert(!!Object.factory(X.Y.classinfo.name));

At least that's what I suspect. ModuleInfo.localClasses recently got commented
out in D2 (thanks a lot Walter), so I don't really feel like continuing finding
out what goes wrong.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 23 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484


Robert Clipsham <robert octarineparrot.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |robert octarineparrot.com


--- Comment #5 from Robert Clipsham <robert octarineparrot.com> 2010-04-24
12:50:38 BST ---
It seems the system for doing this has been replaced in D2, it uses a property
rather than a variable:
http://dsource.org/projects/druntime/browser/trunk/src/object_.d#L1495, it
should still function the same way though.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 24 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484



--- Comment #6 from nfxjfg gmail.com 2010-04-24 06:41:02 PDT ---
But it's not user accessible:
http://dsource.org/projects/druntime/browser/trunk/import/object.di#L226
Well, maybe this is just a temporary regression.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 24 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484


Robert Clipsham <robert octarineparrot.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Depends on|                            |4116


--- Comment #7 from Robert Clipsham <robert octarineparrot.com> 2010-04-24
15:30:03 BST ---
Reported as bug #4116.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 24 2010
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2484


nfxjfg gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |patch


--- Comment #8 from nfxjfg gmail.com 2010-04-24 08:24:31 PDT ---
Here's a partial patch against dmd 1.057:

diff --git a/dsymbol.c b/dsymbol.c
index 7614e13..5fca88e 100644
--- a/dsymbol.c
+++ b/dsymbol.c
   -715,6 +715,20    ScopeDsymbol::ScopeDsymbol(Identifier *id)
     prots = NULL;
 }

+void ScopeDsymbol::addLocalClass(ClassDeclarations * aclasses) {
+    //????????????????????????
+    if (!members)
+        return;
+
+    //printf("members->dim = %d\n", members->dim);
+    for (int i = 0; i < members->dim; i++)
+    {   Dsymbol *member = (Dsymbol *)members->data[i];
+
+        //printf("\tmember '%s'\n", member->toChars());
+        member->addLocalClass(aclasses);
+    }
+}
+
 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
 {
     //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
diff --git a/dsymbol.h b/dsymbol.h
index e566515..49f8750 100644
--- a/dsymbol.h
+++ b/dsymbol.h
   -270,6 +270,8    struct ScopeDsymbol : Dsymbol
     static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);

     ScopeDsymbol *isScopeDsymbol() { return this; }
+
+    void addLocalClass(ClassDeclarations *);
 };

 // With statement scope
diff --git a/template.h b/template.h
index 90b5161..ecbd04e 100644
--- a/template.h
+++ b/template.h
   -87,6 +87,9    struct TemplateDeclaration : ScopeDsymbol
     int isOverloadable();

     void makeParamNamesVisibleInConstraint(Scope *paramscope);
+
+    // don't add uninstantiated template classes
+    void addLocalClass(ClassDeclarations *) {}
 };

 struct TemplateParameter
diff --git a/toobj.c b/toobj.c
index e2d2403..1431e0e 100644
--- a/toobj.c
+++ b/toobj.c
   -92,13 +92,7    void Module::genmoduleinfo()

     ClassDeclarations aclasses;

-    //printf("members->dim = %d\n", members->dim);
-    for (int i = 0; i < members->dim; i++)
-    {  Dsymbol *member = (Dsymbol *)members->data[i];
-
-       //printf("\tmember '%s'\n", member->toChars());
-       member->addLocalClass(&aclasses);
-    }
+    addLocalClass(&aclasses);

     // importedModules[]
     int aimports_dim = aimports.dim;


Here's a test case:

import tango.io.Stdout;

class This {}

struct X {
    class Foo {
    }
}

class C(T) { }

void main() {
    class Goo { } //not detected
    auto z = new Goo();
    C!(int) x = new C!(int);
    ClassInfo cobj = Object.classinfo;
    foreach (ModuleInfo m; ModuleInfo) {
        foreach (ClassInfo ci; m.localClasses) {
            if (ci is This.classinfo) {
                foreach (c; m.localClasses)
                    Stdout.formatln("{}", c.name);
        }
    }
}

It prints:
d.This
d.X.Foo
d.C!(int).C

As can be seen, class Goo is still missing. It seems the patch doesn't search
through functions. Maybe there are other cases where it still fails.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 24 2010