www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Attribute inference for auto functions?

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
There's a discussion that may be of interest to the larger community: 
https://github.com/D-Programming-Language/dmd/pull/1877

Andrei
Apr 16 2013
next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 16 Apr 2013 16:22:56 +0100, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 There's a discussion that may be of interest to the larger community:  
 https://github.com/D-Programming-Language/dmd/pull/1877
I read the whole thing and IMO this pull request is a good idea. I think your last summary covers the various points well: https://github.com/D-Programming-Language/dmd/pull/1877#issuecomment-16403663 Should the first step here be to fix the issue described in 2.1? I agree with your reasoning that (b) seems a decent solution. We don't want 'auto' function bodies in .di files and /more importantly/ IMO interface definitions should be as precise as possible. I would almost suggest that good working practice may be to use auto in the .d file, generate the precise .di then back-port the precise .di definition to the .d file once development was complete (for any given version of the library). This would then make accidental changes to a library interface difficult because and change to the library source which conflicted with the now precise definition would be flagged by the compiler. That is, unless you're doing something nasty with void* and cast or similar. It seems the remaining complaint is the compilation speed issue. Do people recompile .di files with every change? I can imagine if you're in a development loop which involves updating a library, recompiling it, moving to a consumer of that library, updating that and recompiling, then testing the change, then looping back to make more changes, and so on. In this case it is conceivable that a library changes might result in a .di change, which would then result in more recompilation right through. But .. if the .di changes it will do so because the library interface has changed, and those changes are surely important to the consumer, aren't they? Or, is there a sufficiently large sub-set of possible changes you could make to the library which are irrelevant to the consumer? If that is the case, can .di generation from 'auto' leave these off the precise definition? I mean, if we're saying they're irrelevant to the consumer of the library, why put them there in the first place, right? R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Apr 16 2013
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
16-Apr-2013 19:22, Andrei Alexandrescu пишет:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
In the same vane - how about attribute inference for "ordinary" functions? I recall that just a month ago I had an interesting case - a normal function inside of a templated struct. The thing is that depending on some parameters (of struct) it could be safe or not. But it's not a template itself and its return type is always bool. In the end I just added an empty CT parameter set making it a template. Questions are - why are we hell bent on the `auto' return type being a marker? What are the other good markers out there? Should we pick anything else for this auto-magic or let the programmer use some wild-card marker explicitly? If we let a bunch of arcane rules govern the inference that would be a failure. On the other hand not doing it where makes sense would be a failure to realize the benefits of annotations ('cause nobody bothers adding them explicitly). -- Dmitry Olshansky
Apr 16 2013
next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types. Indeed, this is part of the original reason for auto's existence. Denying return type deduction for this use case is a major inconvenience. As it stands, I am against this change. It is an unfortunate situation we are in, with D working best with everything inferred and CTFE-able, yet with those things completely at odds with modularity.
Apr 16 2013
next sibling parent reply "Jesse Phillips" <Jessekphillips+d gmail.com> writes:
On Tuesday, 16 April 2013 at 20:21:00 UTC, Peter Alexander wrote:
 This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto 
 functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types. Indeed, this is part of the original reason for auto's existence. Denying return type deduction for this use case is a major inconvenience.
How frequently do you write a non-templated function which returns a complex template type? It isn't something I really think about, but I'm pretty sure if I am returning a complex template type I've already got the function a template.
Apr 16 2013
next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Wednesday, 17 April 2013 at 01:55:54 UTC, Jesse Phillips wrote:
 On Tuesday, 16 April 2013 at 20:21:00 UTC, Peter Alexander 
 wrote:
 This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto 
 functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types. Indeed, this is part of the original reason for auto's existence. Denying return type deduction for this use case is a major inconvenience.
How frequently do you write a non-templated function which returns a complex template type? It isn't something I really think about, but I'm pretty sure if I am returning a complex template type I've already got the function a template.
Often enough. I often find myself returning ranges, which are almost invariably complex template types. And, to be honest, I would just like to use auto without being locked into inferred attributes. It just feels wrong that these things should be conflated, and I get the feeling we will regret this later on when D starts to be used in larger projects.
Apr 17 2013
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 07:04:16 UTC, Peter Alexander 
wrote:
 Often enough. I often find myself returning ranges, which are 
 almost invariably complex template types.

 And, to be honest, I would just like to use auto without being 
 locked into inferred attributes. It just feels wrong that these 
 things should be conflated, and I get the feeling we will 
 regret this later on when D starts to be used in larger 
 projects.
Note that this is consistent with many choice D made. auto is a storage class. storage class usually stick to the function, not the return type : const Foo bar(); // Error as const qualify bar and not Foo. auto is about type inference. Attribute is part of the function type as much as it return type, and so it is expected that auto applied to a function infer its attributes and its return type. The problem you are talking about is very real, but much broader than this auto thing. The problem is that you have no control on what the storage classes bind on. Examples : extern(C) void function() foo; // does extern binds to foo, foo's type or both ? pure function() function() bar; // is bar a pure function ? is bar() pure ? Noth ? How to choose ? Back to the subject, if auto bind to the function it must infers attributes, if it binds to the return type, it mustn't. And right now, storage class bind to the function.
Apr 17 2013
next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Wednesday, 17 April 2013 at 07:58:42 UTC, deadalnix wrote:
 auto is about type inference. Attribute is part of the function 
 type as much as it return type, and so it is expected that auto 
 applied to a function infer its attributes and its return type.
I disagree. Attributes are completely separate from return value, and I do not think it is "expected" that auto should infer attributes.
 The problem you are talking about is very real, but much 
 broader than this auto thing. The problem is that you have no 
 control on what the storage classes bind on.

 Examples :
 extern(C) void function() foo; // does extern binds to foo, 
 foo's type or both ?
 pure function() function() bar; // is bar a pure function ? is 
 bar() pure ? Noth ? How to choose ?
Yes, that is a problem, but not related to this change.
 Back to the subject, if auto bind to the function it must 
 infers attributes, if it binds to the return type, it mustn't. 
 And right now, storage class bind to the function.
I think you are confusing separate things here. First, 'auto' is a storage class that means 'no other storage class'. It does NOT mean type inference. You do not need to use 'auto' to get type inference. You cannot use 'auto' in conjunction with other storage classes to get type inference. auto foo(); // type inference const foo(); // type inference auto const foo(); // illegal, two storage classes As you can see, auto is neither sufficient, nor required for type inference. The storage class you use has absolutely nothing to do with type inference. Type inference happens if and only if you do not specify a return type. Storage class and type inference are 100% orthogonal. With that matter cleared up, your argument no longer holds water. It doesn't matter what 'auto' binds to because 'auto' has nothing to do with return type inference, and shouldn't affect attribute inference either. The name of this thread is quite misleading. The proposal also has nothing to do with auto. The proposal is to infer attributes when the return type is inferred. I think it's worth being clear on that otherwise people will confuse storage classes with type/attribute inference.
Apr 17 2013
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/17/13, Peter Alexander <peter.alexander.au gmail.com> wrote:
 Type inference happens if and only if you do
 not specify a return type.
That's not true, you still need to use auto. This function definition is illegal: x() { return 1; } As for being able to use 'const' for type inference it's completely an implementation issue. It's not by design at all. You can even substitute 'auto' for meaningless crap like this in module scope: static x() { return 1; } If return type inference is wanted then 'auto' should be required at all times. What's the point in writing obfuscated code like the above?
Apr 17 2013
parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Wednesday, 17 April 2013 at 12:46:53 UTC, Andrej Mitrovic 
wrote:
 On 4/17/13, Peter Alexander <peter.alexander.au gmail.com> 
 wrote:
 Type inference happens if and only if you do
 not specify a return type.
That's not true, you still need to use auto. This function definition is illegal: x() { return 1; }
You don't need to use auto. Any storage class will do.
 As for being able to use 'const' for type inference it's 
 completely an
 implementation issue. It's not by design at all. You can even
 substitute 'auto' for meaningless crap like this in module 
 scope:

 static x() { return 1; }

 If return type inference is wanted then 'auto' should be 
 required at
 all times. What's the point in writing obfuscated code like the 
 above?
Because it's required? This is illegal: auto const foo(); If you want type inference then you just need to use: const foo(); And yes, it is by design. The spec is quite clear on this issue. Type inference is signalled by lack of return type -- not the presence of auto. auto is only required when no other storage class is wanted, to make the parser happy. auto is nothing whatsoever to do with type inference.
Apr 17 2013
parent "Rob T" <alanb ucora.com> writes:
On Wednesday, 17 April 2013 at 13:59:05 UTC, Peter Alexander 
wrote:
[...]
 If you want type inference then you just need to use:

 const foo();

 And yes, it is by design. The spec is quite clear on this 
 issue. Type inference is signalled by lack of return type -- 
 not the presence of auto. auto is only required when no other 
 storage class is wanted, to make the parser happy. auto is 
 nothing whatsoever to do with type inference.
I think you've made some good clarification points. auto is used only when there is no other storage class, and "storage class" is a somewhat misleading term because some storage class's seem to have nothing to do with "storage". The point you made, is that what is being proposed is if or if not D should be extended to perform attribute inference along with type inference. The auto keyword is only required when no other storage class is specified, so it really means that attribute inference will be done all the time unless you specifically specify the attributes. Is this the case? --rt
Apr 17 2013
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/17/13, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 As for being able to use 'const' for type inference it's completely an
 implementation issue. It's not by design at all.
Actually I'm wrong about this now that I've re-read the spec. You can use another storage class instead of auto (strangely I don't remember this being discussed in TDPL though). However there are too many things in DMD which are "storage classes", when they shouldn't be. E.g. property.
Apr 17 2013
parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Wednesday, 17 April 2013 at 12:49:41 UTC, Andrej Mitrovic
wrote:
 On 4/17/13, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 As for being able to use 'const' for type inference it's 
 completely an
 implementation issue. It's not by design at all.
Actually I'm wrong about this now that I've re-read the spec. You can use another storage class instead of auto (strangely I don't remember this being discussed in TDPL though). However there are too many things in DMD which are "storage classes", when they shouldn't be. E.g. property.
Sorry, just saw this. Ignore previous reply.
Apr 17 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 12:22:21 UTC, Peter Alexander 
wrote:
 On Wednesday, 17 April 2013 at 07:58:42 UTC, deadalnix wrote:
 auto is about type inference. Attribute is part of the 
 function type as much as it return type, and so it is expected 
 that auto applied to a function infer its attributes and its 
 return type.
I disagree. Attributes are completely separate from return value, and I do not think it is "expected" that auto should infer attributes.
auto is generally understood as type inference, so ti isn't an heresy.
 The problem you are talking about is very real, but much 
 broader than this auto thing. The problem is that you have no 
 control on what the storage classes bind on.

 Examples :
 extern(C) void function() foo; // does extern binds to foo, 
 foo's type or both ?
 pure function() function() bar; // is bar a pure function ? is 
 bar() pure ? Noth ? How to choose ?
Yes, that is a problem, but not related to this change.
It is, because you can't express both "I want return type inference" and " want full type inference"
 Back to the subject, if auto bind to the function it must 
 infers attributes, if it binds to the return type, it mustn't. 
 And right now, storage class bind to the function.
I think you are confusing separate things here. First, 'auto' is a storage class that means 'no other storage class'. It does NOT mean type inference. You do not need to use 'auto' to get type inference. You cannot use 'auto' in conjunction with other storage classes to get type inference. auto foo(); // type inference const foo(); // type inference auto const foo(); // illegal, two storage classes As you can see, auto is neither sufficient, nor required for type inference. The storage class you use has absolutely nothing to do with type inference. Type inference happens if and only if you do not specify a return type. Storage class and type inference are 100% orthogonal.
It is sufficient. It is true that it isn't required as absence of type + one storage class means type inference. I kind of oversimplyfied that part. The intent of auto is still type inference, as this is a storage class that mean nothing, except that it allow to omit the type.
 The name of this thread is quite misleading. The proposal also 
 has nothing to do with auto. The proposal is to infer 
 attributes when the return type is inferred. I think it's worth 
 being clear on that otherwise people will confuse storage 
 classes with type/attribute inference.
What storage class stand for is already a blurry topic. I don't think any confusion can be added.
Apr 17 2013
parent reply "Rob T" <alanb ucora.com> writes:
On Wednesday, 17 April 2013 at 16:10:02 UTC, deadalnix wrote:
 On Wednesday, 17 April 2013 at 12:22:21 UTC, Peter Alexander 
 wrote:
 On Wednesday, 17 April 2013 at 07:58:42 UTC, deadalnix wrote:
 auto is about type inference. Attribute is part of the 
 function type as much as it return type, and so it is 
 expected that auto applied to a function infer its attributes 
 and its return type.
I disagree. Attributes are completely separate from return value, and I do not think it is "expected" that auto should infer attributes.
auto is generally understood as type inference, so ti isn't an heresy.
 The problem you are talking about is very real, but much 
 broader than this auto thing. The problem is that you have no 
 control on what the storage classes bind on.

 Examples :
 extern(C) void function() foo; // does extern binds to foo, 
 foo's type or both ?
 pure function() function() bar; // is bar a pure function ? 
 is bar() pure ? Noth ? How to choose ?
Yes, that is a problem, but not related to this change.
It is, because you can't express both "I want return type inference" and " want full type inference"
 Back to the subject, if auto bind to the function it must 
 infers attributes, if it binds to the return type, it 
 mustn't. And right now, storage class bind to the function.
I think you are confusing separate things here. First, 'auto' is a storage class that means 'no other storage class'. It does NOT mean type inference. You do not need to use 'auto' to get type inference. You cannot use 'auto' in conjunction with other storage classes to get type inference. auto foo(); // type inference const foo(); // type inference auto const foo(); // illegal, two storage classes As you can see, auto is neither sufficient, nor required for type inference. The storage class you use has absolutely nothing to do with type inference. Type inference happens if and only if you do not specify a return type. Storage class and type inference are 100% orthogonal.
It is sufficient. It is true that it isn't required as absence of type + one storage class means type inference. I kind of oversimplyfied that part. The intent of auto is still type inference, as this is a storage class that mean nothing, except that it allow to omit the type.
 The name of this thread is quite misleading. The proposal also 
 has nothing to do with auto. The proposal is to infer 
 attributes when the return type is inferred. I think it's 
 worth being clear on that otherwise people will confuse 
 storage classes with type/attribute inference.
What storage class stand for is already a blurry topic. I don't think any confusion can be added.
It's certainly not helpful if we keep on blurring the concepts. The "auto" keyword currently means nothing except that when no other storage class is present you can specify it to allow the compiler to proceed without error, otherwise type inference is always performed unless inference is overridden with an explicit type. The proposal therefore seems to be about extending D to always perform attribute inference along with type inference unless the attributes are explicitly specified. The question I have is if the proposal wants to extend the meaning of the "auto' keyword so that it will be required in order for attribute inference to take place, but that indeed does confuse things because we're using the same keyword for two completely two different purposes, and it clashes with the use of auto in some cases. -rt
Apr 17 2013
parent reply "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Wednesday, 17 April 2013 at 16:26:30 UTC, Rob T wrote:
 The proposal therefore seems to be about extending D to always 
 perform attribute inference along with type inference unless 
 the attributes are explicitly specified.

 The question I have is if the proposal wants to extend the 
 meaning of the "auto' keyword so that it will be required in 
 order for attribute inference to take place, but that indeed 
 does confuse things because we're using the same keyword for 
 two completely two different purposes, and it clashes with the 
 use of auto in some cases.

 -rt
This is a very good description of the change. I don't think auto should be made specific to attribute inference. So I think the discussion should consider: const foo()//... would that be something that should also be a attribute inference. I think I'm still ok with that as it is still requesting inference. Note that you can not specify an inferred const return type. That is this makes a the function const (not valid as a free form function), and not the return type.
Apr 17 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 10:35 AM, Jesse Phillips wrote:
 I don't think auto should be made specific to attribute inference. So I think
 the discussion should consider:

 const foo()//...

 would that be something that should also be a attribute inference.
Yes, the pull request does that, too.
Apr 17 2013
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/17/13 3:58 AM, deadalnix wrote:
 Note that this is consistent with many choice D made.

 auto is a storage class. storage class usually stick to the function,
 not the return type :
 const Foo bar(); // Error as const qualify bar and not Foo.

 auto is about type inference. Attribute is part of the function type as
 much as it return type, and so it is expected that auto applied to a
 function infer its attributes and its return type.

 The problem you are talking about is very real, but much broader than
 this auto thing. The problem is that you have no control on what the
 storage classes bind on.

 Examples :
 extern(C) void function() foo; // does extern binds to foo, foo's type
 or both ?
 pure function() function() bar; // is bar a pure function ? is bar()
 pure ? Noth ? How to choose ?

 Back to the subject, if auto bind to the function it must infers
 attributes, if it binds to the return type, it mustn't. And right now,
 storage class bind to the function.
I think this is a solid argument. You may want to paste it in the github discussion for reference. Andrei
Apr 17 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 12:58 AM, deadalnix wrote:
 Back to the subject, if auto bind to the function it must infers attributes, if
 it binds to the return type, it mustn't. And right now, storage class bind to
 the function.
'auto', like all storage class annotations such as 'const', binds to the declaration and the declaration's type. It is perfectly consistent.
 extern(C) void function() foo; // does extern binds to foo, foo's type or both
?
foo is being declared, so it binds to foo.
 pure function() function() bar; // is bar a pure function ? is bar() pure ? 
Noth ? How to choose ? bar is being declared, so it binds to bar.
Apr 17 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 19:53:07 UTC, Walter Bright wrote:
 On 4/17/2013 12:58 AM, deadalnix wrote:
 Back to the subject, if auto bind to the function it must 
 infers attributes, if
 it binds to the return type, it mustn't. And right now, 
 storage class bind to
 the function.
'auto', like all storage class annotations such as 'const', binds to the declaration and the declaration's type. It is perfectly consistent.
 extern(C) void function() foo; // does extern binds to foo,
foo's type or both ? foo is being declared, so it binds to foo.
 pure function() function() bar; // is bar a pure function ?
is bar() pure ? Noth ? How to choose ? bar is being declared, so it binds to bar.
Yes I know. That was my point : auto bind to the function according to current spec, so function type should be inferred, which imply both return type and attributes. Points raised in the thread show that people need in general to be able to annotate specifically the return type or whatever, and this is rather difficult with the current state of thing (and also it seems quite hard to fix).
Apr 17 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 6:28 PM, deadalnix wrote:
 Points raised in the thread show that people need in general to be able to
 annotate specifically the return type or whatever, and this is rather difficult
 with the current state of thing (and also it seems quite hard to fix).
To annotate the return type specifically with, say, const: const(T) foo(); And in fact const with parens works as a general type constructor: const(T)* foo(); // return mutable pointer to const T const without parens applies to the declaration.
Apr 17 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 18 April 2013 at 01:52:10 UTC, Walter Bright wrote:
 To annotate the return type specifically with, say, const:

     const(T) foo();

 And in fact const with parens works as a general type 
 constructor:

     const(T)* foo();  // return mutable pointer to const T

 const without parens applies to the declaration.
This doesn't work with many attributes.
Apr 17 2013
prev sibling next sibling parent reply "qznc" <qznc go.to> writes:
On Wednesday, 17 April 2013 at 07:04:16 UTC, Peter Alexander 
wrote:
 On Wednesday, 17 April 2013 at 01:55:54 UTC, Jesse Phillips 
 wrote:
 On Tuesday, 16 April 2013 at 20:21:00 UTC, Peter Alexander 
 wrote:
 This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto 
 functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types. Indeed, this is part of the original reason for auto's existence. Denying return type deduction for this use case is a major inconvenience.
How frequently do you write a non-templated function which returns a complex template type? It isn't something I really think about, but I'm pretty sure if I am returning a complex template type I've already got the function a template.
Often enough. I often find myself returning ranges, which are almost invariably complex template types. And, to be honest, I would just like to use auto without being locked into inferred attributes. It just feels wrong that these things should be conflated, and I get the feeling we will regret this later on when D starts to be used in larger projects.
I strongly believe you should never use "auto" for API types, because it is too easy to break them. If Dont-Repeat-Yourself/complex types is a problem, they should be solved at the other end by enhancing function body type inference. An alternative approach would be to do this optimization during optimization. However, this means it has to be reimplemented in dmd, LLVM, GCC separately. This is e.g. the case for pure-inference in C code.
Apr 17 2013
parent "David Nadlinger" <see klickverbot.at> writes:
On Wednesday, 17 April 2013 at 08:39:37 UTC, qznc wrote:
 An alternative approach would be to do this optimization during 
 optimization. However, this means it has to be reimplemented in 
 dmd, LLVM, GCC separately. This is e.g. the case for 
 pure-inference in C code.
LDC/LLVM does something very similar already (on the IR level), but obviously not across multiple compilation units, as the function body has to be available to the optimizer. David
Apr 17 2013
prev sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Wednesday, 17 April 2013 at 07:04:16 UTC, Peter Alexander 
wrote:
 Often enough. I often find myself returning ranges, which are 
 almost invariably complex template types.
Hmm, I'm still trying to decide if this is a major concern. Generally when returning a range, this is done because operations are being performed on a container, the specific container isn't important and many times nor is the type in the container. This means my function is a template. The times when I could see returning a complex type where the function isn't templates is when I'm loading the data to be consumed. In this case I generally will return the container itself (since ownership isn't with the called function).
Apr 17 2013
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/17/13, Jesse Phillips <Jessekphillips+d gmail.com> wrote:
 How frequently do you write a non-templated function which
 returns a complex template type?
This can be common if the function is a member function that returns some kind of a range on internal data, for example: import std.range; struct S { int[] arr; auto range() { return cycle(arr).stride(2); } } There's no need to make "range" a template here, but specifying the return type isn't always possible or easy to do.
Apr 17 2013
prev sibling next sibling parent reply "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 16 Apr 2013 21:20:59 +0100, Peter Alexander  
<peter.alexander.au gmail.com> wrote:

 This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types. Indeed, this is part of the original reason for auto's existence. Denying return type deduction for this use case is a major inconvenience.
Solution: You use 'auto' and compile the code producing a .di. With the fix Andrei mentioned the .di has the full and complete function signature, without 'auto', including return type and all deduced attributes etc. You alter the signature to suit and copy it back to the .d file. This is how it should be done, IMO, because now you've explicitly defined your library interface so when you accidentally change/break it by modifying the code in the library function body, the compiler will immediately tell you. It's win-win or so it seems to me.
 It is an unfortunate situation we are in, with D working best with  
 everything inferred and CTFE-able, yet with those things completely at  
 odds with modularity.
I can't see how it can be any other way. An interface needs to be clearly defined or it's consumer can't use it. 'auto' does not suit that purpose at all, currently, and this doesn't change with this pull. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Apr 17 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/17/13, Regan Heath <regan netmail.co.nz> wrote:
 Solution:  You use 'auto' and compile the code producing a .di.  With the
 fix Andrei mentioned the .di has the full and complete function signature,
 without 'auto', including return type and all deduced attributes etc.
This doesn't work with voldemort types.
Apr 17 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/17/13 8:09 AM, Andrej Mitrovic wrote:
 On 4/17/13, Regan Heath<regan netmail.co.nz>  wrote:
 Solution:  You use 'auto' and compile the code producing a .di.  With the
 fix Andrei mentioned the .di has the full and complete function signature,
 without 'auto', including return type and all deduced attributes etc.
This doesn't work with voldemort types.
It's not supposed to; voldemort functions are by definition non-modular. Andrei
Apr 17 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 8:14 AM, Andrei Alexandrescu wrote:
 On 4/17/13 8:09 AM, Andrej Mitrovic wrote:
 On 4/17/13, Regan Heath<regan netmail.co.nz>  wrote:
 Solution:  You use 'auto' and compile the code producing a .di.  With the
 fix Andrei mentioned the .di has the full and complete function signature,
 without 'auto', including return type and all deduced attributes etc.
This doesn't work with voldemort types.
It's not supposed to; voldemort functions are by definition non-modular.
The whole point of voldemort functions is that you cannot name the return type, so there is no way to write a signature for it to put in the .di file. Hence, it not working with voldemort types is moot.
Apr 17 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/16/13 4:20 PM, Peter Alexander wrote:
 This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types.
Attribute inference is always done for templates. Andrei
Apr 17 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 8:07 AM, Andrei Alexandrescu wrote:
 On 4/16/13 4:20 PM, Peter Alexander wrote:
 This is the point I have a problem with:

 2.2. One cannot opt out of nothrow or pure with auto functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types.
Attribute inference is always done for templates.
And, I might add, I cannot recall a single adverse issue that has caused.
Apr 17 2013
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, April 17, 2013 12:35:07 Walter Bright wrote:
 On 4/17/2013 8:07 AM, Andrei Alexandrescu wrote:
 On 4/16/13 4:20 PM, Peter Alexander wrote:
 This is the point I have a problem with:
 2.2. One cannot opt out of nothrow or pure with auto functions.
This argument has one solid answer: don't use auto when the need is to specify an attribute pattern explicitly.
I find this unacceptable. Thanks to the proliferation of template code in D, it is often rather difficult to spell out return types.
Attribute inference is always done for templates.
And, I might add, I cannot recall a single adverse issue that has caused.
If anything, the fact that it doesn't infer more is the problem. The primary risk is if a particular set of template arguments previously resulted in the function being pure, nothrow, or safe but no longer do so after some code changes, and code using the template which requires pure, nothrow, or safe then no longer compiles. But odds are that that's the fault changes to the template arguments and not the template, and requiring explict attributes wouldn't fix the problem anyway, because then you're either stuck with a combinatorial explosion of template declarations or making it so that the template always has the same set of attributes and therefore only works with code that works with that exact set of attributes. Non-templated auto functions are not generally in the same boat, because their types are usually well-known, and therefore explicitly marking the attributes that you want works, but it may still be reasonable to do attribute inferrence for them. - Jonathan M Davis
Apr 22 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/16/2013 07:06 PM, Dmitry Olshansky wrote:
 16-Apr-2013 19:22, Andrei Alexandrescu пишет:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
In the same vane - how about attribute inference for "ordinary" functions? I recall that just a month ago I had an interesting case - a normal function inside of a templated struct. The thing is that depending on some parameters (of struct) it could be safe or not. But it's not a template itself and its return type is always bool. In the end I just added an empty CT parameter set making it a template. ...
This should not be an issue any more. http://d.puremagic.com/issues/show_bug.cgi?id=7511
Apr 16 2013
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
17-Apr-2013 01:13, Timon Gehr пишет:
 On 04/16/2013 07:06 PM, Dmitry Olshansky wrote:
 16-Apr-2013 19:22, Andrei Alexandrescu пишет:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
In the same vane - how about attribute inference for "ordinary" functions? I recall that just a month ago I had an interesting case - a normal function inside of a templated struct. The thing is that depending on some parameters (of struct) it could be safe or not. But it's not a template itself and its return type is always bool. In the end I just added an empty CT parameter set making it a template. ...
This should not be an issue any more. http://d.puremagic.com/issues/show_bug.cgi?id=7511
So it was a bug after all. Good to see it fixed. -- Dmitry Olshansky
Apr 17 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/16/2013 05:22 PM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
I think inferring the return type and inferring the attributes are mostly orthogonal concerns. (and both are unrelated to the 'auto' storage class'.) But since there is precedent for conflating attribute inference with required function bodies, it might be fine. In order not to be hit by Kenji's worst case debug output scenario, use something like the following: void dw(T...)(T args)pure nothrow trusted{ debug try{writeln(args);}catch{assert(0);} else static assert(0); }
Apr 16 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 16 April 2013 at 21:40:18 UTC, Timon Gehr wrote:
 I think inferring the return type and inferring the attributes 
 are mostly orthogonal concerns. (and both are unrelated to the 
 'auto' storage class'.) But since there is precedent for 
 conflating attribute inference with required function bodies, 
 it might be fine.
auto is a storage class, so it should be possible to explicitly specify the return type : auto ulong foo() { // Infered pure, nothrow and everything. Return type is ulong (would have been int if inferred). return 12; }
Apr 16 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 16 April 2013 at 15:22:56 UTC, Andrei Alexandrescu 
wrote:
 There's a discussion that may be of interest to the larger 
 community: 
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
Oh Yes, Yes, Yes, god Yes ! Yes, Yes, Yes ! Ho Yes !
Apr 16 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2013 7:01 PM, deadalnix wrote:
 On Tuesday, 16 April 2013 at 15:22:56 UTC, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
Oh Yes, Yes, Yes, god Yes ! Yes, Yes, Yes ! Ho Yes !
Not sure what you're saying yes to - the pro or the con?
Apr 16 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 02:22:31 UTC, Walter Bright wrote:
 On 4/16/2013 7:01 PM, deadalnix wrote:
 On Tuesday, 16 April 2013 at 15:22:56 UTC, Andrei Alexandrescu 
 wrote:
 There's a discussion that may be of interest to the larger 
 community:
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
Oh Yes, Yes, Yes, god Yes ! Yes, Yes, Yes ! Ho Yes !
Not sure what you're saying yes to - the pro or the con?
Yes to the pull request, yes to the inference. I agree with you, I know it may sound hard to believe, but it had to happen one day :D
Apr 16 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2013 7:30 PM, deadalnix wrote:
 I agree with you, I know it may
 sound hard to believe, but it had to happen one day :D
I'll mark it on my calendar! BTW, I think we can do attribute inference for all private functions, too.
Apr 16 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 04:44:59 UTC, Walter Bright wrote:
 On 4/16/2013 7:30 PM, deadalnix wrote:
 I agree with you, I know it may
 sound hard to believe, but it had to happen one day :D
I'll mark it on my calendar! BTW, I think we can do attribute inference for all private functions, too.
Don't this risk to conflict with LTO ?
Apr 16 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2013 10:31 PM, deadalnix wrote:
 On Wednesday, 17 April 2013 at 04:44:59 UTC, Walter Bright wrote:
 BTW, I think we can do attribute inference for all private functions, too.
Don't this risk to conflict with LTO ?
How so?
Apr 16 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 05:55:07 UTC, Walter Bright wrote:
 On 4/16/2013 10:31 PM, deadalnix wrote:
 On Wednesday, 17 April 2013 at 04:44:59 UTC, Walter Bright 
 wrote:
 BTW, I think we can do attribute inference for all private 
 functions, too.
Don't this risk to conflict with LTO ?
How so?
Never mind, I think I was wrong. It is a good idea.
Apr 16 2013
prev sibling next sibling parent "Jesse Phillips" <Jessekphillips+d gmail.com> writes:
On Tuesday, 16 April 2013 at 15:22:56 UTC, Andrei Alexandrescu 
wrote:
 There's a discussion that may be of interest to the larger 
 community: 
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
I'm not convinced that specifying the exact return type is such a huge inconvenience to those who use separate compilation. I don't view this as an inconsistency, but definitely a change to why one might choose to use auto. I'm pretty much for this change. However, I also think it would be good to introduce attributes to specify a throwing function as it would have uses in a file headed with nothrow: I'd suggest the same for pure, but 'nopure' isn't the greatest of names. Anyway it is the same reason we have system, I'd just hope they don't get added as throws and nopure as that would be inconsistent.
Apr 16 2013
prev sibling next sibling parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
W dniu 16.04.2013 17:22, Andrei Alexandrescu pisze:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877
On demand inference FTW! void fn() auto { ... } auto fn() auto { ... }
Apr 17 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-04-17 10:31, Piotr Szturmaj wrote:

 On demand inference FTW!

 void fn() auto {
      ...
 }

 auto fn() auto {
      ...
 }
Double auto, hehe. -- /Jacob Carlborg
Apr 17 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/17/13 4:31 AM, Piotr Szturmaj wrote:
 W dniu 16.04.2013 17:22, Andrei Alexandrescu pisze:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877
On demand inference FTW! void fn() auto { ... } auto fn() auto { ... }
I think this is a bit much. Simplicity is a good commodity to allow oneself of, and absorbing two different meanings of 'auto' in the same construct is not simple. Andrei
Apr 17 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 8:12 AM, Andrei Alexandrescu wrote:
 I think this is a bit much. Simplicity is a good commodity to allow oneself of,
 and absorbing two different meanings of 'auto' in the same construct is not
simple.
It also goes back to your discussion of the observation that programmers do not go back and annotate the code, even for large benefits.
Apr 17 2013
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-04-16 15:22:56 +0000, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 There's a discussion that may be of interest to the larger community: 
 https://github.com/D-Programming-Language/dmd/pull/1877
I agree attribute inference is needed. I don't think 'auto' is a suitable trigger. It'll encourage people to replace the return type on existing and new functions (making things more obscure) as a way get attribute inference. Instead, all functions should have the benefit of attribute inference. I'd rather have a marker to prevent it when needed than have to opt it. For instance, if providing a stable API for a library is a concern, put that marker on those exported functions. Perhaps "export" could be that marker. Unfortunately, that'll be slow. DMD will have to reprocess the function body for every called function transitively each time it compiles. The solution for that is to use .di files as a cache: in the process of creating a .di file the inferred attributes could be made explicit. Then disallow attribute inference for functions parsed from a .di file (so you can still provide a body for inlining). All this might pose a tricky cache-invalidation problem however: when a function somewhere changes you need to purge all the dependent di files *before* recompiling anything. :-/ Compilation speed is not a problem for functions with the "auto" return type because there are only a few of them. At least that's how it is right now. Allowing attribute inference only for this category of function might change those statistics after a few months in the wild, and then you'll have the compilation performance problems described above. Which might not be a bad thing, as then you'll need to overhaul the compilation model to fix this, and then you'll be able to enable it for all functions. ;-) -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Apr 17 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 10:37 AM, Michel Fortin wrote:
 Compilation speed is not a problem for functions with the "auto" return type
 because there are only a few of them.
It is not a problem right now because the compiler has to semantically analyze their function bodies already in order to determine the return type. It is insignificant to additionally gather the attribute information.
Apr 17 2013
parent Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-04-17 19:05:01 +0000, Walter Bright <newshound2 digitalmars.com> said:

 On 4/17/2013 10:37 AM, Michel Fortin wrote:
 Compilation speed is not a problem for functions with the "auto" return type
 because there are only a few of them.
It is not a problem right now because the compiler has to semantically analyze their function bodies already in order to determine the return type. It is insignificant to additionally gather the attribute information.
True, but beside the point. My point was that if auto allows attribute inference people will be tempted to (and will do) change their return types to auto in their programs just to get that benefit (no one wants to annotate all their functions). Thus, as more and more functions become "auto" compile times will become slower. Pushed to the extreme, you'd get the same result as if you were inferring attributes for all functions, plus more confusion because all the return types are obfuscated. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Apr 17 2013
prev sibling next sibling parent reply "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Tuesday, 16 April 2013 at 15:22:56 UTC, Andrei Alexandrescu 
wrote:
 There's a discussion that may be of interest to the larger 
 community: 
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
I wish to bring Someboddies consern to this form. What does attribute inference mean for inheritance? Do all derived classes need to be known for inference to take place? Not having the ability to claim a base function can be overridden with a throwing function could cause some issue... Hmm but we can still specify the type so I guess it still isn't a major, but I could see auto being used more causing a library writer to make restrictions on their function because what they write is applicable but not really considering derived classes could reasonably throw.
Apr 17 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 10:41 AM, Jesse Phillips wrote:
 I wish to bring Someboddies consern to this form.

 What does attribute inference mean for inheritance?
I specifically addressed his concern in the git page: "This is the same issue as defining a function with 'auto' in one place and referring to it having a specific type/attribute in another. So I think all the same arguments and reasoning discussed above apply equally."
Apr 17 2013
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 12:06 PM, Walter Bright wrote:
 On 4/17/2013 10:41 AM, Jesse Phillips wrote:
 I wish to bring Someboddies consern to this form.

 What does attribute inference mean for inheritance?
I specifically addressed his concern in the git page: "This is the same issue as defining a function with 'auto' in one place and referring to it having a specific type/attribute in another. So I think all the same arguments and reasoning discussed above apply equally."
His followup doesn't change that. It's still the same issue (covariance) which is discussed repeatedly.
Apr 17 2013
parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
Yes, please do attribute inference!
Apr 17 2013
prev sibling next sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Wednesday, 17 April 2013 at 19:06:42 UTC, Walter Bright wrote:
 On 4/17/2013 10:41 AM, Jesse Phillips wrote:
 I wish to bring Someboddies consern to this form.

 What does attribute inference mean for inheritance?
I specifically addressed his concern in the git page: "This is the same issue as defining a function with 'auto' in one place and referring to it having a specific type/attribute in another. So I think all the same arguments and reasoning discussed above apply equally."
Initially I thought you were replying to something further up in the thread as it seemed more applicable to something I read before, and I did feel the issue of inheritance was different. But I think you are correct, it is the same issue.
Apr 17 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
  Th
On 04/17/2013 09:06 PM, Walter Bright wrote:
 On 4/17/2013 10:41 AM, Jesse Phillips wrote:
 I wish to bring Someboddies consern to this form.

 What does attribute inference mean for inheritance?
I specifically addressed his concern in the git page: "This is the same issue as defining a function with 'auto' in one place and referring to it having a specific type/attribute in another. So I think all the same arguments and reasoning discussed above apply equally."
Why is this a valid form of reasoning? The signature of a function that has its return type inferred includes the function body. Furthermore, it is not the same issue. It is the dual issue. The distinction is very relevant because pure and nothrow are designed in an asymmetric way, given inference. Attributes can force the specification in one direction only (provide more guarantees to callers), but not in the other one (require less from subclasses). The concerns the latter can certainly not be dismissed by using the same arguments and reasoning as for the former without any further examination.
Apr 17 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 3:20 PM, Timon Gehr wrote:
 "This is the same issue as defining a function with 'auto' in one place
 and referring to it having a specific type/attribute in another. So I
 think all the same arguments and reasoning discussed above apply equally."
Why is this a valid form of reasoning? The signature of a function that has its return type inferred includes the function body. Furthermore, it is not the same issue. It is the dual issue. The distinction is very relevant because pure and nothrow are designed in an asymmetric way,
They are the same - adding the attribute retains covariance.
 given
 inference. Attributes can force the specification in one direction only
(provide
 more guarantees to callers), but not in the other one (require less from
 subclasses).
Pure and nothrow provide more guarantees, hence covariance.
 The concerns the latter can certainly not be dismissed by using the same
 arguments and reasoning as for the former without any further examination.
They're both the same issue of covariance.
Apr 17 2013
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 17 April 2013 at 23:46:08 UTC, Walter Bright wrote:
 On 4/17/2013 3:20 PM, Timon Gehr wrote:
 "This is the same issue as defining a function with 'auto' in 
 one place
 and referring to it having a specific type/attribute in 
 another. So I
 think all the same arguments and reasoning discussed above 
 apply equally."
Why is this a valid form of reasoning? The signature of a function that has its return type inferred includes the function body. Furthermore, it is not the same issue. It is the dual issue. The distinction is very relevant because pure and nothrow are designed in an asymmetric way,
They are the same - adding the attribute retains covariance.
No : if a super function suddenly become pure because its implementation changed, then all kind of subclasses can broke. Generally, it is a bad idea for a super class to be aware of its subclasses. But defining a function that is going to be overridden as auto is asking for trouble in the first place.
Apr 17 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 6:32 PM, deadalnix wrote:
 No : if a super function suddenly become pure because its implementation
 changed, then all kind of subclasses can broke. Generally, it is a bad idea for
 a super class to be aware of its subclasses.
Yet this is the same issue as auto for other functions.
 But defining a function that is going to be overridden as auto is asking for
 trouble in the first place.
Of course.
Apr 17 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/18/2013 01:46 AM, Walter Bright wrote:
 On 4/17/2013 3:20 PM, Timon Gehr wrote:
 "This is the same issue as defining a function with 'auto' in one place
 and referring to it having a specific type/attribute in another. So I
 think all the same arguments and reasoning discussed above apply
 equally."
Why is this a valid form of reasoning? The signature of a function that has its return type inferred includes the function body. Furthermore, it is not the same issue. It is the dual issue. The distinction is very relevant because pure and nothrow are designed in an asymmetric way,
They are the same
No. In one case you infer guarantees only. (those restrict what can be done in the future without potentially breaking code, but that's it.) In the other case you infer restrictions too, in an unsound way because the inference does not take into consideration the subclasses.
 - adding the attribute retains covariance.
I am sorry, but I do not understand your notion of covariance. Covariance is a precise notion from category theory. (A mapping between categories that conserves morphisms is called a covariant functor.)
 given
 inference. Attributes can force the specification in one direction
 only (provide
 more guarantees to callers), but not in the other one (require less from
 subclasses).
Pure and nothrow provide more guarantees, hence covariance.
 The concerns the latter can certainly not be dismissed by using the same
 arguments and reasoning as for the former without any further
 examination.
They're both the same issue of covariance.
class C{ final foo(){ ... } // <- this signature is foo's signature only auto bar(){ ... } // <- this signature has to fit all overrides } In the first case, inference is mostly fine because you cannot unduly restrict someone: The signature will actually match foo's implementation. In the second case you cannot infer the attributes because you do not know all subclasses. The signature will potentially not match all overrides. Case in point, I just noticed the following regression on git head: import std.stdio; class C(T){ T foo(){ return 2; } } class D : C!int{ override int foo(){ writeln(super.foo()); return 3; } // error } Inference shouldn't be done for virtual functions. http://d.puremagic.com/issues/show_bug.cgi?id=9952
Apr 17 2013
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 11:49 PM, Timon Gehr wrote:
 I am sorry, but I do not understand your notion of covariance.
Overriding functions can add pure or nothrow and remain covariant.
 In the second case you cannot infer the attributes because you do not know all
 subclasses. The signature will potentially not match all overrides.
If you want a precise signature, don't use auto. It's the same case as everywhere else.
 Case in point, I just noticed the following regression on git head:

 import std.stdio;

 class C(T){
      T foo(){ return 2; }
 }

 class D : C!int{
      override int foo(){ writeln(super.foo()); return 3; } // error
 }


 Inference shouldn't be done for virtual functions.

 http://d.puremagic.com/issues/show_bug.cgi?id=9952
This is not an auto issue.
Apr 18 2013
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/18/13 2:49 AM, Timon Gehr wrote:
 On 04/18/2013 01:46 AM, Walter Bright wrote:
 - adding the attribute retains covariance.
I am sorry, but I do not understand your notion of covariance.
I think he means subtyping. An attributed function (pure, nothrow) is a subtype of a non-attributed function. That means it can substitute the non-attributed function. Andrei
Apr 18 2013
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
Apr 17 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 18 April 2013 at 02:40:42 UTC, Walter Bright wrote:
 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger 
 community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
Very nice !
Apr 17 2013
prev sibling next sibling parent reply "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 18 April 2013 at 02:40:42 UTC, Walter Bright wrote:
 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger 
 community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
I don't actually have an opinion on whether attributes should be inferred, but ' auto' (as opposed to ' infer') would be a relatively innocuous way to do it explicitly instead of implicitly.
Apr 17 2013
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 7:50 PM, Zach the Mystic wrote:
 On Thursday, 18 April 2013 at 02:40:42 UTC, Walter Bright wrote:
 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
I don't actually have an opinion on whether attributes should be inferred, but ' auto' (as opposed to ' infer') would be a relatively innocuous way to do it explicitly instead of implicitly.
Except that we already support typeof(return) inside of a function.
Apr 17 2013
parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 18 April 2013 at 03:19:38 UTC, Walter Bright wrote:
 On 4/17/2013 7:50 PM, Zach the Mystic wrote:
 On Thursday, 18 April 2013 at 02:40:42 UTC, Walter Bright 
 wrote:
 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger 
 community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
I don't actually have an opinion on whether attributes should be inferred, but ' auto' (as opposed to ' infer') would be a relatively innocuous way to do it explicitly instead of implicitly.
Except that we already support typeof(return) inside of a function.
Yeah, I basically agree. If I had to choose right now, typeof(return) makes more sense. It relies on the assumption that most of the time when you want to 'auto' the return type, you also are okay with autoing the attributes (hence typeof(return) will be much rarer than 'auto'). It seems like a pretty safe assumption to make. And it's weird but ' ' is just uglier than things without ' ', despite that it would be nice for UDAs and other attributes if that weren't the case.
Apr 17 2013
prev sibling parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
W dniu 18.04.2013 04:50, Zach the Mystic pisze:
 On Thursday, 18 April 2013 at 02:40:42 UTC, Walter Bright wrote:
 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
I don't actually have an opinion on whether attributes should be inferred, but ' auto' (as opposed to ' infer') would be a relatively innocuous way to do it explicitly instead of implicitly.
And this can apply to whole scopes.
Apr 17 2013
parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Thursday, 18 April 2013 at 03:42:50 UTC, Piotr Szturmaj wrote:
 W dniu 18.04.2013 04:50, Zach the Mystic pisze:
 On Thursday, 18 April 2013 at 02:40:42 UTC, Walter Bright 
 wrote:
 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:
 There's a discussion that may be of interest to the larger 
 community:
 https://github.com/D-Programming-Language/dmd/pull/1877
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
I don't actually have an opinion on whether attributes should be inferred, but ' auto' (as opposed to ' infer') would be a relatively innocuous way to do it explicitly instead of implicitly.
And this can apply to whole scopes.
Yeah, that's true... 'typeof(return):' would not look good at the top of a file. I feel like this feature is attempting to turn on a vacuum, seeing how many explicit things can be sucked into the implicit vortex. I think the gold medal would be if there were a way to do everything implicitly, but some things may resist being sucked in, and for good reason. The syntax ' auto' seems like a bronze medal solution, so I'd be glad to see it lose to something better.
Apr 17 2013
prev sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2013/4/18 Walter Bright <newshound2 digitalmars.com>

 On 4/16/2013 8:22 AM, Andrei Alexandrescu wrote:

 There's a discussion that may be of interest to the larger community:
 https://github.com/D-**Programming-Language/dmd/pull/**1877<https://github.com/D-Programming-Language/dmd/pull/1877>
What do you think of this: typeof(return) foo(int x) { return x; } ? That would only infer the return type, not the attributes.
It will break existing code. int foo() { typeof(return) bar() { return 1; } return bar(); } typeof(return) represents the return type of foo, that is int. Kenji Hara
Apr 17 2013
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
 It will break existing code.

 int foo() {
     typeof(return) bar() { return 1; }
     return bar();
 }

 typeof(return) represents the return type of foo, that is int.
That is true :( Don't seem fixable.
Apr 17 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/17/2013 11:34 PM, deadalnix wrote:
 On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
 It will break existing code.

 int foo() {
     typeof(return) bar() { return 1; }
     return bar();
 }

 typeof(return) represents the return type of foo, that is int.
That is true :( Don't seem fixable.
It is fixable if it is special cased, but special cases stink.
Apr 17 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/18/13 2:38 AM, Walter Bright wrote:
 On 4/17/2013 11:34 PM, deadalnix wrote:
 On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
 It will break existing code.

 int foo() {
 typeof(return) bar() { return 1; }
 return bar();
 }

 typeof(return) represents the return type of foo, that is int.
That is true :( Don't seem fixable.
It is fixable if it is special cased, but special cases stink.
Thanks Kenji for a surgical destruction. Andrei
Apr 18 2013
parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
W dniu 18.04.2013 16:58, Andrei Alexandrescu pisze:
 On 4/18/13 2:38 AM, Walter Bright wrote:
 On 4/17/2013 11:34 PM, deadalnix wrote:
 On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
 It will break existing code.

 int foo() {
 typeof(return) bar() { return 1; }
 return bar();
 }

 typeof(return) represents the return type of foo, that is int.
That is true :( Don't seem fixable.
It is fixable if it is special cased, but special cases stink.
Thanks Kenji for a surgical destruction.
What about this: auto inferReturnTypeAndAttributes() { ... } auto(return) inferOnlyReturnType() { ... } or since all attributes are constraints, it can be rewritten to: auto inferOnlyReturnType() pure nothrow safe { ... } It really doesn't make sense to infer impurity, throwing or unsafety because these are the default. I imagine there are some use cases where programmer for example wants to infer all but purity, possibly because some other part of the code relies on pure behavior of his function, and he doesn't care about the other attributes. Example of pure function where nothrow and safety are inferred: auto inferAllButPurity() pure { ... } To sum up: 1. auto - infers all 2. auto(return) - infers only a return type 3. auto fn() attrs... - infers return type and all not specified attributes Second and third are equivalent, thus auto(return) is optional. There were some voices about breaking overriden functions by adding/inferring superclass function attribute. I think this is an oversight, virtual functions should not have attributes inferred.
Apr 19 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 19 April 2013 at 12:43:49 UTC, Piotr Szturmaj wrote:
 What about this:

 auto inferReturnTypeAndAttributes() { ... }
 auto(return) inferOnlyReturnType() { ... }

 or since all attributes are constraints, it can be rewritten to:

 auto inferOnlyReturnType() pure nothrow  safe { ... }

 It really doesn't make sense to infer impurity, throwing or 
 unsafety because these are the default.

 I imagine there are some use cases where programmer for example 
 wants to infer all but purity, possibly because some other part 
 of the code relies on pure behavior of his function, and he 
 doesn't care about the other attributes. Example of pure 
 function where nothrow and safety are inferred:

 auto inferAllButPurity() pure { ... }

 To sum up:

 1. auto               - infers all
 2. auto(return)       - infers only a return type
 3. auto fn() attrs... - infers return type and all not 
 specified attributes

 Second and third are equivalent, thus auto(return) is optional.

 There were some voices about breaking overriden functions by 
 adding/inferring superclass function attribute. I think this is 
 an oversight, virtual functions should not have attributes 
 inferred.
I like this. It provides a good balance of control and automation. how would template functions be treated with auto(return)?
Apr 19 2013
parent Piotr Szturmaj <bncrbme jadamspam.pl> writes:
W dniu 19.04.2013 15:43, John Colvin pisze:
 I like this. It provides a good balance of control and automation.

 how would template functions be treated with auto(return)?
I see no need for special treating of template functions. In this case only return type would be inferred. Programmers should then specify attributes explicitly. By default, template functions with auto(return) would be impure, throwing and unsafe.
Apr 19 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 19 April 2013 at 12:43:49 UTC, Piotr Szturmaj wrote:
 What about this:

 auto inferReturnTypeAndAttributes() { ... }
 auto(return) inferOnlyReturnType() { ... }

 or since all attributes are constraints, it can be rewritten to:

 auto inferOnlyReturnType() pure nothrow  safe { ... }

 It really doesn't make sense to infer impurity, throwing or 
 unsafety because these are the default.

 I imagine there are some use cases where programmer for example 
 wants to infer all but purity, possibly because some other part 
 of the code relies on pure behavior of his function, and he 
 doesn't care about the other attributes. Example of pure 
 function where nothrow and safety are inferred:

 auto inferAllButPurity() pure { ... }

 To sum up:

 1. auto               - infers all
 2. auto(return)       - infers only a return type
 3. auto fn() attrs... - infers return type and all not 
 specified attributes

 Second and third are equivalent, thus auto(return) is optional.

 There were some voices about breaking overriden functions by 
 adding/inferring superclass function attribute. I think this is 
 an oversight, virtual functions should not have attributes 
 inferred.
Except for 2, this is already what is proposed. As of for 2 I'd rather have a standard way to have attribute binding to the return type or the declaration. This is a recurring problem, and auto is simply one instance of it. auto applied to the return type means that we infers the return type, applied to the function it means infers return type AND attributes.
Apr 19 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/19/2013 6:55 AM, deadalnix wrote:
 As of for 2 I'd rather have a standard way to have attribute binding to the
 return type or the declaration. This is a recurring problem, and auto is simply
 one instance of it.
I'm not understanding it being a recurring problem. There is a recurring misunderstanding that attributes are applying to a type when they are defined as applying to the declaration.
 auto applied to the return type means that we infers the return type, applied
to
 the function it means infers return type AND attributes.
auto never applies to a type, it always applies to the declaration and hence the type of that declaration.
Apr 19 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 19 April 2013 at 19:06:39 UTC, Walter Bright wrote:
 On 4/19/2013 6:55 AM, deadalnix wrote:
 As of for 2 I'd rather have a standard way to have attribute 
 binding to the
 return type or the declaration. This is a recurring problem, 
 and auto is simply
 one instance of it.
I'm not understanding it being a recurring problem. There is a recurring misunderstanding that attributes are applying to a type when they are defined as applying to the declaration.
What is type of an impure function that return a pure, extern(C) function n D ?
Apr 19 2013
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/19/2013 09:34 PM, deadalnix wrote:
 On Friday, 19 April 2013 at 19:06:39 UTC, Walter Bright wrote:
 On 4/19/2013 6:55 AM, deadalnix wrote:
 As of for 2 I'd rather have a standard way to have attribute binding
 to the
 return type or the declaration. This is a recurring problem, and auto
 is simply
 one instance of it.
I'm not understanding it being a recurring problem. There is a recurring misunderstanding that attributes are applying to a type when they are defined as applying to the declaration.
What is type of an impure function that return a pure, extern(C) function n D ?
Currently, it exists, yet cannot be named, and the formatted output of the compiler is wrong. alias extern(C) int function()pure P; P foo(){ return null; } pragma(msg, typeof(&foo)); => "extern (C) int function() pure function()"
Apr 19 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 19 April 2013 at 22:16:43 UTC, Timon Gehr wrote:
 Currently, it exists, yet cannot be named, and the formatted 
 output of the compiler is wrong.

 alias extern(C) int function()pure P;
 P foo(){ return null; }

 pragma(msg, typeof(&foo));

 => "extern (C) int function() pure function()"
Yes you have to use a alias to do this kind of thing. But some time, you can't alias (in case of inference for instance) and so can't choose what attribute bind to.
Apr 19 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/19/2013 11:12 PM, deadalnix wrote:
 But some time, you can't
 alias (in case of inference for instance) and so can't choose what attribute
 bind to.
Example, please.
Apr 19 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Saturday, 20 April 2013 at 06:25:09 UTC, Walter Bright wrote:
 On 4/19/2013 11:12 PM, deadalnix wrote:
 But some time, you can't alias (in case of inference for 
 instance) and so can't choose what attribute bind to.
Example, please.
Here you go: void foo(T)(extern(C) T function() function() f); Try making the extern(C) apply to each of: 1. the result of f() 2. the result of f()() without breaking foo()'s type inference.
Apr 20 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/20/2013 1:50 AM, Mehrdad wrote:
 On Saturday, 20 April 2013 at 06:25:09 UTC, Walter Bright wrote:
 On 4/19/2013 11:12 PM, deadalnix wrote:
 But some time, you can't alias (in case of inference for instance) and so
 can't choose what attribute bind to.
Example, please.
Here you go: void foo(T)(extern(C) T function() function() f); Try making the extern(C) apply to each of: 1. the result of f() 2. the result of f()() without breaking foo()'s type inference.
What I've been trying to explain is that there's a difference between a storage class attribute and a type constructor. When pure, for example, is used as a storage class attribute, it applies to the declaration always. When pure is used as a type constructor, it applies to the type, always. There is no ambiguity about this, and no problem about choice. For your example, for purity: void foo(T)(T function() pure function() pure f); The only issue here is that extern(C) is not currently supported as a type constructor. If it were, the example would look like: void foo(T)(T function() extern(C) function() extern(C) f); Again, there is no ambiguity.
Apr 20 2013
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/20/13, Walter Bright <newshound2 digitalmars.com> wrote:
 What I've been trying to explain is that there's a difference between a
 storage
 class attribute and a type constructor.
I've mentioned this before, but we need a good definition of these on dlang.org (for example people coming from other languages like Python will have no idea what these mean). Last time I mentioned it I didn't file a bug, but now I have: http://d.puremagic.com/issues/show_bug.cgi?id=9970 Hopefully someone with more knowledge of these can write some documentation.
Apr 20 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/19/2013 12:34 PM, deadalnix wrote:
 On Friday, 19 April 2013 at 19:06:39 UTC, Walter Bright wrote:
 On 4/19/2013 6:55 AM, deadalnix wrote:
 As of for 2 I'd rather have a standard way to have attribute binding to the
 return type or the declaration. This is a recurring problem, and auto is simply
 one instance of it.
I'm not understanding it being a recurring problem. There is a recurring misunderstanding that attributes are applying to a type when they are defined as applying to the declaration.
What is type of an impure function that return a pure, extern(C) function n D ?
A function foo: extern(C) int function()pure foo() { return null; } A type fp: alias extern(C) int function()pure function() fp;
Apr 19 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 20 April 2013 at 00:03:36 UTC, Walter Bright wrote:
 A function foo:

 extern(C) int function()pure foo() { return null; }
That is not it as foo is extern(C).
 A type fp:

 alias extern(C) int function()pure function() fp;
Same here. In general we lack a mechanism to choose what an attribute bind to.
Apr 19 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/19/2013 11:08 PM, deadalnix wrote:
 On Saturday, 20 April 2013 at 00:03:36 UTC, Walter Bright wrote:
 A function foo:

 extern(C) int function()pure foo() { return null; }
That is not it as foo is extern(C).
That is correct. I was thinking about the pure. The extern(C) can be done in a two step process, as Timon showed.
 In general we lack a mechanism to choose what an attribute bind to.
No, we don't. The attribute binds to the declaration. BTW, in C++ also you gotta do the extern "C" as a two step process to attach it to a function type.
Apr 19 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 20 April 2013 at 06:24:36 UTC, Walter Bright wrote:
 In general we lack a mechanism to choose what an attribute 
 bind to.
No, we don't. The attribute binds to the declaration.
In general we lack a mechanism to choose what direction we turn to. No, we don't. We always turn to the right.
Apr 19 2013
parent reply "Dicebot" <m.strashun gmail.com> writes:
On Saturday, 20 April 2013 at 06:32:50 UTC, deadalnix wrote:
 On Saturday, 20 April 2013 at 06:24:36 UTC, Walter Bright wrote:
 In general we lack a mechanism to choose what an attribute 
 bind to.
No, we don't. The attribute binds to the declaration.
In general we lack a mechanism to choose what direction we turn to. No, we don't. We always turn to the right.
I am quite sure Walter has meant that linkage attribute was not supposed to be tied to a type by design. If you want to use it, you need a symbol (==declaration) and there can be only one at a time.
Apr 20 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 20 April 2013 at 07:03:55 UTC, Dicebot wrote:
 On Saturday, 20 April 2013 at 06:32:50 UTC, deadalnix wrote:
 On Saturday, 20 April 2013 at 06:24:36 UTC, Walter Bright 
 wrote:
 In general we lack a mechanism to choose what an attribute 
 bind to.
No, we don't. The attribute binds to the declaration.
In general we lack a mechanism to choose what direction we turn to. No, we don't. We always turn to the right.
I am quite sure Walter has meant that linkage attribute was not supposed to be tied to a type by design. If you want to use it, you need a symbol (==declaration) and there can be only one at a time.
You don't need a symbol. They also control the ABI, and this isn't always related to a specific symbol.
Apr 20 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Saturday, 20 April 2013 at 07:18:42 UTC, deadalnix wrote:
 You don't need a symbol. They also control the ABI, and this 
 isn't always related to a specific symbol.
Well, this is how it probably should be. But looking at current D state I don't see if it was even planned. Can you have an extern without declaring some symbol at the same time within current D grammar?
Apr 20 2013
prev sibling parent "Jesse Phillips" <Jessekphillips+d gmail.com> writes:
On Thursday, 18 April 2013 at 05:59:20 UTC, kenji hara wrote:
 It will break existing code.

 int foo() {
     typeof(return) bar() { return 1; }
     return bar();
 }

 typeof(return) represents the return type of foo, that is int.

 Kenji Hara
It wouldn't break the code though. It would change the meaning, but the code would compile just as it did before.
Apr 18 2013
prev sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Tuesday, 16 April 2013 at 15:22:56 UTC, Andrei Alexandrescu 
wrote:
 There's a discussion that may be of interest to the larger 
 community: 
 https://github.com/D-Programming-Language/dmd/pull/1877

 Andrei
I just want to say I'm pretty gung-ho about the idea of attribute inference. If the interface files are blown up to their full explicit attributes, then the big problem of the PIMPL idiom could be solved, with modular programs getting all the info they need and the original source code still quite trim and easy to write. In the discussion of the possible uses of the 'scope' parameter attribute, and 'ref' safety in general, there's a lot of subtleties. One solution to the subtleties is additional attributes, which might be cumbersome to write individually, but easier if inference were on the table.
Apr 21 2013