microsoft / STL

MSVC's implementation of the C++ Standard Library.
Other
10.2k stars 1.51k forks source link

Determine ABI stability timeline for C++20 #1814

Closed StephanTLavavej closed 2 years ago

StephanTLavavej commented 3 years ago

We're in a novel situation: never before have we completed a Standard so rapidly. Adding to this concern, <format> is both ABI-sensitive and performance-sensitive, and WG21 is expected to mandate ABI-breaking changes soon.

(C++17 was different; we finished <charconv> in 2019 having completed all other features much earlier, and while it was performance-sensitive, we had time to extensively test and tune it, and its function-oriented nature means that it has no ABI concerns and can be revised in the future.)

We were initially planning to declare ABI stability when finishing C++20 (along with the addition of /std:c++20 as distinct from the always-experimental /std:c++latest), to align with the user expectation that non-experimental features supported for production use are also ABI stable. However, if this locks us into an implementation that can't keep up with retroactive changes to C++20, or freezes an implementation before it's had a chance for significant performance tuning, that will ultimately be harmful to users.

We should consider asking our bosses and boss-like entities for a change of plans: we will still declare C++20 to be feature-complete and ready for production use when we're done (as indicated by the feature-test macros), but we can announce that its ABI will potentially change for some defined period of time (3 months, 6 months, 1 year?) or number of releases (e.g. Dev17 17.x for some specific value of X). This will have no effect for /std:c++14 and /std:c++17 users, and we can expect that, at least initially, the population of /std:c++20 users will be the most eager upgraders for whom rebuilding the world is the least onerous.

Additionally, to mitigate mix-and-match problems, we could add a #pragma detect_mismatch to <format> right now, allowing us to revise it in the future and have the linker detect any OBJ/static LIB mixing.


Update: We arrived at a plan, see the comment below.

sylveon commented 3 years ago

I personally think something like keeping the ABI unstable until the non-preview release of Dev17 would be a good idea.

Freezing it now will lead to major differences between standard libraries because the new changes to the standard library require ABI breakage, meaning some libraries and consumers might be reluctant to adopting C++20 because of inconsistency between compilers/standard library implementations, and this will ultimately be detrimental to the MSVC ecosystem.

timsong-cpp commented 3 years ago

As @brevzin noted, there are three Ranges papers in flight with ABI implications as well (split, default construction, and join).

jovibor commented 3 years ago

We should consider asking our bosses and boss-like entities for a change of plans: we will still declare C++20 to be feature-complete and ready for production use when we're done (as indicated by the feature-test macros), but we can announce that its ABI will potentially change for some defined period of time

Nothing but hoping for your bosses' good sanity😎

hatcat commented 3 years ago

We're in a novel situation: never before have we completed a Standard so rapidly.

I have high hopes for C++23...

miscco commented 3 years ago

We're in a novel situation: never before have we completed a Standard so rapidly.

I have high hopes for C++23...

Will be finished in 22

Lectem commented 3 years ago

If this can help take a decision or convince anybody: Out of the 5 last clients I worked with, 4 said they stopped using some of STL types due to either runtime performance or compile time performance, that could be fixed by changing ABI such as is done in vNext. I'm thinking mainly about debug iterators and regexp. If std::format isn't fast enough (to compile or at runtime) compared to fmt::format, I'm afraid this will only keep fueling arguments against using the STL (and std library in general, whatever implementation it is).

While I am sympathetic to having some kind of ABI stability, I don't think "rushing" a release just to be able to put the "c++ latest compliant" stamp is a good idea if QoI improvements can't follow due to the same ABI stability. An upgrade path must be kept, or some rupture planned to finally take this opportunity to break ABI, just as was done in the past.

MikeGitb commented 3 years ago

Personally, I'm not even that concerned about performance, exactly because there is fmt and the STL is rarely the best performing solution for a given problem anyway.

What I do care about though is correctness and portability. Effectively locking down the ABI before having any significant user contact, real-world testing and (ideally) a second implementation to compare against seems a very risky choice for something so fundamental - especially when people are still trying to "fix" the standard itself.

jovibor commented 3 years ago

Personally, I'm not even that concerned about performance, exactly because there is fmt and the STL is rarely the best performing solution for a given problem anyway.

By this logic, there is no value in using STL at all, because every piece of it has more performant counterpart somewhere anyway. The only reason would be that it's available out-of-the box.

If the performance question is not about years of researching or some rocket science, but only delaying ABI locking by month or so I would definitely consider it as the way to go.

MikeGitb commented 3 years ago

By this logic, there is no value in using STL at all, because every piece of it has more performant counterpart somewhere anyway. The only reason would be that it's available out-of-the box.

That's pretty much the way it is. Yes. Except for

there is no value in using STL at all

Just because there is something faster somewhere doesn't mean the STL doesn't have value. Using 3rd party dependencies comes with it's own costs and even in c++ code, performance is not the only relevant metric.

But that gets off topic.

vitaut commented 3 years ago

Personally, I'm not even that concerned about performance, exactly because there is fmt and the STL is rarely the best performing solution for a given problem anyway.

It's more complicated in case of fmt/std::format compared to, say, containers because here we have the formatter extension point. It would be really unfortunate if we ended up in the world with two sets of incompatible formatter specializations and resulting interoperability problems. I think it's worth taking time and addressing performance differences before ABI is frozen or at least making sure that they can be addressed in the future without ABI breakage.

MikeGitb commented 3 years ago

It's more complicated in case of fmt/std::format compared to, say, containers because here we have the formatter extension point. It would be really unfortunate if we ended up in the world with two sets of incompatible formatter specializations and resulting interoperability problems.

So far we have rarely been using a library provided operator<< for printing (except for printf debugging or quick prototyping), because most of the time we had our own format requirements anyway. In a similar fashoin, I'm not sure how much I'm going to use a 3rd party fmt/std::formatter specialization in a context, where performance matters. Also, performance aside, I expect fmt to stay ahead of std::format feature and compatibility wise for the forseable future, so we'll probably have to live with this duality for quite some time anyway.

Anyway, as I wrote previously: I'm also very much against locking down the ABI right away - just that performance isn't my primary reason for that.

vitaut commented 3 years ago

far we have rarely been using a library provided operator<< for printing

You maybe, others have been using them extensively.

we'll probably have to live with this duality for quite some time anyway.

The important thing is the long term, not the next few years. In the long term I expect fmt::formatter to go away.

MikeGitb commented 3 years ago

You maybe, others have been using them extensively.

Not sure what you are trying to convince me of. I never said, 3rd party overloads of operator<< isn't bein used by others. I said we didn't use it. I also didn't say whatever performance such an ABI freeze would leave on the table isn't a problem for anyone. I said I am not concerned about the performance impact [EDIT: primarily].

The important thing is the long term, not the next few years.

Long term, the current msvc ABI doesn't matter anyway (assuming plans to introduce an new ABI in the Dev17 timeframe come to fruitition). Also, I'd speculate that implementation divergence or unfixable bugs that slipped through will be a much bigger obstacle to the adoption of std::formatter than x% performance difference.

Anyway. I think we agree that we'd prefer ABI not to be frozen right away. Arguing which reason (potential performance difference vs potential divergence/correctness issues or even the danger of preventing improvements to the standard) is "more important" feels silly.

barcharcraz commented 3 years ago

I think std::format is a little less hamstrung by ABI than regex, but these sorts of things are extremely difficult to analyze correctly.

TautvydasZilys commented 3 years ago

This will have no effect for /std:c++14 and /std:c++17 users, and we can expect that, at least initially, the population of /std:c++20 users will be the most eager upgraders for whom rebuilding the world is the least onerous.

Does this mean that you will not be able to link /std:c++14 code with /std:c++20 code once it is properly released? Or is this about mixing /std:c++20 code compiled with VS 17.0-preview4 with /std:c++20 code compiled with VS 17.6?

sylveon commented 3 years ago

The latter

TheStormN commented 3 years ago

I'm concerned about the VS 2022 blog post saying: "If you want to upgrade to Visual Studio 2022 but are worried about compatibility, binary compatibility with the C++ runtime will make it painless."

Which basically means that they are not going to break the ABI of the current runtime for C++11/14/17, which means that some old bugs and performance issues aren't going to be addressed. Not sure if different runtime will be used for the C++20 mode(where older standard features are used), but if it is, then things are getting really confusing.

@StephanTLavavej Could you shed some light on these matters?

sylveon commented 3 years ago

The ABI was not broken for VS 2022, as documented here: https://github.com/microsoft/STL/discussions/1725#discussioncomment-467070

And no, C++20 doesn't use a different runtime, so you can link code compiled for C++20 to code compiled for older standards without issue.

TheStormN commented 3 years ago

The ABI was not broken for VS 2022, as documented here: #1725 (reply in thread)

And no, C++20 doesn't use a different runtime, so you can link code compiled for C++20 to code compiled for older standards without issue.

I see, so unfortunate... Anyway, to be a bit more on the current topic, I also agree that the C++20 ABI should stay unstable a bit more time in order to properly fix issues from WG21.

StephanTLavavej commented 3 years ago

I've set up a meeting with our bosses and boss-like entities to reach a decision here. Thanks to everyone who's expressed interest in this issue; it is very helpful to be able to point to the number of upvotes :smile_cat:

cor3ntin commented 3 years ago

@StephanTLavavej Great to hear!

FYI, the next plenary is on June 7, the ranges papers should be approved then. I also would like to point out this issue - having a few more weeks to resolve it would be greatly appreciated LWG3547.

As a matter of personal opinion (not reflective of anyone in WG21), I think giving WG21 until the next plenary to put out the fires and address known defect would be a lovely compromise, I understand that we cannot keep doing that forever.

At the same time, I like to think that it's in the benefit of everyone to address known issues, while we still can. The long time costs of not doing it would otherwise be paid for many decades by all of C++ developers, or back both WG21 and implementers in an uncomfortable corner.

Mistakes were made, we were blindsided by some issues, and frankly WG21's output also suffers from self-imposed deadlines. Maybe we should have course corrected sooner, but times are challenging.

I apologize for whatever part I had to play in that lack of reactivity.

We can only try our best. And hope there aren't to many unknown problems that will pop up once C++20 is widely deployed.

Congrats on implementing the standard in record time in the midst of a pandemic, and thanks for working with your organization on this issue.

Thanks!

h-vetinari commented 3 years ago

One other aspect that's novel and not mentioned explicitly in the OP, but came up in the reddit thread announcing STL's C++20 completeness (by, IIUC, the same author):

someone: Did open sourcing the library help in any way?

@StephanTLavavej: Yes, beyond our wildest dreams. Our amazing GitHub contributors were responsible for many large and difficult features, stressing both domain expertise and attention to detail. It took some time to migrate the STL to GitHub (an ongoing project) and it takes more time to perform detailed code reviews that communicate how to implement/maintain the STL (something that no book directly teaches; I learned it as an apprentice/minion), but ultimately it's saved a ton of time as our contributors have gone on to write way more (and better!) code than the maintainer team working in isolation ever could have in the old closed system. Without being open source, there's no way we'd have been complete now - probably it'd be calendar year 2022. [...]

It might be helpful for that meeting to point out how the community helped put the STL in a position where the option of declaring feature completeness & ABI stability is even on the table that early. It would be a wonderful way to acknowledge that contribution (on the level of the bosses and upwards) by listening when now many of the same people (not including myself...) are asking for STL's help in turn.

StephanTLavavej commented 3 years ago

@h-vetinari An excellent point, I'll make sure to bring it up!

vrubleg commented 3 years ago

image

StephanTLavavej commented 3 years ago

Ok, we've got a plan approved by our bosses and boss-like entities:

@CaseyCarter is working on the library changes needed to make <format>, <ranges>, and the formatting part of <chrono> available under /std:c++latest only; we'll apply this to the microsoft/STL repo and VS 2022 17.0 simultaneously, then backport to the 16.11 branch internally.

Hope this makes sense! We can answer any questions you might have.

Zingam commented 3 years ago

Very well. How is that going to work in/with CMake?

StephanTLavavej commented 3 years ago

I am not very familiar with CMake, but I've seen our usage of CMAKE_CXX_STANDARD:

https://github.com/microsoft/STL/blob/68145cbc22f25fd9936a58d05b261c5c5767a38a/tools/CMakeLists.txt#L7

According to their documentation for CMAKE_CXX_STANDARD and CXX_STANDARD, "Supported values are 98, 11, 14, 17, 20, 23."

I would expect that CMake should:

I am not sure what the current behavior is.

thewavelength commented 3 years ago

Regarding CMake:

Map 20 to /std:c++20 for MSVC 16.11, 17.0, and beyond

As a casual C++ developer this would be contrary to what I'd expect. According to your explanation I would expect to map 20 to std:latest as long as it is not finalized. So in this case map it to that as long as 17.x can ship with a feature complete and finalized C++20.

Everything else will probably create a lot of headaches if CMake behaves differently for different versions of VS being installed. I can already see people being confused why a more up2date installed VS version is having less features with the same CMakefile.

MikeGitb commented 3 years ago

@thewavelength: stdc++20 with 16.11 and 17.x will provide the full c++20 feature set (at least that's the plan as far as I understand), so I don't get what you are concerned about.

thewavelength commented 3 years ago

@MikeGitb if that's the case I'm fine with it. But I understood it in a way that (probable) ABI incompatible features like format wouldn't be included in those versions in std:c++20 but only in std:latest until it is finalized by the committee.

MikeGitb commented 3 years ago

I think you are right - I overlooked

  • VS 2019 16.11, the last update in the VS 2019 release series, will add /std:c++20. We'll apply library changes so that almost all C++20 STL features will be available in /std:c++20 mode. The exceptions are that <format>, <ranges>, and the formatting part of <chrono> will remain restricted to /std:c++latest due to WG21's upcoming changes.

Sorry

leha-bot commented 3 years ago

I am not very familiar with CMake, but I've seen our usage of CMAKE_CXX_STANDARD:

https://github.com/microsoft/STL/blob/68145cbc22f25fd9936a58d05b261c5c5767a38a/tools/CMakeLists.txt#L7

According to their documentation for CMAKE_CXX_STANDARD and CXX_STANDARD, "Supported values are 98, 11, 14, 17, 20, 23."

I would expect that CMake should:

* Map `20` to `/std:c++latest` for MSVC up to and including 16.10,

* Map `20` to `/std:c++20` for MSVC 16.11, 17.0, and beyond

* Map `23` to `/std:c++latest` for all versions of MSVC (until years from now when C++23 is done).

I am not sure what the current behavior is.

@bradking sorry for mention, but could you confirm/refute this? Thanks in advance :blush:

bradking commented 3 years ago

CMake's logic for mapping standards to MSVC flags is here. It will need an update for /std:c++20 and C++23. Please see our CONTRIBUTING.rst file and open a merge request for that.

bradking commented 3 years ago

See CMake MR 6174 for this update.

StephanTLavavej commented 3 years ago

@thewavelength Yeah, your point makes sense.

@bradking Please note that VS 2019 16.10 Preview 4 differs from the final production release - at the last moment, we removed /std:c++20 (which is the subject of this very long thread). If I understand that CMake merge request correctly, it will attempt to use /std:c++20 with 16.10 which will fail to compile with the production release (available right now).

Additionally, note that /std:c++20 has not been removed from 16.11 Previews (we're going to port STL changes to modify which features it enables).

Zingam commented 3 years ago

@StephanTLavavej Why weren't these 'experimental/unstable' features hidden behind some temporary 'experimental' switch? If I get it correctly in the case of CMake and maybe other build systems as well: <format> etc. will be available in 16.10 with cxx_std_20, then in 16.11 the won't but will appear under cxx_std_23 and then sometime in 17.x again with cxx_std_20. That's probably not a big issue but it will certainly confuse somebody.

MikeGitb commented 3 years ago

My understanding was that all features that require /std:c++latest should be considered unstable. Unfortunately (or maybe fortunately) Cmake doesn't distinguish between stable and unstable features belonging to the same standard version (not sure how useful it would be inpractice).

@StephanTLavavej , @bradking Assuming that it will not make a difference if /std:c++latest or /std:c++20 is used in 16.11 if I don't use the affected headers in the frist place and also assuming that there won't be c++23 features under c++latest in 16.11, I think my personal preference for cmake would be to not use /std:c++20 for any version of VS2019 series at all and just always map cxx_std_20 to /std:c++latest. That way, the behavior is more consistent and I would assume/hope (but could be wrong) that people requiring ABI stability will anyway take much more direct control over what flags are being used exactly instead of relying cmake to consistently select appropriate flags accross compiler and cmake versions.

Not sure what my preferences would be if those assumptions don't hold.

Would of course be great to get feedback from someone who actually relies on ABI stability for their product.

StephanTLavavej commented 3 years ago

I can confirm that we will not backport C++23 features to 16.11. We aren't planning to backport any STL changes aside from #1929 itself, and any fixes for critical bugs that we discover (they'd have to be pretty bad, beyond ordinary bugfixes). Because 16.11 is a permanent stabilization release, feature work is specifically not allowed (only with special exceptions).

bradking commented 3 years ago

VS 2019 16.10 Preview 4 differs from the final production release

In CMake MR 6174, the /std:c++20 flag will be used only for cl version 19.29.30129 or higher. VS 16.10 has cl version 19.29.30037, so we won't use /std:c++20 until VS 16.11.

Cmake doesn't distinguish between stable and unstable features belonging to the same standard version

CMake's cxx_std_## meta-features only care about nominally putting the compiler in a mode aware of the corresponding language standard. For unfinished modes, /std:c++latest is the best it can do. Beyond that, it is up to project code to put appropriate preprocessor conditions around use of advanced language features.

StephanTLavavej commented 3 years ago

Ah, thanks! I didn't inspect the version number closely. :joy_cat:

cor3ntin commented 3 years ago

Here is the list of papers approved as defects for C++20

cor3ntin commented 3 years ago

Note that the Chrono fix will not land officially before October as we were told rushing it would make no difference on your timeline

Sebanisu commented 3 years ago
if (MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30129 AND CMAKE_VERSION VERSION_GREATER 3.20.3)
    # this change happened in CMake 3.20.4
    set(CMAKE_CXX_STANDARD 23) # /std:c++latest - unlocks the non stable cpp20 features. For new 16.11 versions
else ()
    set(CMAKE_CXX_STANDARD 20) # /std:c++latest for msvc and -std=c++20 for everyone else.
endif ()

I had an issue on cmake. They pointed me to this issue. I ended up using this to keep 16.10 and 16.11 compiling with c++ 20. I'm using <ranges> and such. I got that version number from the Cmake source. https://github.com/Kitware/CMake/blob/71bf838cf35fabc27ff009f2901eeffc786fa753/Modules/Compiler/MSVC-CXX.cmake#L32

I had to update the if statement because older versions of cmake don't know how to handle c++ 23.

h-vetinari commented 3 years ago

4 more defect reports approved for C++~20~21 🙃

TheStormN commented 3 years ago

They all seem to be merged now, so finally we can go for stable full featured C++20(21) mode. :)

CaseyCarter commented 2 years ago

FYI, I've closed this issue despite that there's still work to be done to backport <ranges> and <format> to VS 2019 16.11, because all of the work that will take place in this repository is now complete.

SamVanheer commented 2 years ago

Since this issue is closed, is #2492 the issue to keep an eye on for the backporting work?

GF-Huang commented 2 years ago

Why I can't use std::format in VS2022? Namespace std has no member format!!!

image

image

sylveon commented 2 years ago

std::format under /std:c++20 is available in VS 17.2. For now, 17.2 is in preview. It should release to the stable branch at some point.

JonSuper commented 2 years ago

Why I can't use std::format in VS2022? Namespace std has no member format!!!

image

image

需要 VS 2019 16.11.14 or VS 2022 17.2 above