On 12/07/16 17:26, Andrei Alexandrescu wrote:

Thanks. I must have misunderstood - I was looking for something that's
not @safe.


No, I was referring to his statement that features in D tend to create complexity and unexpected/non-intuitive behavior when combined. Sorry if I was not clear.


AffixAllocator is not casting away immutability - that's the beauty of
it. But I'm all for making the language more precise to allow the kind
of work AffixAllocator does portably. Would love some help from you there!

This is a bit academic, but I don't understand how you can get an immutable/const pointer to memory, and then get a pointer to a mutable uint out of it without casting away the constness. Yes, you are subtracting the pointer so it points to outside the original memory, but technically speaking (which is all the compiler really sees, at this point), you are casting "immutable MyClass*" to "uint*". It is only semantically that you know this is fine.

Saw your reference to the code in a different comment. I believe (and I might be wrong) the cast in question to be here:
https://github.com/dlang/phobos/blob/master/std/experimental/allocator/building_blocks/affix_allocator.d#L213

The input might be CI. The output is mutable.

If such cast is UB, then the compiler is free to say "this is nonsense, I'm not going to do it". If we use the C++'s UB definition, the compiler can say "I hereby assume that the buffer is actually mutable". This is, potentially, completely different code generation.


The C++ definition is quite solid. Casting away constness is UB IFF the
buffer was originally const.

Yeah, we might relax that in D as well, albeit for different reasons.

I would love to hear about what are D's reasons, and in what way they are different than C++'s. To clarify, the previous sentence was meant to be read with no cynicism intended.


In this case, your allocator does two UBs. One when allocating (casting
a mutable byte range to immutable reference), and another when
deallocating. Both are defined as undefined by D, which means the
compiler is free to wreak havoc in both without you having the right to
complain.

Which leads me to the conclusion that you cannot write an allocator in
D. I doubt that's a conclusion you'd stand behind.

Again, your help with improving the language definition would be very
welcome. Obviously we do want to have AffixAllocator and other
allocators work properly.

I was thinking about intrusive reference counting, which is the classic case I'd use "mutable" in C++. In that case, the value we're mutating actually is a member of the struct that was passed as const (I think immutable isn't an issue in that use case).

I think a great first step is to relax the UB around casting away CI modifiers where we know, semantically, that the underlying memory is actually mutable.

Shachar

Reply via email to