dotnet / dotnet/roslyn

Poor overload resolution failure diagnostic for first class span Contains scenario

Open
#78,211 2 comments 0 reactions 1 assignee Claimed by @RikkiGibson View on GitHub
Area-Compilers Concept-Diagnostic Clarity Feature - First-class Span Types
Dominant language
C#
Stars
20.7k
Forks
4.3k
PR merge metrics
PR metrics pending

Description

```cs
using System.Diagnostics;

enum OpcodePrefix : byte
{
ADD = 0b1000_0000,
ADDC = 0b1001_0000,
SUB = 0b1010_0000,
SUBC = 0b1011_0000,
INC = 0b0110_0000,
// ...
}

static class OpcodePrefixExtensions
{
public static OpcodePrefix GetPrefix(byte b)
{
byte leftNybble = (byte)(b & 0xf0);
Debug.Assert(Enum.GetValues().Contains((OpcodePrefix)leftNybble)); // ok

// 'OpcodePrefix[]' does not contain a definition for 'Contains' and the best extension method overload 'MemoryExtensions.Contains(ReadOnlySpan, byte)' requires a receiver of type 'System.ReadOnlySpan'CS1929
Debug.Assert(Enum.GetValues().Contains(leftNybble));

// 'ReadOnlySpan' does not contain a definition for 'Contains' and the best extension method overload 'MemoryExtensions.Contains(Span, byte)' requires a receiver of type 'System.Span'CS1929
Debug.Assert(new ReadOnlySpan(Enum.GetValues()).Contains(leftNybble));

// 'Span' does not contain a definition for 'Contains' and the best extension method overload 'MemoryExtensions.Contains(ReadOnlySpan, byte)' requires a receiver of type 'System.ReadOnlySpan'CS1929
Debug.Assert(new Span(Enum.GetValues()).Contains(leftNybble));
return (OpcodePrefix)leftNybble;
}
}
```

Expected behavior: Diagnostics for the last 3 calls to `Contains` blame the `leftNybble` argument.

Actual behavior: Seemingly the receiver is blamed in all cases, even though an overload where the receiver argument has identity conversion to the parameter type is available, and the conversions of the other arguments are equally good (they do not exist in both cases). In effect, the diagnostic tells you to "use ReadOnlySpan" when you use an array or Span, then when you use ReadOnlySpan, it tells you to "use Span", leading you around in a circle. The actual problem is the second argument doesn't convert to the parameter type.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.