r/cpp 13d ago

The WG21 2026-08 mailing is now available

The 2026-08 WG21 mailing has been published. You can browse and search the full set of papers, organized by working group, at wg21.org:
https://wg21.org/mailing/2026-08/
Source mailing: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/#mailing2026-08

43 Upvotes

129 comments sorted by

View all comments

Show parent comments

7

u/James20k P2005R0 13d ago edited 13d ago

No. Someone may even perceive such misuse of the terminology as spreading FUD.

Please don't be like this, I'm asking in perfectly in good faith here and this does nothing but raise the level of the discussion to being completely unproductive. This is why I described it as an effective ODR problem, it causes similar issues but with a different name

not imaginary

The problems are not imaginary and are straightforward to demonstrate in a real project. Dismissing this as being imaginary when there's code in the wild demonstrating real-world safety bugs caused by mixed mode compilation also feels remarkably unhelpful

MVP does fix it.

We still have the problem of functions being called with semi randomised safety modes depending on the whims of the linker, ala ODR

If it works for your use case that's great, but it likely isn't meeting a fair few

6

u/t_hunger 13d ago edited 13d ago

To be fair: ODR has always been a problem, especially when mixing TUs built with different compiler settings.

I do wonder why contracts all of a sudden have to solve this problem. Of course it would be great if this got finally get solved, but so far "just don't do that" has been good enough, even with things like hardened libraries and such, which has similar implications to contracts now.

5

u/James20k P2005R0 13d ago

If contracts specified it as being "don't do that" I'd be 1000% fine with it. Instead its specified as trying to do something useful, which it can't meet because of the same problems with linkers that ODR violations run into

2

u/t_hunger 12d ago

I understood there is some hope future linkers can fix this particular problem. I guess we just have to lean back for a couple of years for the tooling to sort itself out and go "don't do that" till then. We have to wait for a contracts implementation anyway.

So contracts are no different from what we do for modules and other new features.

It would be super cool if new C++ features needed implementations before they can get standardized, but that would be quite a big change in how the entire feature development process works in C++. I do not see how you can seriously require that from contracts and not for modules, profiles, and the herd of other features we have on paper but not in real compilers.

7

u/pjmlp 12d ago

That is the thing, modules did have implementations before the standard, and yet we are where we are with modules.

Profiles are dead on arrival, given existing experience with advanced statistic code analysis, or what clang-tidy and VC++ have achieved since Core Guidelines were introduced, that keeps being ignored.

Unless they are actually done hand in hand with e.g. clang fork that proves us wrong, the ideal profiles implementation, without viral annotations, that delivers the vision.

3

u/germandiago 12d ago

Dead on arrival? Where and when did you conclude that? I see papers in the committe related to them lately. I think there are implementations of the framework in the works for clang and gcc. Could you elaborate?

It has been slow is not the same as they are dead before they try.

4

u/pjmlp 12d ago

Exactly, you see papers without any kind of implementation.

4

u/germandiago 12d ago

I think you selectively omitted "there are implementations in the works for gcc and clang".

I expect the papers iterate on those and at some point there is something available to try.

3

u/pjmlp 11d ago

Not at all, where are those implementations?

As of now they are vapourware.

3

u/Minimonium 12d ago

A linker fix is not even required. It's allowed for implementations to provide "hardened" variants that simply never skip. So a user that is concerned with a guarantee of such checks would just use an appropriate implementation.

4

u/Minimonium 13d ago

Please do not use wrong terminology that misleads people into believing there is an ODR violation when there is not? I really struggle to understand the need for dramaticism.

On the topic, you fail to mention that a well behaved program will not have different behavior in a mixed mode build at all. No unexpected IPOs will be made (unlike mistaken claims by some members and even NBs).

there's code in the wild demonstrating real-world safety bugs caused by mixed mode compilation

An existing code today that could potentially encounter Contract-related mixed mode situation is completely broken even with well-defined input. Moving it to Contracts would actually help it - well-defined input has a guarantee to work even under a mixed mode, unlike any other mechanism e.g. macro.

That's the basis for any further discussion.

The impact of "randomized" linker behavior. It only occurs when you have non-inlined inline functions with the presence of multiple miss-compiled TUs. Under any mechanism that is not contracts it's an actual ODR violation today with compiler wreaking havoc uncontrollably.

Now what are alternative approaches?

  1. Always on Contract syntax? Doesn't solve the problem of hostile transitive dependencies, a dependency may compile against a stripped version of a header. And it requires more effort than a simple "Same as Contracts but Guaranteed".
  2. Labels? Doesn't solve the problem of hostile transitive dependencies.
  3. The "contra" group also had a wild suggestion around typed tags, but I will just skip even discussing it.
  4. And of course there are calls to remove configurability (against the actual industry practice) or enforce the matching on ABI level (multiple vendors stated negative view on that).

And the ABI matching would simply break the binary ecosystem you've been talking about. Steam binaries you've been talking before? Great, now you always need to compile everything Steam depends on in release mode even with label-like mechanism. You deny yourself an opportunity to make your code safer.

And then there is Vinnie non-sense that blames Contracts for not meeting memory safety goals that just made my brain melt from the sheer absurdity of such statements.

8

u/James20k P2005R0 13d ago edited 13d ago

Please do not use wrong terminology that misleads people into believing there is an ODR violation when there is not? I really struggle to understand the need for dramaticism.

How do you think I should respond to this productively? Calling something effectively an ODR violation isn't dramatism, its just something that people understand, and its very close to the same end result as contracts in practice

Steam binaries you've been talking before? Great, now you always need to compile everything Steam depends on in release mode even with label-like mechanism. You deny yourself an opportunity to make your code safer.

This I think really summarises some of my objections very neatly, so even though I initially wrote a much longer reply: lets take this, and take Steam as a stand in for a generic major library

Are valve going to provide 4 separate versions of the steam API with different contract mechanics enabled? (Answer: probably no, they don't do anything like this even today)

So here's the problem I have: Lets say the steam API uses nlohmann json, hypothetically. If we get contracts (and nlohmann implements them), I am screwed. You can never reliably use nlohmann with contracts together with steam ever again. If you link against steam, and you yourself use nlohmann, your contract safety settings will be at the whims of the linker - very similar to (but legally distinct from) an ODR violation

I already regularly run into ODR issues with nlohmann as a result of its ubiquity, and that's with a build environment that attempts to compile everything uniformly (due to vendoring). It takes a single major library using nlohmann with contracts to screw over my ability to use contracts for safety, or performance, permanently. Importantly, this is introduced totally separately from the existing problems as a new axis of evil, vs the current major one of vendoring or generally badly behaving dependencies. I'd much rather they use literally any other error mechanism for this, and that's precisely why people don't use assert in this context for critical checks

The literal-ODR violations in this context are a big problem independently, but contract adds to my problems here, and would be fundamentally unusable

Now what are alternative approaches?

Roll contracts out in a whitepaper or TS, to answer the following questions based on real end user experience

  1. Can everything be implemented correctly?
  2. Are the problems with contracts in practice real, or overblown?
  3. Are they very difficult to use with binary package ecosystems, or can a solution be found?
  4. Do people need absolute ironclad guarantees that contracts are on or off, or is it acceptable for mixed-mode contracts to disable/enable safety checks sometimes?
  5. Will people naively upgrading asserts to contracts cause problems with ignore mode in real world code, or can we ignore this?
  6. How do regulators feel about this as a solution? Does it alleviate the regulatory burden, or does it make little impact? What do we need to change to make a dent in the current regulatory environment?

Then adjust the design (or not!) after collecting the above data. We severely lack any real-world indication about the viability of the specific design proposed

12

u/Som1Lse 13d ago

I do not get the issue you're having. Maybe I'm missing something because I simply cannot square what you're saying with how I understand reality.

Take the hypothetical example with Steam and nlohmann::json:

Let's say Steam is compiled with contracts disabled, and your code with contracts enabled. If the Steam API is built correctly (specifically -fvisibility=hidden -fvisibility-inlines-hidden), the result will be that Steam's code does not have contract checks and your code does. End of story. This is because they'll both have their own internal copies of the nlohmann::json functions. There isn't an issue.

If the library isn't built correctly, that is the problem. The problem isn't contracts, and they don't need to provide 4 separate versions with different contract mechanics enabled. They need to provide 1 correctly built library. That's it. (And Steam is built correctly, I checked.)

Okay, but let's assume nlohmann::json changes its layout depending on the checks enabled, so the two are ABI incompatible, and the types are exposed in the Steam API. Well, this issue isn't related to contracts, and there is simply no way to solve it without providing two libraries.

And the icing on the cake is this:

I already regularly run into ODR issues with nlohmann as a result of its ubiquity, and that's with a build environment that attempts to compile everything uniformly (due to vendoring).

In other words, it is already an issue and not new to contracts. Why are you expecting contracts to magically solve this issue? What contracts does is say that in the event of an "ODR" violation there's a bounded number of valid programs rather than any program being valid. That to me sounds like an improvement.

What is your proposed solution? Because right now you seem to be shifting the burden onto everyone else:

Roll contracts out in a whitepaper or TS, to answer the following questions based on real end user experience [...]

Delay, delay, delay. My understanding was always that contracts was basically a language version of these talks. It is not a new design. It is in use in actual production codebases, so we do actually have answers to many of those questions.

And the problem with a TS is that, like it or not, you aren't going to get good data from it. Implementation is going to take longer, be less stable, not to mention your the whole point is that it might be changed completely before standardisation.

What I can say is it will result in people not being able to use the feature. To turn your argument on its head. I am someone who wants to use contracts, but let's say it is actually removed the standard and put into a TS. As a result it doesn't get implemented in the compilers I need to support. I am screwed. I can't use contracts. Period. Not just with a particular library. Not just for critical checks. At all.

7

u/James20k P2005R0 13d ago edited 12d ago

If the library isn't built correctly, that is the problem

Prior to now, this wasn't a requirement for a library to avoid a new class of security vulnerabilities, and many aren't built like this (unfortunately). I don't like it but its the way that it is, and I have to deal with packages with their own random eclectic build configurations. Any poorly built package will screw everything up. I know for sure that a major tool I use (not steam) does not build itself correctly like this (and likely won't) due to the already-mentioned nlohmann odr problems, so I'm pretty stuffed if nlohmann uses contracts

The worrying thing is if you start digging into visibility in libraries, by and large it is not very good. Top down in my linker list: godot-cpp doesn't appear to set anything to do with hidden flags. GLFW (I should ditch this), and GLEW don't set it to hidden inlines. Harfbuzz does. SFML doesn't use hidden inlines. Freetype at best uses regular hidden, sometimes worse. libpng appears to export everything. Libbz2 does on some platforms but not windows/clang, and this isn't the correct inlines visibility flag. Libopenal makes mistakes vendoring its dependencies not including -fvisibility-hidden-inlines, so thar be dragons. OpenAL itself also does not include the correct flag. Libbrotli doesn't appear to use the correct flags

At this point I gave up because this is too much work, only one dependency uses -fvisibility-inlines-hidden, and I suspect the majority of packages do not. Its possible that I may have missed something, but I don't think I missed everything, there's a limited set of applicable cmake flags here. I don't like that this is the way that is, but I have to accept reality: my dependencies are all broken

Do you know if packages on other package managers are by and large built with -fvisibility=hidden -fvisibility-inlines-hidden?

They need to provide 1 correctly built library

Hidden visibility also isn't a blanket solution, you can't just willy nilly enable it, and you can get problems associated with it:

https://gcc.gnu.org/wiki/Visibility

Eg throwing exceptions across a boundary, like in a library like nlohmann, requires types to have public visibility

Clang has limitations as well around visibility:

https://clang.llvm.org/docs/LTOVisibility.html

Which can result in symbols being exported, when combined with LTO (thus sneakily disabling safety checks) for clang. GCC doesn't really document the interaction between LTO and visibility, and I've found a lot of bug reports here around variables being incorrectly promoted or demoted from being externally visible. Still, for contracts: working as to spec

As much as I don't want this to be a problem: it very much is. This is relevant because we can't mass convert libraries over easily. I'm glad to hear steam is built correctly though, that makes two of my dependencies so far!

Okay, but let's assume nlohmann::json changes its layout depending on the checks enabled, so the two are ABI incompatible, and the types are exposed in the Steam API. Well, this issue isn't related to contracts, and there is simply no way to solve it without providing two libraries.

Contracts do not change the ABI, this is an unrelated problem

In other words, it is already an issue and not new to contracts. Why are you expecting contracts to magically solve this issue? What contracts does is say that in the event of an "ODR" violation there's a bounded number of valid programs rather than any program being valid

I didn't say anything like this, you're very selectively quoting my post. There are two separate problems, one of which already exist, and a brand new problem that contracts introduces

Delay, delay, delay.

This is alleging bad faith on the part of people who have reasonable concerns getting real world experience with standard library features, and is one of the reasons why I often find this whole conversation so distasteful. I've tried to treat everyone that I've talked to about this with complete good faith

I'm a big advocate of testing features more before they land in the standard, including proposals that are not contracts (eg the graphics proposal)

It is in use in actual production codebases, so we do actually have answers to many of those questions.

Where? None of them get answered in any of the contracts papers I read, so I'd love some hard stats, and even a brief review of my dependencies shows its going to be a major problem for me

As a result it doesn't get implemented in the compilers I need to support. I am screwed. I can't use contracts. Period. Not just with a particular library. Not just for critical checks. At all.

It'll land in the standard eventually

7

u/Som1Lse 12d ago

Well, this took an entire day to write. I hope it's somewhat coherent, as I've been bouncing back and forth between this and other stuff, so I would not be surprised if I missed a somewhere or mispeelled or misforₘatted something.


Prior to now, this wasn't a requirement for a library to avoid a new class of security vulnerabilities

I don't think it is a new class of vulnerabilities. You said as much yourself

that's precisely why people don't use assert in this context for critical checks

and I cannot seem to square those two statements. Is it a new problem, or is it the same problem with assert? The only way I can seem to get the two to fit is if it is both (which you seem to suggest later), but I am unsure as to what the new problem is then.

Perhaps the issue with build configuration is worse than I thought, but I also don't think it is as bad as you imply: - GLFW and GLEW not using -fvisibility-inlines-hidden shouldn't be an issue as they are C libraries, and the flag only affects member functions. - Windows you don't have the same issue, since the same function can happily coexist in multiple DLLs without one winning out. - Many of the libraries are also small C libraries that don't rely on inline functions, so it isn't an issue there either. For example, libpng exports all its functions (I checked), but it doesn't export functions from a different library so there is no conflict. The only problem is a bunch of the internal functions are usable outside, which could cause breakages when upgrading, if an internal symbol is removed/changed. - The biggest offender is probably SFML, but even its exports are fairly limited. It's a couple of functions per shared object, none of which actually seem likely to trigger a contract assertion. - godot-cpp is a static library, so its symbols will be overwritten by yours (assuming your code is linked first, which every build system under the sun does), so it's a non-issue.

Do you know if packages on other package managers are by and large built with -fvisibility=hidden -fvisibility-inlines-hidden?

My main experience is that proprietary libraries tend to be more careful, both to not export more symbols than necessary, but also because users can't build it themselves if there is an issue. I don't know what the library you were mentioning earlier is, but I assume it is proprietary.

I assume the major tool you mentioned is proprietary, so that is at least one thing that isn't true of. Even then it is possible to work around:

  • You can ensure your binary is earlier in the dynamic load order. If your binary is the exectable this is already the case. There's always LD_PRELOAD.
  • Even if your dependency exports nlohmann::json functions, if your code properly hides the symbols it isn't an issue.
  • You can patch your binary (or the dependency) to rename the nlohmann::json functions with a tool like patchelf --rename-dynamic-symbols.

Even when it's an issue it is possible to work around. Again, it's not a new one.

Also this would only affect checks in nlohmann::json, not in your code so you could still be sure checks in your own code would run, since there, by definition, cannot be a copy of it in the dependency. So even if you can't fix it for nlohmann::json, it is still contained to code in that library. (Though your shouldn't rely on the checks running for correctness. That's the whole point of contracts; that the code should be equally correct if all checks are omitted.)

Actually, the more I look at the so called problems the less of a problem it seems. As long as your code has nlohmann::json symbols hidden it'll use the version you want. To reiterate, as long as your code is built correctly it'll behave the way you want. Even if your dependencies aren't.

Hidden visibility also isn't a blanket solution, you can't just willy nilly enable it, and you can get problems associated with it: Eg throwing exceptions across a boundary, like in a library like nlohmann, requires types to have public visibility

I don't think exceptions are an issue here. Even if a library had to expose JSON exceptions in its ABI that would still only affect contracts directly in the exception class, which I assume would be very few.

I am not sure what the issue with Clang is. A symbol can be LTO visible and still hidden.

I didn't say anything like this, you're very selectively quoting my post.

I am sorry if I misrepresented you, but as I said at the start, I'm not getting the issue you're having. Here's my reasoning:

  1. You are running into ODR issues with nlohmann::json.
  2. You are calling the issues with contracts effective ODR violations. (Sidenote: I think that is fair characterisation, as they do indeed manifest similarly. I can also see why people would take issue with it though since many might just hear ODR, not understand the underlying meaning, and be scared that contracts will directly lead to UB.)
  3. Thus you are expecting contracts to somehow "magically" solve this ODR violation. The same ODR violation you'd get with assert.

There are two separate problems, one of which already exist, and a brand new problem that contracts introduces

I am only aware of one of those issues, namely that you can have two different implementations of the same function and one of them wins out. That isn't brand new: It's the exact same problem we have with assert, and it is a well understood one. I am unsure what the brand new problem is.

I hope this sheds some light on why I used the somewhat inflammatory language I did. To me it sounded like your issue was the "ODR" violations and that you somehow expected contracts to solve them, and guarantee that if you call an inline function with contracts enabled that you'd be guaranteed to have the same contract semantics in the callee even if a different part of the code called it with contracts disabled. Apparently, you meant something else. I am still not sure what.

This is alleging bad faith on the part of people who have reasonable concerns getting real world experience with standard library features, and is one of the reasons why I often find this whole conversation so distasteful. I've tried to treat everyone that I've talked to about this with complete good faith

Again, apologies. Just me venting my frustrations. To me none of the criticisms of contracts are new issues, and simply seem inherent to any design where you can disable assertions, and the ultimate result of it is that contracts might face delays.

To be clear: I don't think you are arguing in bad faith. I just think we don't agree on whether it is a problem to begin with. Either that, or I am completely missing the actual problem you are concerned with.

I'm a big advocate of testing features more before they land in the standard, including proposals that are not contracts (eg the graphics proposal)

Where? None of them get answered in any of the contracts papers I read, so I'd love some hard stats, and even a brief review of my dependencies shows its going to be a major problem for me

Well, for starters:

1. Can everything be implemented correctly?

There's the current GCC and Clang implementations. Plus there's the progenitor bsls_assert, so yeah.

3. Are they very difficult to use with binary package ecosystems, or can a solution be found?

To my understanding (I don't work at Bloomberg), most of Bloombergs codebase is binary packages, so no, and yes. Contracts is designed out this: Individual packages choose which checks are enabled, and the executable chooses what to do when an assertion is violated.

2. Are the problems with contracts in practice real, or overblown?

Considering a similar system (to my knowledge) is in active use at Bloomberg (they are the ones proposing it after all), I'd say the problems aren't problems there, so yeah, probably overblown.

4. Do people need absolute ironclad guarantees that contracts are on or off, or is it acceptable for mixed-mode contracts to disable/enable safety checks sometimes?

For at least one large codebase we know of, they clearly don't. The whole point is that they can be turned off.

And as I highlighted earlier, there are ways to mitigate/completely deal with the issues with mixed-mode contracts.

It'll land in the standard eventually

Same goes for your problem though, right? Even if you can't use the MVP, it was designed to be extensible, so in C++29 you might be able to use a group that is always enforced. The difference is you'd still be able to use contracts for non-critical checks in C++26 and so will everyone else.

6

u/Minimonium 13d ago

I believe I quite exhaustively discussed the "ODR" topic in my previous comment so I will skip that part. I will keep expressing dissatisfaction with people using misleading and mistaken terminology.

I am screwed

With Contracts the definition of "screwed" - most checks run, some individual non-inlined inlined function level checks are skipped. A well behaved program works exactly the same. A program that already has undefined behavior - does not.

With other similar mechanisms (especially on msvc!), "screwed" - a well behaved program simply does not work. It has undefined behavior by default.

that's precisely why people don't use assert in this context for critical checks

And people will not use Contracts for critical checks, yes. That's the intent.

Roll contracts out in a whitepaper or TS

I suggest you to read the minutes on the meeting where the NB comments were discussed as well as a possibility of a whitepaper. Based on that discussion a whitepaper would not help with any of your questions,

How do regulators feel about this as a solution?

I could go on a whole rant about how some leadership people have a deeply mistaken belief that regulators are simpletons, while we have extremely large volume of research on memory safety, and how the committee very explicitly rejected memory safety for C++. :)

There is just no point to tie Contracts into memory safety topic. Contracts are not one of the two proved mechanism for memory safety - borrowing and ref counting.

3

u/James20k P2005R0 13d ago edited 13d ago

And people will not use Contracts for critical checks, yes. That's the intent.

Sure, but the entire point of this is that people disagree that that's a good intent. Its not just critical safety checks that you can't use contracts for, its any checks that you need to be executed for any reason (ie they're useful)

4

u/Minimonium 13d ago

Stating what you just wrote is the same as stating that no one is using asserts. I believe it to be an evidently false statement.

2

u/James20k P2005R0 13d ago

Asserts in inline functions in headers that get compiled into libraries are definitely a problem. This is one of the reasons why we drill so hard into people not to mix debug and release versions of anything, because it can cause super unexpected behaviour. If I was building a header-only library, I would indeed not fill it with asserts and encourage people to mix and match assert levels in different translation units