JasonBock / Rocks

A mocking library based on the Compiler APIs (Roslyn + Mocks)
MIT License
263 stars 20 forks source link

Special Types in a Member Cannot Be Used in Type Parameters #329

Closed JasonBock closed 2 months ago

JasonBock commented 4 months ago

To Reproduce

Test this code:

var code =
    """
    using Rocks;
    using System;

    [assembly: Rock(typeof(MockTests.ITypedReference), BuildType.Create | BuildType.Make)]

    namespace MockTests
    {
        public interface ITypedReference
        {
            void Use(TypedReference value);
        }
    }
    """;

Expected behavior The mock code is generated and compiles.

Actual behavior Errors occur like this:

error CS0306: The type 'TypedReference' may not be used as a type argument

There are types that can't be passed into type parameters, like pointers and interfaces with static abstract members. I've been able to get around some of this by generating delegates and custom Argument based types. However, TypedReference seems like a one-off "special" case. It's unclear according to the docs which types can't be used in type parameters. This test seems to suggest that the following types will trip CS0306:

Rocks already handles pointers through code generation, so it seems like there's only three types we need handle. There are a couple of strategies to do this:

If I do something here, I may want to create something that generate these projected support types for any given type. That may justify adding the three types into Rocks.

This was found on System.Reflection.Emit.FieldBuilder (the specific method definition is here)