Skip to content

Commit cd61cf6

Browse files
authored
Merge pull request #9494 from DougGregor/common-return-type-cleanup
2 parents 9fa3cec + badffdc commit cd61cf6

File tree

5 files changed

+81
-83
lines changed

5 files changed

+81
-83
lines changed

include/swift/AST/Decl.h

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

50585058
TypeLoc FnRetType;
50595059

5060-
/// If this declaration is part of an overload set, determine if we've
5061-
/// searched for a common overload amongst all overloads, or if we've found
5062-
/// one.
5063-
unsigned HaveSearchedForCommonOverloadReturnType : 1;
5064-
unsigned HaveFoundCommonOverloadReturnType : 1;
5065-
50665060
/// Whether we are statically dispatched even if overridable
50675061
unsigned ForcedStaticDispatch : 1;
50685062

@@ -5103,8 +5097,6 @@ class FuncDecl final : public AbstractFunctionDecl,
51035097
Mutating = false;
51045098
HasDynamicSelf = false;
51055099
ForcedStaticDispatch = false;
5106-
HaveSearchedForCommonOverloadReturnType = false;
5107-
HaveFoundCommonOverloadReturnType = false;
51085100
}
51095101

51105102
static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
@@ -5177,20 +5169,6 @@ class FuncDecl final : public AbstractFunctionDecl,
51775169
return getParameterLists()[i];
51785170
}
51795171

5180-
5181-
bool getHaveSearchedForCommonOverloadReturnType() {
5182-
return HaveSearchedForCommonOverloadReturnType;
5183-
}
5184-
void setHaveSearchedForCommonOverloadReturnType(bool b = true) {
5185-
HaveSearchedForCommonOverloadReturnType = b;
5186-
}
5187-
bool getHaveFoundCommonOverloadReturnType() {
5188-
return HaveFoundCommonOverloadReturnType;
5189-
}
5190-
void setHaveFoundCommonOverloadReturnType(bool b = true) {
5191-
HaveFoundCommonOverloadReturnType = b;
5192-
}
5193-
51945172
/// \returns true if this is non-mutating due to applying a 'mutating'
51955173
/// attribute. For example a "mutating set" accessor.
51965174
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

lib/Sema/CSSolver.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616
#include "ConstraintSystem.h"
1717
#include "ConstraintGraph.h"
18+
#include "swift/AST/ParameterList.h"
1819
#include "swift/AST/TypeWalker.h"
1920
#include "llvm/ADT/Statistic.h"
2021
#include "llvm/Support/Compiler.h"
@@ -2480,6 +2481,28 @@ static bool isGenericOperatorOrUnavailable(Constraint *constraint) {
24802481
decl->getAttrs().isUnavailable(ctx);
24812482
}
24822483

2484+
/// Whether this constraint refers to a symmetric operator.
2485+
static bool isSymmetricOperator(Constraint *constraint) {
2486+
if (constraint->getKind() != ConstraintKind::BindOverload ||
2487+
constraint->getOverloadChoice().getKind() != OverloadChoiceKind::Decl ||
2488+
!constraint->getOverloadChoice().getDecl()->isOperator())
2489+
return false;
2490+
2491+
// If it's a binary operator, check that the types on both sides are the
2492+
// same. Otherwise, don't perform this optimization.
2493+
auto func = dyn_cast<FuncDecl>(constraint->getOverloadChoice().getDecl());
2494+
auto paramList =
2495+
func->getParameterList(func->getDeclContext()->isTypeContext());
2496+
if (paramList->size() != 2)
2497+
return true;
2498+
2499+
auto firstType =
2500+
paramList->get(0)->getInterfaceType()->getLValueOrInOutObjectType();
2501+
auto secondType =
2502+
paramList->get(1)->getInterfaceType()->getLValueOrInOutObjectType();
2503+
return firstType->isEqual(secondType);
2504+
}
2505+
24832506
bool ConstraintSystem::solveSimplified(
24842507
SmallVectorImpl<Solution> &solutions,
24852508
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -2694,7 +2717,8 @@ bool ConstraintSystem::solveSimplified(
26942717

26952718
if (!solveRec(solutions, allowFreeTypeVariables)) {
26962719
if (!firstNonGenericOperatorSolution &&
2697-
!isGenericOperatorOrUnavailable(constraint))
2720+
!isGenericOperatorOrUnavailable(constraint) &&
2721+
isSymmetricOperator(constraint))
26982722
firstNonGenericOperatorSolution = constraint;
26992723

27002724
firstSolvedConstraint = constraint;

lib/Sema/TypeCheckError.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,20 @@ class ApplyClassifier {
428428
// count, then this is a call to the opaque value returned from
429429
// the function.
430430
if (args.size() != fnRef.getNumArgumentsForFullApply()) {
431+
// Special case: a reference to an operator within a type might be
432+
// missing 'self'.
433+
// FIXME: The issue here is that this is an ill-formed expression, but
434+
// we don't know it from the structure of the expression.
435+
if (args.size() == 1 && fnRef.getKind() == AbstractFunction::Function &&
436+
isa<FuncDecl>(fnRef.getFunction()) &&
437+
cast<FuncDecl>(fnRef.getFunction())->isOperator() &&
438+
fnRef.getNumArgumentsForFullApply() == 2 &&
439+
fnRef.getFunction()->getDeclContext()->isTypeContext()) {
440+
// Can only happen with invalid code.
441+
assert(fnRef.getFunction()->getASTContext().Diags.hadAnyError());
442+
return Classification::forInvalidCode();
443+
}
444+
431445
assert(args.size() > fnRef.getNumArgumentsForFullApply() &&
432446
"partial application was throwing?");
433447
return Classification::forThrow(PotentialReason::forThrowingApply());
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
// REQUIRES: asserts
1010
func a{guard let[]=(a||()A

0 commit comments

Comments
 (0)