std.traits: hasFunctionAttributes#4287
Conversation
std/traits.d
Outdated
| See_Also: | ||
| $(LREF functionAttributes) | ||
| */ | ||
| template hasFunctionAttributes(func...) |
There was a problem hiding this comment.
(alias func, strAttributes...)
There was a problem hiding this comment.
I tried this too, but it doesn't work when called with typeof(func)
There was a problem hiding this comment.
Maybe add an overload for (Func, strAttributes...) then? That's best, otherwise at least rename func to args. (It's pretty annoying alias doesn't accept all types).
|
@wilzbach Issue 14835 rears its ugly head once again. |
std/traits.d
Outdated
|
|
||
| Params: | ||
| func = function to check | ||
| attributes = variadic number of function attributes |
There was a problem hiding this comment.
Need to state these are strings, not enums.
There was a problem hiding this comment.
I added "... as strings" - do you prefer a different wording?
f8db352 to
6e0aadd
Compare
std/traits.d
Outdated
| $(LREF functionAttributes) | ||
| */ | ||
| template hasFunctionAttributes(args...) | ||
| if (isCallable!(args[0]) && args.length > 0) |
There was a problem hiding this comment.
What about
if (isCallable!(args[0]) && args.length > 1 && allSatisfy!(isSomeString, args[1 .. $]))
There was a problem hiding this comment.
args are just strings, but with a small wrapper this works well. thanks a lot!
6e0aadd to
4169827
Compare
|
As this exposes a public symbol, it needs the andralex tag ;-) |
std/traits.d
Outdated
| See_Also: | ||
| $(LREF functionAttributes) | ||
| */ | ||
| /// ditto |
There was a problem hiding this comment.
oh that was just a relict from trying to have different overloads. Thanks for spotting that :)
4169827 to
556bfd1
Compare
|
In a similar manner, we could also provide a better API for |
std/traits.d
Outdated
| return res; | ||
| } | ||
|
|
||
| private enum bool isSomeStringInfer(alias T) = isSomeString!(typeof(T)); |
There was a problem hiding this comment.
Private templates should never show up in public template constraints.
556bfd1 to
dcb8ba4
Compare
std/traits.d
Outdated
| && allSatisfy!(isSomeString, typeof(args[1 .. $]))) | ||
| { | ||
| enum bool hasFunctionAttributes = { | ||
| import std.algorithm.searching: canFind; |
thanks @ntrel - that worked! |
dcb8ba4 to
1254ac5
Compare
|
I don't see any other problems. LGTM |
|
Breathtaking, thx.
|
|
I preapprove if (1) is addressed and (2) is at least not precluded by the current design |
1254ac5 to
2565349
Compare
ehm isn't In the huge tests there are also cases where attributes are inferred, e.g.
Yes it could be, but the DLang specification makes an explicit difference between UDA and FunctionAttributes. |
@9il could you please point out why you marked this as "needs work"? I don't see what is blocking on my side & it has already been preapproved. |
auto tester is failing |
2565349 to
87cadb4
Compare
|
@wilzbach, thanks for your PR! By analyzing the annotation information on this pull request, we identified @9rnsr, @sinfu and @WalterBright to be potential reviewers. @9rnsr: The PR was automatically assigned to you, please reassign it if you were identified mistakenly. |
Oh sorry - it looks like DMD got smarter and can now automatically infer |
| int safeF() @safe { return 0; } | ||
|
|
||
| int pureF() pure { return 0; } | ||
| } |
There was a problem hiding this comment.
CodeCov is failing because DMD counts all these functions as uncovered.
(there's a NG thread discussion about not counting unittest blocks, but tl:dr it won't happen)
|
I found this PR -> rebased + squashed it -> it's alive :)
For clarity here again my answers to Andrei's points:
As mentioned above I added: bool myFunc(T)(T b) { return !b; }
static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));However
Yes it could be, but the DLang specification makes an explicit difference between UDA and FunctionAttributes. |
87cadb4 to
936380b
Compare
936380b to
371089d
Compare
|
I had to rebase this PR because I added a changelog entry (btw there were tabs in the changelog file). Is anything else blocking this? |
std/traits.d
Outdated
| { | ||
| if (!funcAttribs.canFind(attribute)) | ||
| { | ||
| b = false; |
There was a problem hiding this comment.
Eh, that's overly complicated. Why not just return false from here?
std/traits.d
Outdated
| break; | ||
| } | ||
| } | ||
| return b; |
std/traits.d
Outdated
| { | ||
| real func(real x) pure nothrow @safe | ||
| { | ||
| return x; |
There was a problem hiding this comment.
In order to avoid false coverage reports, you may want to just declare the function without implementing it.
std/traits.d
Outdated
| { | ||
| struct S | ||
| { | ||
| int noF() { return 0; } |
There was a problem hiding this comment.
same here - all are not covered
| struct S2 | ||
| { | ||
| int pure_const() const pure { return 0; } | ||
| int pure_sharedconst() const shared pure { return 0; } |
There was a problem hiding this comment.
these, too - declare and don't define
c885f25 to
ac81a9c
Compare
| } | ||
| static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow")); | ||
| static assert(!hasFunctionAttributes!(myFunc!bool, "@trusted")); | ||
| static assert(!hasFunctionAttributes!(myFunc!bool, "shared")); |
There was a problem hiding this comment.
This change is just to make the public unittest a bit more interesting and not use @trusted twice.
When this PR initially was submitted a DMD bug prevented this (it wouldn't recognize this properly and warn with "unreachable code"). However, it seems that this has been fixed. Thanks! :)
Ok, I did this for the manually annotated functions. However, the other functions are supposed to check whether automatic attribute inference works correctly. Thus, I added a few dummy calls. |
std/traits.d
Outdated
| import std.algorithm.searching : canFind; | ||
| import std.range : only; | ||
| enum funcAttribs = only(__traits(getFunctionAttributes, args[0])); | ||
| foreach (attribute; args[1..$]) |
There was a problem hiding this comment.
spaces around .. (should be detected by the style checker...)
ac81a9c to
970dff3
Compare
Yeah this is on my backlog. Btw while I like standardization it's not uniformly considered so, see e.g. #4999 |
I added the whitespace, rebased and armed the new merge-bot. |
|
Auto-merge toggled on |
As discussed in #4274 the std.traits API for querying after function attributes is not very user-friendly.
wouldn't it be nicer, if we have a dedicated function for this?
Imho this makes it a lot more intuitive for the user to read and easier for us to maintain.
I heard about a DIP to cleanup and unify function attributes, so having a function allows us to stay flexible for the future ;-)
Btw the
traitgetFunctionAttributesalready returns a string tuple.Ping @ntrel