Skip to content

Commit e0199f2

Browse files
gregomnihborla
authored andcommitted
Add condition for optimizing series of binops that every possible overload is (T,T)->T, with no (T,T)->U
1 parent 529660d commit e0199f2

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/Sema/CSGen.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,26 @@ static bool isArithmeticOperatorDecl(ValueDecl *vd) {
4646
vd->getBaseName() == "%");
4747
}
4848

49+
static bool hasBinOpOverloadWithSameArgTypesDifferingResult(
50+
OverloadedDeclRefExpr *overloads) {
51+
for (auto decl : overloads->getDecls()) {
52+
auto metaFuncType = decl->getInterfaceType()->getAs<AnyFunctionType>();
53+
auto funcType = metaFuncType->getResult()->getAs<FunctionType>();
54+
if (!funcType)
55+
continue;
56+
57+
auto params = funcType->getParams();
58+
if (params.size() != 2)
59+
continue;
60+
61+
if (params[0].getPlainType().getPointer() != params[1].getPlainType().getPointer())
62+
continue;
63+
if (funcType->getResult().getPointer() != params[0].getPlainType().getPointer())
64+
return true;
65+
}
66+
return false;
67+
}
68+
4969
static bool mergeRepresentativeEquivalenceClasses(ConstraintSystem &CS,
5070
TypeVariableType* tyvar1,
5171
TypeVariableType* tyvar2) {
@@ -340,6 +360,9 @@ namespace {
340360
ODR2->getDecls()[0]->getBaseName())
341361
return;
342362

363+
if (hasBinOpOverloadWithSameArgTypesDifferingResult(ODR1))
364+
return;
365+
343366
// All things equal, we can merge the tyvars for the function
344367
// types.
345368
auto rep1 = CS.getRepresentative(fnTy1);

test/Constraints/sr10324.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -typecheck -verify %s
2+
3+
struct A {
4+
static func * (lhs: A, rhs: A) -> B { return B() }
5+
static func * (lhs: B, rhs: A) -> B { return B() }
6+
static func * (lhs: A, rhs: B) -> B { return B() }
7+
}
8+
struct B {}
9+
10+
let (x, y, z) = (A(), A(), A())
11+
12+
let w = A() * A() * A() // works
13+
14+
// Should all work
15+
let a = x * y * z
16+
let b = x * (y * z)
17+
let c = (x * y) * z
18+
let d = x * (y * z as B)
19+
let e = (x * y as B) * z

0 commit comments

Comments
 (0)