Given:
1. A template function
2. An embedded function
3. A function cast inside the embedded function
Given the above pre-requirements, the embedded function will (wrongly) see the cast function as pure, and be wrongly inferred:
//----
//Impure function. Doesn't throw; not marked as such.
void impureFun()
{}
void nothrowFun()() nothrow
{
void fun () nothrow
{
alias nothrow void function() StillImpure_t;
(cast(StillImpure_t)&impureFun)();
};
fun();
}
void main() pure
{
nothrowFun(); //PASSES! (shouldn't)
}
//----
Observations:
If the function is not templated, things are refused correctly. If there is no embedded function, things are refused correctly.
Interesting observation:
If you try to explicitly mark the function as pure, then you *will* be shot down:
//----
void nothrowFun()() nothrow
{
void fun () nothrow pure
{
alias nothrow void function() StillImpure_t;
(cast(StillImpure_t)&impureFun)(); //(here)
};
fun();
}
//----
Error: pure function 'main.nothrowFun!().nothrowFun.fun' cannot call impure function pointer 'cast(void function() nothrow)& impureFun'
Comment #1 by yebblies — 2013-11-20T08:04:12Z
When it gets to checking the call, it calls sc->func->setImpure(), but this is not good enough. This function is not marked as pure, and it is not templated, so of course there is no problem making it impure. It needs to see if any enclosing functions are getting purity inference run on them, like what is done in checkPurity().
I bet Kenji Hara knows how to fix this.
Comment #2 by robert.schadek — 2024-12-13T18:10:38Z