Thread overview
Mixins and auto
Dec 10, 2005
Chris Sauls
Dec 10, 2005
Sean Kelly
Dec 18, 2005
Thomas Kuehne
December 10, 2005
Might be a bug, or might be me doing something silly, but this doesn't work as expected:

# module mix0;
#
# import std.stdio ;
#
# class Foo {
#   this (char[] a_label) {
#     p_label = a_label;
#     writefln(" + ", p_label);
#   }
#
#   ~this () {
#     writefln(" - ", p_label);
#   }
#
#   private char[] p_label ;
# }
#
# template MFoo (char[] T_label) {
#   auto Foo _MFoo_foo = new Foo(T_label);
# }
#
# void main () {
#   { mixin MFoo!("A"); }
#   { mixin MFoo!("B"); }
#   { mixin MFoo!("C"); }
#
#   { auto Foo foo = new Foo("A2"); }
#   { auto Foo foo = new Foo("B2"); }
#   { auto Foo foo = new Foo("C2"); }
# }

The output I expected being:
 | + A
 | - A
 | + B
 | - B
 | + C
 | - C
 | + A2
 | - A2
 | + B2
 | - B2
 | + C2
 | - C2

The output I am getting:
 | + A
 | + B
 | + C
 | + A2
 | - A2
 | + B2
 | - B2
 | + C2
 | - C2
 | - C
 | - B
 | - A

Eh?  Apparently the "auto" variables declared by the mixins aren't getting collected until the end of the entire function, my anonymous blocks be damned, and in reverse order.  And in case anyone wonders, no it doesn't change if I place more code in the blocks.  I ran across this little beaut looking for a way to conditionally compile in my Timer objects with somewhat cleaner reading code. (I like the look of `mixin MTimer!("void main()");` better than `version (Timer) auto Timer t = new Timer("void main()");` ... I guess I'm crazy.)

Any insights?

-- Chris Sauls
December 10, 2005
Chris Sauls wrote:
> Might be a bug, or might be me doing something silly, but this doesn't work as expected:
> 
> # module mix0;
> #
> # import std.stdio ;
> #
> # class Foo {
> #   this (char[] a_label) {
> #     p_label = a_label;
> #     writefln(" + ", p_label);
> #   }
> #
> #   ~this () {
> #     writefln(" - ", p_label);
> #   }
> #
> #   private char[] p_label ;
> # }
> #
> # template MFoo (char[] T_label) {
> #   auto Foo _MFoo_foo = new Foo(T_label);
> # }
> #
> # void main () {
> #   { mixin MFoo!("A"); }
> #   { mixin MFoo!("B"); }
> #   { mixin MFoo!("C"); }
> #
> #   { auto Foo foo = new Foo("A2"); }
> #   { auto Foo foo = new Foo("B2"); }
> #   { auto Foo foo = new Foo("C2"); }
> # }
> 
> The output I expected being:
>  | + A
>  | - A
>  | + B
>  | - B
>  | + C
>  | - C
>  | + A2
>  | - A2
>  | + B2
>  | - B2
>  | + C2
>  | - C2
> 
> The output I am getting:
>  | + A
>  | + B
>  | + C
>  | + A2
>  | - A2
>  | + B2
>  | - B2
>  | + C2
>  | - C2
>  | - C
>  | - B
>  | - A
> 
> Eh?  Apparently the "auto" variables declared by the mixins aren't getting collected until the end of the entire function, my anonymous blocks be damned, and in reverse order.  And in case anyone wonders, no it doesn't change if I place more code in the blocks.  I ran across this little beaut looking for a way to conditionally compile in my Timer objects with somewhat cleaner reading code. (I like the look of `mixin MTimer!("void main()");` better than `version (Timer) auto Timer t = new Timer("void main()");` ... I guess I'm crazy.)
> 
> Any insights?

I think this is similar to auto variables not getting cleaned up if scope exits from a throw.  In both cases, the dtor isn't being called as it should and they're being cleaned up by the next GC cycle.  In the case of mixins however, it seems like a parse issue rather than a runtime issue.


Sean
December 18, 2005
Chris Sauls schrieb am 2005-12-10:
> Might be a bug, or might be me doing something silly, but this doesn't work as expected:
>
> # module mix0;
> #
> # import std.stdio ;
> #
> # class Foo {
> #   this (char[] a_label) {
> #     p_label = a_label;
> #     writefln(" + ", p_label);
> #   }
> #
> #   ~this () {
> #     writefln(" - ", p_label);
> #   }
> #
> #   private char[] p_label ;
> # }
> #
> # template MFoo (char[] T_label) {
> #   auto Foo _MFoo_foo = new Foo(T_label);
> # }
> #
> # void main () {
> #   { mixin MFoo!("A"); }
> #   { mixin MFoo!("B"); }
> #   { mixin MFoo!("C"); }
> #
> #   { auto Foo foo = new Foo("A2"); }
> #   { auto Foo foo = new Foo("B2"); }
> #   { auto Foo foo = new Foo("C2"); }
> # }
>
> The output I expected being:
>  | + A
>  | - A
>  | + B
>  | - B
>  | + C
>  | - C
>  | + A2
>  | - A2
>  | + B2
>  | - B2
>  | + C2
>  | - C2
>
> The output I am getting:
>  | + A
>  | + B
>  | + C
>  | + A2
>  | - A2
>  | + B2
>  | - B2
>  | + C2
>  | - C2
>  | - C
>  | - B
>  | - A
>
> Eh?  Apparently the "auto" variables declared by the mixins aren't getting collected until the end of the entire function, my anonymous blocks be damned, and in reverse order.  And in case anyone wonders, no it doesn't change if I place more code in the blocks.  I ran across this little beaut looking for a way to conditionally compile in my Timer objects with somewhat cleaner reading code. (I like the look of `mixin MTimer!("void main()");` better than `version (Timer) auto Timer t = new Timer("void main()");` ... I guess I'm crazy.)
>
> Any insights?
>
> -- Chris Sauls

Added to DStress as http://dstress.kuehne.cn/run/a/auto_13_A.d http://dstress.kuehne.cn/run/a/auto_13_B.d

Thomas