Skip to content

Commit 6fb66db

Browse files
authored
Merge pull request #76318 from slavapestov/favored-over-disjunction-heuristic
Sema: Generalize heuristic in favoredOverDisjunction()
2 parents 9d2159c + 73aa029 commit 6fb66db

File tree

3 files changed

+61
-22
lines changed

3 files changed

+61
-22
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,36 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
12321232
return true;
12331233
}
12341234

1235+
static bool hasConversions(Type type) {
1236+
if (type->isAnyHashable() || type->isDouble() || type->isCGFloat())
1237+
return true;
1238+
1239+
if (type->getAnyPointerElementType())
1240+
return true;
1241+
1242+
if (auto *structTy = type->getAs<BoundGenericStructType>()) {
1243+
if (auto eltTy = structTy->isArrayType()) {
1244+
return hasConversions(eltTy);
1245+
} else if (auto pair = ConstraintSystem::isDictionaryType(structTy)) {
1246+
return hasConversions(pair->second);
1247+
} else if (auto eltTy = ConstraintSystem::isSetType(structTy)) {
1248+
return hasConversions(*eltTy);
1249+
}
1250+
1251+
return false;
1252+
}
1253+
1254+
if (auto *enumTy = type->getAs<BoundGenericEnumType>()) {
1255+
if (enumTy->getOptionalObjectType())
1256+
return true;
1257+
1258+
return false;
1259+
}
1260+
1261+
return !(type->is<StructType>() || type->is<EnumType>() ||
1262+
type->is<BuiltinType>() || type->is<ArchetypeType>());
1263+
}
1264+
12351265
bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const {
12361266
if (isHole())
12371267
return false;
@@ -1240,30 +1270,10 @@ bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const {
12401270
if (binding.Kind == AllowedBindingKind::Supertypes)
12411271
return false;
12421272

1243-
auto type = binding.BindingType;
1244-
12451273
if (CS.shouldAttemptFixes())
12461274
return false;
12471275

1248-
if (type->isAnyHashable() || type->isDouble() || type->isCGFloat())
1249-
return false;
1250-
1251-
{
1252-
PointerTypeKind pointerKind;
1253-
if (type->getAnyPointerElementType(pointerKind)) {
1254-
switch (pointerKind) {
1255-
case PTK_UnsafeRawPointer:
1256-
case PTK_UnsafeMutableRawPointer:
1257-
return false;
1258-
1259-
default:
1260-
break;
1261-
}
1262-
}
1263-
}
1264-
1265-
return type->is<StructType>() || type->is<EnumType>() ||
1266-
type->is<BuiltinType>();
1276+
return !hasConversions(binding.BindingType);
12671277
})) {
12681278
// Result type of subscript could be l-value so we can't bind it early.
12691279
if (!TypeVar->getImpl().isSubscriptResultType() &&
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-typecheck-verify-swift -solver-disable-shrink
2+
3+
// Self-contained test case
4+
protocol P1 {}; func f<T: P1>(_: T, _: T) -> T { fatalError() }
5+
protocol P2 {}; func f<T: P2>(_: T, _: T) -> T { fatalError() }
6+
protocol P3 {}; func f<T: P3>(_: T, _: T) -> T { fatalError() }
7+
protocol P4 {}; func f<T: P4>(_: T, _: T) -> T { fatalError() }
8+
9+
func f<T>(_: Array<T>, _: Array<T>) -> Array<T> { fatalError() }
10+
11+
let fn1: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) -> Array<Int> = {
12+
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f($0, $1), $2), $3), $4), $5), $6), $7), $8), $9), $10), $11), $12), $13), $14), $15), $16), $17), $18), $19)
13+
}
14+
15+
let fn2: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) -> Array<Int> = {
16+
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f([$0], [$1]), [$2]), [$3]), [$4]), [$5]), [$6]), [$7]), [$8]), [$9]), [$10]), [$11]), [$12]), [$13]), [$14]), [$15]), [$16]), [$17]), [$18]), [$19])
17+
}
18+
19+
let x1: Array<Int> = f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f([0], [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0]), [0])
20+
21+
// Same setup with standard library operator
22+
let fn3: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) -> Array<Int> = {
23+
$0 + $1 + $2 + $3 + $4 + $5 + $6 + $7 + $8 + $9 + $10 + $11 + $12 + $13 + $14 + $15 + $16 + $17 + $18 + $19
24+
}
25+
26+
let fn4: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) -> Array<Int> = {
27+
[$0] + [$1] + [$2] + [$3] + [$4] + [$5] + [$6] + [$7] + [$8] + [$9] + [$10] + [$11] + [$12] + [$13] + [$14] + [$15] + [$16] + [$17] + [$18] + [$19]
28+
}
29+
30+
let x2: Array<Int> = [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0] + [0]

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
func method(_ arg: String, body: () -> [String]) {}
44

55
func test(str: String, properties: [String]) {
6-
// expected-error@+1 {{the compiler is unable to type-check this expression in reasonable time}}
76
method(str + "" + str + "") {
87
properties.map { param in
98
"" + param + "" + param + "" + param + ""

0 commit comments

Comments
 (0)