Skip to content

Commit 5349486

Browse files
committed
[Constraint solver] Shore up "common return type" optimization.
The "common return type" optimization that occurs at constraint-generation time was overly complicated and wrong in a couple of places. Fix up these issues: * Don't cache information about this optimization in the decls themselves; it ignores visibility as well as invalidation that occurs in script mode and playgrounds. Just do the the work again * Don't map type into context; we can bail out when there are type parameters present * Skip the "self" parameters of operators in types (since this only ever occurs for operators). Longer term, this optimization should move into the solver itself. But for now, at least it's cleaner/more correct.
1 parent 5a67ecc commit 5349486

File tree

2 files changed

+41
-81
lines changed

2 files changed

+41
-81
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5035,12 +5035,6 @@ class FuncDecl final : public AbstractFunctionDecl,
50355035

50365036
TypeLoc FnRetType;
50375037

5038-
/// If this declaration is part of an overload set, determine if we've
5039-
/// searched for a common overload amongst all overloads, or if we've found
5040-
/// one.
5041-
unsigned HaveSearchedForCommonOverloadReturnType : 1;
5042-
unsigned HaveFoundCommonOverloadReturnType : 1;
5043-
50445038
/// Whether we are statically dispatched even if overridable
50455039
unsigned ForcedStaticDispatch : 1;
50465040

@@ -5081,8 +5075,6 @@ class FuncDecl final : public AbstractFunctionDecl,
50815075
Mutating = false;
50825076
HasDynamicSelf = false;
50835077
ForcedStaticDispatch = false;
5084-
HaveSearchedForCommonOverloadReturnType = false;
5085-
HaveFoundCommonOverloadReturnType = false;
50865078
}
50875079

50885080
static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
@@ -5155,20 +5147,6 @@ class FuncDecl final : public AbstractFunctionDecl,
51555147
return getParameterLists()[i];
51565148
}
51575149

5158-
5159-
bool getHaveSearchedForCommonOverloadReturnType() {
5160-
return HaveSearchedForCommonOverloadReturnType;
5161-
}
5162-
void setHaveSearchedForCommonOverloadReturnType(bool b = true) {
5163-
HaveSearchedForCommonOverloadReturnType = b;
5164-
}
5165-
bool getHaveFoundCommonOverloadReturnType() {
5166-
return HaveFoundCommonOverloadReturnType;
5167-
}
5168-
void setHaveFoundCommonOverloadReturnType(bool b = true) {
5169-
HaveFoundCommonOverloadReturnType = b;
5170-
}
5171-
51725150
/// \returns true if this is non-mutating due to applying a 'mutating'
51735151
/// attribute. For example a "mutating set" accessor.
51745152
bool isExplicitNonMutating() const;

lib/Sema/CSGen.cpp

Lines changed: 41 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,68 +2335,50 @@ namespace {
23352335
if (auto fnType = CS.getType(fnExpr)->getAs<AnyFunctionType>()) {
23362336
outputTy = fnType->getResult();
23372337
}
2338-
} else if (auto OSR = dyn_cast<OverloadSetRefExpr>(fnExpr)) {
2339-
if (auto FD = dyn_cast<FuncDecl>(OSR->getDecls()[0])) {
2338+
} else if (auto OSR = dyn_cast<OverloadedDeclRefExpr>(fnExpr)) {
2339+
// Determine if the overloads are all functions that share a common
2340+
// return type.
2341+
Type commonType;
2342+
for (auto OD : OSR->getDecls()) {
2343+
auto OFD = dyn_cast<AbstractFunctionDecl>(OD);
2344+
if (!OFD) {
2345+
commonType = Type();
2346+
break;
2347+
}
23402348

2341-
// If we've already agreed upon an overloaded return type, use it.
2342-
if (FD->getHaveSearchedForCommonOverloadReturnType()) {
2343-
2344-
if (FD->getHaveFoundCommonOverloadReturnType()) {
2345-
outputTy = FD->getInterfaceType()->getAs<AnyFunctionType>()
2346-
->getResult();
2347-
outputTy = FD->mapTypeIntoContext(outputTy);
2348-
}
2349-
2350-
} else {
2351-
2352-
// Determine if the overloads all share a common return type.
2353-
Type commonType;
2354-
Type resultType;
2355-
2356-
for (auto OD : OSR->getDecls()) {
2357-
2358-
if (auto OFD = dyn_cast<FuncDecl>(OD)) {
2359-
auto OFT = OFD->getInterfaceType()->getAs<AnyFunctionType>();
2360-
2361-
if (!OFT) {
2362-
commonType = Type();
2363-
break;
2364-
}
2365-
2366-
resultType = OFT->getResult();
2367-
resultType = OFD->mapTypeIntoContext(resultType);
2368-
2369-
if (commonType.isNull()) {
2370-
commonType = resultType;
2371-
} else if (!commonType->isEqual(resultType)) {
2372-
commonType = Type();
2373-
break;
2374-
}
2375-
} else {
2376-
// TODO: unreachable?
2377-
commonType = Type();
2378-
break;
2379-
}
2380-
}
2381-
2382-
// TODO: For now, disallow tyvar, archetype and function types.
2383-
if (!(commonType.isNull() ||
2384-
commonType->getAs<TypeVariableType>() ||
2385-
commonType->getAs<ArchetypeType>() ||
2386-
commonType->getAs<AnyFunctionType>())) {
2387-
outputTy = commonType;
2388-
}
2389-
2390-
// Set the search bits appropriately.
2391-
for (auto OD : OSR->getDecls()) {
2392-
if (auto OFD = dyn_cast<FuncDecl>(OD)) {
2393-
OFD->setHaveSearchedForCommonOverloadReturnType();
2394-
2395-
if (!outputTy.isNull())
2396-
OFD->setHaveFoundCommonOverloadReturnType();
2397-
}
2349+
auto OFT = OFD->getInterfaceType()->getAs<AnyFunctionType>();
2350+
if (!OFT) {
2351+
commonType = Type();
2352+
break;
2353+
}
2354+
2355+
// Look past the self parameter.
2356+
if (OFD->getDeclContext()->isTypeContext()) {
2357+
OFT = OFT->getResult()->getAs<AnyFunctionType>();
2358+
if (!OFT) {
2359+
commonType = Type();
2360+
break;
23982361
}
23992362
}
2363+
2364+
Type resultType = OFT->getResult();
2365+
2366+
// If there are any type parameters in the result,
2367+
if (resultType->hasTypeParameter()) {
2368+
commonType = Type();
2369+
break;
2370+
}
2371+
2372+
if (commonType.isNull()) {
2373+
commonType = resultType;
2374+
} else if (!commonType->isEqual(resultType)) {
2375+
commonType = Type();
2376+
break;
2377+
}
2378+
}
2379+
2380+
if (commonType) {
2381+
outputTy = commonType;
24002382
}
24012383
}
24022384

0 commit comments

Comments
 (0)