On Wed, 23 Feb 2011 15:28:32 -0500, bearophile <bearophileh...@lycos.com> wrote:

Steven Schveighoffer:

I see zero value in disallowing comparing pointers in D.

I have not suggested to disallow comparing all pointers. I have suggested to disallow it only for pointers/references allocated inside a pure function, that are @transparent.

That's not what your example showed. It showed comparing two allocated pointers *outside* a pure function, and expected them to be equal. I see that as disallowing all pointer comparisons.

What kinds of problems does pointer comparison cause?  I know of none.

If you compare pointers created in a pure function, you are breaking the most important constraint of pure functions. A pure function is deterministic. D pure function aren't deterministic, because the value of the memory pointers they return can be different across different calls. If you leave this hole in pure functions, then their purity is much less useful, you can't perform optimizations, you can't reason about code like you are able to do with pure functions.

Currently you are able to write functions like:

pure bool randomPure() {
    int[] a1 = new int[1];
    int[] a2 = new int[2];
    return a1.ptr > a2.ptr;
}

This is the first real example you have made that shows a problem! It uses all valid constructs within pure functions (without casts), and by current rules could be considered strong-pure, however, it violates the rule of pure that the same parameters should result in the same answer.

Is this function pure? It returns a pseudo-random boolean. You are free to define this function as pure, but this form of purity is much less strong than what people think of "pure".

I would not define the function as pure.  The questions to answer are:

1. Can the compiler detect valid reference comparisons without annotation?
2. Is this going to be a common problem?

At first glance, I'd say the answer to number 2 is no. Most people are not going to use the randomness of the memory allocator to subvert purity. It's unlikely that you accidentally write code like that.

The answer to number 1, I don't know. I don't think the compiler can determine the origin of allocated memory without annotation.


With the type system change I have prosed it becomes:

pure bool randomPure() {
    @transparent int[] a1 = new int[1];
    @transparent int[] a2 = new int[2];
return a1.ptr > a2.ptr; // compile-time error, their ptr are @transparent, so they can't be read
}

I can see now the value in this. I just wonder if it would be worth it. Seems like such a rare bug to create a whole new type constructor.

It also has some unpleasant effects. For example, the object equality operator does this:

bool opEquals(Object o1, Object o2)
{
  if(o1 is o2)
    return true;
  ...
}

So this optimization would be unavailable inside pure functions, no? Or require a dangerous cast?

Would it be enough to just require this type of restriction in pure @safe functions?

I feel that a new type of reference is likely overkill for this issue.

Showing an
assert that two pointers are not equal is not evidence of an error, it's
evidence of incorrect expectations.

One of the main purposes of a type system is indeed to disallow programs based on incorrect expectations, to help programmers that may not always remeber what the incorrect expectations are :-)

My point in the above statement is that when you say:

auto a = new int[1];
auto b = new int[1];
assert(a.ptr == b.ptr);

is not evidence of an error :)  This is what you did previously.

-Steve

Reply via email to