Bug 5941 – Using inner struct which references nested function in a no-attribute or auto-return member function causes "nested function cannot be accessed" error
Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-05-07T00:11:00Z
Last change time
2015-06-23T00:46:27Z
Keywords
accepts-invalid
Assigned to
nobody
Creator
kennytm
Comments
Comment #0 by kennytm — 2011-05-07T00:11:05Z
May or may not be the same as issue 5939. Happens at least since 2.042.
Test case:
-----------------------------------------------------------------
auto f() {
static int h(int x) pure nothrow @safe { return x*x*x-x*x; }
struct S {
int get() {
return h(8);
}
}
return S.init;
}
void main() {
typeof(f()) z;
assert(z.get == 448);
assert(z.get == 448);
}
-----------------------------------------------------------------
x.d(11): Error: function x.f is a nested function and cannot be accessed from main
-----------------------------------------------------------------
The bug will appear only when the 'get' function
- is an auto-return function (e.g. '@property auto get()')
- or has no attributes at all (e.g. 'int get()')
The bug is gone when you supply at least one attribute to 'get', e.g. '@safe int get()'.
I don't know if it is a reject-valid or accept-invalid.
Comment #1 by kennytm — 2011-05-07T00:27:39Z
A slight variant is when 'f' is a template function taking a delegate literal as input, it will generate an ICE:
---------------------------------
auto f(alias T)() {
static void h(){}
struct S {
void get() {
h();
}
}
return S();
}
void main() {
typeof(f!((){})()) z;
}
---------------------------------
Internal error: backend/cgcs.c 363
---------------------------------
Comment #2 by clugdbug — 2011-12-21T14:35:39Z
Reduced test case suggests it's related to typeof():
auto fx() {
struct S {
void get() {}
}
return S.init;
}
void main() {
//auto w = fx(); // OK
typeof(fx()) z; // fails!
}
Again, adding any attributes to get() removes the bug -- even though get() is never used.
Comment #3 by clugdbug — 2011-12-21T23:30:26Z
In bug 5939, Walter explicitly stated that the test case is comment 2 is not a bug. However, the fact that it compiles if the function 'get' is removed, or if attributes are added to get(), is surely a bug. Based on Walter's comment, it should never compile. So I'm marking as accepts-invalid.
Comment #4 by yebblies — 2012-01-18T19:04:52Z
In case anyone's wondering about why adding attributes changes anything, the compiler does a scan of all the top level members in a nested struct to determine if it contains any functions, and makes it a static struct otherwise. This is unfortunately done badly/too early and it finds AttributeDeclarations containing functions but doesn't investigate further.
Given that, it sounds like the requirement for having no attributes is really just a requirement for a non-static nested struct.
(In reply to Maksim Zholudev from comment #5)
> Is this behavior correct?
Currently it's correct. A nested struct is not constructible outside of the defined function, because it needs valid enclosing context.
I think the original attribute-dependent issue is fixed.