-
Notifications
You must be signed in to change notification settings - Fork 15.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix failing FieldMask.Merge for well-known wrapper field types #9602
Fix failing FieldMask.Merge for well-known wrapper field types #9602
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). For more information, open the CLA check for this pull request. |
@vassilvk Thank you for the fix! We need the CLA before we can review this, but it sounds like you're already working on sorting that out. Let me know if you need any help dealing with the CLA. |
Thank you @acozzette. We are trying to get through the process of establishing a corporate contributor CLA for my employer (and it is taking some time). |
You can either ask here or feel free to email me at [email protected]. |
@acozzette, FYI, the CLA is signed. |
Do we know whether Java has the same issue? It looks like it, but I don't know if |
Ah, I suspect that in Java it's okay because the reflection value for a wrapper field is still the wrapper, whereas in .NET it's the boxed primitive. However, this leads to an issue in this fix - because it means that the for wrapper fields, |
Hi @jskeet, Please see cef9f67. Please note that the well known wrappers are semantically primitive values in a sense that the Replace* options would have no logical bearing on the outcome of them being merged. In other words, for those fields "merge" is equivalent to "replace". That said, the above commit moves the check into the message branch of the merge operation as per your suggestion. |
I'll have a look at this tomorrow - I'm afraid I won't be able to get to it today. |
Okay, I think I understand now (this whole piece of code is new to me). I think the new behavior is reasonable, but I can imagine it possibly behaving differently to the equivalent Java code. I suspect that in the Java code, the wrapper types are treated like any other message types - so a wrapper type with a value of 0 won't actually end up replacing the original value, because it will be merged field-wise, with the absent value field being ignored. Given the way reflection for wrapper types works in C#, I suspect we don't want to replicate that behavior, but I'd like @acozzette's opinion before merging. |
Hello @acozzette. Any update? |
Sorry I missed this! I think Jon brings up an interesting point about how in Java, a zero-valued wrapper type can't override the original value. I glanced at the C++ implementation and I suspect this is true in C++ as well, and probably in just about every language, since as far as I know we didn't take any special care to handle this situation. So unfortunately I think we probably want to imitate the Java behavior--even though it's less intuitive, I think it's best to aim for consistency across languages. Hopefully this is an easy tweak to make: I think we just want to ignore the source field in the special case where a wrapper field is present in both the source and destination but the contents of the source field are empty. |
Thanks @acozzette. |
I'll have a look later in the week, thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Production code looks good to me, although it's possible that I've missed some subtlety. I think it would be good to separate out a "wrapper field with null value" test (with both ReplaceMessageFields true and false) and "wrapper field with non-null value" (where we probably don't need parameterization).
}, | ||
false); | ||
|
||
// Make sure only the targeted fields were updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect this to look at Int32Field and BoolField... given that StringField is targeted, I wouldn't expect it to be asserted in this section. I suspect we effectively want two commented sections:
- Make sure only the targeted fields were updated (Int32Field and BoolField haven't changed)
- "Prove that ReplaceMessageFields works for wrapper types" - I'd expect the same test for both StringField and Int64Field here (see earlier comment about mixing null and non-null behavior in one test).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see comment above and c4e7df1
} | ||
else | ||
{ | ||
field.Accessor.SetValue(destination, field.MessageType.Parser.ParseFrom(sourceByteString)); | ||
var sourceByteString = ((IMessage)sourceField).ToByteString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for anyone else reviewing this: the code here really hasn't changed at all other than indentation - the diff is just confusing. (It's slightly better in split mode than in unified mode, but either way it's not clear that really we're just conditionalizing the existing behavior.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll merge this, as I believe the production code is correct - but the test really is quite hard to understand at the moment, from the perspective of someone who has come into this "cold" as it were.
Ah, the CLA check is still failing - I'll need to check that manually. |
Hmm - if you could email me ([email protected]) with details about the CLA signing (e.g. whether it's been done in a corporate way rather than for your GitHub account) that would be appreciated. |
Ah, right - thanks. I'll manually override that when I've reviewed the new tests. |
Okay, the CLA manual override process has changed over time. I suspect the simplest approach now is for you to:
That should end up with a single commit just by you, which should avoid all the CLA problems. Sorry for the bureaucracy :( |
9baab1f
to
391e4ed
Compare
391e4ed
to
1aed573
Compare
Hi @jskeet, no problem. |
Thanks for your patience :) |
Thank you for yours too :) |
Hi, do you know when this fix will be released? Thx |
@olivierl: I don't think it made it into 3.21.x, so I'm afraid you'll need to wait for 3.22.x. I don't have a timeline for that. |
Not committing to anything, but I anticipate 22.x will happen in 2 or so months. |
Hi, the issue of FieldMask.Merge with Wrappers has been fixed, or is there any workaround to create path's for wrappers? I just experienced same behavior reported here: #9283 (comment) |
@RogerioWagner: I've just tried the exact repro in #9283, and it's fine using the latest NuGet package. So either you're not actually experiencing the same behavior (i.e. your situation is different in a way we can't know) or you're using an old version where this was still broken. I suggest you file a new issue with a minimal repro. |
@jskeet, you were right, it's a different behavior after I bumped the version to 3.26.0, now instead of an exception, it failed silently with a warning at MaskFilter ({ "@warning": "Invalid FieldMask", "paths": [ "description", "usage", "templateId" ] }), where description is an optional string, usage is an enum and templateId is an optional google.protobuf.Int32Value. |
@RogerioWagner: Rather than half-describing the problem in a merged PR, please file a new issue with a minimal but complete repro. |
Closes #9283.