-
-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First draft of DIP to introduce a small syntax to improve UDAs #196
base: master
Are you sure you want to change the base?
Conversation
As I understand it, First of all, the name is misleading. I had trouble understanding what it intends to do, always wondering what attributes it returns. If it returns an array, i.e. possibly multiple values, choose a plural-sounding name. Secondly, it doesn't resolve to attributes at all. It resolves to attached declarations, so it should have The main problem this DIP will have is justifying the language change, since it's behavior can be replicated by a library and it's not even very difficult. Fast compilation speed is a good argument if it can be supported by data. Ideally, a well-made implementation of the proposal lets you directly compare speed. But even if you don't have one, might be convincing enough to merely compare iterating the a whole module's declarations recursively in search for an attribute versus not doing so. |
My current implementation actually adds a field to (currently The functionality could probably go into traits, but it would be much more complicated to implement (the logic to resolve a default initializer already exists within the compiler whereas writing a new trait might be a lot more complicated due to having to start the resolution from deeper within the bowels of the compiler) and make traits even more bloated that it already is. |
You probably should include an Alternatives section to go into the details why the following pattern has too much drawbacks. That pattern isn't obvious because one wouldn't expect to be able to use a declared symbol as a template argument to a UDA that is attached to that symbol. But, well, it can: template attribute(declarations...)
if (declarations.length > 0)
{
/* implementation */
}
// On module scope:
@attribute!func int func() { return 1; }
//In a struct:
struct S
{
@attribute!(x, y, z)
int x, y, z;
} If needed, a recursive iteration can verify that struct attribute(declarations...)
if (declarations.length > 0)
{
import std.meta : allSatisfy, ApplyRight;
import std.traits : hasUDA;
static assert (allSatisfy!(ApplyRight!(hasUDA, attribute), decls));
// Even without expensive recursive iteration, we can get some
// confidence that `attribute` is used properly.
/* further implementation */
} Notice that one has to make One drawback I see apart from the obvious DRY violation, is overloaded functions. Reiterating the example, if template attribute(decls...)
{
import std.traits : isCallable, Parameters;
static foreach (decl; decls)
static if (isCallable!decl)
static foreach (overload; __traits(getOverloads, __traits(parent, decl), __traits(identifier, decl)))
{
pragma(msg, __traits(identifier, decl), Parameters!overload);
}
}
// On module scope:
@attribute!func int func() { return 1; }
// Intentionally untagged overload:
int func(int x) { return x; } The inner workings of func()
func(int) i.e. it the tag catches both overloads while only the first one is intended to be caught. It can be coped with using another name for the offending overloads' declarations and aliasing them: @attribute!funcImpl
int funcImpl() { return 1; }
alias func = funcImpl; Then, the inner workings of the If an overloaded function is tagged once per overload, that makes no difference as far as "execution" of the inner workings of the template is concerned: it is instantiated with the same parameter(s), so its inner workings will be run only once; as the DIP states, that can be mitigated (in practically all circumstances) by giving it a parameter initialized defaulted to Improper annotation isn't always caught. Copy-paste errors can be likely: @attribute!func1 int func1() { return 0; }
@attribute!func1 int func2() { return 0; } Here, You may want to have a look at the code in action. Your part is arguing out why this isn't a good enough solution. Attack points might be that users of such a library really need to know about the overload case; misuse will not be caught by the compiler without an expensive recursive check. |
…DA_ATTACHED_TO_DECLS__
@Bolpat It's now |
@mdparker draft status is set. I think it's ready as it's ever going to be now. |
Interesting. |
This DIP introduces a new SpecialKeyword to act as a default initializer to make UDAs more powerful and expressive.