-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[ConstraintSystem] Inference of inout for closure parameters in generic contexts #5533
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1410,6 +1410,22 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, | |
case ConstraintKind::ArgumentConversion: | ||
case ConstraintKind::OperatorArgumentTupleConversion: | ||
case ConstraintKind::OperatorArgumentConversion: | ||
if (type1->is<InOutType>() && typeVar2 && | ||
typeVar2->getImpl().canBeInOut()) { | ||
// Upgrade type2 to an InOutType | ||
auto inOutType1 = type1->getAs<InOutType>(); | ||
|
||
unsigned typeVar3Options = typeVar2->getImpl().getOptions(); | ||
typeVar3Options &= ~TVO_CanBeInOut; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I must admit I didn't quite understand what |
||
auto typeVar3 = createTypeVariable(getConstraintLocator(locator), | ||
typeVar3Options); | ||
auto inOutType3 = InOutType::get(typeVar3); | ||
|
||
addConstraint(ConstraintKind::Equal, typeVar2, inOutType3, locator); | ||
return matchTypes(inOutType1->getObjectType(), typeVar3, kind, flags, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems unnecessarily complex, with the introduction of a new type variable that is immediately bound. The effect of this code is, basically, binding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also thought about directly binding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if that were the case this is going to bind the extra typevar anyway in the course of solving the system. I think the new TV Option can be removed in favor of a materializable constraint and a fixed binding. |
||
locator); | ||
} | ||
|
||
// We couldn't solve this constraint. If only one of the types is a type | ||
// variable, perhaps we can do something with it below. | ||
if (typeVar1 && typeVar2) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -137,3 +137,8 @@ func unsafeRawBufferPointerConversions( | |
_ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} | ||
_ = UnsafeRawBufferPointer(start: orp, count: 1) | ||
} | ||
|
||
func pointerInoutEquality(i: Int, p: UnsafeMutablePointer<Int>?) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit of an odd test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept having issues with this kind of expression (found code of this kind in swiftpm or stdlib somewhere) so I thought I might as well add it to the test suite. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, but please add an SR- reference so we can more easily look up why the test exists. |
||
var i = i | ||
_ = (p == &i) | ||
} |
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.
When
type1
is anInOutType
, we have two cases fortypeVar2
: either it allows binding toinout
(in which case we do the binding, as it's doing below), or it does not allow binding toinout
(in which case we should immediately fail). The immediate-failure case might not be strictly necessary, but it would be nice to early-exit with the failure here rather than go through the entirety ofmatchTypes
.Also, could this happen the other way, where
type2
is anInOutType
andtypeVar1
needs to be checked forcanBeInOut
?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, that's correct. I wasn't quite sure if the
inout
toUnsafeMutablePointer
conversion could still happen but just verified that it can't, so early exit should be possible.I couldn't come up with any scenario that needs a conversion the other way round but can't disprove it either.