cathei / LinqGen

Alloc-free and fast replacement for Linq, with code generation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OfType Followed by Some Operations Generates Non-compiling Code

Pentiva opened this issue · comments

I've only tested for Select and Where as delegates, but it may be more widespread. There are tests covering Skip and Take, and they seem to work fine. It will probably only affect operations that take a selector/predicate.

Here is some example user code that causes the problem:

TestData.ObjectStringArray.Gen().OfType<string>().Select(g => string.IsNullOrEmpty(g) ? '\0' : g[0])

TestData.ObjectStringArray.Gen().OfType<string>().Where(g => string.IsNullOrEmpty(g))

The Select generates (with most excluded for brevity)

internal struct Select_uF<TOut_p2> : IInternalStub<char>
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal Select_uF(in OfType_p2<TOut_p2> source, global::System.Func<string, char> selector_uF) : this()
        {
            this.source_n2 = source.source_n2;
            this.selector_uF = selector_uF;
        }
        ...
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool MoveNext()
            {
               ...
                while (true)
                {
                    ...
                    var current_p2 = (TOut_p2)(object)current_n2;
                    var current_uF = parent.selector_uF.Invoke(current_p2); // Error here
                    ...
                }

                return false;
            }

I think the constructor should take a Func<TOut_p2, char> instead of Func<string, char> as the error is Argument type 'TOut_p2' is not assignable to parameter type 'string'

Locally I inserted these two lines at https://github.com/cathei/LinqGen/blob/main/LinqGen.Tests/OperationTests.tt#L94 to generate failing tests:

("OfTypeSelect", "OfType<string>().Select(g => string.IsNullOrEmpty(g) ? '\0' : g[0])", "OfType<string>().Select(g => string.IsNullOrEmpty(g) ? '\0' : g[0])", castSources),
("OfTypeWhere", "OfType<string>().Where(g => string.IsNullOrEmpty(g))", "OfType<string>().Where(g => string.IsNullOrEmpty(g))", castSources),

Thank you for reporting this issue! It was due to operations directly used the inferred type, not applying generic type arguments. It will be fixed in next release.