meetings/2025/LDM-2025-11-05.md
Champion issue: https://github.com/dotnet/csharplang/issues/9704
Specification: https://github.com/dotnet/csharplang/blob/ff88c654e26def239d2f7bcab52fe4e4d016dfba/proposals/unsafe-evolution.md
Related: https://github.com/dotnet/designs/blob/2b9e1b311d16ea142b4047d6eddeef15979ba6de/proposed/caller-unsafe.md
Picking up from last time, we continue to discuss how we want to evolve unsafe in C#. From the last time, the proposal was
revised to include a few more open questions, as well as to reduce the level of breaking change it was proposing. Today, we were able to discuss 2 main topics:
unsafe from meaning "there exists a pointer type" to "there exists memory unsafety, as defined by the
caller unsafe document being proposed for the platform?For the first question, we agreed that yes, this moving unsafe into this newer world is acceptable. That left the majority of the meeting for discussion on warning vs
error, which also bridges into areas of "how would the state be controllable?". The repeated analogy here is to the nullable reference types feature, and we discussed
nearly every way in which nullable allows configuration. However, while the analogy works quite well, we think there are two major differences from the nullable feature:
null can crash an app, but reading uninitialized or unmanaged memory incorrectly can expose the app's data or users to attack. We therefore feel
much more strongly about getting memory safety properly annotated across the ecosystem.Given both the expected smaller blast radius and the higher importance of addressing issues, we believe that we want to start with stricter versions of the rules. We
will therefore start with memory safety diagnostics being errors, with no dedicated suppression mechanism. Wrapping new errors in unsafe with todo comments attached
will be the main form of "suppress for now and come back later" available to authors.
This does pose some adoption problems for users who depend on source generators, as there will be no special affordance given to source generators. This can mean that
if a generator is not updated, and is emitting code that has new memory safety errors in it, the consumer of the generated code will be blocked from enabling the new
rules. While this is harsh, we expect that the majority of the generators that use unsafe code are either first-party, or are from highly-engaged community members
who will be quick to jump on the new rules. If these rules prove too onerous and block widespread adoption of the feature, we can revisit, but we want to start at the
more secure end of the spectrum. We also don't expect that source generators need to be concerned by "unexpected" unsafe. Either the generator was written with the
intent of using unsafe code in mind, or it is an error on the consumption side to provide the generator an unsafe member to interact with if it wasn't expecting it.
Next up, we will be discussing how members are marked unsafe, and what unsafe on a type means.
The core principle of the unsafe evolution feature is accepted. unsafe diagnostics will be errors by default, and no affordance for source generated code will be
given.