C++ Logo


Advanced search

Re: RFC: disjoint qualifier

From: Andreas Ringlstetter <andreas.ringlstetter_at_[hidden]>
Date: Fri, 18 Sep 2020 08:59:36 +0200
How is that supposed to work?

Take e.g.:
   struct foo {}
    struct bar {
        disjoint foo *foobar;
    bar a;
    bar& b = a;
    function_requiring_disjoint_pointers(&a.foobar, &b.foobar);

Proving that the two parameters had been disjoint (or actually not, as
in this case) is a non-trivial task. Furthermore, it's not actually
possible to decide this solely based on a type qualifier, unless that
qualifier had *forbidden* any operation which could have destroyed the
restricted property. Meaning there must never have been more than a
single reference to the storage in existence (think e.g.
std::unique_ptr, but allowing move only, no reference to it), and
there must not be any owner to which more than a single reference can

Your motivation appears to resemble the borrow rules from the Rust
language, but you have to be aware that this only works if unique
references are enforced throughout the whole application top down. You
can't just take a type somewhere in nested data structure and declare
"you are now without aliases". E.g. as the above example showed, there
mustn't have been an instance of `bar` without a disjoint qualifier
(as it had qualified members), the second reference on `a` mustn't be
permitted etc.

Without enforcement, this actually turns dangerous instead. If you are
able to declare a variable disjoint, but it has to be used in a
context where it actually isn't, then it would be unsafe for the
compiler to actually act on that keyword in any form. Think e.g. good
old `memcpy` vs `memmov` problem. Except with restrict (or __restrict
which many compilers do support in C++ syntax) at least you had to aim
before you shoot your own foot, with a propagating disjoint qualifier,
that gun comes pre-aimed for you.

Then there is also another reason why `restrict` has such limited
usage in the C++ language: You don't see pointers often anymore, and
iterators (with the concept of an "past-the-end" iterator) are by
design incompatible with any attempt to declare them as alias-free.

E.g. take:

  void foo_cpp(it a_begin, it a_end, it b_begin, it b_end);
  void foo_c(T * restrict a, size_t a_size, T * restrict b, size_t b_size);

As a_end can be reached by incrementing a_begin, each two parameters
here are not just "not disjoined", but even required to form a single
range or even be identical as the only way to encode an empty range.
Only in the C style interface, it's possible to express aliasing rules
at all.

Am Fr., 18. Sept. 2020 um 03:38 Uhr schrieb Eric Lengyel via
Std-Proposals <std-proposals_at_[hidden]>:
> Standard C++ does not include the “restrict” qualifier from C, and many serious problems arise when attempting to properly incorporate it into the C++ language. The following proposal introduces a superior alternative in the form of a “disjoint” qualifier that functions differently in several important ways. The disjoint qualifier is a clean and natural fit within the established design of the C++ language, and it adds type-safe aliasing controls in a backward-compatible manner.
> http://terathon.com/disjoint_lengyel.pdf
> Please discuss.
> -- Eric Lengyel
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2020-09-18 01:59:51