Incorrect nullable type inference in collection expressions
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
**Version Used**: 2e23a0df5bf8d49f6bf856287b0eb10de08f97d9
**Steps to Reproduce**:
Compile and run the following code:
```csharp
using System;
using System.Collections;
using System.Collections.Generic;
#nullable enable
List obj = new() { null };
C c = [obj]; // no warnings
foreach (List list in c)
foreach (string s in list)
{
Console.WriteLine(s.Length); // NullReferenceException crash
}
// both lines below would report
// CS8620 Argument of type 'List' cannot be used for parameter 't' of type 'List' in 'void Ext.Add(C c, List t)' due to differences in the nullability of reference types.
//c.Add(obj);
//c = new() { obj };
class C : IEnumerable>
{
internal List _list = new();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator> GetEnumerator() => new List>() { _list }.GetEnumerator();
}
static class Ext
{
public static void Add(this C c, List t) => c._list.AddRange(t);
}
```
**Diagnostic Id**:
`CS8620`
**Expected Behavior**:
A nullability mismatch warning is reported for the collection expression.
The warning is the same for both implicit `.Add` call in the collection expression and explicit `.Add` call.
**Actual Behavior**:
No warnings at all are reported in the code above. It crashes with a `NullReferenceException` at runtime.
**Notes**:
I believe that the issue is incorrect nullability type reinference for the implicit `.Add` call in the collection expression. It looks like Roslyn infers the call to be `Ext.Add(C c, List t)` which makes the element argument match. The incorrect inference should result in an mismatching receiver nullability, but Roslyn fails to verify it as reported in https://github.com/dotnet/roslyn/issues/79803
Here's a slightly modified example that led me to this conclusion - Roslyn correctly reports `CS8620` if the parameter is fixed to the correct nullability:
```csharp
using System;
using System.Collections;
using System.Collections.Generic;
#nullable enable
List obj = new() { null };
C c2 = [obj]; // CS8620
class C : IEnumerable>
{
internal List _list = new();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator> GetEnumerator() => new List>() { _list }.GetEnumerator();
}
static class Ext
{
public static void Add(this C c, List t) => c._list.AddRange(t);
}
```
Contributor guide
Assessment
This issue has not been assessed yet.