D does have head const (but maybe it shouldn't)

Petar Petar
Tue Dec 29 20:41:33 UTC 2020


On Tuesday, 29 December 2020 at 17:56:51 UTC, H. S. Teoh wrote:
> [..]

> I don't see why this is considered head const, nor why this 
> should be considered a bug. In the proposed solution `y` is not 
> a value type but a delegate that wraps the reference to *x.  
> Since x itself is non-const, this is perfectly valid, and the 
> `const` in `const y` refers to the immutability of the delegate 
> reference, not to the immutability of the wrapped reference.
>
>
> T

Do you agree with the following statements?

---
The const / immutable type qualifiers being transitive implies 
that it's not possible to mutate any data reachable through an 
object of type qualified with const / immutable. Transitive 
immutable implies that anything reachable through an immutable 
object won't change after being constructed. In contrast, const 
only prevents mutation through const objects - the same data 
aliased otherwise could be mutated.
(This applies for any kind of object, no matter whether if one 
would classify it as of a value or reference type.)
---

The fact that the proposed solution compiles is a contradiction 
of the const transitivity rule that I stated above. Before 
checking the proposed solution, did you consider the example 
solvable?

> I don't see why this is considered head const, nor why this 
> should be considered a bug.

My definition of a head const variable is a variable which it 
can't be re-assigned after construction, but one that allows 
mutation of data reachable through it, in contrast transitive 
const qualified variables.

The behavior of `y` in the proposed solution matches my 
definition of head const.

The root of the issue is that dmd still treats the delegate 
context pointer opaquely as void*.

Instead, the full type returned by the function `f` should be:

struct Delegate
{
     alias F = void function(Context* ptr) pure @safe;
     Context* ptr;
     F funcptr;

     static struct Context
     {
         int** p; // D delegates capture variables by reference
     }
}

If that was the case, I think it's easily apparent why `const` is 
not working as intended, but as "head const" instead in this 
specific case.


More information about the Digitalmars-d mailing list