We need a way to make functions pure and/or nothrow based on the purity and/or nothrowability of the functions that they call

Tomasz Tomasz
Sun Nov 14 07:18:24 PST 2010


== Quote from Jonathan M Davis (jmdavisProg at gmx.com)'s article
> [snip]
> We really need to add a way to have a function marked as nothrow and/or pure
> based on whether the functions that it calls are nothrow and/or pure. Whether
> that should require listing the functions that need to be pure and/or nothrow or
> whether the compiler should be able to figure it out on its own, I don't know.
> But the current situation is ugly.
> The one problem I see is that if the compiler has to determine whether a given
> function can be pure and/or nothrow, it's going to potentially have to go
> arbitrarily deep into the call hierarchy to figure it out (which stinks of the
> halting problem), and it could require the source code of all of the functions
> that it has to check (or require that they've all already determined whether
> they can be pure and/or nothrow). I don't know whether that problem can be
> gotten around or what the best solution is if there is one, but the current
> situation is ugly.
> As it stands, functions are likely to either be impure and be allowed to throw
> simply because doing otherwise would require declaring the function 4 times.
> std.algorithm and std.range are prime targets for places where functions
> _should_ be pure and nothrow if they can, but whether they can or not depends on
> their template arguments. I really think that we need to find a solution to this
> problem and relatively soon.
> Does anyone have some good suggestions on how to solve this issue?

I recall a discussion on this:
http://www.digitalmars.com/d/archives/digitalmars/D/Generic_code_autoconst_autopure_autonothrow_116383.html

Although auto(pure) syntax is nice, I think the way to go is explicit qualifier propagation because of the
problems you mentioned.

There could be a way of attaching a compile-time predicate to a qualifier, either with a new keyword, or by
allowing mixing in qualifiers. It is quite generic, however, I predict it will impose boilerplate in the style of
"if (check if this function is pure/nothrow/...) then (compose a pure/nothrow/... string). Perhaps a simple
qualifier forwarding approach is more appealing:

// Forward a qualifier, if exists on R.empty
@property bool empty() __traits(fwdQual, R.empty, pure, nothrow)
{
    return innerRange.empty;
}

// Forward the intersection of all qualifiers from the functions involved.
auto reduce(fun, R)(R r) __traits(fwdQual, fun, R.empty, R.popFront, R.front);

The (accepted?) proposal of prettifying traits should help too:
__traits(fwdQual, ...) -> meta.fwdQual(...)

I'm a bit concerned how this cooks with the implementation of traits, e.g. I noticed that a TraitsArgument cannot
be a StorageClass...
http://www.d-programming-language.org/traits.html
Any idea how hard it'd be to implement?

--
Tomek


More information about the Digitalmars-d mailing list