zeek / spicy

C++ parser generator for dissecting protocols & files.
https://docs.zeek.org/projects/spicy
Other
243 stars 37 forks source link

Misleading type parameter is missing error when &convert with variable is used #1791

Open awelzel opened 1 month ago

awelzel commented 1 month ago

I've worked on adding a context to Zeek's LDAP analyzer and got stuck with the following message for a while:

src/analyzer/protocol/ldap/ldap.spicy:167:5-167:34: type parameter 1 is missing (ctx)

But that location seemed fine okay:

    163 #-----------------------------------------------------------------------------
    164 public type SASLDispatch = unit(ctx: Ctx&) {
    165   switch( ctx.expect_sasl_krb5_wrapping ) {
    166     True -> :SASLKrb5Stripper(ctx);
    167     False -> :MessageWrapper(ctx);
    168   };
    169 };

It turned out to be the following:

1) A lone var message: Message in MessageWrapper 2) a MessageWrapper(ctx: Ctx) { ... } having a final &convert=self.message 3) Message taking a context as unit parameter.

So yeah, there's something wrong, but it wasn't easy to figure out.

Smaller test:

module Test;

type Ctx = struct {
  x: bool;
};

public type Messages = unit {
  %context = Ctx;
  : MessageWrapper(self.context())[];
};

type MessageWrapper = unit(ctx: Ctx&) {
  var message: Message;
  : Message(ctx) {
    self.message = $$;
  }
} &convert=self.message;

type Message = unit(ctx: Ctx&) {
  a: bytes &size=1 {
    ctx.x = True;
    print $$;
  }
};

type Stripper = unit(ctx: Ctx&) {
  tag: uint8;
  msg: MessageWrapper(ctx);
};

echo -n "x" |  spicy-driver  type-parameter-missing.spicy 
[error] type-parameter-missing.spicy:26:17-29:1: type parameter 1 is missing (ctx)
[error] spicy-driver: aborting after errors

(error is reported in Stripper unit at the bottom).

bbannier commented 1 month ago

This has been behaving this way issue since at least 1.4.0. The issue here seems to be that we do not correctly set up default values for the field in Messages which requires an argument in code we generate. Here is an even more trimmed reproducer:

type Ctx = bool;

public type Messages = unit {
    %context = Ctx;
    : MessageWrapper(self.context());
};

type MessageWrapper = unit(ctx1: Ctx&) {
    message: Message(ctx1);
} &convert=self.message;

type Message = unit(ctx2: Ctx&) {};