Skip to content
This repository was archived by the owner on Jul 15, 2023. It is now read-only.
This repository was archived by the owner on Jul 15, 2023. It is now read-only.

CCRewrite fails with NRE on async method with Ensures.ForAll with captured params because forwarder is null #72

@SergeyTeplyakov

Description

@SergeyTeplyakov

There is another issue with CCRewrite when Contract.Ensures contains Ensures.ForAll with captured lambda. Related issue #69.

Following code lead to another NRE:

  class NonGen {
        public async Task<List<int>> FooAsync(int limit)
        {
            Contract.Ensures(Contract.ForAll(Contract.Result<List<int>>(), i => i < limit));

            await Task.Delay(42);

            return new List<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        }
  }

Trying to use this method lead to NRE at Rewriter.cs:3994:

public override Expression VisitLocal(Local local)
{
    if (HelperMethods.IsClosureType(this.declaringType, local.Type))
    {
        MemberBinding mb;
        if (!closureLocals.TryGetValue(local, out mb))
        {
            // Next line will fail, because this.forwareder is null!
            var closureField = new Field(this.closureClass, null, FieldFlags.Public, local.Name, this.forwarder.VisitTypeReference(local.Type), null);
            this.closureClass.Members.Add(closureField);
            mb = new MemberBinding(this.checkMethod.ThisParameter, closureField);
            closureLocals.Add(local, mb);

            // initialize the closure field
            var instantiatedField = GetMemberInstanceReference(closureField, this.closureClassInstance);
            this.ClosureInitializer.Statements.Add(new AssignmentStatement(new MemberBinding(this.ClosureLocal, instantiatedField), local));

        }
        return mb;
    }
    return local;
}

This issue is similar to #69 but the reason is different. This time the root cause is following code in Rewriter.cs (in `EmitAsyncClosure):

if (from.IsGeneric)
            {
                this.closureClass.TemplateParameters = new TypeNodeList();
                var parentCount = this.declaringType.ConsolidatedTemplateParameters == null ? 0 : this.declaringType.ConsolidatedTemplateParameters.Count;
                for (int i = 0; i < from.TemplateParameters.Count; i++)
                {
                    var tp = HelperMethods.NewEqualTypeParameter(dup, (ITypeParameter)from.TemplateParameters[i], this.closureClass, parentCount + i);

                    this.closureClass.TemplateParameters.Add(tp);
                }
                this.closureClass.IsGeneric = true;
                this.closureClass.EnsureMangledName();
                this.forwarder = new Specializer(this.declaringType.DeclaringModule, from.TemplateParameters, this.closureClass.TemplateParameters);
                this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters);

                taskType = this.forwarder.VisitTypeReference(taskType);

            }
            else
            {
                // In this case forwarder is NULL!
                this.closureClassInstance = this.closureClass;
            }
```c#

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions