Thread overview
[Issue 2179] New: import inside class works but is not in spec
Jun 26, 2008
d-bugmail
Jul 14, 2008
d-bugmail
Jul 14, 2008
d-bugmail
Jul 14, 2008
d-bugmail
Jul 14, 2008
d-bugmail
[Issue 2179] [module] import inside class works but is not in spec
Nov 14, 2009
Leandro Lucarella
Jan 22, 2012
Walter Bright
June 26, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=2179

           Summary: import inside class works but is not in spec
           Product: D
           Version: 1.028
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Keywords: spec
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: wbaxter@gmail.com


DMD accepts imports placed inside of class scopes. This is useful for template mixins because it means you can put the imports needed by the mixin into the template itself.

However it doesn't seem to be allowed by the grammar in the spec.  It is useful, and it works, and therefore I think the grammar should be updated to reflect this.

Here's the test case:
----
module miximport;
import std.stdio;

class Foo {
    import miximport_imp;
    this() {
        writefln("Hi there from Inner - magic value: %s", magic_value);
    }
}

void main() { new Foo; }
----

Running dmd -v gives this, which includes miximport_imp in the list of imports:
----
F:\bax\Code\d\play>dmd -v miximport.d
parse     miximport
semantic  miximport
import    object        (f:\usr\pkg\d\dmd\bin\..\import\tango\object.di)
import    std.stdio     (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\stdio.d)
import    std.compat    (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\compat.d)
import    tango.stdc.stdio
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\stdc\stdio.d)
import    tango.stdc.stdarg
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\stdc\stdarg.d)
import    tango.stdc.stddef
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\stdc\stddef.d)
import    tango.stdc.config
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\stdc\config.d)
import    std.c.stdio   (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\c\stdio.d)
import    std.format    (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\format.d)
import    std.stdarg    (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\stdarg.d)
import    tango.core.Vararg
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\core\Vararg.d)
import    std.c.stdarg
(f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\c\stdarg.d)
import    std.utf       (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\utf.d)
import    std.c.stdlib
(f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\c\stdlib.d)
import    std.stdint    (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\stdint.d)
import    std.c.stddef
(f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\c\stddef.d)
import    tango.stdc.errno
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\stdc\errno.d)
import    std.c.string
(f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\c\string.d)
import    std.string    (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\string.d)
import    std.uni       (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\uni.d)
import    std.array     (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\array.d)
import    tango.core.Exception
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\core\Exception.di)
import    std.ctype     (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\ctype.d)
import    std.gc        (f:\usr\pkg\d\dmd\bin\..\import\tangobos\std\gc.d)
import    tango.core.Memory
(f:\usr\pkg\d\dmd\bin\..\import\tango\tango\core\Memory.di)
import    miximport_imp (miximport_imp.d)
semantic2 miximport
semantic3 miximport
code      miximport
function  this
function  main
----

The spec could be fixed, by for instance sticking ImportDeclaration under ClassBodyDeclaration.

A similar issue may pertain to structs, but I haven't tried that.

Relevant discussions of this elsewhere include:
* http://www.dsource.org/projects/dsss/ticket/193
* http://www.dsource.org/forums/viewtopic.php?p=20054#20054

If it is decided that the spec is correct, and this is not legal, then it should be made an error.  But I will note that there are libraries in existence that depend on this behavior (namely doost, http://www.dsource.org/projects/doost).  There maybe be others, but that's the one where I ran across it.


-- 

July 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=2179





------- Comment #1 from clugdbug@yahoo.com.au  2008-07-14 04:04 -------
Wow! That's a fantastic feature.


-- 

July 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=2179





------- Comment #2 from andrei@metalanguage.com  2008-07-14 08:49 -------
(In reply to comment #1)
> Wow! That's a fantastic feature.

It is pretty interesting, but it would be vastly more so if import would work inside a template and were parameterized with the parameters of the template, or in general if the import could be somehow parameterized. As it is, I'm not seeing many good applications.

For example, say I want to define a module "cloneable" so I can say:

class A { import cloneable; }
class B : A { import cloneable; }

auto x = new A;
auto y = x.clone;

and so on. But in the definition of clone (inside the cloneable module) we'd
need the type of the class under construction. Guess that's where typeof(this)
would come in handy :o).


-- 

July 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=2179





------- Comment #3 from aarti@interia.pl  2008-07-14 10:16 -------
(In reply to comment #2)

> It is pretty interesting, but it would be vastly more so if import would work inside a template

It works right now, but as Bill noticed is not in specs. See: http://www.dsource.org/projects/doost/browser/trunk/doost/util/serializer/archive/JsonArchive.d

> and were parameterized with the parameters of the template, or in general if the import could be somehow parameterized.

AFAIK according spec template alias parameter can be import also. And maybe mixin("import std.stdio;") will work also... Though I did not test it.

> As it is, I'm not
> seeing many good applications.

With imports in templates it is possible to separate specific implementation from general code. So I would not say that it is not useful :-)

> For example, say I want to define a module "cloneable" so I can say:
>
> class A { import cloneable; }
> class B : A { import cloneable; }
> auto x = new A;
> auto y = x.clone;

Although below already works:

class A { mixin cloneable; }
class B : A { mixin cloneable; }

I used it in serializer, which is parametrized with archive class, and then proper class body is imported into base class.

See: http://www.dsource.org/projects/doost/browser/trunk/doost/util/serializer/Serializer.d

It works nice, but there is still a lot of rough edges and developing serializer was sometimes really painful. E.g. I can not remove now (in 1.0 branch) spurious parameter to template archive. Program compiles with this argument, but not without it, although template argument (ARCHIVE) is not used anywhere.

> and so on. But in the definition of clone (inside the cloneable module) we'd
> need the type of the class under construction. Guess that's where typeof(this)
> would come in handy :o).

I don't get this part. For me some clarifications would be helpful, but maybe its just me :-)


-- 

July 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=2179





------- Comment #4 from wbaxter@gmail.com  2008-07-14 15:35 -------
(In reply to comment #2)
> (In reply to comment #1)

> As it is, I'm not seeing many good applications.

It solves the classic problem of how to ensure that you have access to all the symbols that a mixin depends upon.

If in mix.d you have a simple mixin:
import std.stdio;
template() Mix {
   void blarf() { writefln("blarf"); }
}

and then you mixin that in a class in another file, that other file also needs to be sure to have writefln accessible.  You could make std.stdio a public import of Mix (ick) or selectively make public aliases of all the symbols you use in Mix (easy to forget to update).  But both those are foiled if the user decides to use selective import of just Mix.

So what putting the import inside the mixin (and thereby inside the class where it gets mixed in) does is allow you to make sure the dependencies of the mixin always get carried around with the mixin.

I suppose it would also be possible to make aliases to all needed symbols inside the template, but again it's easy to forget one and the list could get quite long.  Much easier to just import the modules the mixin needs inside the mixin.


-- 

November 14, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2179


Leandro Lucarella <llucax@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |llucax@gmail.com
            Summary|import inside class works   |[module] import inside
                   |but is not in spec          |class works but is not in
                   |                            |spec


--- Comment #5 from Leandro Lucarella <llucax@gmail.com> 2009-11-13 16:38:43 PST ---
See bug 3506 (a feature request for allowing import at any scope).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 22, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=2179


Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla@digitalmars.com
         Resolution|                            |WORKSFORME


--- Comment #6 from Walter Bright <bugzilla@digitalmars.com> 2012-01-22 01:44:33 PST ---
It is in the grammar. Under ClassBodyDeclaration in http://dlang.org/class.html, click on Decldef, which will go to http://dlang.org/module.html#DeclDef, under which you'll find ImportDeclaration.

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