Skip to content

Commit 4799acf

Browse files
committed
[CSBindings] Attempt a type variable early if it's constrained by a struct/enum type
If a type variable has a subtype binding which came from a conversion/subtype/equality constraint to a struct or enum (expect to `AnyHashable`, `Unsafe{Mutable}RawPointer`), attempt it early because that type is the only choice which is not going to fail such constraint. For example, in cases like `$T argument convertible to Int` type variable could only be bound to `Int`, `Int!`, or `@lvalue Int` to satisfy that constraint, so it would make sense to attempt to bind it to `Int` early if it doesn't represent a result of a member lookup (that's how IUO and/or `@lvalue` could be inferred)` and doesn't have any direct disjunction associated with it e.g. for coercion or optional matching.
1 parent 2b41bee commit 4799acf

File tree

8 files changed

+59
-17
lines changed

8 files changed

+59
-17
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ class TypeVariableType::Implementation {
360360
/// a type of a key path expression.
361361
bool isKeyPathType() const;
362362

363+
/// Determine whether this type variable represents a subscript result type.
364+
bool isSubscriptResultType() const;
365+
363366
/// Retrieve the representative of the equivalence class to which this
364367
/// type variable belongs.
365368
///

lib/Sema/CSBindings.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,44 @@ bool BindingSet::isViable(PotentialBinding &binding) {
981981
}
982982

983983
bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const {
984-
if (isHole() || isDelayed())
984+
if (isHole())
985+
return false;
986+
987+
if (llvm::any_of(Bindings, [&](const PotentialBinding &binding) {
988+
if (binding.Kind == AllowedBindingKind::Supertypes)
989+
return false;
990+
991+
auto type = binding.BindingType;
992+
993+
if (type->isAnyHashable())
994+
return false;
995+
996+
{
997+
PointerTypeKind pointerKind;
998+
if (type->getAnyPointerElementType(pointerKind)) {
999+
switch (pointerKind) {
1000+
case PTK_UnsafeRawPointer:
1001+
case PTK_UnsafeMutableRawPointer:
1002+
return false;
1003+
1004+
default:
1005+
break;
1006+
}
1007+
}
1008+
}
1009+
1010+
return type->is<StructType>() || type->is<EnumType>();
1011+
})) {
1012+
// Result type of subscript could be l-value so we can't bind it early.
1013+
if (!TypeVar->getImpl().isSubscriptResultType() &&
1014+
llvm::none_of(Info.DelayedBy, [](const Constraint *constraint) {
1015+
return constraint->getKind() == ConstraintKind::Disjunction ||
1016+
constraint->getKind() == ConstraintKind::ValueMember;
1017+
}))
1018+
return true;
1019+
}
1020+
1021+
if (isDelayed())
9851022
return false;
9861023

9871024
// If this bindings are for a closure and there are no holes,

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ bool TypeVariableType::Implementation::isKeyPathType() const {
116116
return locator && locator->isKeyPathType();
117117
}
118118

119+
bool TypeVariableType::Implementation::isSubscriptResultType() const {
120+
if (!(locator && locator->getAnchor()))
121+
return false;
122+
123+
return isExpr<SubscriptExpr>(locator->getAnchor()) &&
124+
locator->isLastElement<LocatorPathElt::FunctionResult>();
125+
}
126+
119127
void *operator new(size_t bytes, ConstraintSystem& cs,
120128
size_t alignment) {
121129
return cs.getAllocator().Allocate(bytes, alignment);

validation-test/Sema/type_checker_perf/slow/fast-operator-typechecking.swift renamed to validation-test/Sema/type_checker_perf/fast/fast-operator-typechecking.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
// rdar://problem/32998180
44
func checksum(value: UInt16) -> UInt16 {
55
var checksum = (((value >> 2) ^ (value >> 8) ^ (value >> 12) ^ (value >> 14)) & 0x01) << 1
6-
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
76
checksum |= (((value) ^ (value >> UInt16(4)) ^ (value >> UInt16(6)) ^ (value >> UInt16(10))) & 0x01)
8-
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
97
checksum ^= 0x02
108
return checksum
119
}

validation-test/Sema/type_checker_perf/slow/rdar32998180.swift renamed to validation-test/Sema/type_checker_perf/fast/rdar32998180.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@
44
func rdar32998180(value: UInt16) -> UInt16 {
55
let result = ((((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1)
66
| (((((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1) << 1)
7-
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
87
return result
98
}

validation-test/Sema/type_checker_perf/slow/rdar46713933_literal_arg.swift renamed to validation-test/Sema/type_checker_perf/fast/rdar46713933_literal_arg.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,4 @@ func wrap<T: ExpressibleByStringLiteral>(_ key: String, _ value: T) -> T { retur
88

99
func wrapped() -> Int {
1010
return wrap("1", 1) + wrap("1", 1) + wrap("1", 1) + wrap("1", 1)
11-
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
1211
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1
2+
// REQUIRES: tools-release,no_asan
3+
4+
struct Value {
5+
let debugDescription: String
6+
}
7+
8+
func test(values: [[Value]]) -> String {
9+
"[" + "" + values.map({ "[" + $0.map({ $0.debugDescription }).joined(separator: ", ") + "]" }).joined(separator: ", ") + "]"
10+
}

validation-test/Sema/type_checker_perf/slow/rdar74035425.swift

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)