c80k / capnproto-dotnetcore

A Cap'n Proto implementation for .NET Standard and .NET Core
Other
146 stars 27 forks source link

Problem in code generation if a method returns an interface wrapped in a generic struct #51

Open kjkriegel opened 4 years ago

kjkriegel commented 4 years ago

Hi, the following schema generates code that does not compile:

@0x8fde3458241b84de;

struct Wrap(T) {
    content @0 :T;
}

interface A {
    interface B {
    }

    foo @0 () -> ( bar :Wrap(B) );
}

The part of the generated code which doesn't compile is:

public static partial class PipeliningSupportExtensions_wrapped_struct
    {
        static readonly MemberAccessPath Path__A_foo_Bar_Content = new MemberAccessPath(0U, 0U);
        public static CapnpGen.A.IB Bar_Content(this Task<CapnpGen.Wrap<CapnpGen.A.IB>> task)
        {
            async Task<IDisposable> AwaitProxy() => (await task).Bar?.Content;
            return (CapnpGen.A.IB)CapabilityReflection.CreateProxy<CapnpGen.A.IB>(Impatient.Access(task, Path__A_foo_Bar_Content, AwaitProxy()));
        }
    }

The error message is:

Error   CS1061  'Wrap<A.IB>' does not contain a definition for 'Bar' and no accessible extension method 'Bar' accepting a first argument of type 'Wrap<A.IB>' could be found (are you missing a using directive or an assembly reference?)

wrapped_struct.zip

c80k commented 4 years ago

Thanks for reporting! This is definitively a code generation bug. A workaround is to add another output argument, like this:

@0x8fde3458241b84de;

struct Wrap(T) {
    content @0 :T;
}

interface A {
    interface B {
    }

    foo @0 () -> ( bar :Wrap(B), other: Int32);
}
bergm commented 3 years ago

Hi,

I think this is related, but as the error message looks slightly different, I thought I still post it. I stumbled over the second case with the interface A and while trying to get this minimal example with interface B. There another problem appeared where the compiler complains about the Proxy attributes (... an attribute can't use type parameters ...).

interface A(T) {
  m @0 () -> S;

  interface CB1 {
    call @0 ();
  }

  struct S {
    res @0 :T;
    callback @1 :CB1;
  }
}

interface CB2 {
  call @0 ();
}

interface B(T) {
  m @0 () -> S;

  struct S {
    res @0 :T;
    callback @1 :CB2;
  }
}

The error messages are:

error CS0416: 'Mas.Rpc.Persistence.A<TT>.CB1_Proxy': an attribute argument cannot use type parameters
error CS0416: 'Mas.Rpc.Persistence.A<TT>.CB1_Skeleton': an attribute argument cannot use type parameters
error CS0246: The type or namespace name 'TT' could not be found (are you missing a using directive or an assembly reference?)

The last error message (I removed duplicate ones) is as above related to the extension methods in the static class and can be fixed by making the extension method itself generic. But I didn't go there and try to really compile it as the code generator will overwrite it immediately. But the red squiggles disappear. If this is worth anything.

I see tomorrow if the above hint can make it work.

Cheers, Michael