As part of this proposal, we will also loosen the type requirements on `??` to allow variables typed with the unconstrained type parameter to be used on the left-hand side.
Which follows the [existing semantic rules for compound assignment operators](https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#compound-assignment), except that we elide the assignment if the left-hand side is non-null. The rules for this feature are as follows.
Given `a ??= b`, where `A` is the type of `a`, `B` is the type of `b`, and `A0` is the underlying value type of `A` if `A` is the nullable type.
1. If `A` does not exist or is a non-nullable value type, a compile-time error occurs.
2. If `B` is not implicitly convertible to `A` or `A0`, a compile-time error occurs.
3. The type of `a ??= b` is `A`.
4.`a ??= b` is evaluated at runtime as `a ?? (a = b)`, except that `a` is only evaluated once.
Note that rule 4 means that if `B` is implicitly convertible to both `A` and `A0`, we will prefer the conversion to `A` over `A0`.
For the relaxation of the type requirements of `??`, we update the spec where it currently states that, given `a ?? b`, where `A` is the type of `a`:
> 1. If A exists and is not a nullable type or a reference type, a compile-time error occurs.
We relax this requirement to:
1. If A exists and is a non-nullable value type, a compile-time error occurs.
As with any language feature, we must question whether the additional complexity to the language is repaid in the additional clarity offered to the body of C# programs that would benefit from the feature.
## Alternatives
[alternatives]: #alternatives
The programmer can write `(x = x ?? y)` or `if (x == null) x = y;` by hand.