Jump to page: 1 2
Thread overview
[Issue 8863] New: struct passed to template: cannot access frame pointer
Oct 21, 2012
Jameson
Nov 07, 2012
Kenji Hara
Nov 14, 2012
Walter Bright
Nov 14, 2012
Kenji Hara
Nov 14, 2012
Walter Bright
Nov 14, 2012
Kenji Hara
Nov 14, 2012
Kenji Hara
Nov 14, 2012
Walter Bright
Nov 14, 2012
Kenji Hara
Dec 26, 2012
Walter Bright
October 21, 2012
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


--- Comment #0 from Jameson <beatgammit@gmail.com> 2012-10-21 11:13:20 PDT ---
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: -------
November 07, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #1 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-07 05:12:10 PST ---
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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863


Walter Bright <bugzilla@digitalmars.com> changed:

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


--- Comment #2 from Walter Bright <bugzilla@digitalmars.com> 2012-11-13 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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #3 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-14 00:13:59 PST ---
(In reply to comment #2)
> 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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #4 from Walter Bright <bugzilla@digitalmars.com> 2012-11-14 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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #5 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-14 01:07:54 PST ---
(In reply to comment #4)
> 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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #6 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-14 01:08:01 PST ---
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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #7 from Walter Bright <bugzilla@digitalmars.com> 2012-11-14 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: -------
November 14, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #8 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-14 02:05:18 PST ---
(In reply to comment #7)
> 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: -------
December 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8863



--- Comment #9 from github-bugzilla@puremagic.com 2012-12-25 18:28:58 PST ---
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: -------
« First   ‹ Prev
1 2