Skip to content

Commit 68326d7

Browse files
authored
Merge pull request #36931 from xedin/bind-value-types-early
[Perf][CSBindings] Attempt a type variable early if it's constrained by a s…
2 parents 2783443 + bbdc5b1 commit 68326d7

File tree

8 files changed

+63
-17
lines changed

8 files changed

+63
-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: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,47 @@ 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 (CS.shouldAttemptFixes())
994+
return false;
995+
996+
if (type->isAnyHashable() || type->isDouble() || type->isCGFloat())
997+
return false;
998+
999+
{
1000+
PointerTypeKind pointerKind;
1001+
if (type->getAnyPointerElementType(pointerKind)) {
1002+
switch (pointerKind) {
1003+
case PTK_UnsafeRawPointer:
1004+
case PTK_UnsafeMutableRawPointer:
1005+
return false;
1006+
1007+
default:
1008+
break;
1009+
}
1010+
}
1011+
}
1012+
1013+
return type->is<StructType>() || type->is<EnumType>();
1014+
})) {
1015+
// Result type of subscript could be l-value so we can't bind it early.
1016+
if (!TypeVar->getImpl().isSubscriptResultType() &&
1017+
llvm::none_of(Info.DelayedBy, [](const Constraint *constraint) {
1018+
return constraint->getKind() == ConstraintKind::Disjunction ||
1019+
constraint->getKind() == ConstraintKind::ValueMember;
1020+
}))
1021+
return true;
1022+
}
1023+
1024+
if (isDelayed())
9851025
return false;
9861026

9871027
// 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
}
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/rdar46713933_literal_arg.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ func wrap<T: ExpressibleByFloatLiteral>(_ key: String, _ value: T) -> T { return
77
func wrap<T: ExpressibleByStringLiteral>(_ key: String, _ value: T) -> T { return value }
88

99
func wrapped() -> Int {
10-
return wrap("1", 1) + wrap("1", 1) + wrap("1", 1) + wrap("1", 1)
10+
return wrap("1", 1) + wrap("1", 1) + wrap("1", 1) + wrap("1", 1) + wrap("1", 1) + wrap("1", 1)
1111
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
1212
}

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

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

0 commit comments

Comments
 (0)