# C# Language Design Meeting for November 5th, 2025

## Agenda

- [Unsafe evolution](#unsafe-evolution)

## Quote of the Day

- "Do COM interfaces need to be unsafe?" "[with a look of visible pain] Well that's a \*\*\*\* question"

## Discussion

### Unsafe evolution

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](LDM-2025-10-29.md#unsafe-evolution), 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:

1. Do we accept the core kernel of the proposal, moving `unsafe` from meaning "there exists a pointer type" to "there exists memory unsafety, as defined by the
   [caller unsafe](https://github.com/dotnet/designs/blob/2b9e1b311d16ea142b4047d6eddeef15979ba6de/proposed/caller-unsafe.md) document being proposed for the platform?
2. Will the new rules be warnings, errors, or some form of suppressible error between?

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:

* We expect the amount of code in the average project that will need to change to adopt new memory safety rules is quite low. The majority of projects shouldn't even
  be impacted. This is extremely different to nullable, where every single line of executable code, and most lines of definitions, were impacted. We expect that this
  should reduce the number of configuration options needed.
* Ignoring nullable warnings can cause bugs, and potentially even vulnerabilities in the form of DOS attacks, but memory safety issues are much more severe. Reading
  an unintentional `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.

#### Conclusion

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.
