p4-spec icon indicating copy to clipboard operation
p4-spec copied to clipboard

P4_16 Allow `type` and `typedef` inside scope of controls and parsers

Open jafingerhut opened this issue 6 years ago • 7 comments

Right now I believe the language spec and p4c only allow type and typedef at the top level of your program.

@vgurevich proposed allowing such types also to be defined locally inside of controls and parsers. Such types would only be usable within the lexical scope of that control or parser where it is declared.

I will let him add his own comment for why he thinks there are use cases to justify adding this to the language. Right now I have no strong opinion one way or the other, and am creating this issue to capture the idea for future discussion.

One consequence of adding this to the language:

Any values with such 'locally scoped types' that appear in the control plane API, e.g. table keys, action parameters, fields of digest extern calls, etc., should be represented in the P4Runtime info file, and since the same local type name could appear in multiple different scopes, with different definitions (e.g. one could be bit<5>, another a struct type X), the type names would need to be made globally unique. I would guess there is no issue in using the same hierarchical names used today for tables and action names in p4c, e.g. 'ingress.T' and 'egress.T', but I may be missing some issues with that approach.

jafingerhut avatar Nov 04 '18 01:11 jafingerhut

Thanks for capturing this. I think it is kinda natural and also similar to what other languages allow. It also allows writing controls and parsers in a more readable way without polluting the global namespace.

For example, when one needs to do lookahead, the safest away it to create a type that corresponds only to the beginning of a header. Such type is not needed outside the parser.

vgurevich avatar Nov 04 '18 03:11 vgurevich

I actually do not know a language that allows you to define local types, which are only locally visible. Can you point to an example?

The first draft I wrote for P4-16 actually had local types, but ran into all sorts of problems with the implementation so we decided to scrape this feature for the initial release. The problem with local types is that they can leak outside the scope where they are defined. One example which was difficult was something like this:

control C<T>() { ... } // generic control, now forbidden

control D() {
    typedef bit<32> TI;
    C<TI> ci;
   apply { ci.apply(); }
}

The compiler will actually specialize the implementation of C for the actual type argument, creating a control CSpec which is C where T is replaced with TI. But TI is not visible in the outer scope, so the compiler had no place where to insert CSpec after the definition of TI. I am not saying that there is no way to solve this problem; what I am saying is that sometimes simple proposals can cause big complications, so we have to analyze them thoroughly and understand all their corner cases.

I think that the right solution for this problem is a module system. That would take care of naming and scoping, including for types. It is one of the open problems in the language design.

mihaibudiu avatar Nov 05 '18 16:11 mihaibudiu

C++ lets you define local types inside a function body, which is useful for RAII programming:

void my_function() {
    struct A {
        A() { /* open a resource */ }
        ~A() { /* cleanup */ }
    };
    A a;
    // do stuff with a
}

I have tried several times to define a struct locally in P4 (in a control), but of course it is not legal P4 at the moment.

antoninbas avatar Nov 05 '18 18:11 antoninbas

Is the function allowed to return an object of type A?

mihaibudiu avatar Nov 05 '18 18:11 mihaibudiu

Not as far as I know; A is only locally visible in the function body, you cannot declare the return type as A.

antoninbas avatar Nov 05 '18 18:11 antoninbas

@mbudiu-vmw : In C if you use a typedef inside a function, it is not visible outside.

vgurevich avatar Nov 06 '18 05:11 vgurevich

Is the function allowed to return an object of type A?

Yes, in C++14 you can return a local type by using the auto keyword and having the compiler figure out the return type via the return statement. Like:

auto f(void)
{
  struct local {int i;};
  local v;
  v.i = 1;
  return v;
}

Though I doubt many people know to use/abuse C++14 like this but it is how it is designed.

apinski-cavium avatar May 14 '22 23:05 apinski-cavium

This seems interesting, but in the interest of tidying up our list of active issues, I'm going to mark this as "stalled."

jnfoster avatar Aug 28 '23 12:08 jnfoster