-
Notifications
You must be signed in to change notification settings - Fork 515
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
[ObjCRuntime] Change Runtime.GetNSObject<T> to create a new instance if the existing one is of the wrong type. Fixes #13704. #16491
Conversation
…if the existing one is of the wrong type. Fixes xamarin#13704. Objective-C has an optimization where creating an empty dictionary would return the same instance every time (probably to a constant empty dictionary). This causes a problem with how we've bound generic dictionaries, because all empty dictionaries would have the same native handle, even if we'd bound them with different managed types. This surfaces in unfortunate ways when we try to look up a managed instance given a native handle, we find that we already have a managed instance, but the managed instance is of the wrong type. Example code: var a = new NSDictionary (); var b = new NSDictionary<NSString, NSString> (); var c = new NSDictionary<NSString, NSObject> (); Console.WriteLine ($"a: 0x{a.Handle:X}"); Console.WriteLine ($"b: 0x{b.Handle:X}"); Console.WriteLine ($"c: 0x{c.Handle:X}"); would produce something like: a: 0x0x7fff80821080 b: 0x0x7fff80821080 c: 0x0x7fff80821080 now for this code: Runtime.GetNSObject<NSDictionary<NSString, NSString>> (b.Handle) it would throw an exception like this: Unable to cast object of type 'Foundation.NSDictionary`2[[Foundation.NSString],[Foundation.NSObject]]' to type 'Foundation.NSDictionary`2[[Foundation.NSString],[Foundation.NSString]]' because we'll have the 'c' object (with type `NSDictionary<NSString, Object>`) in our dictionary of native handles -> managed instances, and that's not compatible with the desired return type from GetNSObject (`NSDictionary<NSString, NSString>`) This likely happens with all the non-mutable collection types we have a generic version of (NSArray, NSDictionary, NSOrderedSet, NSSet). Fixes xamarin#16378. Fixes xamarin#13704.
Related? #5325 (comment) |
✅ API diff for current PR / commitLegacy Xamarin (No breaking changes)
NET (empty diffs)
✅ API diff vs stableLegacy Xamarin (No breaking changes).NET (No breaking changes)✅ Generator diffGenerator diff is empty Pipeline on Agent |
💻 [PR Build] Tests on macOS M1 - Mac Big Sur (11.5) passed 💻✅ All tests on macOS M1 - Mac Big Sur (11.5) passed. Pipeline on Agent |
Yes, probably. |
This comment has been minimized.
This comment has been minimized.
🚀 [CI Build] Test results 🚀Test results✅ All tests passed on VSTS: simulator tests. 🎉 All 223 tests passed 🎉 Tests counts✅ bcl: All 69 tests passed. Html Report (VSDrops) Download Pipeline on Agent |
/sudo backport xcode14.1 |
Backport Job to branch xcode14.1 Created! The magic is happening here |
Hooray! Backport succeeded! Please see https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=6890728 for more details. |
…ew instance if the existing one is of the wrong type. Fixes #13704. (#16502) Objective-C has an optimization where creating an empty dictionary would return the same instance every time (probably to a constant empty dictionary). This causes a problem with how we've bound generic dictionaries, because all empty dictionaries would have the same native handle, even if we'd bound them with different managed types. This surfaces in unfortunate ways when we try to look up a managed instance given a native handle, we find that we already have a managed instance, but the managed instance is of the wrong type. Example code: var a = new NSDictionary (); var b = new NSDictionary<NSString, NSString> (); var c = new NSDictionary<NSString, NSObject> (); Console.WriteLine ($"a: 0x{a.Handle:X}"); Console.WriteLine ($"b: 0x{b.Handle:X}"); Console.WriteLine ($"c: 0x{c.Handle:X}"); would produce something like: a: 0x0x7fff80821080 b: 0x0x7fff80821080 c: 0x0x7fff80821080 now for this code: Runtime.GetNSObject<NSDictionary<NSString, NSString>> (b.Handle) it would throw an exception like this: Unable to cast object of type 'Foundation.NSDictionary`2[[Foundation.NSString],[Foundation.NSObject]]' to type 'Foundation.NSDictionary`2[[Foundation.NSString],[Foundation.NSString]]' because we'll have the 'c' object (with type `NSDictionary<NSString, Object>`) in our dictionary of native handles -> managed instances, and that's not compatible with the desired return type from GetNSObject (`NSDictionary<NSString, NSString>`) This likely happens with all the non-mutable collection types we have a generic version of (NSArray, NSDictionary, NSOrderedSet, NSSet). Fixes #16378. Fixes #13704. This PR is somewhat simpler to review by ignoring whitespace: https://github.com/xamarin/xamarin-macios/pull/16491/files?w=1 Backport of #16491 Co-authored-by: Rolf Bjarne Kvinge <[email protected]>
Objective-C has an optimization where creating an empty dictionary would
return the same instance every time (probably to a constant empty dictionary).
This causes a problem with how we've bound generic dictionaries, because all
empty dictionaries would have the same native handle, even if we'd bound them
with different managed types.
This surfaces in unfortunate ways when we try to look up a managed instance
given a native handle, we find that we already have a managed instance, but
the managed instance is of the wrong type.
Example code:
would produce something like:
now for this code:
it would throw an exception like this:
because we'll have the 'c' object (with type
NSDictionary<NSString, Object>
)in our dictionary of native handles -> managed instances, and that's not
compatible with the desired return type from GetNSObject
(
NSDictionary<NSString, NSString>
)This likely happens with all the non-mutable collection types we have a
generic version of (NSArray, NSDictionary, NSOrderedSet, NSSet).
Fixes #16378.
Fixes #13704.
This PR is somewhat simpler to review by ignoring whitespace: https://github.com/xamarin/xamarin-macios/pull/16491/files?w=1