Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bogus "need 'this'" error with aggregate field passed in alias parameter #19254

Open
dlangBugzillaToGithub opened this issue May 25, 2017 · 6 comments
Labels
Arch:x86_64 Issues specific to x86_64 Feature:alias alias and alias this OS:Linux P3 Severity:normal

Comments

@dlangBugzillaToGithub
Copy link

ag0aep6g reported this on 2017-05-25T20:39:37Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=17435

CC List

Description

This should compile:

----
struct S { int field; }
bool ft(alias ignored)() { return true; }
alias f = ft!(S.field); /* accepted */
enum e = f(); /* Error: need 'this' for 'ft' of type 'bool()' */
----

Works when `ft` is marked as `static`, which should be a NOP:

----
struct S { int field; }
static bool ft(alias ignored)() { return true; }
alias f = ft!(S.field);
enum e = f(); /* no error */
----

Curiously, taking a function pointer and calling it also works, but only at run time and only when done in two steps:

----
struct S { int field; }
bool ft(alias ignored)() { return true; }
alias f = ft!(S.field);

void main()
{
    bool function() fptr = &f; /* accepted */
    assert(fptr()); /* accepted and passes */
    
    /+ These fail; should all work:
    assert(f()); /* Error: need 'this' for 'ft' of type 'pure nothrow @nogc @safe bool()' */
    assert((&f)()); /* ditto */
    static bool function() fptr2 = &f; /* Error: non-constant expression & ft */
    +/
}
----

Related thread in D.learn: http://forum.dlang.org/post/cgkwbfspmljbhrmqqmkc@forum.dlang.org
@dlangBugzillaToGithub
Copy link
Author

dlang-bugzilla (@CyberShadow) commented on 2017-05-26T03:56:41Z

(In reply to ag0aep6g from comment #0)
> This should compile:

AFAIU, detecting whether an alias parameter should be passed with context or not is a difficult problem because it changes the function's mangling and ABI signature.

> Works when `ft` is marked as `static`, which should be a NOP:

Here static applies to the template, not function. You can observe this by explicitly rewriting the function template into an eponymous template.

> Curiously, taking a function pointer and calling it also works

It looks like you found a different bug here. A function template that takes an alias parameter can be implicitly cast to a function pointer, even when it uses the alias parameter:

---
struct S { int field; }
int ft(alias a)() { return a; }
alias f = ft!(S.field);

void main()
{
    int function() fptr = &f; /* accepted */
    int i = fptr(); /* accepted and passes */
}
---

The above compiles and segfaults at runtime.

That should be filed as a separate accepts-invalid bug.

@dlangBugzillaToGithub
Copy link
Author

ag0aep6g commented on 2017-05-26T14:41:21Z

(In reply to Vladimir Panteleev from comment #1)
> Here static applies to the template, not function. You can observe this by
> explicitly rewriting the function template into an eponymous template.

In the code I showed, `static` applies to the template, yes. But applying it to the function also makes the code compile. And it should be a NOP either way. At least as far as I know. In the language, there's no such thing as a static module-level function/template that's distinct from a non-static module-level function/template, or is there?

[...]
> It looks like you found a different bug here. A function template that takes
> an alias parameter can be implicitly cast to a function pointer, even when
> it uses the alias parameter:
[...]
> That should be filed as a separate accepts-invalid bug.

Sure. Issue 17439.

@dlangBugzillaToGithub
Copy link
Author

dlang-bugzilla (@CyberShadow) commented on 2017-05-26T14:53:06Z

(In reply to ag0aep6g from comment #2)
> In the language, there's no such thing as a
> static module-level function/template that's distinct from a non-static
> module-level function/template, or is there?

If a template has an alias parameter, the template becomes nested inside the same context as the alias argument's context. E.g. if the alias argument is a local variable inside a function, the template becomes nested in that function, i.e. acts as if it was declared inside the function's body. "static" here has the same effect as on symbols inside function bodies or aggregate types: they force the compiler to not create a context pointer.

I've discussed this topic at this DConf a bit.

Some additional links:

https://github.com/D-Programming-Language/dmd/pull/2794
https://github.com/D-Programming-Language/dmd/pull/3884
https://github.com/D-Programming-Language/dmd/pull/3345
https://issues.dlang.org/show_bug.cgi?id=11946
https://issues.dlang.org/show_bug.cgi?id=7805
https://github.com/CyberShadow/ae/blob/master/utils/meta/caps.d

@dlangBugzillaToGithub
Copy link
Author

dlang-bugzilla (@CyberShadow) commented on 2017-05-26T14:54:11Z

(In reply to Vladimir Panteleev from comment #3)
> Some additional links:

https://wiki.dlang.org/Brush_Up_Language_Features#Nested_Symbols

@dlangBugzillaToGithub
Copy link
Author

ag0aep6g commented on 2017-05-26T15:08:42Z

(In reply to Vladimir Panteleev from comment #3)
> If a template has an alias parameter, the template becomes nested inside the
> same context as the alias argument's context. E.g. if the alias argument is
> a local variable inside a function, the template becomes nested in that
> function, i.e. acts as if it was declared inside the function's body.

Makes sense.

> "static" here has the same effect as on symbols inside function bodies or
> aggregate types: they force the compiler to not create a context pointer.

That sounds reasonable, but it needs a paragraph in the spec. Or is it in there and I just can't find it?

If that kind of `static` gets (or is) defined in the spec, this issue could be closed as invalid on the grounds that the "static" version is the correct way to write the code.

@dlangBugzillaToGithub
Copy link
Author

snarwin+bugzilla commented on 2023-02-24T15:32:35Z

*** Issue 23738 has been marked as a duplicate of this issue. ***

@thewilsonator thewilsonator added the Feature:alias alias and alias this label Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Arch:x86_64 Issues specific to x86_64 Feature:alias alias and alias this OS:Linux P3 Severity:normal
Projects
None yet
Development

No branches or pull requests

2 participants