February 07, 2013
On Wed, Feb 06, 2013 at 10:09:48PM -0800, Walter Bright wrote:
> On 2/6/2013 8:16 PM, Marco Leise wrote:
> >As for the address taking, I hope it doesn't end up in being nannied to much by the language. Like in the case with printf, it could really piss people off that don't understand the reasoning behind it. Make the error message informative for that: "Potential escape of pointer to stack local" or similar.
> 
> I think C++ missed an opportunity with reference types. All they are in C++ are just another way to express a pointer. They don't really offer any semantic improvement - you can even have null references.
> 
> In D, we have an opportunity to define reference types as a kind of "safe" pointer type - where we can get much of the advantages of pointers without the potential for memory corruption.

D ref types are currently highly crippled because of the inability to declare ref variables, which mandates ugly workarounds. It should be a first-class type qualifier IMO. (Yes I know it's currently a *function* qualifier, not a type qualifier... which makes it all the more ugly.)


T

-- 
Дерево держится корнями, а человек - друзьями.
February 07, 2013
On 2/7/13 1:34 AM, H. S. Teoh wrote:
> On Wed, Feb 06, 2013 at 10:09:48PM -0800, Walter Bright wrote:
>> On 2/6/2013 8:16 PM, Marco Leise wrote:
>>> As for the address taking, I hope it doesn't end up in being
>>> nannied to much by the language. Like in the case with printf,
>>> it could really piss people off that don't understand the
>>> reasoning behind it. Make the error message informative for
>>> that: "Potential escape of pointer to stack local" or
>>> similar.
>>
>> I think C++ missed an opportunity with reference types. All they are
>> in C++ are just another way to express a pointer. They don't really
>> offer any semantic improvement - you can even have null references.
>>
>> In D, we have an opportunity to define reference types as a kind of
>> "safe" pointer type - where we can get much of the advantages of
>> pointers without the potential for memory corruption.
>
> D ref types are currently highly crippled because of the inability to
> declare ref variables, which mandates ugly workarounds. It should be a
> first-class type qualifier IMO. (Yes I know it's currently a *function*
> qualifier, not a type qualifier... which makes it all the more ugly.)

Unfortunately type qualifiers have very high complexity costs. I think it's very neat that we managed to keep ref the way it is. Yes, I, too, would like to have a ref variable sometimes, but overall I'm please with the way it's working (post DIP25 especially).

Andrei
February 07, 2013
Am Wed, 06 Feb 2013 23:45:51 +0100
schrieb Robert <jfanatiker@gmx.at>:

> What happened to the scope storage class for parameters.
> 
> Wouldn't this solve the problems, with the simple rule that you are not allowed to pass transient objects by reference if the parameter was not declared with scope? And if I understood correctly, the compiler is already capable of locally ensuring that the address does not escape (to ensure the scope requirement), so we are all set?

This is an important question. How would this new proposal interact with scope parameters?

Scope parameters could at least:
* Allow some otherwise trusted code to be safe:
---------
@trusted bool parse1(ref double v) {
    // Use C's scanf
    return scanf("%f", addressOf(v)) == 1; // Fine
}
---------
can be @safe if scanf parameters are scope parameters. Ditto for the parse2 example with addressOf.

* Taking the address of a stack variable or a ref parameter could be
  allowed and @safe as long as it's only passed as scope parameters.
  (All examples in "Taking address" could work if scanf were using
  scope parameters)


IIRC the main problem with scope parameters was that escape analysis isn't implemented yet. http://d.puremagic.com/issues/show_bug.cgi?id=6931
February 07, 2013
On Thursday, 7 February 2013 at 07:41:57 UTC, Johannes Pfau wrote:
> Am Wed, 06 Feb 2013 23:45:51 +0100
> schrieb Robert <jfanatiker@gmx.at>:
>
>> What happened to the scope storage class for parameters.
>> 
>> Wouldn't this solve the problems, with the simple rule that you are
>> not allowed to pass transient objects by reference if the parameter
>> was not declared with scope? And if I understood correctly, the
>> compiler is already capable of locally ensuring that the address does
>> not escape (to ensure the scope requirement), so we are all set?
>
> This is an important question. How would this new proposal interact with
> scope parameters?
>

scope in not enough, as you can alias parameters (for instance swap).
February 07, 2013
Am Wed, 06 Feb 2013 02:38:17 -0500
schrieb Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:

> Probably it'll need a fair amount of tweaking. Anyhow it's in destroyable form.
> 
> http://wiki.dlang.org/DIP25
> 
> 
> Thanks,
> 
> Andrei

Regarding the questions about scope parameters and allowing & in system code, wouldn't it make sense to change the rules to the following:

* Taking the address in @system code is allowed. You can do everything
  with the returned address just as right now.

* Taking the address in @safe code is also allowed, but you can't do
  anything with it: You can't assign it to anything, can't return it
  and can't dereference it.

** Once full escape analysis and scope parameters are implemented,
   those rule will be relaxed a little and passing such pointers to
   some functions (e.g. as scope parameters) will be allowed in @safe
   code.

** addressOf isn't necessary as you can take addresses in @system code
   anyway

This makes more sense than disallowing the & operator completely
as we'd have to reintroduce it anyway once scope is implemented. This
way we start with a strict, conservative way and relax the rules when
the compiler can prove that the operations are really safe.
February 07, 2013
On Thursday, 7 February 2013 at 06:23:10 UTC, Walter Bright wrote:
> On 2/6/2013 10:13 PM, deadalnix wrote:
>> It is a given that @properties can't 100M emulate field, but the goal should be
>> to close he gap as much as possible.
>
> Ok, why should "as much as possible" be the goal? There are other considerations - what merit should they have?
>

I don't think anyone have interest to get back on that. If you have another answer to that question, please share.

> For example, I consider having an easily understood mental model of how things work to be very important. Having the language doing mysterious heroic things under the hood trying to implement someone else's idea of human intuition impairs anyone's ability to understand a language.
>

Ease come from 2 main things :
 - Fit the mental model that an user have in realted area (ie other programing languages)
 - Simplicity (which is very different from ease).

The current proposal seems easy to you because it is close o YOUR mental model, working on D. But on a larger scale, it fails at both criteria mentioned above : it is different from what exists in any languages mentioned in this NG, and a same identifier can refers to 3 different distinct (however related) concepts.

DIP25 aim to solve the ref issue. Which is clearly useful. Conflating that goal with making previous DIP on function call is only going to export the mess in another area of the language.

This is the very example of why simplicity in semantic is key.

>> It doesn't change anything in many cases. Especially for template alias
>> parameters.
>
> Why? foo seems straightforward as a template alias parameter, meaning the function foo. Alias parameters do not take expressions as arguments - so the expression rules do not apply.
>

An alias template parameter bind to a symbol. A symbol can be either a first-class function or a the other entity that have no name (the symbol resulting of a function declaration).

>
>> It doesn't change the intrinsic complexity of the proposal that
>> conflate a function (as first class object), its return value, and the useless
>> C/C++ entity that is a function.
>
> Removing an ambiguous case does reduce the intrinsic complexity.

I'm sure that, as a developer that specialized itself in compilers, you perfectly know the difference between syntax and semantic. And that solving a syntax issue that is symptom of a semantic issue will not fix the semantic issue.
February 07, 2013
On Thursday, 7 February 2013 at 05:54:29 UTC, deadalnix wrote:
> On Thursday, 7 February 2013 at 05:43:24 UTC, Rob T wrote:
>> In other words @safe should explicitly mean "I hereby verify that the code is safe" not "I will silently re-write your code in unknown ways to make it safe".
>>
>
> @safe never meant that and Andrei never suggested that.

I must have misunderstood something. What did he mean by this?

------------
> So you are saying this should compile?:
>
> struct S{
> int x;
> int foo()@safe{ return x; }
> }
>
> int delegate()@safe foo()@safe{
> S s;
> return &s.foo;
> }

Yah, it should, and it also should detect the escape and allocate foo's
frame on the heap.

Andrei
------------

What is being allocated on the heap?

--rt
February 07, 2013
On Thursday, 7 February 2013 at 08:48:30 UTC, Rob T wrote:
> On Thursday, 7 February 2013 at 05:54:29 UTC, deadalnix wrote:
>> On Thursday, 7 February 2013 at 05:43:24 UTC, Rob T wrote:
>>> In other words @safe should explicitly mean "I hereby verify that the code is safe" not "I will silently re-write your code in unknown ways to make it safe".
>>>
>>
>> @safe never meant that and Andrei never suggested that.
>
> I must have misunderstood something. What did he mean by this?
>
> ------------
>> So you are saying this should compile?:
>>
>> struct S{
>> int x;
>> int foo()@safe{ return x; }
>> }
>>
>> int delegate()@safe foo()@safe{
>> S s;
>> return &s.foo;
>> }
>
> Yah, it should, and it also should detect the escape and allocate foo's
> frame on the heap.
>
> Andrei
> ------------
>
> What is being allocated on the heap?
>

The frame pointer is, and it isn't dependent of @system or @safe .
February 07, 2013
On 2/7/2013 12:22 AM, deadalnix wrote:
>> Ok, why should "as much as possible" be the goal? There are other
>> considerations - what merit should they have?
> I don't think anyone have interest to get back on that. If you have another
> answer to that question, please share.


The point is, there must always be a balance of competing interests. That's certainly true here.



>> For example, I consider having an easily understood mental model of how things
>> work to be very important. Having the language doing mysterious heroic things
>> under the hood trying to implement someone else's idea of human intuition
>> impairs anyone's ability to understand a language.
>>
>
> Ease come from 2 main things :
>   - Fit the mental model that an user have in realted area (ie other programing
> languages)
>   - Simplicity (which is very different from ease).
>
> The current proposal seems easy to you because it is close o YOUR mental model,
> working on D. But on a larger scale, it fails at both criteria mentioned above :
> it is different from what exists in any languages mentioned in this NG,

Does C# always allow taking the address of a getter's return value? I don't know, but I'd be surprised if it did.


> and a same identifier can refers to 3 different distinct (however related) concepts.

It is not unusual for an identifier to mean different things in different constructs.


> DIP25 aim to solve the ref issue. Which is clearly useful. Conflating that goal
> with making previous DIP on function call is only going to export the mess in
> another area of the language.
>
> This is the very example of why simplicity in semantic is key.

Simplicity is great, but it does not always trump everything else. It's also possible for reasonable people to disagree on what is simple or intuitive.



>>> It doesn't change anything in many cases. Especially for template alias
>>> parameters.
>>
>> Why? foo seems straightforward as a template alias parameter, meaning the
>> function foo. Alias parameters do not take expressions as arguments - so the
>> expression rules do not apply.
>>
>
> An alias template parameter bind to a symbol. A symbol can be either a
> first-class function

Yes.

> or a the other entity that have no name (the symbol resulting of a function declaration).

Yes. But I don't see the issue. &foo cannot bind to an alias parameter, nor can foo().


>>> It doesn't change the intrinsic complexity of the proposal that
>>> conflate a function (as first class object), its return value, and the useless
>>> C/C++ entity that is a function.
>>
>> Removing an ambiguous case does reduce the intrinsic complexity.
>
> I'm sure that, as a developer that specialized itself in compilers, you
> perfectly know the difference between syntax and semantic. And that solving a
> syntax issue that is symptom of a semantic issue will not fix the semantic issue.

What &foo means is a semantic issue, not a syntactic one. It's not an ambiguous grammar. Semantic ambiguity issues are resolved by creating rules (which one may consider intuitive or arbitrary) and applying them, which is what we're doing here.

There are several such ambiguities in D that are resolved by applying semantic disambiguation rules. This is done because although it makes the spec (and the compiler) more complex, it is actually simpler for the user.

Saying that one cannot take the address of a return value solves the semantic ambiguity problem with &foo.
February 07, 2013
On Thursday, 7 February 2013 at 09:23:20 UTC, Walter Bright wrote:
> The point is, there must always be a balance of competing interests. That's certainly true here.
>

That is an assertion not an argument.

> Does C# always allow taking the address of a getter's return value? I don't know, but I'd be surprised if it did.
>

C# don't have address of. It isn't a system language. Even if you consider the whole stuff without the address problem, the D way is different than C#'s. The 'funny' things is that C#'s would cause syntax problem issue with address of, where D does.

>> and a same identifier can refers to 3 different distinct (however related) concepts.
>
> It is not unusual for an identifier to mean different things in different constructs.
>

Usually not when they resolve to the same symbol. And it has to be proven that this is a good thing.

> Simplicity is great, but it does not always trump everything else. It's also possible for reasonable people to disagree on what is simple or intuitive.
>

Here we have a more complex solution, and more problem with it. Conclude whatever you want, but each time I choose the complex path in my programmer life, I ended up with that kind of effect.

You also seems to conflate simple and intuitive, which are really unrelated. Simplicity is mostly objective, when intuition is mostly subjective. Both combined usually lead to ease.

> Yes.
>
>> or a the other entity that have no name (the symbol resulting of a function declaration).
>
> Yes. But I don't see the issue. &foo cannot bind to an alias parameter, nor can foo().
>

void function() foo can.

> What &foo means is a semantic issue, not a syntactic one. It's not an ambiguous grammar. Semantic ambiguity issues are resolved by creating rules (which one may consider intuitive or arbitrary) and applying them, which is what we're doing here.
>

You should hear ambiguous as ambiguous for the parser here. This is possible to make any crazy insane syntax unambiguous for the parser.

> There are several such ambiguities in D that are resolved by applying semantic disambiguation rules. This is done because although it makes the spec (and the compiler) more complex, it is actually simpler for the user.
>

I don't think it is, and looking at other languages choices, I'm not alone.

This kind of thing always seems simple of some cases, but ends up creating a huge minefield of special case when you start to combine feature together. And this is something that most D users experiences.

It result in users not using advanced D features (see HIGGS topic for instance, or many codebases on github in general) or user having trouble. It is often advised to stay away form advanced features of D for production quality stuff and I have to say I share the observation. Working on large codebase (well large . . . for a personal project, but clearly ridiculous compared to many companies codebase : ~25 000LOC) using advanced features of D, I run in such troubles almost on a daily basis, and have developed some knowledge of area of the language I should not even try to go in.