www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mitigating the attribute proliferation - attribute inference for

reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
Sorry to open yet another topic.

I'm repeatedly finding myself in situations where I write functions like
this.

    private  property bool empty() const  safe pure nothrow  nogc
    {
        return impl is null || !impl.count;
    }

This is obviously a joke, because the compiler very well knows the
attributes and I don't need to guarantee them as part of an API.
The situation is getting somewhat out of hands and we need to find a way
to make attribute inference for functions feasible.

At the last D Meetup [¹] I had a nice chat with Dicebot about this.
We both had the same notion of how things should be. People should put
attributes on their exported API functions (or main() for apps), thereby
making API guarantees and transitively enforcing them, but the compiler
should infer attributes for internal functions.

This wouldn't help with separate compilation of modules, because the
compiler only knows the attributes of a function after semantically
analyzing it, but it works extremely well for libraries that are
compiled as batch.
And given that separate compilation is inherently inefficient anyhow,
it's well worth to look at this approach in more detail.

The main problem of attribute inference for functions presents as
follows on API borders.

/// An API function that guarantees certain attributes
public size_t foo(string a)  safe  nogc pure nothrow
{
    // and calls an internal function
    return impl(a);
}

/// An API template function with the same guarantees
public size_t bar(R)(R a)  safe  nogc pure nothrow
{
    // that calls an internal function
    return impl("something");
}

/// A function with inferred attributes
private size_t impl(string a)
{
    return a.length;
}

Applying attribute inference to `impl` would work for `foo` because code
calling `foo` doesn't need to check the attributes of `impl`, except
when foo gets inlined.
This doesn't work for the template function bar, because attributes are
checked when the template is instantiated, leaving us with the following
options on how the compiler could deal with missing attributes of a
function.

1) If that function has source code available, it gets semantically
analyzed and additional attributes are inferred.

2) The compiler errors because of missing attributes.

3) Don't inline functions when that would require to infer attributes of
a private/package function.

4) ???

Option 1 isn't really viable because it turns into a whole program
compilation model.

Option 2 is basically what we have today. Without a clear border of
where the compiler stops to analyze your implementation details, it'd
still be necessary to annotate every function.

Option 3 defines such a border which allows to use attribute inference
for internal functions. In the above example `bar` wouldn't work without
inference on `impl`, but it's possible to manually annotate the private
functions directly used by a template.

Those ideas aren't thought through too well, but it's an important issue
that requires a solution.

-Martin

[¹]: http://www.meetup.com/Berlin-D-Programmers/events/220702368/
Apr 11 2015
next sibling parent "w0rp" <devw0rp gmail.com> writes:
Shouldn't the inference with analysis be possible when you have 
the source available at least? You will still have to specify the 
attributes in a .di file if you are statically or dynamically 
linking to D libraries, but for source libraries or in parts of 
your project, you should be able to perform that inference.

That would at the very least reduce attributes to the boundaries 
of APIs.

// inferred
private void bar() {}
// inferred
private void baz() {}

 ngoc  safe pure nothrow
public void foo() { bar(); baz(); }

At some point in D,  safe should probably be the default, but 
that's a whole problem in itself.
Apr 11 2015
prev sibling next sibling parent reply "weaselcat" <weaselcat gmail.com> writes:
On Saturday, 11 April 2015 at 21:47:20 UTC, Martin Nowak wrote:

 Option 1 isn't really viable because it turns into a whole 
 program
 compilation model.
How does this differ from e.g, if the function was templated?
Apr 11 2015
parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 04/12/2015 12:35 AM, weaselcat wrote:
 How does this differ from e.g, if the function was templated?
It doesn't, if you decide to analyze each imported function to perform attribute inference, then that's just like treating all of them like template instances. This approach doesn't scale to bigger projects, because the compiler always has to analyze the complete source code. That's also the reason why an optimization was added to dmd whereby it doesn't instantiate templates, that are already instantiated in an imported module.
Apr 11 2015
parent reply "weaselcat" <weaselcat gmail.com> writes:
On Sunday, 12 April 2015 at 01:45:16 UTC, Martin Nowak wrote:
 On 04/12/2015 12:35 AM, weaselcat wrote:
 How does this differ from e.g, if the function was templated?
It doesn't, if you decide to analyze each imported function to perform attribute inference, then that's just like treating all of them like template instances. This approach doesn't scale to bigger projects, because the compiler always has to analyze the complete source code. That's also the reason why an optimization was added to dmd whereby it doesn't instantiate templates, that are already instantiated in an imported module.
I thought as much, that's unsettling because dmd is already starting to feel dog slow.
Apr 11 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Sunday, 12 April 2015 at 02:07:54 UTC, weaselcat wrote:
 I thought as much, that's unsettling because dmd is already 
 starting to feel dog slow.
We might have some sort of performance bug in the latest release. https://issues.dlang.org/show_bug.cgi?id=14431 If you know how to use a profiler, I'd be glad for more info.
Apr 12 2015
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Attribute inference works when the source to a function must exist (i.e. be 
available to the compiler). Currently, it is done for template functions and 
function literals.

At one point, I had implemented it for auto return functions, because the
source 
must exist for them, too, but it got a lot of resistance and was dropped.
Apr 12 2015
next sibling parent reply "weaselcat" <weaselcat gmail.com> writes:
On Sunday, 12 April 2015 at 07:12:47 UTC, Walter Bright wrote:
 Attribute inference works when the source to a function must 
 exist (i.e. be available to the compiler). Currently, it is 
 done for template functions and function literals.

 At one point, I had implemented it for auto return functions, 
 because the source must exist for them, too, but it got a lot 
 of resistance and was dropped.
Is this really an issue that comes up? How often do people in D not have access to the source of the libraries they're working with? Martin seemed to be advocating heavily for not inferring between packages, and using it to clean up internal functions. Is there a reason functions marked private and package couldn't infer? Is the main issue with this the extra compilation time it would take?
Apr 12 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/12/2015 12:33 AM, weaselcat wrote:
 Is there a reason functions marked private and package couldn't infer?
There's still an issue of a private function being called by a template, and the definition of that private function is compiled separately.
 Is the main issue with this the extra compilation time it would take?
No.
Apr 12 2015
parent reply "Martin Nowak" <code dawg.eu> writes:
On Sunday, 12 April 2015 at 08:55:17 UTC, Walter Bright wrote:
 There's still an issue of a private function being called by a 
 template, and the definition of that private function is 
 compiled separately.
That's the problem of the author of that template. He would still have to annotate that private function manually like today. But everything called by that function doesn't need to be attributed.
Apr 12 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/12/2015 2:55 AM, Martin Nowak wrote:
 On Sunday, 12 April 2015 at 08:55:17 UTC, Walter Bright wrote:
 There's still an issue of a private function being called by a template, and
 the definition of that private function is compiled separately.
That's the problem of the author of that template. He would still have to annotate that private function manually like today.
Keeping them in sync could be a problem, as the time errors are seen would be at link time.
 But everything called by that function doesn't need to be attributed.
Apr 12 2015
prev sibling next sibling parent "Martin Nowak" <code dawg.eu> writes:
On Sunday, 12 April 2015 at 07:12:47 UTC, Walter Bright wrote:
 At one point, I had implemented it for auto return functions, 
 because the source must exist for them, too, but it got a lot 
 of resistance and was dropped.
I thought that was already in, but it isn't. https://github.com/D-Programming-Language/dmd/pull/1877#issuecomment-16353774 The resistance to the pull this isn't directed against attribute inference but against the problems that may arise. Looks like we need to come up with a comprehensive proposal, that addresses those problems. Anyone wants to help with a DIP?
Apr 12 2015
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/12/15 12:12 AM, Walter Bright wrote:
 At one point, I had implemented it for auto return functions, because
 the source must exist for them, too, but it got a lot of resistance and
 was dropped.
It's perhaps time to revisit that. I think the resistance was not properly motivated at all. -- Andrei
Apr 12 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 12 April 2015 at 18:34:55 UTC, Andrei Alexandrescu 
wrote:
 On 4/12/15 12:12 AM, Walter Bright wrote:
 At one point, I had implemented it for auto return functions, 
 because
 the source must exist for them, too, but it got a lot of 
 resistance and
 was dropped.
It's perhaps time to revisit that. I think the resistance was not properly motivated at all. -- Andrei
Yes, I though it was more or less agreed upon, but nobody took the time to make it work. That would greatly help, please reconsider.
Apr 12 2015
parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Mon, Apr 13, 2015 at 01:29:15AM +0000, deadalnix via Digitalmars-d wrote:
 On Sunday, 12 April 2015 at 18:34:55 UTC, Andrei Alexandrescu wrote:
On 4/12/15 12:12 AM, Walter Bright wrote:
At one point, I had implemented it for auto return functions,
because the source must exist for them, too, but it got a lot of
resistance and was dropped.
It's perhaps time to revisit that. I think the resistance was not properly motivated at all. -- Andrei
Yes, I though it was more or less agreed upon, but nobody took the time to make it work. That would greatly help, please reconsider.
Resistance or not, I support expanding the scope of auto-inference. It's the only feasible long-term solution to attribute proliferation. T -- I see that you JS got Bach.
Apr 12 2015
prev sibling next sibling parent reply "Daniel N" <ufo orbiting.us> writes:
On Saturday, 11 April 2015 at 21:47:20 UTC, Martin Nowak wrote:
 Sorry to open yet another topic.

 I'm repeatedly finding myself in situations where I write 
 functions like
 this.

     private  property bool empty() const  safe pure nothrow 
  nogc
     {
         return impl is null || !impl.count;
     }
FYI, I wrote an enhancement request for this already. In case the discussion reaches a conclusion this time around, you might want to update the status: https://issues.dlang.org/show_bug.cgi?id=13567
Apr 12 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Sunday, 12 April 2015 at 09:42:19 UTC, Daniel N wrote:
 FYI, I wrote an enhancement request for this already. In case 
 the discussion reaches a conclusion this time around, you might 
 want to update the status:

 https://issues.dlang.org/show_bug.cgi?id=13567
Oh great, can you help me to turn this into a DIP? We need to define a sane behavior for when public templates call private functions. One idea I'm carrying around for some time is the following. For functions with inferred attributes the compiler could emit an additional alias symbol with the mangling of the function before the inference. That would allow to link against that function without running inference and still use inference for the same function internally. Note that this relies on covariant attributes, i.e. void foo() safe nogc pure nothrow is implicitly convertible to void foo() This could work out quite well, you only need to add attributes to your private functions to support public templates, but typically this should only be few entry points of your library. One problem arising from that is testing your API. ---- void tmpl(T)(T t) { return func(t.foo); } private void func(size_t v) { return v; } unittest safe nogc pure nothrow { static struct S { size_t foo; } tmpl(S()); // works here, but not outside of this module } ----
Apr 12 2015
prev sibling next sibling parent reply "Zach the Mystic" <reachzach gggmail.com> writes:
Please scan this thread for any useful ideas:

http://forum.dlang.org/post/vlzwhhymkjgckgyoxlrq forum.dlang.org

I don't have the technical expertise to know if it's useful or 
could work. The basic suggestion is that D has a function 
attribute which expressly indicates that a function is separately 
compiled, thus eliminating all ambiguity and mystery about what 
can and can't be inferred.
Apr 12 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Sunday, 12 April 2015 at 22:45:37 UTC, Zach the Mystic wrote:
 The basic suggestion is that D has a function attribute which 
 expressly indicates that a function is separately compiled, 
 thus eliminating all ambiguity and mystery about what can and 
 can't be inferred.
Yeah, as you already seem to know, we want to get `export` in shape to be usable for this and other purposes. See http://wiki.dlang.org/DIP45.
Apr 12 2015
prev sibling next sibling parent reply "Dicebot" <public dicebot.lv> writes:
I think point about `export` is important. Tying definition of 
"API" to `export` instead of `public` fits much better definition 
of those attributes (latter only guarantees symbol access, former 
also ensures cross-binary availablity) and allows for more 
explicit migration step (as `export` is widely underused right 
now).

Also the issue you have pointed out about API templates that call 
private functions is essentially same issue as Benjamin was 
pointing out here : 
http://forum.dlang.org/post/m9lhc3$1r1v$1 digitalmars.com

I can't propose good solution here right now but I do believe 
those 2 problems need to be solved in one step.
Apr 12 2015
parent "Dicebot" <public dicebot.lv> writes:
On Monday, 13 April 2015 at 05:52:47 UTC, Dicebot wrote:
 I think point about `export` is important. Tying definition of 
 "API" to `export` instead of `public` fits much better 
 definition of those attributes (latter only guarantees symbol 
 access, former also ensures cross-binary availablity) and 
 allows for more explicit migration step (as `export` is widely 
 underused right now).

 Also the issue you have pointed out about API templates that 
 call private functions is essentially same issue as Benjamin 
 was pointing out here : 
 http://forum.dlang.org/post/m9lhc3$1r1v$1 digitalmars.com

 I can't propose good solution here right now but I do believe 
 those 2 problems need to be solved in one step.
Although I'd still want to see dust around reference counting DIPs settled first to get a full attention on this matter and avoid commiting to premature solution.
Apr 13 2015
prev sibling next sibling parent reply "Kagamin" <spam here.lot> writes:
On Saturday, 11 April 2015 at 21:47:20 UTC, Martin Nowak wrote:
 1) If that function has source code available, it gets 
 semantically
 analyzed and additional attributes are inferred.

 2) The compiler errors because of missing attributes.
I'd say, if you have the function body, you can infer its attributes, else you have its signature annotated with attributes, then they are honored normally.
Apr 13 2015
parent "w0rp" <devw0rp gmail.com> writes:
On Monday, 13 April 2015 at 12:13:26 UTC, Kagamin wrote:
 On Saturday, 11 April 2015 at 21:47:20 UTC, Martin Nowak wrote:
 1) If that function has source code available, it gets 
 semantically
 analyzed and additional attributes are inferred.

 2) The compiler errors because of missing attributes.
I'd say, if you have the function body, you can infer its attributes, else you have its signature annotated with attributes, then they are honored normally.
I was saying the same before. If you have the source, do inference. If you don't, no inference will be done. I think that will remove a lot of typing already. There are many cases where it won't be able to infer the attributes, but it's still better than nothing.
Apr 13 2015
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/11/15 5:46 PM, Martin Nowak wrote:
 Sorry to open yet another topic.

 I'm repeatedly finding myself in situations where I write functions like
 this.

      private  property bool empty() const  safe pure nothrow  nogc
      {
          return impl is null || !impl.count;
      }

 This is obviously a joke, because the compiler very well knows the
 attributes and I don't need to guarantee them as part of an API.
 The situation is getting somewhat out of hands and we need to find a way
 to make attribute inference for functions feasible.
Have you considered the evolution of code? For example, what if a nogc-inferred function changes implementation and then uses the GC? The author of said function didn't care if it was nogc or not, but the compiler helpfully makes it nogc. But now, the authors code works (again, he didn't care), but anyone using it that does use nogc now cannot. The API changed but not on purpose. Now, I understand you only want to apply this inference to internal functions. The problem is, there aren't very many of those. In fact, your sample above is not an internal function, so this whole idea is useless for it. I fear this would be a change with a lot of work, and very little benefit. It is highly dependent on how much "impl" functions you have, and most of the time, using some kind of private implementation is to make all the work done in one place, and have many public API functions access it. It seems like the wrong level of cost to benefit. Sadly, I do not have a good answer. There are two purposes behind tagging a function, one is "because it is" and one is "because I want it to be". The first provides accessibility, the second is to double-check your API design against implementation. What we need is a way to say the first explicitly. We could do some kind of inferattributes attribute, but I don't know if this is better or worse, and I don't know what this will mean. Does it mean "the attributes on this can change, beware"? Is that useful for a public API? At the very least, it can say "I guarantee the body of this function will always be available." -Steve
Apr 13 2015
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Monday, 13 April 2015 at 14:09:22 UTC, Steven Schveighoffer 
wrote:
 On 4/11/15 5:46 PM, Martin Nowak wrote:
 Sorry to open yet another topic.

 I'm repeatedly finding myself in situations where I write 
 functions like
 this.

     private  property bool empty() const  safe pure nothrow 
  nogc
     {
         return impl is null || !impl.count;
     }

 This is obviously a joke, because the compiler very well knows 
 the
 attributes and I don't need to guarantee them as part of an 
 API.
 The situation is getting somewhat out of hands and we need to 
 find a way
 to make attribute inference for functions feasible.
Have you considered the evolution of code? For example, what if a nogc-inferred function changes implementation and then uses the GC? The author of said function didn't care if it was nogc or not, but the compiler helpfully makes it nogc.
This is exactly what "explicit API" thing is about. If symbol is `export` it must have explicit attributes. If it isn't, inferring is fine because no promises are actually made.
Apr 13 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/13/15 10:23 AM, Dicebot wrote:
 On Monday, 13 April 2015 at 14:09:22 UTC, Steven Schveighoffer wrote:
 On 4/11/15 5:46 PM, Martin Nowak wrote:
 Sorry to open yet another topic.

 I'm repeatedly finding myself in situations where I write functions like
 this.

     private  property bool empty() const  safe pure nothrow  nogc
     {
         return impl is null || !impl.count;
     }

 This is obviously a joke, because the compiler very well knows the
 attributes and I don't need to guarantee them as part of an API.
 The situation is getting somewhat out of hands and we need to find a way
 to make attribute inference for functions feasible.
Have you considered the evolution of code? For example, what if a nogc-inferred function changes implementation and then uses the GC? The author of said function didn't care if it was nogc or not, but the compiler helpfully makes it nogc.
This is exactly what "explicit API" thing is about. If symbol is `export` it must have explicit attributes. If it isn't, inferring is fine because no promises are actually made.
I thought 'export' was for dll/so? In order for this to work, code that is "external" better not be able to call any non-export functions. This is not a change I think we should pursue. -Steve
Apr 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Monday, 13 April 2015 at 14:42:33 UTC, Steven Schveighoffer 
wrote:
 This is exactly what "explicit API" thing is about. If symbol 
 is
 `export` it must have explicit attributes. If it isn't, 
 inferring is
 fine because no promises are actually made.
I thought 'export' was for dll/so?
It is necessary for dll/so but the very same definition makes it naturally suitable for denoting any API that must persist through binary boundaries. It does not have any special effects other than simply saying "this symbol must be accessible externally".
 In order for this to work, code that is "external" better not 
 be able to call any non-export functions. This is not a change 
 I think we should pursue.
Why so? It is only a problem for export templates, because compiler can't verify the attributes until it is instantiated. For fixed symbols there are no restrictions on what can be called - all called functions have attributes inferred and compiler verifies that result matches what programmer has put on API function itself.
Apr 13 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/13/15 10:49 AM, Dicebot wrote:
 On Monday, 13 April 2015 at 14:42:33 UTC, Steven Schveighoffer wrote:
 This is exactly what "explicit API" thing is about. If symbol is
 `export` it must have explicit attributes. If it isn't, inferring is
 fine because no promises are actually made.
I thought 'export' was for dll/so?
It is necessary for dll/so but the very same definition makes it naturally suitable for denoting any API that must persist through binary boundaries. It does not have any special effects other than simply saying "this symbol must be accessible externally".
For instance, no phobos code has export attributes. I've never written one for my private libraries either.
 In order for this to work, code that is "external" better not be able
 to call any non-export functions. This is not a change I think we
 should pursue.
Why so? It is only a problem for export templates, because compiler can't verify the attributes until it is instantiated. For fixed symbols there are no restrictions on what can be called - all called functions have attributes inferred and compiler verifies that result matches what programmer has put on API function itself.
It's a problem for any API code that is not a template, because it currently does not have inferred attributes, but now it will because you didn't put "export" on it. This means you have assumed that every piece of code written without "export" is not public API, when in most cases, it actually is because it's public. Or am I reading this wrong? -Steve
Apr 13 2015
parent "Dicebot" <public dicebot.lv> writes:
On Monday, 13 April 2015 at 15:47:44 UTC, Steven Schveighoffer 
wrote:
 On 4/13/15 10:49 AM, Dicebot wrote:
 On Monday, 13 April 2015 at 14:42:33 UTC, Steven Schveighoffer 
 wrote:
 This is exactly what "explicit API" thing is about. If 
 symbol is
 `export` it must have explicit attributes. If it isn't, 
 inferring is
 fine because no promises are actually made.
I thought 'export' was for dll/so?
It is necessary for dll/so but the very same definition makes it naturally suitable for denoting any API that must persist through binary boundaries. It does not have any special effects other than simply saying "this symbol must be accessible externally".
For instance, no phobos code has export attributes. I've never written one for my private libraries either.
Yep, this is one of reason I think this is lucky coincidence. See below.
 In order for this to work, code that is "external" better not 
 be able
 to call any non-export functions. This is not a change I 
 think we
 should pursue.
Why so? It is only a problem for export templates, because compiler can't verify the attributes until it is instantiated. For fixed symbols there are no restrictions on what can be called - all called functions have attributes inferred and compiler verifies that result matches what programmer has put on API function itself.
It's a problem for any API code that is not a template, because it currently does not have inferred attributes, but now it will because you didn't put "export" on it. This means you have assumed that every piece of code written without "export" is not public API, when in most cases, it actually is because it's public. Or am I reading this wrong?
What I mean is that right now literally no one actually states any clear API stability, attribute inference or not. Sometimes it happens to work, sometimes it doesn't - there is no culture of providing such guarantees. The fact that export is almost unused provides and opportunity to set up such culture in a way endorsed by a language - by stating intended purpose in release X, fixing it for shared libraries in release X+1 and enabling attribute inferences in releases X+2 / X+3 (optionally -> mandatory). That way people will be forced to slowly review their code to actually make decisions what IS public API and how it must be defined. Saying that current public methods define API is incredibly far from truth unless you mean only Phobos. I'd like that to become explicit deliberate decision in the long term.
Apr 13 2015
prev sibling parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 04/13/2015 04:09 PM, Steven Schveighoffer wrote:
 
 Now, I understand you only want to apply this inference to internal
 functions. The problem is, there aren't very many of those.
What? Phobos is a special case, not the norm. A typical library consists of an API and an implementation. Think of OpenSSL, zip, curl, freetype, a rasterizer, a web framework, a database client.
Jul 17 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/17/15 8:45 AM, Martin Nowak wrote:
 On 04/13/2015 04:09 PM, Steven Schveighoffer wrote:
 Now, I understand you only want to apply this inference to internal
 functions. The problem is, there aren't very many of those.
What? Phobos is a special case, not the norm. A typical library consists of an API and an implementation. Think of OpenSSL, zip, curl, freetype, a rasterizer, a web framework, a database client.
Sorry, I'm trying to recollect my thoughts here, this was 3 months ago. Looking at your request, it seems reasonable, maybe I didn't read it with the right mindset. But I'm not 100% sure what it is you are asking. Are you asking for function attribute inference on all functions, or just on private ones? I can see that private functions probably can have attribute inference since they are only accessible from within the module, obviously the source is always available to other functions being compiled in the module, and it's not part of the public API. If you are asking to be able to infer attributes on public functions, I don't think we should do that. My point may have been that the bulk of functions written are public, especially for aggregate types like classes or structs. I don't think that's atypical. -Steve
Jul 20 2015
prev sibling next sibling parent "Elie Morisse" <syniurge gmail.com> writes:
Freeing D users from the burden of writing redundant attributes 
that the compiler can infer would be a fantastic enhancement imo.

For public functions I was thinking of a way to make inference 
safer: generating a .di file with the inferred attributes and 
auto substituted by the return type, and then make the compiler 
check the inferred attributes against the previous ones and 
trigger an error if there was an API breakage, forcing the 
programmer to acknowledge it by removing the function from the 
.di file, or by fixing the function to match its previous 
signature. Would this make inference safe enough for public 
functions?
Apr 13 2015
prev sibling parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
I have to bring this up again, b/c I consider the heavy investment in
attributes one of the worst decisions lately.

It's very very hard and time consuming to write attribute correct code.

Consider dup
(https://github.com/D-Programming-Language/druntime/pull/760) a
seemingly simple piece, blown up 2-3x in complexity to deal with all the
attribute/inference craze.

This is how move would look like to support  safe inference.

void move(T)(ref T source, ref T target)
{
        if (()  trusted { return &source == &target; }()) return;
        // Most complicated case. Destroy whatever target had in it
        // and bitblast source over it
        static if (hasElaborateDestructor!T) ()  trusted {
typeid(T).destroy(&target); }();

        static if (hasElaborateAssign!T || !isAssignable!T)
            ()  trusted { memcpy(&target, &source, T.sizeof); }();
        else
            target = source;

        // If the source defines a destructor or a postblit hook, we
must obliterate the
        // object in order to avoid double freeing and undue aliasing
        static if (hasElaborateDestructor!T ||
hasElaborateCopyConstructor!T)
        {
            // If T is nested struct, keep original context pointer
            static if (__traits(isNested, T))
                enum sz = T.sizeof - (void*).sizeof;
            else
                enum sz = T.sizeof;

            auto init = typeid(T).init();
            ()  trusted {
                if (init.ptr is null) // null ptr means initialize to 0s
                    memset(&source, 0, sz);
                else
                    memcpy(&source, init.ptr, sz);
            }();
        }
}


There is a 3x overhead to write correct smart pointers/refs when taking
attributes into account. I don't think this complexity and ugliness is
justified.

=================== Attributes are hardly useful ======================

The assumption that code with attributes is better than code without
attributes is flawed.

- nothrow

  Nice, the compiler must not emit exception handling code, but the real
problem is how bad dmd's EH code is.
https://issues.dlang.org/show_bug.cgi?id=12442
  State of the art EH handling is almost "zero cost", particularly if
compared to other error handling schemes.

-  nogc

  Why is this needed on a per function level? If one doesn't want to use
the GC it could be disabled on a per-thread or per-process level.
  We now have a GC profiler, which is a good tool to find unwanted
allocations.
  Of course we need to change many phobos functions to avoid
allocations, but  nogc doesn't help us to design better APIs.

- pure

  The compiler can reuse the result of a strongly pure function call,
  but compilers can do CSE [¹] for ages. CSE requires inlining to determine
  whether a function has a sideeffect, but reusing of results is almost
exclusively useful for functions that are small enough to be inlined anyhow.

  The result of a strongly pure functions has unique ownership and can
be implicitly cast to immutable. Nice insight, but is that any good?

-  safe

  Nice idea in theory, but why not do this as a compiler switch for the
modules being compiled (with an  unsafe {} guard).
  The way we do it currently with  trusted/ safe doesn't guarantee
anything for  trusted/ safe foreign code anyhow.

-Martin

[¹]: https://en.wikipedia.org/wiki/Common_subexpression_elimination
Jul 17 2015
next sibling parent reply "Kagamin" <spam here.lot> writes:
On Friday, 17 July 2015 at 12:43:33 UTC, Martin Nowak wrote:
 The assumption that code with attributes is better than code 
 without attributes is flawed.

 - nothrow

   Nice, the compiler must not emit exception handling code, but 
 the real
 problem is how bad dmd's EH code is.
 https://issues.dlang.org/show_bug.cgi?id=12442
   State of the art EH handling is almost "zero cost", 
 particularly if
 compared to other error handling schemes.
nothrow is not only performance, but also semantics. Yeah, an optimization was planned to not run cleanups on Error, without it you can't inline cleanups, and nothrow functions can throw Errors.
 -  nogc

   Why is this needed on a per function level? If one doesn't 
 want to use
 the GC it could be disabled on a per-thread or per-process 
 level.
   We now have a GC profiler, which is a good tool to find 
 unwanted
 allocations.
   Of course we need to change many phobos functions to avoid
 allocations, but  nogc doesn't help us to design better APIs.
Hmm, it sounds interesting to make nogc a language option instead of function attribute.
 - pure

   The compiler can reuse the result of a strongly pure function 
 call,
   but compilers can do CSE [¹] for ages. CSE requires inlining 
 to determine
   whether a function has a sideeffect, but reusing of results 
 is almost
 exclusively useful for functions that are small enough to be 
 inlined anyhow.
You don't always have the source for the function, and currently purity needs only the function signature alone. Also a function attribute allows to enforce purity.
 -  safe

   Nice idea in theory, but why not do this as a compiler switch 
 for the
 modules being compiled (with an  unsafe {} guard).
   The way we do it currently with  trusted/ safe doesn't 
 guarantee
 anything for  trusted/ safe foreign code anyhow.
You mean SafeD allows unsafe code?
Jul 17 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 14:32:35 UTC, Kagamin wrote:
 You don't always have the source for the function, and 
 currently purity needs only the function signature alone. Also 
 a function attribute allows to enforce purity.
If you don't have the source, e.g. it's in a foreign library, then the function is likely heavyweight and you'll cache it yourself. You wouldn't call fib(30) or sin(x) anytime you need it and rely on the compiler to figure out the refusing.
Jul 17 2015
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 17-Jul-2015 15:43, Martin Nowak wrote:
 I have to bring this up again, b/c I consider the heavy investment in
 attributes one of the worst decisions lately.

 It's very very hard and time consuming to write attribute correct code.
For sure. Personally I ignore all but pure and nothrow. Not in Phobos however... [snip]
 =================== Attributes are hardly useful ======================

 The assumption that code with attributes is better than code without
 attributes is flawed.
 -  nogc

    Why is this needed on a per function level? If one doesn't want to use
 the GC it could be disabled on a per-thread or per-process level.
    We now have a GC profiler, which is a good tool to find unwanted
 allocations.
    Of course we need to change many phobos functions to avoid
 allocations, but  nogc doesn't help us to design better APIs.
Agreed. Not only no-allocation crowd had expressed the concern in going only nogc but not noheap route but it's pretty redundant compared to all the other tools and niche enough to not bring much to the table.
 -  safe

    Nice idea in theory, but why not do this as a compiler switch for the
 modules being compiled (with an  unsafe {} guard).
    The way we do it currently with  trusted/ safe doesn't guarantee
 anything for  trusted/ safe foreign code anyhow.
` safe` is still both poorly specified (on exception rather then allowance basis) and leaves a lot to be desired w.r.t. trusted blocks in otherwise safe code. Not to mention the unfortunate interplay with templates where you need an unsafe operation but don't want to blindly accept potential unsafety of the user-defined type itself.
 - nothrow

    Nice, the compiler must not emit exception handling code, but the real
 problem is how bad dmd's EH code is.
 https://issues.dlang.org/show_bug.cgi?id=12442
    State of the art EH handling is almost "zero cost", particularly if
 compared to other error handling schemes.
There is huge value in this. Even C++ choose to add noexcept into otherwise exteramly complicated language. nothrow is all about semnatics not only performance, e.g. I can write tryivial exception-safe code if I choose to accept only nothrow callbacks.
 - pure

    The compiler can reuse the result of a strongly pure function call,
    but compilers can do CSE [¹] for ages. CSE requires inlining to determine
    whether a function has a sideeffect, but reusing of results is almost
 exclusively useful for functions that are small enough to be inlined anyhow.
CSE is cool but need something both simpler and working with binary libraries and separate compilation.
    The result of a strongly pure functions has unique ownership and can
 be implicitly cast to immutable. Nice insight, but is that any good?
pure and nothrow actually about the only ones bringing the benefit to outweight the cost I esp. like how immutable + pure goes nicely with FP classics. -- Dmitry Olshansky
Jul 17 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 15:24:46 UTC, Dmitry Olshansky wrote:
 There is huge value in this. Even C++ choose to add noexcept 
 into otherwise exteramly complicated language.
https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
Jul 17 2015
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, 17 July 2015 at 12:43:33 UTC, Martin Nowak wrote:
 =================== Attributes are hardly useful 
 ======================
nothrow and pure - pure especially - help with reasoning about code. You actually lose out a fair bit with them IMHO when they're inferred, since a lot of their value is derived from the programmer knowing for sure that a function is nothrow or pure. pure then allows for some other nice stuff from the compiler like optimizations and implicit casting, but I suspect that the compiler really isn't taking advantage of it like it should. For nothrow, I'm not sure of how much value the optimization opportunities are, though having the compiler scream at you when you mark something as nothrow is definitely useful when it isn't actually nothrow. In principle, safe is great, though it's going to be worse in druntime and Phobos, because we're more likely to interacting with the C APIs. However, it has way too many holes in it still, because we've blacklisted rather than whitelisted, and it's arguably a disaster with templates if you have to do anything which is system, because you have to make sure that you only use trusted on stuff that you've actually verified and not stuff being called on template arguments. So, the situation with safe is worse than it should be, but I also think that it would be a mistake to get rid of it rather than fix it. It should be recognized though that thanks to trusted, it doesn't really guarantee memory safety. It just restricts the number of places that you have to look when you screw it up (which is quite valuable, but it's not the same at all as guaranteeing memory safety). nogc is mostly a PR thing IMHO. It has value in that it helps you find places where you accidentally used the GC (though if you really care, you can always use the profiler as you point out), and if nogc is marked explicitly, it makes it easier to see which functions can be used in nogc code, but ultimately, it really seems like it's there simply to appease the folks who don't want any GC usage at all. Overall, I think that we're between a rock and a hard place, because in many ways, a lot of the benefit of attributes come from the fact that they're marked explicitly on the API, so having tons of attribute inference would actually make them worse in that regard. Also, adding attributes automatically could result in effectively giving guarantees about functions which aren't intended - especially if the inferred attributes end up in the docs for non-templated functions. Honestly, what we should do if we don't care about code breakage is make pure and safe the default, since they really should be the rule rather than the exception. That would reduce the problem considerably. But the problem is that that breaks code, and without safe whitelisting stuff instead of blacklisting it, it would probably make the breakage related to fixing safe holes even worse. So, I very much doubt that we can do it at this point, much as that's really where we want to be. - Jonathan M Davis
Jul 17 2015
next sibling parent "ponce" <contact gam3sfrommars.fr> writes:
On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
  nogc is mostly a PR thing IMHO. It has value in that it helps 
 you find places where you accidentally used the GC (though if 
 you really care, you can always use the profiler as you point 
 out), and if  nogc is marked explicitly, it makes it easier to 
 see which functions can be used in  nogc code, but ultimately, 
 it really seems like it's there simply to appease the folks who 
 don't want any GC usage at all.
I thought it was a PR thing, but because few things use malloc implicitely and nogc enforce no GC, I find it actually useful to check if a function does zero allocations. Not the worst attribute.
 Honestly, what we should do if we don't care about code 
 breakage is make pure and  safe the default, since they really 
 should be the rule rather than the exception. That would reduce 
 the problem considerably. But the problem is that that breaks 
 code, and without  safe whitelisting stuff instead of 
 blacklisting it, it would probably make the breakage related to 
 fixing  safe holes even worse. So, I very much doubt that we 
 can do it at this point, much as that's really where we want to 
 be.
Please no. Code is born ugly and then gets better and attributed. For scripting and peace of mind, D gets every default right; it's just that some attributes are not really worth it and should be killed imho.
Jul 17 2015
prev sibling next sibling parent "rsw0x" <anonymous anonymous.com> writes:
On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
  nogc is mostly a PR thing IMHO. It has value in that it helps 
 you find places where you accidentally used the GC (though if 
 you really care, you can always use the profiler as you point 
 out), and if  nogc is marked explicitly, it makes it easier to 
 see which functions can be used in  nogc code, but ultimately, 
 it really seems like it's there simply to appease the folks who 
 don't want any GC usage at all.
nogc is great for making sure code doesn't allocate(by GC means, anyways.)
Jul 17 2015
prev sibling next sibling parent reply "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
 On Friday, 17 July 2015 at 12:43:33 UTC, Martin Nowak wrote:
 =================== Attributes are hardly useful 
 ======================
nothrow and pure - pure especially - help with reasoning about code. You actually lose out a fair bit with them IMHO when they're inferred, since a lot of their value is derived from the programmer knowing for sure that a function is nothrow or pure.
But I already know if a function is "logically" pure or not from what it does. http.get -> impure writeln -> impure swap -> pure reduce/map/filter/any algo -> pure containers -> pure (no longer when they use std.allocator?) gettime -> impure random -> impure format string -> pure fib -> pure (even when using a TLS memorization) Using global state in a non-obvious way is an indicator for bad code.
Jul 17 2015
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, 17 July 2015 at 17:36:08 UTC, Martin Nowak wrote:
 On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
 On Friday, 17 July 2015 at 12:43:33 UTC, Martin Nowak wrote:
 =================== Attributes are hardly useful 
 ======================
nothrow and pure - pure especially - help with reasoning about code. You actually lose out a fair bit with them IMHO when they're inferred, since a lot of their value is derived from the programmer knowing for sure that a function is nothrow or pure.
But I already know if a function is "logically" pure or not from what it does. http.get -> impure writeln -> impure swap -> pure reduce/map/filter/any algo -> pure containers -> pure (no longer when they use std.allocator?) gettime -> impure random -> impure format string -> pure fib -> pure (even when using a TLS memorization) Using global state in a non-obvious way is an indicator for bad code.
Yes, but being able to have the compiler guarantee it is useful, and we've already seen some benefits from it in terms of implicit casts. I don't think that we've gotten the optimization benefits out of it that we should though. And while it's usually obvious that there's no global state, it's not always obvious - especially when you're dealing with higher level functions - and you can inadvertently end up with global state if a function buried in the chain didn't behave. Honestly, I think that pure is the biggest win out of all of the various attributes. - Jonathan M Davis
Jul 17 2015
prev sibling parent "Kagamin" <spam here.lot> writes:
On Friday, 17 July 2015 at 17:36:08 UTC, Martin Nowak wrote:
 gettime -> impure
Convert UTC time to local time -> pure?
 random -> impure
People expressed concerns about reproducibility of PRNG output, which among other things requires them to be pure.
 format string -> pure
Doesn't it depend on locale? Though that dependency is probably unimportant.
 Using global state in a non-obvious way is an indicator for bad 
 code.
Convert relative path to absolute path -> pure? thread-safe? bad design? Just nitpicking, but anyway.
Jul 18 2015
prev sibling parent reply "jmh530" <john.michael.hall gmail.com> writes:
On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
 However, it has way too many holes in it still, because we've 
 blacklisted rather than whitelisted
Not being a fan of constantly writing these attributes, I had been thinking a month or so ago that it would be cool if you could just specify defaults for the function attributes on a module-by-module basis. However, it's pretty easy to just set something similar up using the existing language features. import std.traits; safe { int foo(int x) { return x * 2; } int bar(int x) system { return x * 2; } } void main() { static assert(functionAttributes!foo & FunctionAttribute.safe); static assert(functionAttributes!bar & FunctionAttribute.system); } It even generates the correct documentation that foo is safe and bar is system. I think this might be similar to Martin Nowak's point about unsafe { } guards, but I'm not entirely sure what he meant.
Jul 17 2015
next sibling parent "extrawurst" <stephan extrawurst.org> writes:
On Friday, 17 July 2015 at 18:23:58 UTC, jmh530 wrote:
 On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
 [...]
Not being a fan of constantly writing these attributes, I had been thinking a month or so ago that it would be cool if you could just specify defaults for the function attributes on a module-by-module basis. However, it's pretty easy to just set something similar up using the existing language features. [...]
also pretty useful: safe: ...
Jul 17 2015
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 17 July 2015 at 18:23:58 UTC, jmh530 wrote:
 On Friday, 17 July 2015 at 16:40:56 UTC, Jonathan M Davis wrote:
 However, it has way too many holes in it still, because we've 
 blacklisted rather than whitelisted
Not being a fan of constantly writing these attributes, I had been thinking a month or so ago that it would be cool if you could just specify defaults for the function attributes on a module-by-module basis. However, it's pretty easy to just set something similar up using the existing language features.
Yes, and in case you don't know yet, you don't even need braces: module test; safe: // everything from here on is safe
Jul 18 2015
prev sibling next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 17 July 2015 at 12:43:33 UTC, Martin Nowak wrote:
 - nothrow

   Nice, the compiler must not emit exception handling code, but 
 the real
 problem is how bad dmd's EH code is.
 https://issues.dlang.org/show_bug.cgi?id=12442
   State of the art EH handling is almost "zero cost", 
 particularly if
 compared to other error handling schemes.
As others have pointed out, it's an important semantic distinction. The performance gains (if any) are secondary.
 -  nogc

   Why is this needed on a per function level? If one doesn't 
 want to use
 the GC it could be disabled on a per-thread or per-process 
 level.
   We now have a GC profiler, which is a good tool to find 
 unwanted
 allocations.
   Of course we need to change many phobos functions to avoid
 allocations, but  nogc doesn't help us to design better APIs.
Disagree here, too. Thread, process or module level is too coarse. nogc as an attribute allows to avoid the GC on those levels, but can also be used in a much finer-grained way.
 - pure

   The compiler can reuse the result of a strongly pure function 
 call,
   but compilers can do CSE [¹] for ages. CSE requires inlining 
 to determine
   whether a function has a sideeffect, but reusing of results 
 is almost
 exclusively useful for functions that are small enough to be 
 inlined anyhow.
Agreed, that's probably unimportant.
   The result of a strongly pure functions has unique ownership 
 and can
 be implicitly cast to immutable. Nice insight, but is that any 
 good?
Yes, definitely. Uniqueness is an important property, and we just don't utilize it properly yet. I believe what we have right now is barely the beginning.
 -  safe

   Nice idea in theory, but why not do this as a compiler switch 
 for the
 modules being compiled (with an  unsafe {} guard).
Not sure I understand the part in parentheses. Likely, module level will be too coarse. Or do you mean we should have safe-by-default, but only opt out of it with an unsafe block, which however only works with a particular compiler switch? I don't see much use for such a switch. (Of course, there are various other problems with the current concept and implementation.) In general, I'm not sure why you choose to go the way of abolishing the attributes. Didn't you have a concept for inference that would mostly solve the problems?
Jul 17 2015
parent reply "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 17:54:52 UTC, Marc Schütz wrote:
 In general, I'm not sure why you choose to go the way of 
 abolishing the attributes. Didn't you have a concept for 
 inference that would mostly solve the problems?
Because I want to overhaul smart pointers/refs (Unique, RC). A seemingly trivial task, should take a few hours, but I already spent days to hack around all the attribute issues.
Jul 17 2015
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, 17 July 2015 at 18:11:46 UTC, Martin Nowak wrote:
 On Friday, 17 July 2015 at 17:54:52 UTC, Marc Schütz wrote:
 In general, I'm not sure why you choose to go the way of 
 abolishing the attributes. Didn't you have a concept for 
 inference that would mostly solve the problems?
Because I want to overhaul smart pointers/refs (Unique, RC). A seemingly trivial task, should take a few hours, but I already spent days to hack around all the attribute issues.
Lower level template code is definitely where attributes are hell. - Jonathan M Davis
Jul 17 2015
prev sibling next sibling parent reply "Jack Stouffer" <jack jackstouffer.com> writes:
On Friday, 17 July 2015 at 18:11:46 UTC, Martin Nowak wrote:
 Because I want to overhaul smart pointers/refs (Unique, RC).
 A seemingly trivial task, should take a few hours, but I 
 already spent days to hack around all the attribute issues.
I think the axiom "make it hard for engineers so it's easy for users" applies here. As others have said safe, pure, nothrow, and nogc, while they could be improved somewhat, have value in that they provide guarantees to the programmer (user) and API end users. One thing that no one has mentioned is that nogc lets me know which part of my program is using GC allocations without reaching for a profiler. Saying "just use -profile=gc" would be like always reaching for gdb when printf will solve your problem faster. This however, makes the phobos maintainer (engineers) job harder, and I respect that. But, as a casual D user, I think attributes make D a better language.
Jul 17 2015
parent reply "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 19:14:21 UTC, Jack Stouffer wrote:
 As others have said  safe, pure, nothrow, and  nogc, while they 
 could be improved somewhat, have value in that they provide 
 guarantees to the programmer (user) and API end users.
As I mentioned, safe doesn't provide any guarantee and pure/nothrow provide nice guarantees, but ones that should be a matter of course depending on the API.
 One thing that no one has mentioned is that  nogc lets me know 
 which part of my program is using GC allocations without 
 reaching for a profiler.
Except that it hardly works, b/c noone made the effort to attribute all of druntime/phobos. We also have the -vgc switch btw.
 This however, makes the phobos maintainer (engineers) job 
 harder, and I respect that. But, as a casual D user, I think 
 attributes make D a better language.
One of our biggest issues is the lack of good contributions, so deciding to spend a significant overhead on attributes is a big deal, which I doubt will ever pay off.
Jul 17 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 22:16:03 UTC, Martin Nowak wrote:
 One of our biggest issues is the lack of good contributions
Let's better say our small dev resources and the slow pace.
Jul 17 2015
prev sibling parent reply "Meta" <jared771 gmail.com> writes:
On Friday, 17 July 2015 at 18:11:46 UTC, Martin Nowak wrote:
 On Friday, 17 July 2015 at 17:54:52 UTC, Marc Schütz wrote:
 In general, I'm not sure why you choose to go the way of 
 abolishing the attributes. Didn't you have a concept for 
 inference that would mostly solve the problems?
Because I want to overhaul smart pointers/refs (Unique, RC). A seemingly trivial task, should take a few hours, but I already spent days to hack around all the attribute issues.
What are the specific issues? I've encountered attribute hell as well, but with const/immutable/inout as opposed to pure/nothrow/ nogc/ safe.
Jul 17 2015
parent "Martin Nowak" <code dawg.eu> writes:
On Friday, 17 July 2015 at 19:23:23 UTC, Meta wrote:
 What are the specific issues? I've encountered attribute hell 
 as well, but with const/immutable/inout as opposed to 
 pure/nothrow/ nogc/ safe.
Just to name 2 issues. I can't convert derived classes with a destructor to their base class without constructor b/c the latter doesn't have attributes. https://github.com/MartinNowak/phobos/commit/1bac938f28110f1ab2ba797adae7ab4611245cc2?diff=unified#diff-4e008aedb3026d4a84f58323e53bf017R50 https://github.com/MartinNowak/phobos/commit/1bac938f28110f1ab2ba797adae7ab4611245cc2?diff=unified#diff-4e008aedb3026d4a84f58323e53bf017R274 Inference totally fails if you mix lowlevel library code with UDTs, e.g. for constructing, copying, destroying.
Jul 17 2015
prev sibling parent "Kagamin" <spam here.lot> writes:
On Friday, 17 July 2015 at 12:43:33 UTC, Martin Nowak wrote:
 This is how move would look like to support  safe inference.

 void move(T)(ref T source, ref T target)
 {
         if (()  trusted { return &source == &target; }()) 
 return;
         // Most complicated case. Destroy whatever target had 
 in it
         // and bitblast source over it
         static if (hasElaborateDestructor!T) ()  trusted {
 typeid(T).destroy(&target); }();

         static if (hasElaborateAssign!T || !isAssignable!T)
             ()  trusted { memcpy(&target, &source, T.sizeof); 
 }();
This looks complicated by safety, while other attributes are inferred transparently.
Jul 18 2015