-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[pigeon] removes safe casting from nullables in kotlin and swift #3284
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
Conversation
var aNullableEnum: AnEnum? = nil | ||
if let aNullableEnumRawValue = list[12] as? Int { | ||
if let aNullableEnumRawValue = list[12] as! Int? { | ||
aNullableEnum = AnEnum(rawValue: aNullableEnumRawValue) | ||
} |
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.
you can avoid the var
by either
let aNullableEnum: AnEnum?
if ... {
aNullableEnum = ...
} else {
aNullableEnum = nil
}
or using a map:
let aNullableEnum = (list[12] as! Int?).map { AnEnum(rawValue: $0) }
@@ -37,7 +37,7 @@ class AllDatatypesTests: XCTestCase { | |||
|
|||
func testAllEquals() throws { | |||
let everything = AllNullableTypes( | |||
aNullableBool: false, | |||
aNullableBool: true, |
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.
were you able to resolve the Bool type issue the other day? What was the fix?
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.
switching from Any? to Any
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.
Can you provide more details? Not sure which Any?
you are referring to.
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.
it's the same decode issue as the other comments I've replied to
let aBool = list[0] as! Bool | ||
let anInt = list[1] as! Int32 | ||
let aDouble = list[2] as! Double | ||
let aByteArray = list[3] as! FlutterStandardTypedData | ||
let a4ByteArray = list[4] as! FlutterStandardTypedData | ||
let a8ByteArray = list[5] as! FlutterStandardTypedData | ||
let aFloatArray = list[6] as! FlutterStandardTypedData | ||
let aList = list[7] as! [Any?] | ||
let aList = list[7] as! [Any] |
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.
do we want to test out both [Any?]
and [Any]
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.
What do you mean? I'm not sure why we would need Any? for anything in this context since Any can already be nil
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.
Oh interesting - what about the maps below? Do you also want to remove the ?
e.g.
var aNullableMap: [AnyHashable: Any?]? = nil
var nullableMapWithObject: [String?: Any?]? = nil
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.
probably a good idea
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'm not sure why we would need Any? for anything in this context since Any can already be nil
Actually, Any
cannot represent nil
in Swift:
Hmmm, if I provide concrete type of nil then it works. I think it's fine to keep Any
then. Though I am not sure how this is related to the Bool?
crash you had the other day. May be helpful if you can provide a minimal reproducible code snippet so I can try out in playground.
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.
The Bool?
crash was nil
attempting to be cast to Bool?
, it failed for the reasons mentioned here. I'm not sure how to replicate it without a lot of extra steps.
@@ -179,7 +179,7 @@ data class TestMessage ( | |||
companion object { | |||
@Suppress("UNCHECKED_CAST") | |||
fun fromList(list: List<Any?>): TestMessage { | |||
val testList = list[0] as? List<Any?> | |||
val testList = list[0] as List<Any?>? |
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.
The kotlin version is still List<Any?>
, but Swift changed from [Any?]
to [Any]
. Is it intended?
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.
Swift optional Any causes issues with force casting into optional types when the data is nil. Kotlin doesn't have that problem.
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.
Swift optional Any causes issues with force casting into optional types when the data is nil.
Not sure if I follow this. Can you share a short code snippet when it fails? Are you talking about this following scenario?
let list: [Any?] = [nil, 1, "Hi"]
let optionalBool = list[0] as! Bool?
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.
this is the scenario that was happening before. The only difference now is
list: [Any]
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.
Interesting. This scenario actually did not crash when I try it on the playground.
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.
The kotlin version is still
List<Any?>
, but Swift changed from[Any?]
to[Any]
. Is it intended?
The core answer here is that Any
is fundamentally different between the two languages: Any
is a root type in Swift, but not Kotlin.
This Kotlin code:
val i: Int? = null
println(i is Any)
println(i is Any?)
prints
false
true
but this Swift code:
var i: Int? = nil
print(i is Any)
print(i is Any?)
prints
true
true
We're generating different code because the expression of "any type, including nullable types" is different in the two languages.
(I wasn't aware of this difference when reviewing the initial generator code, so didn't catch the incorrect use of Any?
in Swift in the first place.)
val aNullable4ByteArray = list[4] as IntArray? | ||
val aNullable8ByteArray = list[5] as LongArray? | ||
val aNullableFloatArray = list[6] as DoubleArray? | ||
val aNullableList = list[7] as List<Any?>? |
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'm curious - in Kotlin, can Any
already represent a nullable?
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.
nope
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.
The PR itself LGTM. Though I am still very curious why nil
would fail to be casted to Bool?
since my code snippet worked. I would need a minimal reproducible example to look into, but looks like you cannot create such example easily...
@@ -179,7 +179,7 @@ data class TestMessage ( | |||
companion object { | |||
@Suppress("UNCHECKED_CAST") | |||
fun fromList(list: List<Any?>): TestMessage { | |||
val testList = list[0] as? List<Any?> | |||
val testList = list[0] as List<Any?>? |
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.
The kotlin version is still
List<Any?>
, but Swift changed from[Any?]
to[Any]
. Is it intended?
The core answer here is that Any
is fundamentally different between the two languages: Any
is a root type in Swift, but not Kotlin.
This Kotlin code:
val i: Int? = null
println(i is Any)
println(i is Any?)
prints
false
true
but this Swift code:
var i: Int? = nil
print(i is Any)
print(i is Any?)
prints
true
true
We're generating different code because the expression of "any type, including nullable types" is different in the two languages.
(I wasn't aware of this difference when reviewing the initial generator code, so didn't catch the incorrect use of Any?
in Swift in the first place.)
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.
LGTM!
…tter#3284) [pigeon] removes safe casting from nullables in kotlin and swift
Removes safe casting during decode process for kotlin and swift to avoid hiding potential data type inconsistencies across channels.
fixes flutter/flutter#116999
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.