Skip to content

Commit 70ac657

Browse files
committed
[CSBindings] Don't delay bindings inferred through inout conversion
Delaying such bindings is too restrictive and leads to subpar selections. For `$T1` to be array or C-style pointer it would have to be connected either to a type variable that could be bound to array/pointer or directly to array/pointer type which would result in the solver either selecting the other type variable first (because it appears in adjacent variables of `$T1`) or provide an additional binding(s) for `$T1` (including literals). Consider the following constraint system: ``` $T2 arg conv $T1 $T2 conforms ExpressibleByIntegerLiteral inout $T1 arg conv UnsafeMutablePointer<UInt8>? ``` If `$T1` and `$T2` are the only viable type variables delaying `$T1` would mean that `$T2` is picked to attempt its default type `Int` which is incorrect (it doesn't get `UInt8` because there is no transitive inference through conversions).
1 parent 56ec625 commit 70ac657

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,11 +1518,6 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
15181518
if (auto pointeeTy = second->lookThroughAllOptionalTypes()
15191519
->getAnyPointerElementType()) {
15201520
if (!pointeeTy->isTypeVariableOrMember()) {
1521-
// The binding is as a fallback in this case because $T could
1522-
// also be Array<X> or C-style pointer.
1523-
if (constraint->getKind() >= ConstraintKind::ArgumentConversion)
1524-
DelayedBy.push_back(constraint);
1525-
15261521
return PotentialBinding(pointeeTy, AllowedBindingKind::Exact,
15271522
constraint);
15281523
}

test/Constraints/valid_pointer_conversions.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,22 @@ do {
6969
test(&outputs[name]!) // Ok
7070
}
7171
}
72+
73+
do {
74+
func test<O>(_ initialValue: O, _ action: (inout O) -> Void) -> O {
75+
}
76+
77+
func compute(_: UnsafeMutablePointer<UInt8>!) {
78+
}
79+
80+
let result1 = test(0) { // `0` should be inferred as `UInt8`
81+
compute(&$0)
82+
}
83+
84+
let result2 = test([0]) { // `0` should be inferred as `UInt8`
85+
compute(&$0)
86+
}
87+
88+
let _: UInt8 = result1 // Ok
89+
let _: [UInt8] = result2 // Ok
90+
}

0 commit comments

Comments
 (0)