Skip to content

Commit 202d521

Browse files
committed
[Constraint system] Generalize effective-overload-type computation.
Extend the computation of effective overload types, used in common result type and common type computations, to also handle subscripts and variables. This allows the optimization to also apply to subscripts, which did not previously have a peephole in constraint generation.
1 parent 5f99d91 commit 202d521

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

lib/Sema/CSGen.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,10 +1123,6 @@ namespace {
11231123

11241124
if (outputTy.isNull()) {
11251125
outputTy = CS.createTypeVariable(resultLocator, TVO_CanBindToLValue);
1126-
} else {
1127-
// TODO: Generalize this for non-subscript-expr anchors, so that e.g.
1128-
// keypath lookup benefits from the peephole as well.
1129-
CS.setFavoredType(anchor, outputTy.getPointer());
11301126
}
11311127

11321128
// FIXME: This can only happen when diagnostics successfully type-checked
@@ -1171,6 +1167,13 @@ namespace {
11711167
memberTy,
11721168
fnLocator);
11731169

1170+
Type fixedOutputType =
1171+
CS.getFixedTypeRecursive(outputTy, /*wantRValue=*/false);
1172+
if (!fixedOutputType->isTypeVariableOrMember()) {
1173+
CS.setFavoredType(anchor, fixedOutputType.getPointer());
1174+
outputTy = fixedOutputType;
1175+
}
1176+
11741177
return outputTy;
11751178
}
11761179

lib/Sema/ConstraintSystem.cpp

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,7 @@ Type ConstraintSystem::getFixedTypeRecursive(Type type,
712712
/// \param baseType - the type of the base on which this object
713713
/// is being accessed; must be null if and only if this is not
714714
/// a type member
715-
static bool doesStorageProduceLValue(TypeChecker &TC,
716-
AbstractStorageDecl *storage,
715+
static bool doesStorageProduceLValue(AbstractStorageDecl *storage,
717716
Type baseType, DeclContext *useDC,
718717
const DeclRefExpr *base = nullptr) {
719718
// Unsettable storage decls always produce rvalues.
@@ -775,7 +774,7 @@ Type TypeChecker::getUnopenedTypeOfReference(
775774

776775
// Qualify storage declarations with an lvalue when appropriate.
777776
// Otherwise, they yield rvalues (and the access must be a load).
778-
if (doesStorageProduceLValue(*this, value, baseType, UseDC, base) &&
777+
if (doesStorageProduceLValue(value, baseType, UseDC, base) &&
779778
!requestedType->hasError()) {
780779
return LValueType::get(requestedType);
781780
}
@@ -1247,7 +1246,7 @@ ConstraintSystem::getTypeOfMemberReference(
12471246
if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
12481247
auto elementTy = subscript->getElementInterfaceType();
12491248

1250-
if (doesStorageProduceLValue(TC, subscript, baseTy, useDC, base))
1249+
if (doesStorageProduceLValue(subscript, baseTy, useDC, base))
12511250
elementTy = LValueType::get(elementTy);
12521251

12531252
// See ConstraintSystem::resolveOverload() -- optional and dynamic
@@ -1467,7 +1466,8 @@ static ArrayRef<OverloadChoice> partitionSIMDOperators(
14671466

14681467
/// Retrieve the type that will be used when matching the given overload.
14691468
static Type getEffectiveOverloadType(const OverloadChoice &overload,
1470-
bool allowMembers) {
1469+
bool allowMembers,
1470+
DeclContext *useDC) {
14711471
switch (overload.getKind()) {
14721472
case OverloadChoiceKind::Decl:
14731473
// Declaration choices are handled below.
@@ -1513,13 +1513,36 @@ static Type getEffectiveOverloadType(const OverloadChoice &overload,
15131513
if (!allowMembers)
15141514
return Type();
15151515

1516-
// FIXME: This is overly restrictive for now.
1517-
if ((!isa<FuncDecl>(decl) && !isa<EnumElementDecl>(decl)) ||
1518-
(decl->isInstanceMember() &&
1519-
(!overload.getBaseType() || !overload.getBaseType()->getAnyNominal())))
1520-
return Type();
1516+
if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
1517+
auto elementTy = subscript->getElementInterfaceType();
15211518

1522-
type = type->castTo<FunctionType>()->getResult();
1519+
if (doesStorageProduceLValue(subscript, overload.getBaseType(), useDC))
1520+
elementTy = LValueType::get(elementTy);
1521+
1522+
// See ConstraintSystem::resolveOverload() -- optional and dynamic
1523+
// subscripts are a special case, because the optionality is
1524+
// applied to the result type and not the type of the reference.
1525+
if (subscript->getAttrs().hasAttribute<OptionalAttr>() ||
1526+
overload.getKind() == OverloadChoiceKind::DeclViaDynamic)
1527+
elementTy = OptionalType::get(elementTy->getRValueType());
1528+
1529+
auto indices = subscript->getInterfaceType()
1530+
->castTo<AnyFunctionType>()->getParams();
1531+
type = FunctionType::get(indices, elementTy);
1532+
} else if (auto var = dyn_cast<VarDecl>(decl)) {
1533+
type = var->getInterfaceType();
1534+
if (doesStorageProduceLValue(var, overload.getBaseType(), useDC))
1535+
type = LValueType::get(type);
1536+
} else if (isa<FuncDecl>(decl) || isa<EnumElementDecl>(decl)) {
1537+
if (decl->isInstanceMember() &&
1538+
(!overload.getBaseType() ||
1539+
!overload.getBaseType()->getAnyNominal()))
1540+
return Type();
1541+
1542+
type = type->castTo<FunctionType>()->getResult();
1543+
} else {
1544+
return type;
1545+
}
15231546
}
15241547

15251548
return type;
@@ -1776,7 +1799,7 @@ Type ConstraintSystem::findCommonResultType(ArrayRef<OverloadChoice> choices) {
17761799
// If we can't even get a type for the overload, there's nothing more to
17771800
// do.
17781801
Type overloadType =
1779-
getEffectiveOverloadType(overload, /*allowMembers=*/true);
1802+
getEffectiveOverloadType(overload, /*allowMembers=*/true, /*FIXME:*/DC);
17801803
if (!overloadType) {
17811804
return true;
17821805
}
@@ -1827,7 +1850,7 @@ Type ConstraintSystem::findCommonOverloadType(
18271850
// If we can't even get a type for the overload, there's nothing more to
18281851
// do.
18291852
Type overloadType =
1830-
getEffectiveOverloadType(overload, /*allowMembers=*/false);
1853+
getEffectiveOverloadType(overload, /*allowMembers=*/false, /*FIXME:*/DC);
18311854
if (!overloadType) {
18321855
return true;
18331856
}

0 commit comments

Comments
 (0)