Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Allow constant folding of serializable enums of different types#5246

Open
ChrisDodd wants to merge 1 commit intop4lang:mainfrom
ChrisDodd:cdodd-enumcmp
Open

Allow constant folding of serializable enums of different types#5246
ChrisDodd wants to merge 1 commit intop4lang:mainfrom
ChrisDodd:cdodd-enumcmp

Conversation

Copy link
Contributor

ChrisDodd commented May 1, 2025

Typechecking (and the P4 spec) allow comparing values of serializable enum types, however, ConstantFolding was hitting a BUG_CHECK when that happened with two constants of different serializable enums.

ChrisDodd requested review from asl and fruffy May 1, 2025 01:41
fruffy added the core Topics concerning the core segments of the compiler (frontend, midend, parser) label May 2, 2025
vlstill reviewed May 2, 2025
auto re = EnumInstance::resolve(eright, typeMap);
if (le != nullptr && re != nullptr) {
BUG_CHECK(le->type == re->type, "%1%: different enum types in comparison", e);
if (le != nullptr && re != nullptr && le->type == re->type) {
Copy link
Member

vlstill May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the type guaranteed to have the same identity (pointer value) here?

Copy link
Contributor Author

ChrisDodd May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not -- that's what the check is for. If it is NOT the same type, we need to compare the values of the enum instances (which is what will happen if we fall through and don't do this special-case handling of enums of the same type.)

Copy link
Member

vlstill May 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my question was a bit too abridged. I mean to say: is the type pointer guaranteed to have the same identity if it represents same type (i.e. bit<8> on both side)? I think it is possible to create two different IR::Type_Bits instances with the same "value" that are nevertheless different pointers.

Copy link
Contributor Author

ChrisDodd Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be possible to to that -- all creation of Type_Bits instances should happen though IR::Type_Bits::get which ensures that only a single instance of each type gets created.

Copy link
Member

vlstill commented May 2, 2025

Typechecking (and the P4 spec) allow comparing values of serializable enum types, however, ConstantFolding was hitting a BUG_CHECK when that happened with two constants of different serializable enums.

Frankly I don't see where the spec would allow comparison of enums of two different types. I think that would be the only place such comparison is allowed. There may be an argument that it is an implicit cast to the underlying type and then comparison (https://p4.org/wp-content/uploads/2024/10/P4-16-spec-v1.2.5.html#sec-implicit-casts):

For enums with an underlying type, it can be implicitly cast to its underlying type whenever appropriate, including but not limited to in shifts, concatenation, bit slicing indexes, header stack indexes as well as other unary and binary operations.

But this is a somewhat weird implicit cast as the resulting type is given by the fact it is an enum, not by it being used in a place where such a type would be expected. I don't think we have something like "overload resolution rules for operators" which would be the thing to clarify this in languages like C++ (or at least I am not aware of them). Maybe we should have such rules.


I am also not sure this is a good idea. Of course, the compiler should not crash, but I am not sure implicit comparison of two different enum types is a good idea because it could hide an error where someone accidentally compares a value to enum of different type.

Copy link
Contributor Author

ChrisDodd commented May 2, 2025

I am also not sure this is a good idea. Of course, the compiler should not crash, but I am not sure implicit comparison of two different enum types is a good idea because it could hide an error where someone accidentally compares a value to enum of different type.

The spec says

an enum with an underlying type can be thought of as being a type derived from the underlying type carrying equality, assignment, and casts to/from the underlying type.

which implies you can use the enum type as if it is the underlying type. Maybe typechecking should be inserting casts here, but we avoid doing that currently because we don't want to eliminate the enum type (which is what having a cast would end up doing), as having the enum type is sometimes important to the control-plane/runtime interface generation (and it ends up exposed there sometimes). So figuring out exactly when to do that and when not to would be tricky.

Copy link
Contributor

asl commented May 2, 2025

I am also not sure this is a good idea. Of course, the compiler should not crash, but I am not sure implicit comparison of two different enum types is a good idea because it could hide an error where someone accidentally compares a value to enum of different type.

I tend to agree and this could potentially lead to error-prone behavior. If there is explicit cast to the underlying type, then fine (e.g. (bit<2>)foo == (bit<2>)bar.Case. Implicit casts to underlying type is fine as well foo == 2w2, but just allowing foo == bar.Case looks quite problematic to me.

vlstill reacted with thumbs up emoji

vlstill mentioned this pull request May 13, 2025
ChrisDodd force-pushed the cdodd-enumcmp branch from 30258e5 to 526de36 Compare May 29, 2025 03:53
ChrisDodd force-pushed the cdodd-enumcmp branch from 526de36 to 04e0fd2 Compare July 22, 2025 00:39
ChrisDodd force-pushed the cdodd-enumcmp branch from 04e0fd2 to cd3e1e3 Compare August 19, 2025 00:59
Copy link
Contributor Author

ChrisDodd commented Aug 19, 2025

It would be good to check in this fix that avoids the BUG_CHECK regardless of the eventual resolution of the spec questions -- if it should be an error, it should be diagnosed in TypeChecking and not crash in ConstantFolding.

ChrisDodd force-pushed the cdodd-enumcmp branch from cd3e1e3 to 8162d7d Compare August 19, 2025 01:02
ChrisDodd requested a review from vlstill August 19, 2025 01:02
ChrisDodd force-pushed the cdodd-enumcmp branch from 8162d7d to 371f0b4 Compare September 30, 2025 18:12
ChrisDodd force-pushed the cdodd-enumcmp branch from 371f0b4 to b43f971 Compare November 4, 2025 23:46
ChrisDodd force-pushed the cdodd-enumcmp branch from b43f971 to 1dc7a46 Compare December 3, 2025 22:41
ChrisDodd force-pushed the cdodd-enumcmp branch from 1dc7a46 to 509ab39 Compare February 11, 2026 07:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

asl Awaiting requested review from asl

fruffy Awaiting requested review from fruffy

vlstill Awaiting requested review from vlstill

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

core Topics concerning the core segments of the compiler (frontend, midend, parser)

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

4 participants