[Issue 15464] Template parameter-dependent attributes

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Tue Dec 22 16:23:45 PST 2015


https://issues.dlang.org/show_bug.cgi?id=15464

--- Comment #4 from Kenji Hara <k.hara.pg at gmail.com> ---
(In reply to Andrei Alexandrescu from comment #0)
> Per Timon Gehr's reply, implementation could achieved the feature by means of a lowering.

A function template declaration:

void foo(T)() @attr(T.field) {}

Is now lowered to:

@attr(T.field) template foo(T) { void foo() {} }

So, as Timon said, if we change the lowered form as follows, it will support
the enhancement naturally.

template foo(T) { void foo() @attr(T.field) {} }


However, I have some questions about the corner cases in the change.

Q1. The enhancement will move prefix and postfix UDAs into the template member.
But it would not change the label and block style UDAs  behavior. Today, a
template declaration can have UDAs. So the change would change the behavior of
currently working code.

----
enum attr;

void foo(T)(T t) @attr {}
// Now equivalent with:
// @attr { templete foo(T) { void foo(T t) {} } }

// After the change, it will become same with:
// templete foo(T) { @attr { void foo(T t) {} } }

alias fooInt = foo!int;

// Now:
pragma(msg, __traits(getAttributes, foo));      // tuple((attr))
pragma(msg, __traits(getAttributes, fooInt));   // tuple((attr))

// After the change:
//pragma(msg, __traits(getAttributes, foo));      // tuple()   --> breaking!
//pragma(msg, __traits(getAttributes, fooInt));   // tuple((attr))
----

----
enum attr;

@attr:  void foo1(T)(T t) {}            // label
@attr { void foo2(T)(T t) {} }          // block
@attr   void foo3(T)(T t) {}            // prefix
        void foo4(T)(T t) @attr {}      // postfix

// Now
pragma(msg, __traits(getAttributes, foo1));   // tuple(attr)
pragma(msg, __traits(getAttributes, foo2));   // tuple(attr)
pragma(msg, __traits(getAttributes, foo3));   // tuple(attr)
pragma(msg, __traits(getAttributes, foo4));   // tuple(attr)

// After
//pragma(msg, __traits(getAttributes, foo1));   // tuple(attr)
//pragma(msg, __traits(getAttributes, foo2));   // tuple(attr)
//pragma(msg, __traits(getAttributes, foo3));   // tuple()  --> breaking!
//pragma(msg, __traits(getAttributes, foo4));   // tuple()  --> breaking!
----

Q2. For the consistency, prefix UDAs should be handled specially for any other
templates. Right?

----
// All of them will be changed to workable?
@uda(T.field) class C(T) {}
@uda(T.field) struct S(T) {}
@uda(T.field) interface I(T) {}
@uda(T.field) union U(T) {}
@uda(T.field) template Foo(T) {}

// But those will be left as unworkable?
// block style
@uda(T.field) { class C(T) {} }
@uda(T.field) { struct S(T) {} }
@uda(T.field) { interface I(T) {} }
@uda(T.field) { union U(T) {} }
@uda(T.field) { template Foo(T) {} }
// label style
public { @uda(T.field): class C(T) {} }
public { @uda(T.field): struct S(T) {} }
public { @uda(T.field): interface I(T) {} }
public { @uda(T.field): union U(T) {} }
public { @uda(T.field): template Foo(T) {} }
----

--


More information about the Digitalmars-d-bugs mailing list