Thread overview
alias and UDAs
May 11, 2017
Andre Pany
May 11, 2017
Stanislav Blinov
May 11, 2017
Andre Pany
May 11, 2017
ag0aep6g
May 11, 2017
Hi,

in this example, both asserts fails. Is my assumption right, that UDA on alias have no effect? If yes, I would like to see a compiler warning.

But anyway, I do not understand why the second assertion fails. Are UDAs on arrays not allowed?

import std.traits: hasUDA;

enum Flattened;

struct Foo
{
	int bar;
}

@Flattened alias FooList = Foo[];

struct Baz
{
	FooList fooList1;
	@Flattened FooList[] fooList2;
}

void main()
{	
	Baz baz;
	static assert(hasUDA!(baz.fooList1, "Flattened")); // => false
	static assert(hasUDA!(baz.fooList2, "Flattened")); // => false
}

Kind regards
André
May 11, 2017
On Thursday, 11 May 2017 at 10:39:03 UTC, Andre Pany wrote:
> Hi,
>
> in this example, both asserts fails. Is my assumption right, that UDA on alias have no effect? If yes, I would like to see a compiler warning.
>
> But anyway, I do not understand why the second assertion fails. Are UDAs on arrays not allowed?
>
> import std.traits: hasUDA;
>
> enum Flattened;
>
> struct Foo
> {
> 	int bar;
> }
>
> @Flattened alias FooList = Foo[];
>
> struct Baz
> {
> 	FooList fooList1;
> 	@Flattened FooList[] fooList2;
> }
>
> void main()
> {	
> 	Baz baz;
> 	static assert(hasUDA!(baz.fooList1, "Flattened")); // => false
> 	static assert(hasUDA!(baz.fooList2, "Flattened")); // => false
> }
>
> Kind regards
> André

It should've been

alias FooList = @Flattened Foo[];

which will generate a compile-time error (UDAs not allowed for alias declarations).

And then:

static assert(hasUDA!(baz.fooList2, Flattened));

No quotes, since Flattened is an enum, not a string
May 11, 2017
On Thursday, 11 May 2017 at 10:57:22 UTC, Stanislav Blinov wrote:
> On Thursday, 11 May 2017 at 10:39:03 UTC, Andre Pany wrote:
>> [...]
>
> It should've been
>
> alias FooList = @Flattened Foo[];
>
> which will generate a compile-time error (UDAs not allowed for alias declarations).
>
> And then:
>
> static assert(hasUDA!(baz.fooList2, Flattened));
>
> No quotes, since Flattened is an enum, not a string

Thanks for the explanation. I think I will create a bug report for this statement:
@Flattened alias FooList = Foo[];

The UDA has no effect as far as I understand.

Kind regards
André
May 11, 2017
On 05/11/2017 12:39 PM, Andre Pany wrote:
> in this example, both asserts fails. Is my assumption right, that UDA on
> alias have no effect? If yes, I would like to see a compiler warning.
>
> But anyway, I do not understand why the second assertion fails. Are UDAs
> on arrays not allowed?
>
> import std.traits: hasUDA;
>
> enum Flattened;
>
> struct Foo
> {
>     int bar;
> }
>
> @Flattened alias FooList = Foo[];
>
> struct Baz
> {
>     FooList fooList1;
>     @Flattened FooList[] fooList2;
> }
>
> void main()
> {
>     Baz baz;
>     static assert(hasUDA!(baz.fooList1, "Flattened")); // => false
>     static assert(hasUDA!(baz.fooList2, "Flattened")); // => false
> }

1) You have to test against `Flattened`, not `"Flattened"`. A string is a valid UDA, but you're not using the string on the declarations.

When you fix this, the second assert passes.

2) `Baz.fooList1` doesn't have any attributes. Attributes apply to declarations. If it's valid, the attribute on `FooList` applies only to `FooList`. It doesn't transfer to `Baz.fooList1`.

If anything, you could assert that `hasUDA!(FooList, Flattened)` holds. Maybe you could, if it compiled.

3) Why does `hasUDA!(FooList, Flattened)` fail to compile?

The error message reads: "template instance hasUDA!(Foo[], Flattened) does not match template declaration hasUDA(alias symbol, alias attribute)".

We see that `FooList` has been replaced by `Foo[]`. It's clear then why the instantiation fails: `Foo[]` isn't a symbol.

Unfortunately, the spec is a bit muddy on this topic. On the one hand it says that "AliasDeclarations create a symbol", but it also says that "Aliased types are semantically identical to the types they are aliased to" [1].

In practice, the compiler doesn't seem to create a symbol. The alias identifier is simply replaced with the aliased thing, and you can't use the alias identifier as a symbol.

That means, you might be able to add an attribute to `FooList`, but you can't get back to it, because whenever you use `FooList` it's always replaced by `Foo[]`. And `Foo[]` doesn't have the attribute, of course.

I agree that it would probably make sense to disallow putting attributes on aliases. You can also mark aliases `const`, `static`, `pure`, etc. And they all have no effect.


[1] http://dlang.org/spec/declaration.html#AliasDeclaration