D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 19668 - Using init instead of construction causes crash if type is parameterized on alias to function that accesses frame
Summary: Using init instead of construction causes crash if type is parameterized on a...
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 regression
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2019-02-11 18:15 UTC by Ali Ak
Modified: 2023-01-09 15:33 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Ali Ak 2019-02-11 18:15:45 UTC
The following code causes a crash at runtime:

struct S(alias fun) {
    auto call(Args...)(Args args) {
        return fun(args);
    }
    static auto construct() {
        auto a = typeof(this).init; // 1
        return a;
    }
}

void main() {
    int count = 0;
    auto func() {
        return count++; // 2
    }
    
    auto s = S!func.construct; // 3

    s.call(); // crashes
}

@1 if you change it to S!fun you get a compiler Error: cannot access frame pointer of onlineapp.main.S!(func).S.

@2 if you remove the "count" variable access from inside func, and just return some literal, then there's no crash (no frame pointer access)

@3 if you don't use construct and just call S!func() then s.call doesn't crash (frame pointer is accessed fine in this case??)

It seems like a regression from dmd version 2.071.2 since it gave a compiler error from 2.061 up till 2.071.2

Up to      2.060  : Failure with output: --- killed by signal 11
2.061   to 2.071.2: Failure with output:
-----
onlineapp.d(5): Error: function onlineapp.main.S!(func).S.call!().call cannot access frame of function D main
onlineapp.d(20): Error: template instance onlineapp.main.S!(func).S.call!() error instantiating
-----

Since      2.072.2: Failure with output: Error: program killed by signal 11
Comment 1 Ali Ak 2019-02-11 18:51:35 UTC
Actually you don't need a static func. This crashes:

struct S(alias fun) {
    auto call(Args...)(Args args) {
        return fun(args);
    }
}
auto construct(alias fun)() {
    auto a = S!fun.init; // 1
    return a;
}

void main() {
    int count = 0;
    auto func() { return count++; }

    auto s = construct!func;

    s.call(); // crashes
}

And if you change @1 to "auto a = S!fun();" then all is well.
Comment 2 Nick Treleaven 2023-01-09 15:33:55 UTC
main.func captures a runtime variable `count` whose address is not known at compile-time. S.init must be known at compile-time. So using S.init will cause a null context pointer for func instead of one pointing to main.count. You need to call S's constructor, not use S.init.