C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Float the idea: First-class effect annotations and resource contracts for C++

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 8 Jun 2026 11:28:15 -0400
On Sun, Jun 7, 2026 at 4:49 PM Ville Voutilainen via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Sun, 7 Jun 2026 at 23:41, Michael Galuszka via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > What I'd like feedback on
> >
> > 1. Is SG14/EWG broadly receptive to Layer 1 as a generalization of
> noexcept — that is, an effect specifier that is part of the function type,
> not an attribute?
>
> To add more function-type (and pointer-to-function and
> reference-to-function) specifiers that lead to different template
> specializations,
> and needs to be accommodated by various function wrappers, the added
> facility needs to cure cancer.


+1.
(And since this list's members tend to have trouble with the
direction-of-causality here: what Ville's saying IIUC, and what I'm +1'ing,
is not "...so you should proceed to make this facility cure cancer, so that
it can be accepted" but rather "...so this facility *does not* have good
enough cost/benefit ratio and it will *not* be accepted.")

Every time someone brings up the idea of a richer set of type qualifiers, I
mention the CQual project. (Although I rarely remember its name; I keep
wanting to call it "QualC," which is wrong.)
- Jeffrey S. Foster, Manual Fähndrich, Alexander Aiken, "A Theory of Type
Qualifiers"
<https://theory.stanford.edu/~aiken/publications/papers/pldi99.pdf> (PLDI
1999)
- Jeffrey S. Foster, Tachio Terauchi, Alex Aiken, "Flow-sensitive type
qualifiers"
<https://theory.stanford.edu/~aiken/publications/papers/pldi02.pdf> (PLDI
2002)
- Brian Chin, Shane Markstrum, Todd Millstein, "Semantic Type Qualifiers"
<https://web.cs.ucla.edu/~todd/research/pldi05.pdf> (PLDI 2005)
- Adrian Sampson, "Quala: Custom Type Systems for Clang"
<https://www.cs.cornell.edu/~asampson/blog/quala.html> (2014)

Reflection (on C++26 annotations) might be able to get you some of the
benefit here.
The big problem I see in practice — the one that makes it really impossible
for the compiler to help, and (merely) tedious for the user-programmer to
program himself — is that it's not obvious how to combine the various
qualifiers/attributes you might dream up. For example, suppose you were
trying to verify stack usage, which is one of your Layer 2 examples. You
might write
    [[=stack_usage(256)]] void g() { }
    [[=stack_usage(512)]] void h();
    [[=stack_usage(1024)]] void f() {
      { char buf[1024]; g(); }
      h();
    }
Does `f` use 1024 bytes of stack, 1024+256 bytes, 1024+512 bytes, or
1024+512+256 bytes?
Another difficulty is templates. Given
    template<class T> void f() { T::g(); }
is that function non-allocating? Non-blocking? Well, it depends on what
`T::g()` does. So perhaps we want a way to propagate these properties
bottom-up through unannotated templates; or we want something like
`noexcept(auto)`; or else we want a query language for them, which would be
hella tedious and error-prone.
But vice versa, it seems to me that most of the benefit of these
annotations would come from enforcing them top-down — "a nonblocking
function must not call any function that is not itself nonblocking," for
example.
Unfortunately then you have the problem that no function today is marked
nonblocking! For example `htonl` is not marked nonblocking, so any function
that calls `htonl` will be assumed to block. (Analogously, today, `htonl`
is not noexcept, so any function that calls `htonl` will be assumed to throw
<https://godbolt.org/z/oKE5bWbPn>.)

And then you have the problem, probably, that in the Unix world just about
every function could be blocking or could be nonblocking, depending on the
state of the objects passed to it (e.g. the values of its bitmask
arguments, e.g. whether a socket is in nonblocking mode or not). This can
be worked around — the user-programmer just has to split each offending
function into two wrappers and make sure they're used properly (custom
qualifiers might help with that).


On the other hand, actual compilers that target embedded systems, like
Green Hills MULTI, definitely already have reliable checkers for the
complicated stuff like "stack usage." They actually know what the codegen
looks like, which no source-level annotation can ever discover (because you
need to actually codegen the instructions before you can see what the stack
usage is). I dare say that's the right approach: start with a problem you
can solve, and solve it, and see what the solution looks like. If you find
that multiple vendors have solved the problem in similar ways, *then* think
about whether it would help to standardize the solution.

HTH,
Arthur

Received on 2026-06-08 15:28:31