www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Code behaves incorrectly if it is compiled in std.functional

reply "Meta" <jared771 gmail.com> writes:
This is so completely bizarre that I thought I was going crazy at 
first, but the same behaviour is exhibited whether I'm using my 
own copy of std.functional or a copy cloned straight from phobos 
master. The following code snippet exhibits different behaviour 
when it is put in a standalone file than when it is in 
std.functional:

unittest
{
     struct Foo2
     {
         int fun(int n) pure nothrow  safe  nogc
         {
             return n;
         }
     }

     import std.traits;
     pragma(msg, ParameterTypeTuple!(typeof(Foo2.fun)));
}

If I put the following snippet in test.d and run `dmd -unittest 
-main test.d`, it prints `(int)`.

HOWEVER, if I append the snippet to the end of std.functional and 
run
`dmd -unittest -main std\functional.d`, it prints `(auto int)` 
instead.

Can anyone else duplicate this bug at the very least? What in the 
world could be causing this?
Jun 04 2015
next sibling parent "krzaq" <dlangmailinglist krzaq.cc> writes:
I reproduced this bug on my arch linux with DMD 2.067 and git 
phobos (4cea8f1e4dd839568cc9e581bc15ee84f02e7135)
Jun 04 2015
prev sibling parent reply "ketmar" <ketmar ketmar.no-ip.org> writes:
here's dustmited source:

template unaryFun(alias fun, string parmName="a") {
   static if (is(typeof(fun)))
     auto unaryFun(ElementType) (auto ElementType __a) {
       mixin("alias " ~ parmName ~ " = __a ;");
       return mixin(fun);
     } else static if (needOpCallAlias) {
       unaryFun fun;
     }
}


unittest {
   cast(void)unaryFun!"a+1"(41); // silence warning
}


unittest {
   struct Foo2 {
     int fun (int n) pure nothrow  safe  nogc { return n; }
   }

   import std.traits;
   pragma(msg, ParameterTypeTuple!(typeof(Foo2.fun)));
}




note that after removing any attribute from `Foo2.foo` will emit 
correct `(int)`.
Jun 04 2015
parent reply "anonymous" <anonymous example.com> writes:
On Friday, 5 June 2015 at 02:38:39 UTC, ketmar wrote:
 here's dustmited source:
Further reduced: void unaryFun()(auto int a) pure nothrow safe nogc {} alias Identity(F) = F; void main() { unaryFun!()(41); static void fun(int n) pure nothrow safe nogc {} alias F = typeof(fun); pragma(msg, F); /* ...(int n) */ pragma(msg, Identity!F); /* ...(auto int) */ }
Jun 04 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 03:15:45 +0000, anonymous wrote:

 On Friday, 5 June 2015 at 02:38:39 UTC, ketmar wrote:
 here's dustmited source:
=20 Further reduced: =20 void unaryFun()(auto int a) pure nothrow safe nogc {} alias Identity(F) =3D F; void main() { unaryFun!()(41); static void fun(int n) pure nothrow safe nogc {} alias F =3D typeof(fun); pragma(msg, F); /* ...(int n) */ pragma(msg, Identity!F); /* ...(auto int) */ }
`auto int a`?! it shouldn't be accepted at all! O_O=
Jun 04 2015
parent reply "anonymous" <anonymous example.com> writes:
On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
Yeah, but it's the same with "auto ref".
Jun 04 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 03:56:05 +0000, anonymous wrote:

 On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
=20 Yeah, but it's the same with "auto ref".
`auto ref` has a well-defined meaning. yet `auto int` is nonsence. it's=20 definitely a compiler bug. ;-)=
Jun 04 2015
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 04:39:28 +0000, ketmar wrote:

 On Fri, 05 Jun 2015 03:56:05 +0000, anonymous wrote:
=20
 On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
=20 Yeah, but it's the same with "auto ref".
=20 `auto ref` has a well-defined meaning. yet `auto int` is nonsence. it's definitely a compiler bug. ;-)
i mean "there are at least two different things in that code, and they=20 triggers two different compiler bugs".=
Jun 04 2015
prev sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 5 June 2015 at 04:39:28 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 03:56:05 +0000, anonymous wrote:

 On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
Yeah, but it's the same with "auto ref".
`auto ref` has a well-defined meaning. yet `auto int` is nonsence. it's definitely a compiler bug. ;-)
I don't think so. `auto` is a valid storage class like `const`, `immutable` and `shared`.
Jun 05 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 09:44:09 +0000, Marc Sch=C3=BCtz wrote:

 On Friday, 5 June 2015 at 04:39:28 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 03:56:05 +0000, anonymous wrote:

 On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
=20 Yeah, but it's the same with "auto ref".
`auto ref` has a well-defined meaning. yet `auto int` is nonsence. it's definitely a compiler bug. ;-)
=20 I don't think so. `auto` is a valid storage class like `const`, `immutable` and `shared`.
`auto` is not a storage class, but a `type placeholder`. at least this is=20 what i've been told by W or A (sorry, i can't remember the link; i think=20 it was somewhere in NG... or in bugzilla...). there is one exception to=20 this rule, though: `auto ref`.=
Jun 05 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 5 June 2015 at 10:54:36 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 09:44:09 +0000, Marc Schütz wrote:

 On Friday, 5 June 2015 at 04:39:28 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 03:56:05 +0000, anonymous wrote:

 On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
Yeah, but it's the same with "auto ref".
`auto ref` has a well-defined meaning. yet `auto int` is nonsence. it's definitely a compiler bug. ;-)
I don't think so. `auto` is a valid storage class like `const`, `immutable` and `shared`.
`auto` is not a storage class, but a `type placeholder`. at least this is what i've been told by W or A (sorry, i can't remember the link; i think it was somewhere in NG... or in bugzilla...). there is one exception to this rule, though: `auto ref`.
My understanding is that `auto` is just C legacy, and originally had the same meaning as in C. But apparently the language has moved away from that over time.
Jun 05 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 11:53:29 +0000, Marc Sch=C3=BCtz wrote:

 My understanding is that `auto` is just C legacy, and originally had the
 same meaning as in C. But apparently the language has moved away from
 that over time.
i agree, i think it was a keyword used 'cause it was already used in C.=20 but it's meaning is completely redefined in D.=
Jun 05 2015
next sibling parent reply "Mafi" <mafi example.org> writes:
On Friday, 5 June 2015 at 12:33:35 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 11:53:29 +0000, Marc Schütz wrote:

 My understanding is that `auto` is just C legacy, and 
 originally had the
 same meaning as in C. But apparently the language has moved 
 away from
 that over time.
i agree, i think it was a keyword used 'cause it was already used in C. but it's meaning is completely redefined in D.
AFAIK auto is a stotage class (like in C). It is the no-op storage and therefore does not not change the stotage or type etc. But in a statement it definitely marks as a declaration because only those can contain storage classes. In D any declaration can omit the type so let it be inferred. That's why this also works: const x = 10; static y = 20; enum z = 30; Auto is only needed to unambigiously mark a statement as declaration when the lack of type would make it look like an ExpressionStatement. But still auto int x = 10; should work. It's just consistent.
Jun 05 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 15:17:50 +0000, Mafi wrote:

 auto int x  =3D 10;
=20
 should work. It's just consistent.
then `auto auto` should work too. it's a "declaration mark" + "storage=20 class".=
Jun 05 2015
parent reply "Mafi" <mafi example.org> writes:
On Friday, 5 June 2015 at 16:26:34 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 15:17:50 +0000, Mafi wrote:

 auto int x  = 10;
 
 should work. It's just consistent.
then `auto auto` should work too. it's a "declaration mark" + "storage class".
Well, no. Any storage class marks a declaration just by itself. You don't use it as a "declaration mark" or "storage class", just use a storage class which definitely declares something new. See also http://dlang.org/declaration.html A declaration is either <StorageClasses(opt) BasicType Declarators> or <AutoDeclaration>. An AutoDeclaration is the one with type inference. And it is marked by any storage class, not just auto (http://dlang.org/declaration.html#AutoDeclaration): <StorageClasses AutoDeclarationX>. Well admittently http://dlang.org/declaration.html#StorageClass does not feature 'auto' as a storage class but this must be an error because the description of AutoDeclaration uses 'auto' in the place of StorageClasses. It is just about grammar. A declaration needs a type, a storage class or both to not be mistaken for a statement with an assign expression. You use the 'auto' storage class so the statement cannot possibly be an expression when leaving out the type and not using any meaningful storage class.
Jun 05 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 16:42:25 +0000, Mafi wrote:

 On Friday, 5 June 2015 at 16:26:34 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 15:17:50 +0000, Mafi wrote:

 auto int x  =3D 10;
=20
 should work. It's just consistent.
then `auto auto` should work too. it's a "declaration mark" + "storage class".
=20 Well, no. Any storage class marks a declaration just by itself. You don't use it as a "declaration mark" or "storage class", just use a storage class which definitely declares something new. See also http://dlang.org/declaration.html =20 A declaration is either <StorageClasses(opt) BasicType Declarators> or <AutoDeclaration>. An AutoDeclaration is the one with type inference. And it is marked by any storage class, not just auto (http://dlang.org/declaration.html#AutoDeclaration): <StorageClasses AutoDeclarationX>. Well admittently http://dlang.org/declaration.html#StorageClass does not feature 'auto' as a storage class but this must be an error because the description of AutoDeclaration uses 'auto' in the place of StorageClasses. =20 It is just about grammar. A declaration needs a type, a storage class or both to not be mistaken for a statement with an assign expression. You use the 'auto' storage class so the statement cannot possibly be an expression when leaving out the type and not using any meaningful storage class.
`const int` works, so i can't see why `auto auto` is failing.=
Jun 05 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 5 June 2015 at 17:50:55 UTC, ketmar wrote:
 `const int` works, so i can't see why `auto auto` is failing.
Wrong analogy. Try `const const`, and it will fail with the same error as `auto auto`: "redundant attribute".
Jun 05 2015
next sibling parent reply "krzaq" <dlangmailinglist krzaq.cc> writes:
On Friday, 5 June 2015 at 18:35:51 UTC, Marc Schütz wrote:
 On Friday, 5 June 2015 at 17:50:55 UTC, ketmar wrote:
 `const int` works, so i can't see why `auto auto` is failing.
Wrong analogy. Try `const const`, and it will fail with the same error as `auto auto`: "redundant attribute".
const auto ans = 42; compiles fine for me, so auto clearly can be used as a type.
Jun 05 2015
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 5 June 2015 at 19:45:18 UTC, krzaq wrote:
 const auto ans = 42;

 compiles fine for me, so auto clearly can be used as a type.
So does "auto immutable" or "auto pure" or "pure a". They're all storage classes and any storage class can kick off a declaration: nogc a = 10; // compiles! dmd is just not really consistent on when it issues errors on redundant, conflicting, or useless storage classes.
Jun 05 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 18:35:49 +0000, Marc Sch=C3=BCtz wrote:

 On Friday, 5 June 2015 at 17:50:55 UTC, ketmar wrote:
 `const int` works, so i can't see why `auto auto` is failing.
=20 Wrong analogy. Try `const const`, and it will fail with the same error as `auto auto`: "redundant attribute".
nope. in `auto auto` one `auto` is storage type, and another `auto` is a=20 type placeholder. see, `const auto` works, so `auto` can play role of a=20 type placeholder. so `auto auto` should be accepted, if you insists that=20 it can play a role of storage class.=
Jun 05 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 6 June 2015 at 06:05:46 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 18:35:49 +0000, Marc Schütz wrote:

 On Friday, 5 June 2015 at 17:50:55 UTC, ketmar wrote:
 `const int` works, so i can't see why `auto auto` is failing.
Wrong analogy. Try `const const`, and it will fail with the same error as `auto auto`: "redundant attribute".
nope. in `auto auto` one `auto` is storage type, and another `auto` is a type placeholder.
No, as others have explained.
 see, `const auto` works, so `auto` can play role of a
 type placeholder. so `auto auto` should be accepted, if you 
 insists that
 it can play a role of storage class.
`const auto` isn't contradictory. It's simply two storage classes, one of which is the default. Besides, there's not much sense in doing experiments with DMD to find out "the true nature" of auto. DMD is clearly inconsistent, as seen from your observation about foreach().
Jun 06 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 06 Jun 2015 12:36:09 +0000, Marc Sch=C3=BCtz wrote:

 `const auto` isn't contradictory. It's simply two storage classes, one
 of which is the default.
means here? what is that "default storage class" then, and why it doesn't=20 apply here?
 Besides, there's not much sense in doing experiments with DMD to find
 out "the true nature" of auto. DMD is clearly inconsistent,
 as seen from your observation about foreach().
ok, but what i should consult then? specs? but specs clearly allows `const=20 immutable shared auto scope inout __gshared int i =3D 42;`. yes, specs=20 clearly says that `auto` is a storage class. specs also allowing `auto=20 auto auto auto auto int i =3D 42;`. what should i check to see what is *really* allowed, why two storage=20 classes allowed with one combination and not allowed with another?=
Jun 06 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 6 June 2015 at 15:12:38 UTC, ketmar wrote:
 what should i check to see what is *really* allowed, why two 
 storage
 classes allowed with one combination and not allowed with 
 another?
Well, you can look at the compiler's source... But I'm sure this is not the answer you wanted ;-)
Jun 06 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 06 Jun 2015 18:49:00 +0000, Marc Sch=C3=BCtz wrote:

 On Saturday, 6 June 2015 at 15:12:38 UTC, ketmar wrote:
 what should i check to see what is *really* allowed, why two storage
 classes allowed with one combination and not allowed with another?
=20 Well, you can look at the compiler's source... =20 But I'm sure this is not the answer you wanted ;-)
sure. now i'm completely lost. i shouldn't use DMD to find out things,=20 yet i have to use DMD to find out things. ok, let's be serious. what i'm trying to say is that there should be not=20 only grammar with comments inside it here and there, but the document=20 that explains "what is what", what's compatible with what and so on. the=20 "specs" in the meaning that one can point to it and say: "this is how it=20 is supposed to be. now fix your code". or "now let's fix the compiler." the specs where no "undefined behavior" words are used, and no "it's left=20 to compiler implementer to decide". (but "look at DMDFE source" is=20 allowed ;-).=
Jun 06 2015
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Sunday, 7 June 2015 at 05:02:47 UTC, ketmar wrote:
 On Sat, 06 Jun 2015 18:49:00 +0000, Marc Schütz wrote:

 On Saturday, 6 June 2015 at 15:12:38 UTC, ketmar wrote:
 what should i check to see what is *really* allowed, why two 
 storage
 classes allowed with one combination and not allowed with 
 another?
Well, you can look at the compiler's source... But I'm sure this is not the answer you wanted ;-)
sure. now i'm completely lost. i shouldn't use DMD to find out things, yet i have to use DMD to find out things.
Im my defense, you asked what _is_ really allowed, not what _should_ be allowed...
 ok, let's be serious. what i'm trying to say is that there 
 should be not
 only grammar with comments inside it here and there, but the 
 document
 that explains "what is what", what's compatible with what and 
 so on. the
 "specs" in the meaning that one can point to it and say: "this 
 is how it
 is supposed to be. now fix your code". or "now let's fix the 
 compiler."

 the specs where no "undefined behavior" words are used, and no 
 "it's left
 to compiler implementer to decide". (but "look at DMDFE source" 
 is
 allowed ;-).
Brian Schott did a lot of work finding inconsistencies and ambiguities in the grammar, and I believe his DConf talk was partially about it.
Jun 07 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/05/2015 02:33 PM, ketmar wrote:
 i agree, i think it was a keyword used 'cause it was already used in C.
 but it's meaning is completely redefined in D.
The meaning is exactly the same. It's the default storage class.
Jun 05 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 06 Jun 2015 00:28:51 +0200, Timon Gehr wrote:

 On 06/05/2015 02:33 PM, ketmar wrote:
 i agree, i think it was a keyword used 'cause it was already used in C.
 but it's meaning is completely redefined in D.
=20 The meaning is exactly the same. It's the default storage class.
then i'll fill a bug about `auto auto` and will reopen it until it's=20 fixed.=
Jun 05 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/06/2015 08:06 AM, ketmar wrote:
 On Sat, 06 Jun 2015 00:28:51 +0200, Timon Gehr wrote:

 On 06/05/2015 02:33 PM, ketmar wrote:
 i agree, i think it was a keyword used 'cause it was already used in C.
 but it's meaning is completely redefined in D.
The meaning is exactly the same. It's the default storage class.
then i'll fill a bug about `auto auto` and will reopen it until it's fixed.
This is valid C: int main(){ const auto int x=2; return 0; } This is not valid C: int main(){ auto auto int x=2; return 0; } What is the problem?
Jun 07 2015
next sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 06/07/15 18:49, Timon Gehr via Digitalmars-d wrote:
 This is valid C:
 
 int main(){
    const auto int x=2;
    return 0;
 }
 
 This is not valid C:
 
 int main(){
    auto auto int x=2;
    return 0;
 }
 
 What is the problem?
The problem is the apparently common misunderstanding that 'auto' is a thing in D. It is not; it's just a grammar hack. The (very simplified) rule for declarations in C/C++/D is <storage_class> <type> lhs = rhs In C, you can omit the /storage_class/ and it then defaults to 'auto'. Obviously, the 'auto' keyword is redundant and nobody actually uses it. In D, you can omit the /type/ and it's then propagated from the /rhs/ expression. The compiler already knows the type that 'rhs' evaluates to. But you can not omit both the /type/ and the /storage_class/ as 'lhs=rhs' would be indistinguishable from an assignment. In some contexts for the compiler, but, more importantly, for the human. Hence 'auto lhs = rhs'. [The exceptions are either because of backward C compatibility (function args) or no need for such compatibility (foreach)] Still, 'auto' isn't as bad as 'static', which D redefined to mean something different than in C/C++, and did this so subtly that the C version will still compile, giving unexpected results without even a warning. artur
Jun 07 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 07 Jun 2015 18:49:24 +0200, Timon Gehr wrote:

 On 06/06/2015 08:06 AM, ketmar wrote:
 On Sat, 06 Jun 2015 00:28:51 +0200, Timon Gehr wrote:

 On 06/05/2015 02:33 PM, ketmar wrote:
 i agree, i think it was a keyword used 'cause it was already used in
 C.
 but it's meaning is completely redefined in D.
The meaning is exactly the same. It's the default storage class.
then i'll fill a bug about `auto auto` and will reopen it until it's fixed.
This is valid C: =20 int main(){ const auto int x=3D2; return 0; } =20 This is not valid C: =20 int main(){ auto auto int x=3D2; return 0; } =20 What is the problem?
sorry, i didn't realized that this is NG for C language.=
Jun 08 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 09:28 AM, ketmar wrote:
 On Sun, 07 Jun 2015 18:49:24 +0200, Timon Gehr wrote:

 On 06/06/2015 08:06 AM, ketmar wrote:
 On Sat, 06 Jun 2015 00:28:51 +0200, Timon Gehr wrote:

 On 06/05/2015 02:33 PM, ketmar wrote:
 i agree, i think it was a keyword used 'cause it was already used in
 C.
 but it's meaning is completely redefined in D.
The meaning is exactly the same. It's the default storage class.
then i'll fill a bug about `auto auto` and will reopen it until it's fixed.
This is valid C: int main(){ const auto int x=2; return 0; } This is not valid C: int main(){ auto auto int x=2; return 0; } What is the problem?
sorry, i didn't realized that this is NG for C language.
This is valid D, but it is pointless: int main(){ const auto x=2; return 0; } int main(){ auto const x=2; return 0; } This is valid D: int main(){ const x=2; return 0; } This is not valid D: int main(){ auto auto x=2; return 0; } int main(){ int const x=2; return 0; } This could be valid D, but isn't (assuming DMD behaves correctly here, I don't think this is documented), because it is pointless, and the compiler is now arbitrarily trying to be helpful: int main(){ const auto int x=2; return 0; } The error message: tt.d(2): Error: variable tt.main.x storage class 'auto' has no effect if type is not inferred, did you mean 'scope'? Note "storage class". Ditto: int main(){ auto const int x=2; return 0; }
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 14:28:06 +0200, Timon Gehr wrote:

 On 06/08/2015 09:28 AM, ketmar wrote:
 On Sun, 07 Jun 2015 18:49:24 +0200, Timon Gehr wrote:

 On 06/06/2015 08:06 AM, ketmar wrote:
 On Sat, 06 Jun 2015 00:28:51 +0200, Timon Gehr wrote:

 On 06/05/2015 02:33 PM, ketmar wrote:
 i agree, i think it was a keyword used 'cause it was already used
 in C.
 but it's meaning is completely redefined in D.
The meaning is exactly the same. It's the default storage class.
then i'll fill a bug about `auto auto` and will reopen it until it's fixed.
This is valid C: int main(){ const auto int x=3D2; return 0; } This is not valid C: int main(){ auto auto int x=3D2; return 0; } What is the problem?
sorry, i didn't realized that this is NG for C language.
This is valid D, but it is pointless: =20 int main(){ const auto x=3D2; return 0; } =20 int main(){ auto const x=3D2; return 0; } =20 =20 This is valid D: =20 int main(){ const x=3D2; return 0; } =20 This is not valid D: =20 int main(){ auto auto x=3D2; return 0; } =20 int main(){ int const x=3D2; return 0; } =20 =20 This could be valid D, but isn't (assuming DMD behaves correctly here, I don't think this is documented), because it is pointless, and the compiler is now arbitrarily trying to be helpful: =20 int main(){ const auto int x=3D2; return 0; } =20 The error message: tt.d(2): Error: variable tt.main.x storage class 'auto' has no effect if type is not inferred, did you mean 'scope'? =20 Note "storage class". =20 =20 Ditto: =20 int main(){ auto const int x=3D2; return 0; }
so specifying two storage classes are sometimes valid and sometimes=20 invalid. a perfect consistency!=
Jun 08 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 03:11 PM, ketmar wrote:
 so specifying two storage classes are sometimes valid and sometimes
 invalid. a perfect consistency!
The compiler sometimes compiles the program and sometimes terminates with an error message instead. That's life.
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 15:47:33 +0200, Timon Gehr wrote:

 On 06/08/2015 03:11 PM, ketmar wrote:
 so specifying two storage classes are sometimes valid and sometimes
 invalid. a perfect consistency!
=20 The compiler sometimes compiles the program and sometimes terminates with an error message instead. That's life.
yeah. "you can't logically deduce it, you have to remember it!" that's=20 the way to success.=
Jun 08 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 8 June 2015 at 15:09:21 UTC, ketmar wrote:
 On Mon, 08 Jun 2015 15:47:33 +0200, Timon Gehr wrote:

 On 06/08/2015 03:11 PM, ketmar wrote:
 so specifying two storage classes are sometimes valid and 
 sometimes
 invalid. a perfect consistency!
The compiler sometimes compiles the program and sometimes terminates with an error message instead. That's life.
yeah. "you can't logically deduce it, you have to remember it!" that's the way to success.
That's only if you're talking about the details of the grammar. But for everyday use (even advanced use!) of the language, these are not important. You _don't_ "have to remember it", because you simply don't need it. Noone forces you to write `auto const`, and it gives you no advantages over just `const`. But if you really feel an urge to use strange combinations of storage classes and type modifiers, just do it, and the compiler will tell you whether it's good or not. No need to remember anything. OTOH, if you encounter such a combination in someone else's code, it's still pretty obvious what it means. No problem there either.
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 15:30:24 +0000, Marc Sch=C3=BCtz wrote:

 On Monday, 8 June 2015 at 15:09:21 UTC, ketmar wrote:
 On Mon, 08 Jun 2015 15:47:33 +0200, Timon Gehr wrote:

 On 06/08/2015 03:11 PM, ketmar wrote:
 so specifying two storage classes are sometimes valid and sometimes
 invalid. a perfect consistency!
=20 The compiler sometimes compiles the program and sometimes terminates with an error message instead. That's life.
yeah. "you can't logically deduce it, you have to remember it!" that's the way to success.
=20 That's only if you're talking about the details of the grammar. But for everyday use (even advanced use!) of the language, these are not important. You _don't_ "have to remember it", because you simply don't need it. Noone forces you to write `auto const`, and it gives you no advantages over just `const`. But if you really feel an urge to use strange combinations of storage classes and type modifiers, just do it, and the compiler will tell you whether it's good or not. No need to remember anything. OTOH, if you encounter such a combination in someone else's code, it's still pretty obvious what it means. No problem there either.
i'll keep citing `foreach (auto i)` thingy. it can't be deduced by using=20 the knowledge of other language constructs, it can be only remembered.=20 the less things one can't deduce language has, the better.=
Jun 09 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/09/2015 11:11 AM, ketmar wrote:
 On Mon, 08 Jun 2015 15:30:24 +0000, Marc Schütz wrote:

 On Monday, 8 June 2015 at 15:09:21 UTC, ketmar wrote:
 On Mon, 08 Jun 2015 15:47:33 +0200, Timon Gehr wrote:

 On 06/08/2015 03:11 PM, ketmar wrote:
 so specifying two storage classes are sometimes valid and sometimes
 invalid. a perfect consistency!
The compiler sometimes compiles the program and sometimes terminates with an error message instead. That's life.
yeah. "you can't logically deduce it, you have to remember it!" that's the way to success.
That's only if you're talking about the details of the grammar. But for everyday use (even advanced use!) of the language, these are not important. You _don't_ "have to remember it", because you simply don't need it. Noone forces you to write `auto const`, and it gives you no advantages over just `const`. But if you really feel an urge to use strange combinations of storage classes and type modifiers, just do it, and the compiler will tell you whether it's good or not. No need to remember anything. OTOH, if you encounter such a combination in someone else's code, it's still pretty obvious what it means. No problem there either.
i'll keep citing `foreach (auto i)` thingy. it can't be deduced by using the knowledge of other language constructs, it can be only remembered. the less things one can't deduce language has, the better.
http://en.wikipedia.org/wiki/Lambda_calculus
Jun 09 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Tue, 09 Jun 2015 13:09:22 +0200, Timon Gehr wrote:

 i'll keep citing `foreach (auto i)` thingy. it can't be deduced by
 using the knowledge of other language constructs, it can be only
 remembered. the less things one can't deduce language has, the better.
http://en.wikipedia.org/wiki/Lambda_calculus
what i should see there? will it explain to me why `while (i)` doesn't=20 introduce new variable? ah, there is no ";" after it! ok, well, it's very=20 human-friendly.=
Jun 09 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 09:44:09 +0000, Marc Sch=C3=BCtz wrote:

 On Friday, 5 June 2015 at 04:39:28 UTC, ketmar wrote:
 On Fri, 05 Jun 2015 03:56:05 +0000, anonymous wrote:

 On Friday, 5 June 2015 at 03:45:18 UTC, ketmar wrote:
 `auto int a`?! it shouldn't be accepted at all!
=20 Yeah, but it's the same with "auto ref".
`auto ref` has a well-defined meaning. yet `auto int` is nonsence. it's definitely a compiler bug. ;-)
=20 I don't think so. `auto` is a valid storage class like `const`, `immutable` and `shared`.
p.s. if "auto" is a storage class, the following code should be accepted=20 (while it isn't): int foo () { return 42; } void main () { auto auto i =3D foo(); } as it's logically "an auto-typed var with "auto" storage class".=
Jun 05 2015
parent reply "Mafi" <mafi example.org> writes:
On Friday, 5 June 2015 at 10:56:36 UTC, ketmar wrote:

 p.s. if "auto" is a storage class, the following code should be 
 accepted
 (while it isn't):

   int foo () { return 42; }

   void main () {
     auto auto i = foo();
   }

 as it's logically "an auto-typed var with "auto" storage class".
Here lies your mistake. There is no such thing as "auto"-typed (leaving aside function signatures, which might be special-cased and are different beast altogether). Auto is not a type. auto* or auto[] aren't valied either. Auto is just a storage class, no more, no less. You use it if the grammar needs a storage class but you don't want to give special attributes to the variable (like const or static). To make a declaration with inferred type you need at least one storage class. To make it work with "normal" variables you use "auto".
Jun 05 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 20:36:19 +0000, Mafi wrote:

 On Friday, 5 June 2015 at 10:56:36 UTC, ketmar wrote:
=20
=20
 p.s. if "auto" is a storage class, the following code should be
 accepted (while it isn't):

   int foo () { return 42; }

   void main () {
     auto auto i =3D foo();
   }

 as it's logically "an auto-typed var with "auto" storage class".
=20 Here lies your mistake. There is no such thing as "auto"-typed (leaving aside function signatures, which might be special-cased and are different beast altogether). Auto is not a type. auto* or auto[] aren't valied either. Auto is just a storage class, no more, no less. You use it if the grammar needs a storage class but you don't want to give special attributes to the variable (like const or static). To make a declaration with inferred type you need at least one storage class. To make it work with "normal" variables you use "auto".
so either `const auto` should not be accepted, or `auto auto` should be=20 accepted. if `auto` plays a role of "default storage class", the `const=20 auto` should trigger the error about redundant storage specifier. if=20 `auto` can play a role of type placeholder, then `auto auto` should be=20 accepted, as it's clearly the "default storage class with type=20 placeholder". current situation is inconsistent and that inconsistency must be fixed.=
Jun 05 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/06/2015 08:10 AM, ketmar wrote:
 if `auto` can play a role of type placeholder
There is no such thing as a type placeholder.
Jun 07 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 07 Jun 2015 18:50:07 +0200, Timon Gehr wrote:

 On 06/06/2015 08:10 AM, ketmar wrote:
 if `auto` can play a role of type placeholder
=20 There is no such thing as a type placeholder.
there is: `immutable auto` -- ok `immutable const` -- not ok ergo, `auto` is not a storage class, but type placeholder.=
Jun 08 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 8 June 2015 at 07:30:06 UTC, ketmar wrote:
 On Sun, 07 Jun 2015 18:50:07 +0200, Timon Gehr wrote:

 On 06/06/2015 08:10 AM, ketmar wrote:
 if `auto` can play a role of type placeholder
There is no such thing as a type placeholder.
there is: `immutable auto` -- ok
Allocate a variable on the stack, and make it immutable => OK
 `immutable const` -- not ok
Make the variable immutable, and make it const => nonsense
 ergo, `auto` is not a storage class, but type placeholder.
No.
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 09:27:34 +0000, Marc Sch=C3=BCtz wrote:

 ergo, `auto` is not a storage class, but type placeholder.
=20 No.
and it's not a storage class too. `foreach (auto i; 0..42)` doesn't work,=20 white `foreach (immutable i; 0..42)` works ok.=
Jun 08 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 8 June 2015 at 09:33:56 UTC, ketmar wrote:
 On Mon, 08 Jun 2015 09:27:34 +0000, Marc Schütz wrote:

 ergo, `auto` is not a storage class, but type placeholder.
No.
and it's not a storage class too. `foreach (auto i; 0..42)` doesn't work, white `foreach (immutable i; 0..42)` works ok.
That's a bug ;-)
Jun 08 2015
parent reply "Temtaime" <temtaime gmail.com> writes:
Auto was a storage class in C, but in D it's a type placeholder.
Jun 08 2015
parent Daniel =?UTF-8?B?S296w6Fr?= via Digitalmars-d writes:
On Mon, 08 Jun 2015 10:21:25 +0000
Temtaime via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Auto was a storage class in C, but in D it's a type placeholder.
It is still a storage class in D too. http://dlang.org/grammar.html#StorageClasses
Jun 08 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 11:33 AM, ketmar wrote:
 On Mon, 08 Jun 2015 09:27:34 +0000, Marc Schütz wrote:

 ergo, `auto` is not a storage class, but type placeholder.
No.
and it's not a storage class too. `foreach (auto i; 0..42)` doesn't work, white `foreach (immutable i; 0..42)` works ok.
foreach(static i;0..42) doesn't work either, and 'static' is a storage class. 'immutable' is a type constructor besides being a storage class. The attributes allowed in `foreach' are those that are considered to make sense, and they are specified in the grammar: http://dlang.org/statement.html#ForeachTypeAttributes Furthermore, both of those declarations are valid: static i = 2; immutable j = 3; What is important is that the type was left out, not that it was replaced by 'auto'.
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 13:47:09 +0200, Timon Gehr wrote:

 On 06/08/2015 11:33 AM, ketmar wrote:
 On Mon, 08 Jun 2015 09:27:34 +0000, Marc Sch=C3=83=C2=BCtz wrote:

 ergo, `auto` is not a storage class, but type placeholder.
No.
and it's not a storage class too. `foreach (auto i; 0..42)` doesn't work, white `foreach (immutable i; 0..42)` works ok.
foreach(static i;0..42) doesn't work either, and 'static' is a storage class. =20 'immutable' is a type constructor besides being a storage class. =20 The attributes allowed in `foreach' are those that are considered to make sense, and they are specified in the grammar: http://dlang.org/statement.html#ForeachTypeAttributes =20 Furthermore, both of those declarations are valid: =20 static i =3D 2; immutable j =3D 3; =20 What is important is that the type was left out, not that it was replaced by 'auto'.
i tried to explain to some people why `foreach (i; 0..42)` doesn't reuse=20 previously declared `i` and failed. it doesn't look like variable=20 declaration at all, and there is no way to make it look like variable=20 declaration without specifying a type or `const/immutable/etc.`. so=20 "default storage class" doesn't make sense in `foreach`? now i'm REALLY=20 puzzled about what "default storage class" means at all. seems that it's=20 "random storage class that means anything /dev/urandom returns".=
Jun 08 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 03:17 PM, ketmar wrote:
 ...

 i tried to explain to some people why `foreach (i; 0..42)` doesn't reuse
 previously declared `i` and failed.
The reason is that it wouldn't make any sense.
 it doesn't look like variable declaration at all,
It looks like a variable declaration because it is a variable declaration. It declares the foreach loop variable.
 and there is no way to make it look like variable
 declaration without specifying a type or `const/immutable/etc.`. so
 "default storage class" doesn't make sense in `foreach`?
I didn't make the decision, but it is redundant.
Jun 08 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 15:54:23 +0200, Timon Gehr wrote:

 On 06/08/2015 03:17 PM, ketmar wrote:
 ...

 i tried to explain to some people why `foreach (i; 0..42)` doesn't
 reuse previously declared `i` and failed.
=20 The reason is that it wouldn't make any sense. =20
 it doesn't look like variable declaration at all,
=20 It looks like a variable declaration because it is a variable declaration. It declares the foreach loop variable.
no. it looks like "let's use our previously declared `i` as a counter".=20 there is no single sign of variable declaration here. like `while (i)`=20 will not declare a new variable, or `foo(i, n)`, or `if (i)`.
 and there is no way to make it look like variable declaration without
 specifying a type or `const/immutable/etc.`. so "default storage class"
 doesn't make sense in `foreach`?
=20 I didn't make the decision, but it is redundant.
only if D doesn't meant to be a language which is easily readable by=20 humans. declaring new variable by simply specifying it's name isn't used=20 anywhere else. oh, well, another exception to remember. another good step=20 to success. the more exceptions, the more steps...=
Jun 08 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 09:30 AM, ketmar wrote:
 On Sun, 07 Jun 2015 18:50:07 +0200, Timon Gehr wrote:

 On 06/06/2015 08:10 AM, ketmar wrote:
 if `auto` can play a role of type placeholder
There is no such thing as a type placeholder.
there is: `immutable auto` -- ok `immutable const` -- not ok ergo, `auto` is not a storage class, but type placeholder.
This analogy does not work. 'immutable' and 'automatic storage' do not conflict. 'immutable' and 'const' do conflict. 'immutable auto' is exactly the same as 'auto immutable'. There is no 'int immutable'.
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 13:38:08 +0200, Timon Gehr wrote:

 On 06/08/2015 09:30 AM, ketmar wrote:
 On Sun, 07 Jun 2015 18:50:07 +0200, Timon Gehr wrote:

 On 06/06/2015 08:10 AM, ketmar wrote:
 if `auto` can play a role of type placeholder
There is no such thing as a type placeholder.
there is: `immutable auto` -- ok `immutable const` -- not ok ergo, `auto` is not a storage class, but type placeholder.
This analogy does not work. 'immutable' and 'automatic storage' do not conflict. 'immutable' and 'const' do conflict. =20 'immutable auto' is exactly the same as 'auto immutable'. There is no 'int immutable'.
ok. what that "automatic storage" means after all? except being a=20 placeholder.=
Jun 08 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 03:12 PM, ketmar wrote:
 On Mon, 08 Jun 2015 13:38:08 +0200, Timon Gehr wrote:

 On 06/08/2015 09:30 AM, ketmar wrote:
 On Sun, 07 Jun 2015 18:50:07 +0200, Timon Gehr wrote:

 On 06/06/2015 08:10 AM, ketmar wrote:
 if `auto` can play a role of type placeholder
There is no such thing as a type placeholder.
there is: `immutable auto` -- ok `immutable const` -- not ok ergo, `auto` is not a storage class, but type placeholder.
This analogy does not work. 'immutable' and 'automatic storage' do not conflict. 'immutable' and 'const' do conflict. 'immutable auto' is exactly the same as 'auto immutable'. There is no 'int immutable'.
ok. what that "automatic storage" means after all?
For all practical and theoretical purposes, it means absolutely nothing.
 except being a placeholder.
It indicates to the parser that what follows is a declaration. Nothing more. It does not hold the place of anything else.
Jun 08 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 08 Jun 2015 15:46:22 +0200, Timon Gehr wrote:

 It indicates to the parser that what follows is a declaration. Nothing
 more. It does not hold the place of anything else.
so it's not a "default storage type", but simply "a mark for a parser".=20 well, the third definition.=
Jun 08 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/08/2015 05:15 PM, ketmar wrote:
 On Mon, 08 Jun 2015 15:46:22 +0200, Timon Gehr wrote:

 It indicates to the parser that what follows is a declaration. Nothing
 more. It does not hold the place of anything else.
so it's not a "default storage type", but simply "a mark for a parser". well, the third definition.
That's not a definition. It is a rationale.
Jun 08 2015
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 20:36:19 +0000, Mafi wrote:

 On Friday, 5 June 2015 at 10:56:36 UTC, ketmar wrote:
=20
=20
 p.s. if "auto" is a storage class, the following code should be
 accepted (while it isn't):

   int foo () { return 42; }

   void main () {
     auto auto i =3D foo();
   }

 as it's logically "an auto-typed var with "auto" storage class".
=20 Here lies your mistake. There is no such thing as "auto"-typed (leaving aside function signatures, which might be special-cased and are different beast altogether). Auto is not a type. auto* or auto[] aren't valied either. Auto is just a storage class, no more, no less. You use it if the grammar needs a storage class but you don't want to give special attributes to the variable (like const or static). To make a declaration with inferred type you need at least one storage class. To make it work with "normal" variables you use "auto".
p.s. even more samples: `foreach (auto n; 0..10)`. this doesn't work at=20 all. why? `foreach (immutable n; 0..10)` works perfectly. so `auto`=20 clearly is not a "storage class", as it is forbidden where storage=20 classes are allowed.=
Jun 05 2015
prev sibling next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Friday, 5 June 2015 at 03:15:46 UTC, anonymous wrote:
 On Friday, 5 June 2015 at 02:38:39 UTC, ketmar wrote:
 here's dustmited source:
Further reduced: void unaryFun()(auto int a) pure nothrow safe nogc {} alias Identity(F) = F; void main() { unaryFun!()(41); static void fun(int n) pure nothrow safe nogc {} alias F = typeof(fun); pragma(msg, F); /* ...(int n) */ pragma(msg, Identity!F); /* ...(auto int) */ }
'auto int' doesn't compile with 2.067.1. I know because this is blocking a PR I'm working on.
Jun 05 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 05 Jun 2015 11:07:19 +0000, Meta wrote:

 On Friday, 5 June 2015 at 03:15:46 UTC, anonymous wrote:
 On Friday, 5 June 2015 at 02:38:39 UTC, ketmar wrote:
 here's dustmited source:
Further reduced: void unaryFun()(auto int a) pure nothrow safe nogc {} alias Identity(F) =3D F; void main() { unaryFun!()(41); static void fun(int n) pure nothrow safe nogc {} alias F =3D typeof(fun); pragma(msg, F); /* ...(int n) */ pragma(msg, Identity!F); /* ...(auto int) */ }
=20 'auto int' doesn't compile with 2.067.1. I know because this is blocking a PR I'm working on.
but it does! both with 2.067.1 downloaded from dlang.org and with git=20 HEAD. it may not do what you expect it to do (i don't know what it should=20 do anyway), but dmd happily accepts that code.=
Jun 05 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Friday, 5 June 2015 at 12:32:03 UTC, ketmar wrote:
 but it does! both with 2.067.1 downloaded from dlang.org and 
 with git
 HEAD. it may not do what you expect it to do (i don't know what 
 it should
 do anyway), but dmd happily accepts that code.
Hmm, maybe I'm only on 2.070 then. I'll upgrade and see if it still fails to compile.
Jun 05 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/5/15 12:19 PM, Meta wrote:
 On Friday, 5 June 2015 at 12:32:03 UTC, ketmar wrote:
 but it does! both with 2.067.1 downloaded from dlang.org and with git
 HEAD. it may not do what you expect it to do (i don't know what it should
 do anyway), but dmd happily accepts that code.
Hmm, maybe I'm only on 2.070 then. I'll upgrade and see if it still fails to compile.
Hello from the future!!! When I use auto int a in a normal function, I get this: Error: auto can only be used for template function parameters But unaryFun()(auto int a) is a template. Perhaps your blocker is for non-templates? -Steve
Jun 05 2015
parent "Meta" <jared771 gmail.com> writes:
On Friday, 5 June 2015 at 19:38:06 UTC, Steven Schveighoffer 
wrote:
 On 6/5/15 12:19 PM, Meta wrote:
 On Friday, 5 June 2015 at 12:32:03 UTC, ketmar wrote:
 but it does! both with 2.067.1 downloaded from dlang.org and 
 with git
 HEAD. it may not do what you expect it to do (i don't know 
 what it should
 do anyway), but dmd happily accepts that code.
Hmm, maybe I'm only on 2.070 then. I'll upgrade and see if it still fails to compile.
Hello from the future!!! When I use auto int a in a normal function, I get this: Error: auto can only be used for template function parameters But unaryFun()(auto int a) is a template. Perhaps your blocker is for non-templates? -Steve
Yes, this is a non-template function that is auto-generated.
Jun 05 2015
prev sibling parent "anonymous" <anonymous example.com> writes:
On Friday, 5 June 2015 at 03:15:46 UTC, anonymous wrote:
 On Friday, 5 June 2015 at 02:38:39 UTC, ketmar wrote:
 here's dustmited source:
Further reduced: void unaryFun()(auto int a) pure nothrow safe nogc {} alias Identity(F) = F; void main() { unaryFun!()(41); static void fun(int n) pure nothrow safe nogc {} alias F = typeof(fun); pragma(msg, F); /* ...(int n) */ pragma(msg, Identity!F); /* ...(auto int) */ }
Filed two issues: https://issues.dlang.org/show_bug.cgi?id=14656 https://issues.dlang.org/show_bug.cgi?id=14657
Jun 05 2015