November 05, 2009
Walter Bright wrote:
> Steven Schveighoffer wrote:
>> If unsafe means you cannot pass pointers to local variables, then half of tango (and other performance oriented libs which use stack allocation as much as possible) will fail to compile.
>>
>> My vote is for unsafe as the default.  It's the least intrusive option, to ensure that current projects still compile.  Then let the project authors ensure their projects are safe one module/function at a time.
> 
> I agree. Also, dealing with safeness is something that comes later on as a project scales to a larger size. As such, it's more of a nuisance on a small program than a help.
> 
>> Also keep in mind that @safe annotations for a mostly safe project will be once at the top of each module.  They won't be "everywhere".
> 
> Right. Adding:
> 
>    @safe:
> 
> at the top will do it.

But that forces a library writer to *always* think about safety. I can imagine you implementing this and then 100 bugzilla tickets saying "I can't call phobos' function foo in my safe function because it is not marked as safe". Then they have to wait for the next release. And the same will happen with library writers. I don't want to think about safety all the time, just let me code! If something is unsafe I'll mark it for you, compiler, no problem, but do you think I'm just some crazy unsafe maniac? I program safely.
November 05, 2009
grauzone wrote:
> Frank Benoit wrote:
>> safe should be the default. The unsafe part should take the extra
>> typing, not the other way. Make the user prefer the safe way.
> 
> No. D is not C#.

D is an unsafe language.
C# is a safe language.

Like that? :)
November 05, 2009
grauzone schrieb:
> Frank Benoit wrote:
>> safe should be the default. The unsafe part should take the extra typing, not the other way. Make the user prefer the safe way.
> 
> No. D is not C#.

As I understand the philosophy of D, it should be easy to write correct/good code, but it shall also be possible to do dirty thing. This is exactly implying that "safe" shall be the default.
November 05, 2009
Nick Sabalausky wrote:
> "Walter Bright" <newshound1@digitalmars.com> wrote in message news:hcv5p9$2jh1$1@digitalmars.com...
>> Based on Andrei's and Cardelli's ideas, I propose that Safe D be defined as the subset of D that guarantees no undefined behavior. Implementation defined behavior (such as varying pointer sizes) is still allowed.
>>
>> Safety seems more and more to be a characteristic of a function, rather than a module or command line switch. To that end, I propose two new attributes:
>>
>> @safe
>> @trusted
>>
> 
> Sounds great! The lower-grained safeness makes a lot of sense, and I'm thrilled at the idea of safe D finally encompassing more than just memory safety - I'd been hoping to see that happen ever since I first heard that "safeD" only ment memory-safe. 

I can think of division by zero as an example. What others are out there?

Andrei
November 05, 2009
Steven Schveighoffer wrote:
> On Thu, 05 Nov 2009 15:20:34 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Thu, 05 Nov 2009 14:57:48 -0500, Michel Fortin <michel.fortin@michelf.com> wrote:
>>>
>>>> On 2009-11-05 13:33:09 -0500, Walter Bright <newshound1@digitalmars.com> said:
>>>>
>>>>> Safety seems more and more to be a characteristic of a function, rather than a module or command line switch. To that end, I propose two new attributes:
>>>>>  @safe
>>>>> @trusted
>>>>
>>>> Looks like a good proposal.
>>>>
>>>> That said, since most functions are probably going to be safe, wouldn't it be better to remove @safe and replace it by its counterpart: an @unsafe attribute? This would make things safe by default, which is undoubtedly safer, and avoid the unnecessary clutter of @safe annotations everywhere.
>>>  If unsafe means you cannot pass pointers to local variables, then half of tango (and other performance oriented libs which use stack allocation as much as possible) will fail to compile.
>>
>> While I agree with your point, quick question: could you use ref parameters instead? Ref will be usable in SafeD.
> 
> Most of the usages are like this:
> 
> ubyte[1024] buffer;
> functionThatNeedsBufferSpace(buffer);
> 
> where functionThatNeedsBufferSpace takes a ubyte[], thereby taking an address of the local data.
> 
> So it's not explicit address taking, but it's the same thing under the hood.  There always exists the potential for the stack reference to escape.

I see, thank you. I am confident that a trusted reap could be implemented in the standard library. (google reap)

> Similar case is scope classes (which are sometimes used to allocate a temporary class for performance in tango).  I can't see scope classes being allowed if you can't take addresses of local variables.

Yah, in fact I think scope classes should just go. But don't hold that against me. :o)

> I'm not saying that safed needs to allow these kinds of things somehow (thereby employing escape analysis), but it might be too restrictive for performance-oriented libs/apps.  I think it's acceptable that tango eventually gets marked with @trusted, but by making @safe the default, you will immediately make many D1 projects not compile without significant effort, which might drive away developers from D2, or else make people automatically mark all files as @trusted without thinking about it.  By defaulting to untrusted and unsafe, you allow people to incrementally add @safe and @trusted tags where they are appropriate and correct.

I agree.


Andrei
November 05, 2009
On Thu, Nov 05, 2009 at 10:19:27PM +0100, Ary Borenszweig wrote:
> I don't want to think about safety all the time, just let me code! If something is unsafe I'll mark it for you, compiler, no problem, but do you think I'm just some crazy unsafe maniac? I program safely.

This might be a problem. If safe functions can only call other safe functions and all functions are safe by default, unsafe becomes viral.

Let me give an example:

void main() {
  doSomething();
  doSomethingElse();
}

void doSomething() { does safe things }
void doSomethingElse() { oneMoreFunction(); }

void oneMoreFunction() { byte* a = cast(byte*) 0xb80000000L; // unsafe!}


Now, to actually call oneMoreFunction, you have to mark it as unsafe. Then, since it is called in doSomethingElse, you have to mark it as unsafe. Then, since it is called from main, it too must be marked unsafe.

This would just get annoying.


This is bypassed by marking oneMoreFunction() as @trusted. Having an @unsafe
is unworkable in safe by default. It is just default (safe) and marked
(trusted).



Which is going to work best for existing code? With Walter's idea, you compile it, then fix functions piece by piece to make them safe. Since your other unsafe functions can still call them, the change is localized and you get safer with each revision.

With safe by default, you'd probably make existing code compile just by slapping @trusted: at the top and being done with it. That's not actually safe - you're just telling the compiler to shut up about it.


-- 
Adam D. Ruppe
http://arsdnet.net
November 05, 2009
On Thu, 05 Nov 2009 15:19:46 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Steven Schveighoffer wrote:
>> Care to define some rules for "undefined behavior?"
>
> My list may be of help.

Thanks, I found it.

I note that you specify "No escape of a pointer or reference to a local variable outside its scope"  There are definitely different degrees of detecting this.

From reading some of your other posts, I take it you mean:
 * you cannot pass such a pointer to another function except by reference
 * you cannot return such a reference or pointer
 * you cannot take the address of a 'ref' parameter, because that parameter could be allocated on the stack.

Without doing full escape-analysis, there are some problems with this.  For example, let's take the function std.string.split.  It takes a reference to data and returns a reference to that same data.  However, the compiler is unaware of where the data being returned comes from.

For example:

char[] getFirstWordOfFile()
{
char buf[1024];
auto x = buf[0..readFile("foo.d", buf)];
return split(x)[0]; // memory escape
}

I'm not a phobos guy, so I don't know exactly how to do readFile, but I think we all know what it means.

readFile will obviously be marked as @trusted, since it does not escape any memory, but calls a (potentially) unsafe C function (read).

But what about split?  Should it be illegal to pass in the reference to the stack memory?  Should it be illegal to mark the split function as safe?  How does safeD prevent this mistake?

My point is, because without full analysis, the compiler cannot connect the outputs of a function with its inputs, only functions which heap-allocate defensively, or don't use references, can be marked as safe.  Because safety is sometimes contextual, it will be impossible to use the all-or-nothing @safe marker on many functions (such as split).

I'm still not sure how to solve this, or whether it will have a large impact on how safed works.

-Steve
November 05, 2009
On Thu, 05 Nov 2009 16:30:42 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

>>  Most of the usages are like this:
>>  ubyte[1024] buffer;
>> functionThatNeedsBufferSpace(buffer);
>>  where functionThatNeedsBufferSpace takes a ubyte[], thereby taking an address of the local data.
>>  So it's not explicit address taking, but it's the same thing under the hood.  There always exists the potential for the stack reference to escape.
>
> I see, thank you. I am confident that a trusted reap could be implemented in the standard library. (google reap)

I did.  Couldn't find anything.

>> Similar case is scope classes (which are sometimes used to allocate a temporary class for performance in tango).  I can't see scope classes being allowed if you can't take addresses of local variables.
>
> Yah, in fact I think scope classes should just go. But don't hold that against me. :o)

They are great when you need temporary objects to do things like filters.  It works well in Tango's i/o subsystem where everything uses interfaces.

I think they have their place, as long as structs don't implement interfaces and the interface concept isn't removed from D.

-Steve
November 05, 2009
On Thu, 05 Nov 2009 16:13:01 -0500, Frank Benoit <keinfarbton@googlemail.com> wrote:

> safe should be the default. The unsafe part should take the extra
> typing, not the other way. Make the user prefer the safe way.

Let's find out how painful/painless "safe" is before making that assertion :)  I suspect that the rules for safed will be too strict for lots of provably safe code.

-Steve
November 05, 2009
Ary Borenszweig wrote:
> grauzone wrote:
>> Frank Benoit wrote:
>>> safe should be the default. The unsafe part should take the extra
>>> typing, not the other way. Make the user prefer the safe way.
>>
>> No. D is not C#.
> 
> D is an unsafe language.
> C# is a safe language.
> 
> Like that? :)

If you mean memory safety, then yes and will probably forever be for all practical uses (unless D gets implemented on a Java or .net like VM).