Skip to content

Conversation

@ghost
Copy link

@ghost ghost commented Jun 4, 2025

When collecting dependencies for types in cel-java, for some reason, only public imports are considered. Because of this, if a message type from another file is referenced within an expression, the type will not be resolved, leading to strange, unexpected errors. In most cases, things will work purely by accident, obscuring the broken resolution behavior.

We should try to follow this up with an upstream fix as soon as possible.

When collecting dependencies for types in cel-java, for some reason, only public imports are considered. Because of this, if a message type from another file is referenced within an expression, the type will not be resolved, leading to strange, unexpected errors. In most cases, things will work purely by accident, obscuring the broken resolution behavior. We should try to follow this up with an upstream fix as soon as possible.
@ghost ghost requested review from pkwarren and smaye81 June 4, 2025 06:42
Copy link
Member

@timostamm timostamm left a comment

Choose a reason for hiding this comment

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

Looks like registering a Protobuf type with ProtoTypeRegistry will register all types declared in the containing file (including public imports, which make imports appear as local declarations).

Seems like it might be a deliberate choice? Either way, registering all referenced types regardless of file boundaries is the behavior I'd expect in the context of protovalidate.

private void collectDependencies(Set<Descriptor> dependencyTypes, Descriptor desc) {
dependencyTypes.add(desc);
for (FieldDescriptor field : desc.getFields()) {
if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

Hmmm, now that you mention it though, I think I probably Do have to cover the map entry case. I'm not sure why I didn't do that last night, maybe I was yet again making the mistake of thinking it's fine since it's a message on the wire. (I keep doing that even though I know it doesn't look that way in the reflection API.)

Copy link
Member

Choose a reason for hiding this comment

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

We don't care about the synthetic message for map entries, but we do care about the message M in map<int32, M>.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, exactly. However, guess what? I just debugged this thoroughly and... this code actually does traverse the synthetic map entry and therefore the value message in maps. I don't really know why, but I'm going to just add the tests showing that it works (validated by stepping through to make sure it's really not working by accident) and just call it for now since this is a rather urgent fix. At least in Java protobuf, the map fields actually do have type MESSAGE.

@ghost ghost merged commit ed6392d into main Jun 4, 2025
4 checks passed
@ghost ghost deleted the jchadwick/fix-import-bug branch June 4, 2025 16:30
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants