Skip to content

Compile Error CS0426 with Custom Formatter for Generic Type in External Package #2133

@Funkest

Description

@Funkest

Bug Description

Compile error CS0426 occurs when using a custom formatter for a generic custom type from an external package.

Repro Steps

  • Version Used: 3.1.1
  • Runtime: .NET Core (other runtimes not tested)

Steps to reproduce the issue:

  1. Create a custom generic class and its formatter as a NuGet package. Example:
    (For the sake of simplicity, the class body and formatter are described within the same package here, but I think it is standard practice to separate them in a package.)

    namespace Shared.PackageFormatterExample  
    {  
        public class Foo<T> { }  
    
        // Formatter  
        public class FooMessagePackFormatter<T> : IMessagePackFormatter<Foo<T>>  
        {  
            public Foo<T> Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) => throw new NotImplementedException();  
            public void Serialize(ref MessagePackWriter writer, Foo<T> value, MessagePackSerializerOptions options) => throw new NotImplementedException();  
        }  
    
        // Resolver  
        public class FooMessagePackResolver : IFormatterResolver  
        {  
            public IMessagePackFormatter<T>? GetFormatter<T>() => throw new NotImplementedException();  
        }  
    }  
  2. Add a reference to the package in a project and use the custom type. Example:

    using Shared.PackageFormatterExample;  
    
    namespace MainProject  
    {  
        [MessagePackObject]  
        class Tester  
        {  
            [Key(0)]  
            public Foo<int> Foo { get; set; } = new Foo<int>();  
        }  
    }  

Expected Behavior

The code should compile without error CS0426.

Actual Behavior

Compile error CS0426 occurs in the generated MessagePack.GeneratedMessagePackResolver.g.cs, preventing compilation.

Additional Context

  • When the custom formatter is implemented directly in the main project (not via a package), the code compiles as expected.
  • Example of problematic generated code in MessagePack.GeneratedMessagePackResolver.g.cs:
    private static class GeneratedMessagePackResolverGetFormatterHelper  
    {  
        ...  
        internal static object GetFormatter(global::System.Type t)  
        {  
            if (closedTypeLookup.TryGetValue(t, out int closedKey))  
            {  
                switch (closedKey)  
                {  
                    // THE NEXT LINE SHOULD NOT BE GENERATED
                    case 0: return new global::MessagePack.GeneratedMessagePackResolver.Shared.PackageFormatterExample.FooFormatter<int>();
                    case 1: return new global::MessagePack.GeneratedMessagePackResolver.TesterFormatter();  
                    default: return null; // unreachable  
                }  
            }  
            return null;  
        }  
    }  

It appears that the generated code incorrectly tries to instantiate a formatter using the wrong namespace or path, leading to the error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions