www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 11946] New: "need 'this' to access member" when passing field to template parameter

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

           Summary: "need 'this' to access member" when passing field to
                    template parameter
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: rejects-valid
          Severity: regression
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: thecybershadow gmail.com


--- Comment #0 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-19
01:25:45 EET ---
////////////////////////////////////////
static // http://d.puremagic.com/issues/show_bug.cgi?id=7805
int f(A...)() { return 0; }

struct S { int x; enum y = f!x(); }
////////////////////////////////////////

This used to compile, but it was broken by
https://github.com/D-Programming-Language/dmd/pull/2794

Also, issue 7805 was not fixed. It was marked as a duplicate of issue 11533,
which the above pull request claims to fix. Whereas before, the "static" was
required to avoid a compiler error, now it makes no difference as a compiler
error occurs with and without "static".

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 18 2014
next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #1 from Kenji Hara <k.hara.pg gmail.com> 2014-01-18 23:45:48 PST ---
It's intended behavior introduced by issue 11533. Now, alias parameter is
preferred than 'static' attribute _on template_.

If you really need the syntax f!x(), you should define function template 'f'
like follows:

template f(alias X)
{
    static string f()
    {
        //int x = X;
        return X.stringof; // OK
    }
}
struct S
{
    int i;
    enum y = f!i();
    pragma(msg, y);
}

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 18 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #2 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-19
17:20:28 EET ---
It still seems like pointless breaking of code. If it really is intentional,
then the diagnostic needs to be improved to tell the user how exactly to change
their code.

Also, there is still no sensible reason why "static" is required on a free
function, regardless of whether it's in a template or not.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 19 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull


--- Comment #3 from Kenji Hara <k.hara.pg gmail.com> 2014-01-20 03:41:05 PST ---
(In reply to comment #2)
 It still seems like pointless breaking of code. If it really is intentional,
 then the diagnostic needs to be improved to tell the user how exactly to change
 their code.
 
 Also, there is still no sensible reason why "static" is required on a free
 function, regardless of whether it's in a template or not.

OK, I reopen issue 7805 as an enhancement request. And fixing it will also fix this regression. https://github.com/D-Programming-Language/dmd/pull/3126 -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 20 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #4 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-20
15:50:53 EET ---
 OK, I reopen issue 7805 as an enhancement request.

Unless the enhancement is making the error message better, it is still a regression and not an enhancement, is it not? From my observations of related errors, I think there seems to be some conflation between aliases to declarations (without context pointers) and aliases to actual variables (which do have context pointers). For example, S.field and s.field. These bug reports and those where the compiler complains that "this for X should be type Y not type Z" indicates that in a lot of cases, the compiler attempts to pass the context pointer to blocks where it makes no sense to. IMO, all "this for X should be type Y not type Z" errors are confusing and useless, and need to be eliminated. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 20 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946


Walter Bright <bugzilla digitalmars.com> changed:

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


--- Comment #5 from Walter Bright <bugzilla digitalmars.com> 2014-01-21
00:25:04 PST ---
(In reply to comment #0)
 ////////////////////////////////////////
 static // http://d.puremagic.com/issues/show_bug.cgi?id=7805
 int f(A...)() { return 0; }
 
 struct S { int x; enum y = f!x(); }
 ////////////////////////////////////////
 
 This used to compile, but it was broken by
 https://github.com/D-Programming-Language/dmd/pull/2794
 
 Also, issue 7805 was not fixed. It was marked as a duplicate of issue 11533,
 which the above pull request claims to fix. Whereas before, the "static" was
 required to avoid a compiler error, now it makes no difference as a compiler
 error occurs with and without "static".

This should never have compiled. static should never have affected a template in global scope. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 21 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #6 from Kenji Hara <k.hara.pg gmail.com> 2014-01-22 21:52:01 PST ---
I change my argue to that this regression should be marked as invalid.

(In reply to comment #5)
 (In reply to comment #0)
 ////////////////////////////////////////
 static // http://d.puremagic.com/issues/show_bug.cgi?id=7805
 int f(A...)() { return 0; }
 
 struct S { int x; enum y = f!x(); }
 ////////////////////////////////////////
 

in global scope.

I also think so. But it had been worked because 'static' attribute is always inherited to the instantiated function. I *fixed* the bug in the PR:
 This used to compile, but it was broken by
 https://github.com/D-Programming-Language/dmd/pull/2794


=== The main point of enhancment 11533 is that 'static template' should always behave as same as module-level templates, regardless its declared position. It's increasing consistency with currently known language concepts: - 'static' attribute on module level declaration is just redundant (meaningless). - 'static' declaration inside aggregates/functions should behave as same as module level declarations. * static member function is equivalent with free functions. * static local function is equivalent with free functions. By the fix, `static int f(A...)(){ ... }` and `int f(A...)(){ ... }` have now no difference at module level. Therefore, instantiated f!(S.x) always requires hidden 'this' pointer on the call. To be more precise, current D language alias template parameter is not designed just to take a symbol that is needed just only at compile-time. If given template argument has implicit runtime context, compiler will _always_ try to take runtime context at the same time. (To resolve the issue, "nested-ness interence" is sometimes proposed. But I'm still not sure it is possible feature.) To ignore the implicit automatic capturing, you need to write the idiom I explained in comment#1. As a conclusion: the reported breaking change is necessary due to add more consistency to the language spec. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 22 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #7 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-23
08:51:03 EET ---
 It's increasing consistency with currently known language concepts:

Yes, this is all fine and well, but it does not justify making code that worked before now break with an indecipherable error message! The message "need 'this' to access member f" is an outright lie and is only good at showing a glaring compiler implementation problem. (In reply to comment #1)
 template f(alias X)
 {
     static string f()
     {
         //int x = X;
         return X.stringof; // OK
     }
 }

This just shows another bug - that you still need "static" (which makes NO sense for a free function, templated or not), but now you must hide it inside a template!
 To be more precise, current D language alias template parameter is not designed
 just to take a symbol that is needed just only at compile-time.
 If given template argument has implicit runtime context, compiler will _always_
 try to take runtime context at the same time.

So fix this first before breaking code?
 To ignore the implicit automatic capturing, you need to write the idiom I
 explained in comment#1.

If one needs to go to a bugtracker and learn of a hacky workaround (put a static function in a template) from a compiler developer to make their code compile, this is a terrible situation for D.
 As a conclusion: the reported breaking change is necessary due to add more
 consistency to the language spec.

I suggest that consistency bugs are fixed only after there is an immediate and obvious way to transition code that should not have compiled, to correct code which functions in the same way. In either case, this bug remains a REGRESSION. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 22 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #8 from Kenji Hara <k.hara.pg gmail.com> 2014-01-22 23:41:23 PST ---
(In reply to comment #7)
 It's increasing consistency with currently known language concepts:

Yes, this is all fine and well, but it does not justify making code that worked before now break with an indecipherable error message! The message "need 'this' to access member f" is an outright lie and is only good at showing a glaring compiler implementation problem.

There's no lie. The instantiated function _always_ needs valid runtime context, *regardless* the context is really used or not inside function body. Unfortunately current D has _no_ language feature to remove unused context pointer (I call it "nested-ness inference").
 (In reply to comment #1)
 template f(alias X)
 {
     static string f()
     {
         //int x = X;
         return X.stringof; // OK
     }
 }

This just shows another bug - that you still need "static" (which makes NO sense for a free function, templated or not), but now you must hide it inside a template!

It's not a bug. If the symbol X needs runtime context ('this' object or function frame), f() will be instantiated like as member function or nested function. To remove the implicit context pointer, 'static' will work. --- After fixing issue 11533, these two declarations have different meanings. template f(alias X) { static string f() { return null; } } // A static template f(alias X) { string f() { return null; } } // B In A, 'static' attribute is always added to the instantiated function 'f'. So Even if X requires runtime context, 'f' still cannot access it. In B, 'static' attribute is added _if_ X has no runtime context. If X needs runtime context, instantiated 'f' also take the context to access valid runtime storage of X. ---
 To be more precise, current D language alias template parameter is not designed
 just to take a symbol that is needed just only at compile-time.
 If given template argument has implicit runtime context, compiler will _always_
 try to take runtime context at the same time.

So fix this first before breaking code?

It would be a not trivial language enhancement that still not yet designed.
 To ignore the implicit automatic capturing, you need to write the idiom I
 explained in comment#1.

If one needs to go to a bugtracker and learn of a hacky workaround (put a static function in a template) from a compiler developer to make their code compile, this is a terrible situation for D.

To explain the behavior, I'll update webside documentation and add a section in release note.
 As a conclusion: the reported breaking change is necessary due to add more
 consistency to the language spec.

I suggest that consistency bugs are fixed only after there is an immediate and obvious way to transition code that should not have compiled, to correct code which functions in the same way.

I already explained the way to do it in comment#1. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 22 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #9 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-23
09:53:40 EET ---
(In reply to comment #8)
 (In reply to comment #7)
 It's increasing consistency with currently known language concepts:

Yes, this is all fine and well, but it does not justify making code that worked before now break with an indecipherable error message! The message "need 'this' to access member f" is an outright lie and is only good at showing a glaring compiler implementation problem.

There's no lie. The instantiated function _always_ needs valid runtime context, *regardless* the context is really used or not inside function body.

What?!?!? This makes absolutely no sense! There is nothing in the D spec about this! Templated functions must behave in the same way as free functions (whether the function itself is templated or it is inside an explicit template declaration), and "static" is meaningless on free functions! We are not talking about template mixins! The instantiation of non-mixin templates uses the template declaration's context!
 Unfortunately current D has _no_ language feature to remove unused context
 pointer (I call it "nested-ness inference").

As far as I can see, this is just a compiler implementation detail! Can you provide an example where this "feature" (passing context pointer from template instantiation site to a free function) is actually used?
 It's not a bug. If the symbol X needs runtime context ('this' object or
 function frame), 

It doesn't! .stringof does not need a gosh-darn context pointer!
 f() will be instantiated like as member function or nested
 function. 

WHY?!? It is a free function!
 To remove the implicit context pointer, 'static' will work.

...
 After fixing issue 11533, these two declarations have different meanings.
 
 template f(alias X) { static string f() { return null; } }  // A
 static template f(alias X) { string f() { return null; } }  // B
 
 In A, 'static' attribute is always added to the instantiated function 'f'. So
 Even if X requires runtime context, 'f' still cannot access it.
 In B, 'static' attribute is added _if_ X has no runtime context. If X needs
 runtime context, instantiated 'f' also take the context to access valid runtime
 storage of X.

This looks like absurd overcomplication. Do you really expect D users to have to understand the difference?
 It would be a not trivial language enhancement that still not yet designed.

Then I suggest that you postpone all breaking changes until all that is figured out. Breaking code to clean up compiler internals is inexcusable, IMO!
 To explain the behavior, I'll update webside documentation and add a section in
 release note. 

The more I think about it the less sense it makes to me. Maybe it makes sense from the point of view of a compiler developer (to use Chen Raymond's phraseology, you're looking at the world through "compiler-tinted glasses"). But as a D user, your explanation reads like one giant WTF to me. It is completely unintuitive and to me it seems that things are broken at a much more fundamental level if you defend the current logic in this way. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 22 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #10 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 01:29:55 PST
---
(In reply to comment #9)
 (In reply to comment #8)
 There's no lie. The instantiated function _always_ needs valid runtime context,
 *regardless* the context is really used or not inside function body.

What?!?!? This makes absolutely no sense! There is nothing in the D spec about this! Templated functions must behave in the same way as free functions (whether the function itself is templated or it is inside an explicit template declaration), and "static" is meaningless on free functions! We are not talking about template mixins! The instantiation of non-mixin templates uses the template declaration's context!

Yes, I'm talking about normal templates. Even if the template is defined in module level, if it has alias parameter, instantiated function may have implicit context. Indeed it is part of the implementation detail, but today it is mostly unavoidable issue. If you interest, you can read issue 5710 discussion.
 Unfortunately current D has _no_ language feature to remove unused context
 pointer (I call it "nested-ness inference").

As far as I can see, this is just a compiler implementation detail! Can you provide an example where this "feature" (passing context pointer from template instantiation site to a free function) is actually used?

// This is module level template function that have alias parameter. int foo(alias sym)() { return sym; } class C { int n; void test() { this.n = 10; alias fooN = foo!(C.n); // fooN has implicit context to access field variable n in class C. static assert(is(typeof(&fooN) == delegate)); assert(fooN() == 10); } } void main() { int n = 10; alias fooN = foo!n; // fooN has implicit context to access local variable n in main. static assert(is(typeof(&fooN) == delegate)); assert(fooN() == 10); new C().test(); } foo(alias sym) is module level template, but in both case instantiated functions will have implicit context pointer to access runtime data of 'sym'.
 It's not a bug. If the symbol X needs runtime context ('this' object or
 function frame), 

It doesn't! .stringof does not need a gosh-darn context pointer!

Again, current compiler does not consider that the context is not really used inside function.
 f() will be instantiated like as member function or nested
 function. 

WHY?!? It is a free function!

No. It's a template function that is defined in module level.
 To remove the implicit context pointer, 'static' will work.

...
 After fixing issue 11533, these two declarations have different meanings.
 
 template f(alias X) { static string f() { return null; } }  // A
 static template f(alias X) { string f() { return null; } }  // B
 
 In A, 'static' attribute is always added to the instantiated function 'f'. So
 Even if X requires runtime context, 'f' still cannot access it.
 In B, 'static' attribute is added _if_ X has no runtime context. If X needs
 runtime context, instantiated 'f' also take the context to access valid runtime
 storage of X.

This looks like absurd overcomplication. Do you really expect D users to have to understand the difference?

In many cases, learning it would not be necessary. But in your case the difference is necessary. Honestly, the alias parameter usage in your code does not fit the expected usage in language design. At least from D1 age, template alias parameter is designed to use the given symbol in runtime at instantiated code.
 It would be a not trivial language enhancement that still not yet designed.

Then I suggest that you postpone all breaking changes until all that is figured out. Breaking code to clean up compiler internals is inexcusable, IMO!
 To explain the behavior, I'll update webside documentation and add a section in
 release note. 

The more I think about it the less sense it makes to me. Maybe it makes sense from the point of view of a compiler developer (to use Chen Raymond's phraseology, you're looking at the world through "compiler-tinted glasses"). But as a D user, your explanation reads like one giant WTF to me. It is completely unintuitive and to me it seems that things are broken at a much more fundamental level if you defend the current logic in this way.

I agree that it is hard to understand behavior. That's why I had tried to fix the issue at first. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #11 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 07:50:17 PST
---
(In reply to comment #8)
 To explain the behavior, I'll update webside documentation and add a section in
 release note. 

I opened a document improvement for the existing "Nested Templates" feature. https://github.com/D-Programming-Language/dlang.org/pull/479 -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #12 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-23
20:24:12 EET ---
(In reply to comment #10)
   // This is module level template function that have alias parameter.
   int foo(alias sym)() { return sym; }
 
   class C
   {
     int n;
     void test()
     {
       this.n = 10;
       alias fooN = foo!(C.n);
       // fooN has implicit context to access field variable n in class C.
       static assert(is(typeof(&fooN) == delegate));
       assert(fooN() == 10);
     }
   }

Thank you, I finally understand what's going on. But the situation looks really bad. What if you want to pass the "n" variable from both the struct and the function, to the same template? Or if the template already has a context pointer (it is a templated method)? The context pointers should be tied to the variables, not the same "this" pointer that is used in calling methods. Doing it that way just produces absurd error messages. In either case, at the very least the error message needs to be improved. The simplest solution would be to just change the wording for such cases to make it Google-able. But of course ideally the problem should be solved at its root.
 Again, current compiler does not consider that the context is not really used
 inside function.

Well, this is another bug then.
 It is a free function!

No. It's a template function that is defined in module level.

I do not believe that the distinction needs to be forced upon the users.
 In many cases, learning it would not be necessary. But in your case the
 difference is necessary.
 Honestly, the alias parameter usage in your code does not fit the expected
 usage in language design.
 At least from D1 age, template alias parameter is designed to use the given
 symbol in runtime at instantiated code.

I just tested another bit of code: struct O { int f(A...)() { return 0; } struct S { int x; void g() { auto y = f!x(); } } } With this one, we get: test3.d(11,13): Error: template instance f!(x) cannot use local 'x' as parameter to non-global template f(A...)() test3.d(11,16): Error: this for f needs to be type O not type S IMHO the correct solution would be to pass the context pointers of alias parameters separately, so as to not interfere with any existing context pointers of the template. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #13 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-24
04:48:25 EET ---
After some thinking:

"static" must not affect whether alias parameters receive context pointers.
Currently, there can only be one context pointer per function, but this
limitation will hopefully be lifted in the future. When that happens, there
will be no way to decide whether each alias parameter carries along a context
pointer or not. Therefore, "static" must only untie the function from its
immediate surrounding declaration context (struct, class or function frame).

As I understand, currently, if a declaration CAN have a context pointer, the
compiler seems to demand it at all times when passing it as an alias parameter.

Instead, it should pass a context pointer if and only if if it is actually
available at the scope of the template instantiation.

For example, it will be available when calling a templated function from a
non-static method, but it will not be available when declaring an enum, or
calling from a static method.

Later, if the template function's code attempts to do anything with the alias
parameter which ACTUALLY requires its context, for example reading/writing it
or taking its address, then it should raise an error. So, the context pointer
check needs to stop being eager and be made as late as possible.

Additionally, if you want to explicitly choose whether you want to pass an
alias parameter WITH or WITHOUT a context pointer, I think the language already
has the necessary syntax, and for class/struct fields it is quite intuitive:
C.x (no context pointer) vs. c.x (c is the context pointer), or this.x vs.
typeof(this).x etc. It is more complicated with local variables, but I think
__traits(getMember, __traits(parent, n), "n") would work. However, I believe
this should not be necessary at all, since the compiler should not demand a
context pointer without even bothering to check if the template actually needs
it.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #14 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 19:51:25 PST
---
(In reply to comment #13)
 After some thinking:
 
 "static" must not affect whether alias parameters receive context pointers.

 "static" must only untie the function from its
 immediate surrounding declaration context (struct, class or function frame).

This is just same with the behavior that was implemented by issue 11533. In git-head, static attribute on template does only unite instantiated functions and aggregate types from its immediate surrounding declaration context. void main() { int x; // Adding 'static' on local template foo unlinks instantied function // from the enclosing main() function context. static void foo(alias fun)() { // x = 10; // NG fun(); } static void bar() {} foo!bar(); pragma(msg, is(typeof(&foo!bar) == delegate)); // prints false // And nested-ness of the instantiated function only depends on // the passed argument on the alias parameter void nested() {} pragma(msg, is(typeof(&foo!nested) == delegate)); // prints true } So in the OP code: static int f(A...)() { return 0; } struct S { int x; enum y = f!x(); } f!x is now tied to the runtime object S, and calling it on context-less scope is rejected. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #15 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 19:52:56 PST
---
(In reply to comment #14)
  static attribute on template does only unite instantiated functions ...

static attribute on template does only >>untied<< instantiated functions ... -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #16 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-24
05:54:06 EET ---
OK... but then why does your suggestion in comment#1 work? If it is as you say,
then "static" should have no effect on free functions, regardless if they are
in a template or not, right?

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #17 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 20:16:30 PST
---
(In reply to comment #16)
 OK... but then why does your suggestion in comment#1 work? If it is as you say,
 then "static" should have no effect on free functions, regardless if they are
 in a template or not, right?

Again, 'f' is not a free function, it is a function template that declared in module level. Therefore, instantiated function f!x will become nested if inner static attribute does not exist. // static int f(A...)() { return 0; } is equivalent with static template f(A...) { int f() { return 0; } } struct S { int x; enum y = f!x // f!x is equivalent with member function of S. } On the other hand: template f(A...) { static int f() { return 0; } } struct S { int x; enum y = f!x // f!x is equivalent with 'static' member function of S. } -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #18 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-24
07:34:14 EET ---
OK, but when I said:

 "static" must not affect whether alias parameters receive context pointers.

 "static" must only untie the function from its
 immediate surrounding declaration context (struct, class or function frame).

I specifically meant this case. It should not matter whether the function is in a template or not, if it is not declared in a struct/class/function, then "static" should have no effect (or even be forbidden, as the compiler now forbids many senseless attributes). With your change, "static" is still used as a mechanism to tell the compiler whether the function needs the context at the INSTANTIATION site, which should not be necessary, as I said in comment#13 the compiler should instantiate/evaluate the function regardless of whether a context pointer is needed, and if the function's code actually needs the context pointer then the compiler will complain at that point. But to get back on topic, you said that you're not sure if this problem will ever be solved. But there have been a few unanswered suggestions here and in the other discussion you mentioned, do you think they are all unfeasible? -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #19 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 22:47:53 PST
---
(In reply to comment #18)
 OK, but when I said:
 
 "static" must not affect whether alias parameters receive context pointers.

 "static" must only untie the function from its
 immediate surrounding declaration context (struct, class or function frame).

I specifically meant this case. It should not matter whether the function is in a template or not, if it is not declared in a struct/class/function, then "static" should have no effect (or even be forbidden, as the compiler now forbids many senseless attributes).

Maybe you're misunderstanding the effect of 'static' attribute. As far as I know, it means that: - If 'static' attribute is specified to a nested declaration, it will make the nested declaration 'unnested'. In above description, of course 'nested declaration' contains the instantiated functions that implicitly made nested, like f!x. That's why static attribute on module level declaration is meaningless - module level declaration is always non-nested, so 'unnesting' has no effect, and adding static attribute to the instantiated nested function is meaningful.
 With your change, "static" is still used as
 a mechanism to tell the compiler whether the function needs the context at the
 INSTANTIATION site

As I explained above, It is expected behavior of 'static' attribute.
 which should not be necessary, as I said in comment#13

Even if it will become possible in the future, but currently it isn't. I have no opinion about non existing feature. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #20 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-24
08:55:12 EET ---
(In reply to comment #19)
 Maybe you're misunderstanding the effect of 'static' attribute.
 As far as I know, it means that:

I think I understand how it works now. But I don't think this is how it SHOULD work, because it is not intuitive. No other programming language does this, and no one expects it to act like this. So I think it is a limitation imposed by implementation detail that needs to be fixed.
 Even if it will become possible in the future, but currently it isn't.
 I have no opinion about non existing feature.

I hope it will be fixed, I think this is an important issue. Maybe Facebook will place a nice bounty in the next round :) -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #21 from Kenji Hara <k.hara.pg gmail.com> 2014-01-23 23:33:10 PST
---
(In reply to comment #20)
 (In reply to comment #19)
 Maybe you're misunderstanding the effect of 'static' attribute.
 As far as I know, it means that:

I think I understand how it works now. But I don't think this is how it SHOULD work, because it is not intuitive. No other programming language does this, and no one expects it to act like this. So I think it is a limitation imposed by implementation detail that needs to be fixed.

I think it is enough reasonable definition because: 1. Currently dmd works that way. 2. It is consistent definition and allow such the code in comment#1. Anyway, can you agree that the OP code needs fixup with 2.065 and this issue should me marked as INVALID? -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #22 from Vladimir Panteleev <thecybershadow gmail.com> 2014-01-24
09:40:21 EET ---
No, I do not agree that this bug is INVALID. It is still a regression, and I
maintain that the current behavior and your suggested workaround are illogical.

 1. Currently dmd works that way.

This is not a good argument - if it works in a wrong way, it needs to be fixed.
 2. It is consistent definition and allow such the code in comment#1.

It shouldn't be required to either use "static" or put the function in a template block. Anyway, I understand if this is a very complicated problem that is not worth stopping the release for, so I would agree with a WONTFIX (or REMIND/LATER?) resolution. But I think it would be good to hear someone else's opinion in this discussion first. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #23 from Walter Bright <bugzilla digitalmars.com> 2014-01-26
12:31:01 PST ---
 This just shows another bug - that you still need "static" (which makes NO

template! I agree. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 26 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #24 from Walter Bright <bugzilla digitalmars.com> 2014-01-26
12:46:49 PST ---
Some thoughts:

1. 'static' in D has come to mean "a context pointer is not supplied". For
example, in C:

    void foo() {
       static int x;
    }

x can be accessed without the "context pointer", in this case the stack
pointer. Static doesn't mean it is unnested or global.

2. Alias template arguments are never "passed" to a template in the way that
arguments are passed to functions. They simply make the symbol in scope in the
template body.

3. Static as an attribute makes no sense in a context where there is no context
pointer. I.e. declarations at global level, declarations inside global
templates, etc.

4. A use of a symbol, where that use does not require a context pointer, should
not issue an error if a context pointer is not supplied.

5. I don't think we're going to resolve this easily without a lot of careful
thought.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 26 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #25 from Walter Bright <bugzilla digitalmars.com> 2014-01-26
12:51:42 PST ---
I suspect this should work:

  int f(alias A)() { return 0; }
  struct S { int x; enum y = f!x(); }

whereas this should not:

  int f(alias A)() { return A; }
  struct S { int x; enum y = f!x(); }

i.e. this check:

  foo3.d(1): Error: function foo3.S.f!(x).f need 'this' to access member f

should not be done for arguments to template alias parameters.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 26 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #26 from Kenji Hara <k.hara.pg gmail.com> 2014-01-29 18:23:31 PST
---
(In reply to comment #24)
 Some thoughts:
 
 1. 'static' in D has come to mean "a context pointer is not supplied". For
 example, in C:
 
     void foo() {
        static int x;
     }
 
 x can be accessed without the "context pointer", in this case the stack
 pointer. Static doesn't mean it is unnested or global.

I used the word 'unnested' to represent the equivalent meaning with "a context pointer is not supplied". So basically I agree with this.
 2. Alias template arguments are never "passed" to a template in the way that
 arguments are passed to functions. They simply make the symbol in scope in the
 template body.

About the merely visibility of the passed alias parameter, it is correct. But, instantiated function f!(x).f should have a context to access context-full symbol 'x'. _Currently_ this is not avoidable.
 3. Static as an attribute makes no sense in a context where there is no context
 pointer. I.e. declarations at global level, declarations inside global
 templates, etc.

Yes.
 4. A use of a symbol, where that use does not require a context pointer, should
 not issue an error if a context pointer is not supplied.

Essentially yes. But current compiler does not support the principle, because of the lack of language feature.
 5. I don't think we're going to resolve this easily without a lot of careful
 thought.

Definitely yes. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 29 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #27 from Kenji Hara <k.hara.pg gmail.com> 2014-01-29 18:28:07 PST
---
(In reply to comment #25)
 I suspect this should work:
 
   int f(alias A)() { return 0; }
   struct S { int x; enum y = f!x(); }
 
 whereas this should not:
 
   int f(alias A)() { return A; }
   struct S { int x; enum y = f!x(); }
 
 i.e. this check:
 
   foo3.d(1): Error: function foo3.S.f!(x).f need 'this' to access member f
 
 should not be done for arguments to template alias parameters.

Currently this is necessary. As a technical talk, in current semantic analysis system, the "context-ness" of a function - whether a function really needs a context or not - should be determined without its body analysis. As far as I see, current dmd code relies on the assumption. To relax the limitation, we should infer the context-ness as same as attribute inference, but it should be considered as a new language enhancement but it is not definitely so small. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 29 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #28 from Kenji Hara <k.hara.pg gmail.com> 2014-01-29 18:44:24 PST
---
On the other hand, the purpose of issue 11533 is simple and consistent.

If a module level declaration is moved into function/aggreage scope with
additional 'static' attribute, it should have exactly same behavior.

Examples:

module a;
int var;
void foo();
class C {}
void bar(T)(T) {}
struct S(alias pred) { void f() {} }
void baz(alias v)(T) { v = 1; }

class Test {
    static int var;
    static void foo();
    static class C {}
    static void bar(T)(T) {}
    static struct S(alias pred) { void f() {} }  // New!
    static void baz(alias v)(T) { v = 1; }  // New!
}
void test() {
    static int var;
    static void foo();
    static class C {}
    static void bar(T)(T) {}
    static struct S(alias pred) { void f() {} }  // New!
    static void baz(alias v)(T) { v = 1; }  // New!
}

The case of 'S' and 'baz' are newly supported by fixing 11533.
- S(alias pred) will become context-free if 'pred' is context-free.
- baz(alias v) will become context-free if 'v' is context-free.

Indeed, to support baz case current 'static' attribute semantics is made a
little complex, but the introduced behavior is simple, consistent, and easy
understandable.
I think fixiing 11533 is a huge win for the D code locality.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 29 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946


Dicebot <public dicebot.lv> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |public dicebot.lv


--- Comment #29 from Dicebot <public dicebot.lv> 2014-03-03 07:42:12 PST ---
I agree with Vladimir here. This is basically replacing one hack with another
so that both code will break and no desired solution will be introduced. Such
change can't be justified and this supposed win is imaginary.

About anything that legitimates statement "templated free function is not a
free function" is a huge "NO!" in my opinion.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #30 from Vladimir Panteleev <thecybershadow gmail.com> 2014-03-03
17:56:27 EET ---
The irony is that as much as I dislike this approach, it does allow doing more
things with template alias parameters, and I've started to rely on it in my own
code. I even took it a step further in
https://github.com/D-Programming-Language/dmd/pull/3345 to do the same things
with methods.

I noticed Kenji wrote this on the D Wiki:
http://wiki.dlang.org/Brush_Up_Language_Features#Nested_Symbols

The idea is to introduce "static alias" template parameters, which make it
explicit if the alias parameter needs to transmit the symbol's context to the
template (and thus nest the template within that context), or not. I think it
is a sensible approach in lieu of automagically determining if that context is
needed by the template (which Kenji claims is "mostly impossible").

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #31 from Dicebot <public dicebot.lv> 2014-03-03 08:08:42 PST ---
(In reply to comment #30)
 The irony is that as much as I dislike this approach, it does allow doing more
 things with template alias parameters, and I've started to rely on it in my own
 code. I even took it a step further in

It does not really matter. What is the point of adding more features is they break basic guarantees? It does not fit nicely with idea that templates are not affected by instantiation scope and forces you to pollute your code with loads of boilerplate just to be sure. I am effectively forced to go though my code upon next release and replace all void foo(alias X)(...) {} with template foo(alias X) { static void foo(...) {] } _everywhere_. How I am even supposed to not hate it?
 The idea is to introduce "static alias" template parameters, which make it
 explicit if the alias parameter needs to transmit the symbol's context to the
 template (and thus nest the template within that context), or not. I think it
 is a sensible approach in lieu of automagically determining if that context is
 needed by the template (which Kenji claims is "mostly impossible").

It should be other way around, "dynamic alias" for those who do want a context pointer. "Don't pay for what you don't use" and principle of least surprise. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #32 from Vladimir Panteleev <thecybershadow gmail.com> 2014-03-03
18:12:41 EET ---
(In reply to comment #31)
 It does not really matter. What is the point of adding more features is they
 break basic guarantees? It does not fit nicely with idea that templates are not
 affected by instantiation scope and forces you to pollute your code with loads
 of boilerplate just to be sure.

I certainly won't complain if this change is reverted and replaced with a suitable alternative, even if it means I'll have to rewrite all the code that depends on it.
 It should be other way around, "dynamic alias" for those who do want a context
 pointer. "Don't pay for what you don't use" and principle of least surprise.

Fair enough, though we don't have a "dynamic" keyword we can abuse here... -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #33 from Kenji Hara <k.hara.pg gmail.com> 2014-03-03 08:16:49 PST
---
(In reply to comment #30)
 I noticed Kenji wrote this on the D Wiki:
 http://wiki.dlang.org/Brush_Up_Language_Features#Nested_Symbols
 
 The idea is to introduce "static alias" template parameters, which make it
 explicit if the alias parameter needs to transmit the symbol's context to the
 template (and thus nest the template within that context), or not. I think it
 is a sensible approach in lieu of automagically determining if that context is
 needed by the template (which Kenji claims is "mostly impossible").

In my thought, excepting lambdas, the context-inference feature is not implementable, because it will make the mangling names of the function local symbols unstable. (On lambdas, they have unique names in their declared scope, so we can stop encoding their 'this' pointer into the mangled name.) So if we really need to capture any symbols without their contexts, the idea "static alias parameter" would be the most better solution. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #34 from Vladimir Panteleev <thecybershadow gmail.com> 2014-03-03
18:18:37 EET ---
(In reply to comment #33)
 because it will make the mangling names of the function local symbols
unstable. 

Could you please explain this further? Isn't name mangling only done once all semantics are resolved, so it will happen once the compiler knows if the template needs the context or not? -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #35 from Kenji Hara <k.hara.pg gmail.com> 2014-03-03 08:26:28 PST
---
(In reply to comment #34)
 (In reply to comment #33)
 because it will make the mangling names of the function local symbols
unstable. 

Could you please explain this further? Isn't name mangling only done once all semantics are resolved, so it will happen once the compiler knows if the template needs the context or not?

Read the section "Do not mangle context-ness of parent lambdas" in http://wiki.dlang.org/Brush_Up_Language_Features -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #36 from Vladimir Panteleev <thecybershadow gmail.com> 2014-03-03
18:50:14 EET ---
(In reply to comment #35)
 Read the section "Do not mangle context-ness of parent lambdas" in
 http://wiki.dlang.org/Brush_Up_Language_Features

Thanks. Sorry I missed that. So do you think that if we solve the lambda mangling problem, it would be possible to infer static-ness of alias parameters, thus avoiding the need of "static alias"? -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #37 from Kenji Hara <k.hara.pg gmail.com> 2014-03-03 22:45:48 PST
---
(In reply to comment #36)
 (In reply to comment #35)
 So do you think that if we solve the lambda mangling problem, it would be
 possible to infer static-ness of alias parameters, thus avoiding the need of
 "static alias"?

My opinion is that would be impossible to infer static-ness in generic case. We can avoid the issue about lambdas by adding a hack for the mangling scheme, but the hack won't work for non-lambda functions. -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 03 2014
prev sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=11946



--- Comment #38 from Vladimir Panteleev <thecybershadow gmail.com> 2014-03-04
10:27:47 EET ---
Well, IMHO mangleof should just result in a forward reference error in such
cases. As far as I can see, static inference is much more important than
mangleof of nested functions inside those functions.

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