Bug 4841 – -inline wrecks certain nested structs causing error "*** is a nested function and cannot be accessed from ***"
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-09-08T04:08:00Z
Last change time
2013-10-10T04:59:50Z
Keywords
accepts-invalid, pull, rejects-valid
Assigned to
nobody
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2010-09-08T04:08:00Z
This is a D2 program:
import std.algorithm: map;
import std.array: array;
void main() {
int c;
array(map!((x){return c;})([1]));
}
It works if you compile it with dmd 2.048 with:
dmd test.d
But if use inlining:
dmd -inline test.d
It doesn't compile and dmd returns:
test.d(5): Error: function D main is a nested function and cannot be accessed from array
I think this is a compiler bug because inlining should not affect the compilability of a program.
Comment #1 by clugdbug — 2010-09-10T00:02:24Z
Original title: "An array()/map inlining problem"
Here's a simpler case that gives the same error message, only with -inline:
---
struct Struct4841(alias pred)
{
this(int k) { }
}
void bug4841a() {
Struct4841!( (t) { any_old_garbage;} )( 1 );
}
void bug4841b() {
bug4841a();
}
---
This is a problem with delegates and alias templates. It's not a regression.
There also seems to be an accepts-invalid bug in this. You can put any old garbage inside the alias, which seems odd. And you cannot declare a variable of type Struct4841!( (t) { any_old_garbage;} ) --- it's rejected at the parsing stage.
Comment #2 by hoganmeier — 2012-01-16T12:41:31Z
I think the following test case also belongs to this issue:
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
{
return simpleMindedFind!pred(haystack, needle);
}
R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, R2 needle)
{
bool haystackTooShort()
{
return true;
}
return haystack;
}
sizediff_t indexOf(Char1, Char2)(const(Char1)[] s, const(Char2)sub)
{
const(Char1)[] balance = find!({})(s, sub);
return -1;
}
string extStr;
void main()
{
extStr.indexOf("bla");
}
Comment #3 by dsimcha — 2012-01-24T13:41:43Z
*** Issue 4724 has been marked as a duplicate of this issue. ***
Comment #4 by clugdbug — 2012-01-27T00:35:53Z
Further reduced shows neither constructor nor delegate is required.
struct Struct4841(alias pred)
{
void unused_func();
}
void bug4841a() {
int w;
Struct4841!( w ) m;
}
void bug4841b() {
bug4841a();
}
----------------
The unused function is required only because it makes Struct4841 into a nested struct.
I think it is because moving a templated nested struct changes its type - the enclosing function is part of the mangled name, or something like that. It can't trivially be moved around.
Comment #5 by github-bugzilla — 2012-02-05T12:34:31Z
I just tested the fix that was merged recently. It only fixes some cases such as Don's and Tass3r's. Bearophile's case is still broken, as is the case I reported in Bug 4724.
Comment #7 by bugzilla — 2012-02-05T22:08:20Z
I believe this is the same as bug 5939.
Comment #8 by clugdbug — 2012-02-06T10:00:46Z
(In reply to comment #7)
> I believe this is the same as bug 5939.
I don't think bug 5939 involves -inline, but this one definitely does. Unless there are plans to make compiler changes are to fix bug 5939, the inliner shouldn't be making this transformation.
Comment #9 by bearophile_hugs — 2012-02-21T14:18:15Z
See also Issue 7559
Comment #10 by issues.dlang — 2013-02-16T15:54:35Z
Another example of this would be:
import std.string;
void main()
{
auto str = new char[](5);
assert(sformat(str, "%s", 42) == "42");
}
If you compile with -inline, it fails to compile with the latest master, giving
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2593): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2593): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2596): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2596): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2596): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2597): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2593): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2593): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2596): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2596): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2596): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2597): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2601): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2601): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2604): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2604): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2604): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2605): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, char[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2601): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2601): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)[]).put
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/string.d(2604): Error: function std.string.sformat!(char, int).sformat is a nested function and cannot be accessed from std.range.put!(Sink, const(char)[]).put
Comment #11 by bearophile_hugs — 2013-03-01T04:42:22Z
import std.array: array;
import std.algorithm: map;
void main() {
int[] foo;
auto r1 = map!(i => foo[0])([0]);
auto r2 = array(r1);
}
Gives (dmd 2.063 alpha):
temp.d(5): Error: function D main is a nested function and cannot be accessed
from std.array.array!(MapResult!(__lambda2, int[])).array
Comment #12 by verylonglogin.reg — 2013-06-10T05:40:53Z
*** Issue 9187 has been marked as a duplicate of this issue. ***
Comment #13 by verylonglogin.reg — 2013-06-10T05:43:09Z
*** Issue 9996 has been marked as a duplicate of this issue. ***
Comment #14 by verylonglogin.reg — 2013-06-10T05:46:21Z
*** Issue 7129 has been marked as a duplicate of this issue. ***
Comment #15 by verylonglogin.reg — 2013-06-10T05:47:35Z
Currently failing tests:
1. From Description
---
import std.algorithm: map;
import std.array: array;
void main()
{
int c;
map!(x => c)([1]).array();
}
---
2. From Comment 10
---
import std.string;
void main()
{
assert(new char[5].sformat("%s", 42) == "42");
}
---
3. From Issue 7129 Comment 4
---
auto fun()
{
int i;
struct Result
{
this(int u) {}
auto bar() { i = 42; }
}
return Result();
}
void main()
{
auto t = fun();
t.bar();
}
---
Comment #16 by verylonglogin.reg — 2013-06-10T05:54:37Z
As mixing -inline/non-inline modules may result in a wrong code because of Issue 9193 one can use "-inline" only for toy D projects.
Comment #17 by bearophile_hugs — 2013-06-10T15:13:45Z
(In reply to comment #16)
> As mixing -inline/non-inline modules may result in a wrong code because of
> Issue 9193 one can use "-inline" only for toy D projects.
If you believe that to be true, then I think you should raise the Importance of this issue to Major.