Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Aug 6, 2025

The AotConverterGenerator was generating incorrect pattern matching code for tuple types, causing compilation errors when using implicit operators with tuple parameters.

Problem

When generating AOT converters for implicit operators that accept tuple parameters like (int Value1, int Value2), the generator was creating positional patterns:

if (value is (int Value1, int Value2) typedValue)
{
    return (Foo)typedValue;
}

This syntax is interpreted as a positional pattern that looks for a Deconstruct method on the object type, which doesn't exist, resulting in compilation errors:

CS1061: 'object' does not contain a definition for 'Deconstruct'
CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'object'

Solution

The fix detects when the source type is a tuple type using IsTupleType and generates the correct ValueTuple<T1, T2, ...> pattern matching syntax instead:

if (value is global::System.ValueTuple<int, int> typedValue)
{
    return (Foo)typedValue;
}

This works correctly because it pattern matches against the actual underlying ValueTuple type rather than using tuple literal syntax that gets interpreted as a positional pattern.

Example

This code now compiles successfully:

public record Foo
{
    public static implicit operator Foo((int Value1, int Value2) tuple) => new();
}

public class Tests
{
    [Test]
    [MethodDataSource(nameof(Data))]
    public void Test1(Foo data) { }

    public static IEnumerable<Foo> Data() => [new()];
}

The fix handles tuple types of any arity (2-tuple, 3-tuple, etc.) and maintains backward compatibility with existing non-tuple conversion operators.

Fixes #2798.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits August 6, 2025 18:45
Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
… types

Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
Copilot AI changed the title [WIP] Generic data types with implicit tuple operators don't compile in 0.52.25 Fix tuple pattern matching in AotConverterGenerator to use ValueTuple types Aug 6, 2025
Copilot AI requested a review from thomhurst August 6, 2025 18:54
Copilot finished work on behalf of thomhurst August 6, 2025 18:54
@thomhurst thomhurst marked this pull request as ready for review August 6, 2025 19:02
@thomhurst thomhurst enabled auto-merge (squash) August 6, 2025 19:02
@Brokolis
Copy link

Brokolis commented Aug 7, 2025

I believe this can be fixed in a more clean/less manual way by creating a special SymbolDisplayFormat instead of trying to build the display type manually:

public static readonly SymbolDisplayFormat FullyQualifiedGenericWithGlobalPrefixForPatternMatching = FullyQualifiedGenericWithGlobalPrefix
    .AddMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.ExpandValueTuple);

This display type can then be used for any type that will be used in pattern matching, so there is no need to handle ValueTuple specially. This SymbolDisplayFormat gives me these results (tested on Microsoft.CodeAnalysis.CSharp version 4.14.0):

For (int Value1, int Value2):

global::System.ValueTuple<int, int>

For (int, int, int, int, int, int, int, int, int, int, int, int, int, int) tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14):

global::System.ValueTuple<int, int, int, int, int, int, int, global::System.ValueTuple<int, int, int, int, int, int, int>>

For int:

int

For reference, FullyQualifiedGenericWithGlobalPrefix gives me these results:

For (int Value1, int Value2):

(int Value1, int Value2)

For (int, int, int, int, int, int, int, int, int, int, int, int, int, int) tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14):

global::System.ValueTuple<int, int, int, int, int, int, int, (int, int, int, int, int)>

For int:

int

@thomhurst thomhurst closed this Aug 7, 2025
auto-merge was automatically disabled August 7, 2025 18:12

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generic data types with implicit tuple operators don't compile in 0.52.25

3 participants