-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Sema: Explicitly allow Optional-to-IUO when converting functions. #7153
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
@swift-ci Please 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.
Yeah, this looks okay as a narrow fix. Be warned that the cherry-pick to the 3.1 branch will be a little annoying, because enumerateOptionalConversionRestrictions
is a refactor on master that didn't get cherry-picked.
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. Glad you found a narrow fix here to restore the old behavior.
Build failed |
@@ -1232,7 +1233,7 @@ static bool isPotentiallyMoreOptionalThan(Type objType1, | |||
/// Enumerate all of the applicable optional conversion restrictions | |||
static void enumerateOptionalConversionRestrictions( | |||
Type type1, Type type2, | |||
ConstraintKind kind, | |||
ConstraintKind kind, bool isFunctionInputOrResult, |
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.
Instead of adding another flag would it make more sense if you look at the locator instead?
Are you going to do the proper fix too? ;) BTW I think SILGen only supports Subtype conversions for function parameters and returns right now. This includes a fair number of conversions, like existential erasure, class upcasts, injection into optionals, and some random ones like metatype to object conversions. I think Conversion does some additional things that SILGen does not support. |
I don't think there is a proper fix that maintains Swift 3 compatibility. If you look at the JIRA you can see a record of some of the other things I tried. Everything else has much wider ripple effects. Looking at the locator's not a bad idea. The query's just "are we anywhere in ConstraintLocator::FunctionArgument or ConstraintLocator::FunctionResult". I'll try that. |
Look at how locators have a summary flags field. I think this gives you what you want. |
Not sure what's up with the test failure. It has nothing to do with this patch. |
We limit Optional-to-IUO as an implicit conversion to avoid making common expressions ambiguous. However, this runs into trouble with function-to-function conversions, which always look for a "Subtype" relationship for their inputs and outputs. This is a conservative way for Sema to avoid emitting conversions that SILGen cannot handle. The problem case here is converting a closure with type '(Any!) -> Void' to a value of type '(Any?) -> Void': let f: ((Any?) -> Void) = { (arg: Any!) in } This is clearly a safe conversion, since 'Any!' and 'Any?' have the same representation at run time, but historically we've disallowed it because of the above rules. However, in Swift 3.0 this particular case was permitted, with the type checker deciding that the 'Any?' argument to 'f' could first itself be put into an 'Any', then /that/ value could go through a value-to-optional conversion to make 'Any!'. Fortunately the emitted code didn't follow this incorrect conversion path. This patch doesn't even try to emulate the old behavior. Instead, it just weakens the restriction on Optional-to-IUO via a new type matching flag that only applies within the context of matching function types. We can consider opening up function conversions in Swift 4 to anything that supports conversion---not just subtyping---now that SILGen knows how to automatically reabstract most such things. But whether we do or not, Optional/IUO is a special case. https://bugs.swift.org/browse/SR-3758
0d01210
to
9d90d7e
Compare
@swift-ci Please test |
Build failed |
Build failed |
@swift-ci Please test |
Build failed |
@swift-ci Please test macOS |
…iftlang#7153) We limit Optional-to-IUO as an implicit conversion to avoid making common expressions ambiguous. However, this runs into trouble with function-to-function conversions, which always look for a "Subtype" relationship for their inputs and outputs. This is a conservative way for Sema to avoid emitting conversions that SILGen cannot handle. The problem case here is converting a closure with type '(Any!) -> Void' to a value of type '(Any?) -> Void': let f: ((Any?) -> Void) = { (arg: Any!) in } This is clearly a safe conversion, since 'Any!' and 'Any?' have the same representation at run time, but historically we've disallowed it because of the above rules. However, in Swift 3.0 this particular case was permitted, with the type checker deciding that the 'Any?' argument to 'f' could first itself be put into an 'Any', then /that/ value could go through a value-to-optional conversion to make 'Any!'. Fortunately the emitted code didn't follow this incorrect conversion path. This patch doesn't even try to emulate the old behavior. Instead, it just weakens the restriction on Optional-to-IUO via a new type matching flag that only applies within the context of matching function types. We can consider opening up function conversions in Swift 4 to anything that supports conversion---not just subtyping---now that SILGen knows how to automatically reabstract most such things. But whether we do or not, Optional/IUO is a special case. https://bugs.swift.org/browse/SR-3758
) (#7168) We limit Optional-to-IUO as an implicit conversion to avoid making common expressions ambiguous. However, this runs into trouble with function-to-function conversions, which always look for a "Subtype" relationship for their inputs and outputs. This is a conservative way for Sema to avoid emitting conversions that SILGen cannot handle. The problem case here is converting a closure with type '(Any!) -> Void' to a value of type '(Any?) -> Void': let f: ((Any?) -> Void) = { (arg: Any!) in } This is clearly a safe conversion, since 'Any!' and 'Any?' have the same representation at run time, but historically we've disallowed it because of the above rules. However, in Swift 3.0 this particular case was permitted, with the type checker deciding that the 'Any?' argument to 'f' could first itself be put into an 'Any', then /that/ value could go through a value-to-optional conversion to make 'Any!'. Fortunately the emitted code didn't follow this incorrect conversion path. This patch doesn't even try to emulate the old behavior. Instead, it just weakens the restriction on Optional-to-IUO via a new type matching flag that only applies within the context of matching function types. We can consider opening up function conversions in Swift 4 to anything that supports conversion---not just subtyping---now that SILGen knows how to automatically reabstract most such things. But whether we do or not, Optional/IUO is a special case. https://bugs.swift.org/browse/SR-3758
We limit Optional-to-IUO as an implicit conversion to avoid making common expressions ambiguous. However, this runs into trouble with function-to-function conversions, which always look for a "Subtype" relationship for their inputs and outputs. This is a conservative way for Sema to avoid emitting conversions that SILGen cannot handle.
The problem case here is converting a closure with type
(Any!) -> Void
to a value of type(Any?) -> Void
:This is clearly a safe conversion, since
Any!
andAny?
have the same representation at run time, but historically we've disallowed it because of the above rules. However, in Swift 3.0 this particular case was permitted, with the type checker deciding that theAny?
argument tof
could first itself be put into anAny
, then that value could go through a value-to-optional conversion to makeAny!
. Fortunately the emitted code didn't follow this incorrect conversion path.This patch doesn't even try to emulate the old behavior. Instead, it just weakens the restriction on Optional-to-IUO via a new type matching flag that only applies within the context of matching function types.
We can consider opening up function conversions in Swift 4 to anything that supports conversion—not just subtyping—now that SILGen knows how to automatically reabstract most such things. But whether we do or not, Optional/IUO is a special case.
SR-3758 / rdar://problem/30235814