www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 8863] New: struct passed to template: cannot access frame pointer

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

           Summary: struct passed to template: cannot access frame pointer
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: regression
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: beatgammit gmail.com



import std.traits;

    auto fun(T)(out T ret) {
    }

    version(none) {
        auto fun(T)(T ret) {
        }
    }

    void main() {
        struct A {
            auto f() {
            }
        }

        A a;
        fun!A(a);
    }

With the latest dmd (from HEAD), I get the following compile errors:

    test.d(3): Error: cannot access frame pointer of test.main.A
    test.d(18): Error: template instance test.fun!(A) error instantiating

This only happens when the struct has a function and it's passed as an out
parameter. This worked fine on DMD 2.060, but breaks with the HEAD on master.

Any following will cause this to compile:

* remove f()
* make A static
* change out in fun to anything else (ref, in, ...)

This may be related to http://d.puremagic.com/issues/show_bug.cgi?id=8850

Tests run on Linux x64, dmd compiled with 'gmake -f posix.mak MODEL=64;'

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 21 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863




This is a corner case of fixing bug 8339, but I think the current behavior is
intended.

Let's try to replace the out parameter usage to a simple pointer in your code.

auto fun(T)(T* ret) {
  *ret = T();  // Initialize the referred variable to T.init.
               // It's automatically inserted by the compiler.
}
void main() {
  struct A {
    auto f() {}
  }
  A a;
  fun!A(&a);
}

With current dmd the 'out' variable is initialized at the callee side, not
caller side. It requires A's enclosing frame pointer for the correct
initialization, but fun!A cannot access to main's frame, so compiler reports
errors as you have shown.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 07 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla digitalmars.com



23:37:24 PST ---
D templates have an interesting feature where they can be "locally
instantiated" if their arguments refer to local arguments. This is controlled
by the "isnested" member in template.c, set by
TemplateInstance::hasNestedArgs().

It should have the effect of moving the definition of fun() into main(), like
this:

--------------------------
void main() {
   auto fun(T)(T* ret) {
      *ret = T();
   }

  struct A {
    auto f() {}
  }
  A a;
  fun!A(&a);
}
-----------------------

which compiles successfully. So I'd say it is a bug, and the fault is likely in
TemplateInstance::hasNestedArgs().

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 13 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863





 So I'd say it is a bug, and the fault is likely in
 TemplateInstance::hasNestedArgs().
I think that the rule should not be applied to the template type argument, even if the type is a nested struct. Let's consider more complicated case. This code currently compiles successfully. auto foo() { struct X { void f(){} } // nested return X(); } auto bar() { struct Y { void g(){} } // nested return Y(); } // import std.typecons; struct Tuple(T...) { T field; } Tuple!T tuple(T...)(T args) { return typeof(return)(args); } void main() { auto t = tuple(foo(), bar()); } In above code, the template struct Tuple is instantiated with X and Y. If the nested struct type argument make the given template instance nested, Tuple!(X, Y) should have two context pointers, but the code generation will fail. Then the change you say will break much existing code. I think it is not mostly acceptable. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863




00:31:21 PST ---
The example you gave an example of a bug where a reference to a local is
returned, something entirely different.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 14 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863





 The example you gave an example of a bug where a reference to a local is
 returned, something entirely different.
No, they are is related. My argue is: there is no generic rule which make Tuple!(X, Y) un-nested but fun!A make nested. TemplateInstance::hasNestedArgs() works on the template instance, so it cannot know the actual instantiated result is a type (from Tuple!(X, Y)) or a function (from fun!A). It's time paradox. To implement your argument, we need much special code to support the case. It increases the compiler complexity for the much less benefit. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863




Furthermore, the original code had generated incorrect code silently. This
slight complicated code might cause access violation in 2.060 or earlier.

auto fun(T)(out T ret) {
    // ret is incorrectly initialized,
    // and has null context pointer
    ret.f();    // Access Violation
}
void main() {
    int val;
    struct A {
        auto f(){ val = 1; }
    }
    A a;
    fun!A(a);
}

So, I'd like to argue that this issues should be an 'accepts-invalid' bug
rather than a regression.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 14 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863




01:13:28 PST ---
I agree that the original code silently generated wrong code. So this isn't
really a regression.

But I think we can fix it. There is no way to make your example work, because
it is returning a reference to a local. But the original one can work, and
there are many examples of local structs being used as parameters to global
templates, and they work because of the isnested logic.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 14 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863





 But I think we can fix it. There is no way to make your example work, because
 it is returning a reference to a local. But the original one can work, and
 there are many examples of local structs being used as parameters to global
 templates, and they work because of the isnested logic.
Since months ago, I have fixed some nested struct and template bugs not to break existing codes. From the experience, it seems much difficult to *fix* this issue. If you can implement that without ugly hack, I'd like to see it before merging to the main trunk. Could you create a pull request for that? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863




Commit pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/c6a41c414aa9177aef7dac6ac131addba20abf32
possible fix Issue 8863

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 25 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8863


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|regression                  |normal



18:31:43 PST ---
This isn't a regression, it was an error not detected before.

The commit is a fix for it, but the fix breaks the test suite (nested.d) and
the phobos unittests for std.array. I suspect the test suite is wrong, but for
the moment the fix is commented out.

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