Skip to content

Commit b9cd303

Browse files
committed
[ConstraintSystem] Do not attempt to force references of unapplied functions.
We were inserting function conversion expressions that were then turned into forces of values in cases where we merely referenced functions, but did not actually call them. Fixes rdar://problem/37241550.
1 parent c4ddd22 commit b9cd303

File tree

4 files changed

+85
-56
lines changed

4 files changed

+85
-56
lines changed

lib/Sema/CSApply.cpp

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -544,10 +544,11 @@ namespace {
544544

545545
public:
546546
/// \brief Build a reference to the given declaration.
547-
Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
547+
Expr *buildDeclRef(OverloadChoice choice, DeclNameLoc loc, Type openedType,
548548
ConstraintLocatorBuilder locator, bool implicit,
549549
FunctionRefKind functionRefKind,
550550
AccessSemantics semantics) {
551+
auto *decl = choice.getDecl();
551552
// Determine the declaration selected for this overloaded reference.
552553
auto &ctx = cs.getASTContext();
553554

@@ -612,7 +613,7 @@ namespace {
612613
if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
613614
refExpr = fnConv->getSubExpr();
614615

615-
return forceUnwrapIfExpected(refExpr, decl, locator);
616+
return forceUnwrapIfExpected(refExpr, choice, locator);
616617
}
617618
}
618619
}
@@ -623,7 +624,7 @@ namespace {
623624
TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
624625
cs.cacheExprTypes(base);
625626

626-
return buildMemberRef(base, openedType, SourceLoc(), decl, loc,
627+
return buildMemberRef(base, openedType, SourceLoc(), choice, loc,
627628
openedFnType->getResult(), locator, locator,
628629
implicit, functionRefKind, semantics,
629630
/*isDynamic=*/false);
@@ -659,7 +660,7 @@ namespace {
659660
loc, implicit, semantics, type);
660661
cs.cacheType(declRefExpr);
661662
declRefExpr->setFunctionRefKind(functionRefKind);
662-
return forceUnwrapIfExpected(declRefExpr, decl, locator);
663+
return forceUnwrapIfExpected(declRefExpr, choice, locator);
663664
}
664665

665666
/// Describes an opened existential that has not yet been closed.
@@ -899,11 +900,12 @@ namespace {
899900

900901
/// \brief Build a new member reference with the given base and member.
901902
Expr *buildMemberRef(Expr *base, Type openedFullType, SourceLoc dotLoc,
902-
ValueDecl *member, DeclNameLoc memberLoc,
903+
OverloadChoice choice, DeclNameLoc memberLoc,
903904
Type openedType, ConstraintLocatorBuilder locator,
904905
ConstraintLocatorBuilder memberLocator, bool Implicit,
905906
FunctionRefKind functionRefKind,
906907
AccessSemantics semantics, bool isDynamic) {
908+
ValueDecl *member = choice.getDecl();
907909
auto &tc = cs.getTypeChecker();
908910
auto &context = tc.Context;
909911

@@ -949,7 +951,7 @@ namespace {
949951
ref->setFunctionRefKind(functionRefKind);
950952
auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
951953
base, dotLoc, ref, cs.getType(ref)));
952-
return forceUnwrapIfExpected(DSBI, member, memberLocator);
954+
return forceUnwrapIfExpected(DSBI, choice, memberLocator);
953955
}
954956

955957
// The formal type of the 'self' value for the member's declaration.
@@ -1088,8 +1090,9 @@ namespace {
10881090
// We also need to handle the implicitly unwrap of the result
10891091
// of the called function if that's the type checking solution
10901092
// we ended up with.
1091-
return forceUnwrapIfExpected(ref, member, memberLocator,
1092-
member->getAttrs().hasAttribute<OptionalAttr>());
1093+
return forceUnwrapIfExpected(
1094+
ref, choice, memberLocator,
1095+
member->getAttrs().hasAttribute<OptionalAttr>());
10931096
}
10941097

10951098
// For types and properties, build member references.
@@ -1115,7 +1118,7 @@ namespace {
11151118
cs.setType(memberRefExpr, simplifyType(openedType));
11161119
Expr *result = memberRefExpr;
11171120
closeExistential(result, locator);
1118-
return forceUnwrapIfExpected(result, member, memberLocator);
1121+
return forceUnwrapIfExpected(result, choice, memberLocator);
11191122
}
11201123

11211124
// Handle all other references.
@@ -1135,7 +1138,7 @@ namespace {
11351138
ApplyExpr *apply;
11361139
if (isa<ConstructorDecl>(member)) {
11371140
// FIXME: Provide type annotation.
1138-
ref = forceUnwrapIfExpected(ref, member, memberLocator);
1141+
ref = forceUnwrapIfExpected(ref, choice, memberLocator);
11391142
apply = new (context) ConstructorRefCallExpr(ref, base);
11401143
} else if (!baseIsInstance && member->isInstanceMember()) {
11411144
// Reference to an unbound instance method.
@@ -1144,11 +1147,11 @@ namespace {
11441147
cs.getType(ref));
11451148
cs.cacheType(result);
11461149
closeExistential(result, locator, /*force=*/openedExistential);
1147-
return forceUnwrapIfExpected(result, member, memberLocator);
1150+
return forceUnwrapIfExpected(result, choice, memberLocator);
11481151
} else {
11491152
assert((!baseIsInstance || member->isInstanceMember()) &&
11501153
"can't call a static method on an instance");
1151-
ref = forceUnwrapIfExpected(ref, member, memberLocator);
1154+
ref = forceUnwrapIfExpected(ref, choice, memberLocator);
11521155
apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base);
11531156
if (Implicit) {
11541157
apply->setImplicit();
@@ -1449,10 +1452,10 @@ namespace {
14491452
if (selected->choice.getKind() ==
14501453
OverloadChoiceKind::DynamicMemberLookup)
14511454
locatorKind = ConstraintLocator::Member;
1452-
1453-
newSubscript = forceUnwrapIfExpected(
1454-
newSubscript, selected->choice.getDecl(),
1455-
locator.withPathElement(locatorKind));
1455+
1456+
newSubscript =
1457+
forceUnwrapIfExpected(newSubscript, selected->choice,
1458+
locator.withPathElement(locatorKind));
14561459
}
14571460

14581461
return newSubscript;
@@ -2471,8 +2474,9 @@ namespace {
24712474
}
24722475
}
24732476

2474-
bool shouldForceUnwrapResult(Decl *decl, ConstraintLocatorBuilder locator) {
2475-
if (!decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
2477+
bool shouldForceUnwrapResult(OverloadChoice choice,
2478+
ConstraintLocatorBuilder locator) {
2479+
if (!choice.isImplicitlyUnwrappedValueOrReturnValue())
24762480
return false;
24772481

24782482
auto *choiceLocator = cs.getConstraintLocator(locator.withPathElement(
@@ -2481,10 +2485,10 @@ namespace {
24812485
return solution.getDisjunctionChoice(choiceLocator);
24822486
}
24832487

2484-
Expr *forceUnwrapIfExpected(Expr *expr, Decl *decl,
2488+
Expr *forceUnwrapIfExpected(Expr *expr, OverloadChoice choice,
24852489
ConstraintLocatorBuilder locator,
2486-
bool forForcedOptional =false) {
2487-
if (!shouldForceUnwrapResult(decl, locator))
2490+
bool forForcedOptional = false) {
2491+
if (!shouldForceUnwrapResult(choice, locator))
24882492
return expr;
24892493

24902494
// Force the expression if required for the solution.
@@ -2503,12 +2507,9 @@ namespace {
25032507
cs.setType(expr, varDecl->getType());
25042508
return expr;
25052509
}
2506-
2507-
auto choice = selected->choice;
2508-
auto decl = choice.getDecl();
25092510

2510-
return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
2511-
locator, expr->isImplicit(),
2511+
return buildDeclRef(selected->choice, expr->getNameLoc(),
2512+
selected->openedFullType, locator, expr->isImplicit(),
25122513
expr->getFunctionRefKind(),
25132514
expr->getAccessSemantics());
25142515
}
@@ -2539,9 +2540,8 @@ namespace {
25392540
auto locator = cs.getConstraintLocator(expr);
25402541
auto selected = getOverloadChoice(locator);
25412542
auto choice = selected.choice;
2542-
auto decl = choice.getDecl();
25432543

2544-
return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
2544+
return buildDeclRef(choice, expr->getNameLoc(), selected.openedFullType,
25452545
locator, expr->isImplicit(),
25462546
choice.getFunctionRefKind(),
25472547
AccessSemantics::Ordinary);
@@ -2566,7 +2566,7 @@ namespace {
25662566
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
25672567
return buildMemberRef(
25682568
expr->getBase(), selected.openedFullType, expr->getDotLoc(),
2569-
selected.choice.getDecl(), expr->getNameLoc(), selected.openedType,
2569+
selected.choice, expr->getNameLoc(), selected.openedType,
25702570
cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
25712571
selected.choice.getFunctionRefKind(), expr->getAccessSemantics(),
25722572
isDynamic);
@@ -2594,7 +2594,6 @@ namespace {
25942594
auto memberLocator = cs.getConstraintLocator(
25952595
expr, ConstraintLocator::UnresolvedMember);
25962596
auto selected = getOverloadChoice(memberLocator);
2597-
auto member = selected.choice.getDecl();
25982597

25992598
// If the member came by optional unwrapping, then unwrap the base type.
26002599
if (selected.choice.getKind()
@@ -2614,7 +2613,7 @@ namespace {
26142613
bool isDynamic
26152614
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
26162615
auto result = buildMemberRef(
2617-
base, selected.openedFullType, expr->getDotLoc(), member,
2616+
base, selected.openedFullType, expr->getDotLoc(), selected.choice,
26182617
expr->getNameLoc(), selected.openedType,
26192618
cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
26202619
selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary,
@@ -2651,9 +2650,10 @@ namespace {
26512650
Expr *applyCtorRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc,
26522651
DeclNameLoc nameLoc, bool implicit,
26532652
ConstraintLocator *ctorLocator,
2654-
ConstructorDecl *ctor,
2655-
FunctionRefKind functionRefKind,
2656-
Type openedType) {
2653+
OverloadChoice choice,
2654+
FunctionRefKind functionRefKind, Type openedType) {
2655+
2656+
auto *ctor = cast<ConstructorDecl>(choice.getDecl());
26572657

26582658
// If the member is a constructor, verify that it can be legally
26592659
// referenced from this base.
@@ -2665,7 +2665,7 @@ namespace {
26652665
// constructor.
26662666
if (cs.getType(base)->is<AnyMetatypeType>()) {
26672667
return buildMemberRef(
2668-
base, openedType, dotLoc, ctor, nameLoc, cs.getType(expr),
2668+
base, openedType, dotLoc, choice, nameLoc, cs.getType(expr),
26692669
ConstraintLocatorBuilder(cs.getConstraintLocator(expr)),
26702670
ctorLocator, implicit, functionRefKind, AccessSemantics::Ordinary,
26712671
/*isDynamic=*/false);
@@ -2731,10 +2731,9 @@ namespace {
27312731
ConstraintLocator::ConstructorMember);
27322732
if (auto selected = getOverloadChoiceIfAvailable(ctorLocator)) {
27332733
auto choice = selected->choice;
2734-
auto *ctor = cast<ConstructorDecl>(choice.getDecl());
2735-
return applyCtorRefExpr(expr, base, dotLoc, nameLoc, implicit,
2736-
ctorLocator, ctor, choice.getFunctionRefKind(),
2737-
selected->openedFullType);
2734+
return applyCtorRefExpr(
2735+
expr, base, dotLoc, nameLoc, implicit, ctorLocator, choice,
2736+
choice.getFunctionRefKind(), selected->openedFullType);
27382737
}
27392738

27402739
// Determine the declaration selected for this overloaded reference.
@@ -2783,11 +2782,11 @@ namespace {
27832782
case OverloadChoiceKind::DeclViaDynamic: {
27842783
bool isDynamic
27852784
= selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
2786-
return buildMemberRef(
2787-
base, selected.openedFullType, dotLoc, selected.choice.getDecl(),
2788-
nameLoc, selected.openedType, cs.getConstraintLocator(expr),
2789-
memberLocator, implicit, selected.choice.getFunctionRefKind(),
2790-
AccessSemantics::Ordinary, isDynamic);
2785+
return buildMemberRef(base, selected.openedFullType, dotLoc,
2786+
selected.choice, nameLoc, selected.openedType,
2787+
cs.getConstraintLocator(expr), memberLocator,
2788+
implicit, selected.choice.getFunctionRefKind(),
2789+
AccessSemantics::Ordinary, isDynamic);
27912790
}
27922791

27932792
case OverloadChoiceKind::TupleIndex: {
@@ -4370,7 +4369,7 @@ namespace {
43704369
baseTy = component.getComponentType();
43714370
resolvedComponents.push_back(component);
43724371

4373-
if (shouldForceUnwrapResult(property, locator)) {
4372+
if (shouldForceUnwrapResult(foundDecl->choice, locator)) {
43744373
auto objectTy = getObjectType(baseTy);
43754374
auto loc = origComponent.getLoc();
43764375
component = KeyPathExpr::Component::forOptionalForce(objectTy, loc);
@@ -4451,7 +4450,7 @@ namespace {
44514450
baseTy = component.getComponentType();
44524451
resolvedComponents.push_back(component);
44534452

4454-
if (shouldForceUnwrapResult(subscript, locator)) {
4453+
if (shouldForceUnwrapResult(foundDecl->choice, locator)) {
44554454
auto objectTy = getObjectType(baseTy);
44564455
auto loc = origComponent.getLoc();
44574456
component = KeyPathExpr::Component::forOptionalForce(objectTy, loc);
@@ -7469,17 +7468,16 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
74697468

74707469
// We have the constructor.
74717470
auto choice = selected->choice;
7472-
auto decl = choice.getDecl();
74737471

74747472
// Consider the constructor decl reference expr 'implicit', but the
74757473
// constructor call expr itself has the apply's 'implicitness'.
74767474
bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
7477-
Expr *declRef =
7478-
buildMemberRef(fn, selected->openedFullType,
7479-
/*dotLoc=*/SourceLoc(), decl, DeclNameLoc(fn->getEndLoc()),
7480-
selected->openedType, locator, ctorLocator,
7481-
/*Implicit=*/true, choice.getFunctionRefKind(),
7482-
AccessSemantics::Ordinary, isDynamic);
7475+
Expr *declRef = buildMemberRef(fn, selected->openedFullType,
7476+
/*dotLoc=*/SourceLoc(), choice,
7477+
DeclNameLoc(fn->getEndLoc()),
7478+
selected->openedType, locator, ctorLocator,
7479+
/*Implicit=*/true, choice.getFunctionRefKind(),
7480+
AccessSemantics::Ordinary, isDynamic);
74837481
if (!declRef)
74847482
return nullptr;
74857483
declRef->setImplicit(apply->isImplicit());
@@ -8173,8 +8171,10 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
81738171
ExprRewriter rewriter(cs, solution,
81748172
/*suppressDiagnostics=*/false);
81758173

8174+
auto choice =
8175+
OverloadChoice(openedFullType, witness, FunctionRefKind::SingleApply);
81768176
auto memberRef = rewriter.buildMemberRef(
8177-
base, openedFullType, base->getStartLoc(), witness,
8177+
base, openedFullType, base->getStartLoc(), choice,
81788178
DeclNameLoc(base->getEndLoc()), openedType, dotLocator, dotLocator,
81798179
/*Implicit=*/true, FunctionRefKind::SingleApply,
81808180
AccessSemantics::Ordinary,

lib/Sema/ConstraintSystem.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,6 +1957,23 @@ DeclName OverloadChoice::getName() const {
19571957
}
19581958

19591959
bool OverloadChoice::isImplicitlyUnwrappedValueOrReturnValue() const {
1960-
return isDecl() &&
1961-
getDecl()->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
1960+
if (!isDecl())
1961+
return false;
1962+
1963+
auto *decl = getDecl();
1964+
if (!decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
1965+
return false;
1966+
1967+
auto itfType = decl->getInterfaceType();
1968+
if (!itfType->getAs<AnyFunctionType>())
1969+
return true;
1970+
1971+
switch (getFunctionRefKind()) {
1972+
case FunctionRefKind::Unapplied:
1973+
case FunctionRefKind::Compound:
1974+
return false;
1975+
case FunctionRefKind::SingleApply:
1976+
case FunctionRefKind::DoubleApply:
1977+
return true;
1978+
}
19621979
}

lib/Sema/OverloadChoice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class OverloadChoice {
190190
result.BaseAndDeclKind.setPointer(base);
191191
result.DeclOrKind = value;
192192
result.DynamicNameAndFRK.setPointer(name);
193+
result.DynamicNameAndFRK.setInt(FunctionRefKind::SingleApply);
193194
return result;
194195
}
195196

test/Constraints/iuo.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,14 @@ func cast<T : P>(_ t: T) {
167167
let _: (Bool) -> T? = id(T.iuoResultStatic as (Bool) -> T?)
168168
let _: T! = id(T.iuoResultStatic(true))
169169
}
170+
171+
class rdar37241550 {
172+
public init(blah: Float) { fatalError() }
173+
public convenience init() { fatalError() }
174+
public convenience init!(with void: ()) { fatalError() }
175+
176+
static func f(_ fn: () -> rdar37241550) {}
177+
static func test() {
178+
f(rdar37241550.init) // no error, the failable init is not applicable
179+
}
180+
}

0 commit comments

Comments
 (0)