Skip to content

Commit dafcaeb

Browse files
committed
[CS] Simplify getCalleeDeclAndArgs
Now that we associate argument labels for key path subscript components, remove the special logic for it. In addition, we can now search for callees directly by using `getCalleeLocator`, as it should now be able to find all the correct callees that `getCalleeDeclAndArgs` does. By using `getCalleeLocator`, we now also correctly resolve callees for operator calls, meaning that we can now use them with function builders. In addition, we no longer incorrectly resolve callees for calls made on SubscriptExprs. Resolves SR-11439 & SR-11440.
1 parent b9ad96a commit dafcaeb

File tree

3 files changed

+70
-101
lines changed

3 files changed

+70
-101
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 31 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -735,124 +735,54 @@ static std::tuple<ValueDecl *, bool, ArrayRef<Identifier>, bool,
735735
ConstraintLocator *>
736736
getCalleeDeclAndArgs(ConstraintSystem &cs,
737737
ConstraintLocatorBuilder callBuilder) {
738-
ArrayRef<Identifier> argLabels;
739-
bool hasTrailingClosure = false;
740-
ConstraintLocator *targetLocator = nullptr;
738+
auto formUnknownCallee =
739+
[]() -> std::tuple<ValueDecl *, bool, ArrayRef<Identifier>, bool,
740+
ConstraintLocator *> {
741+
return std::make_tuple(/*decl*/ nullptr, /*hasAppliedSelf*/ false,
742+
/*argLabels*/ ArrayRef<Identifier>(),
743+
/*hasTrailingClosure*/ false,
744+
/*calleeLocator*/ nullptr);
745+
};
741746

742747
auto *callLocator = cs.getConstraintLocator(callBuilder);
743748
auto *callExpr = callLocator->getAnchor();
744749

745750
// Break down the call.
746751
if (!callExpr)
747-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
748-
hasTrailingClosure, targetLocator);
752+
return formUnknownCallee();
749753

750-
auto path = callLocator->getPath();
751754
// Our remaining path can only be 'ApplyArgument'.
755+
auto path = callLocator->getPath();
752756
if (!path.empty() &&
753757
!(path.size() <= 2 &&
754758
path.back().getKind() == ConstraintLocator::ApplyArgument))
755-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
756-
hasTrailingClosure, targetLocator);
759+
return formUnknownCallee();
757760

758761
// Dig out the callee information.
759-
if (auto argInfo = cs.getArgumentInfo(callLocator)) {
760-
argLabels = argInfo->Labels;
761-
hasTrailingClosure = argInfo->HasTrailingClosure;
762-
targetLocator = cs.getConstraintLocator(
763-
isa<CallExpr>(callExpr) ? cast<CallExpr>(callExpr)->getDirectCallee()
764-
: callExpr);
765-
} else if (auto keyPath = dyn_cast<KeyPathExpr>(callExpr)) {
766-
if (path.size() != 2)
767-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
768-
hasTrailingClosure, nullptr);
769-
770-
// We must have a KeyPathComponent followed by an ApplyArgument.
771-
auto componentElt = path[0].getAs<LocatorPathElt::KeyPathComponent>();
772-
if (!componentElt || path[1].getKind() != ConstraintLocator::ApplyArgument)
773-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
774-
hasTrailingClosure, nullptr);
775-
776-
auto componentIndex = componentElt->getIndex();
777-
if (componentIndex >= keyPath->getComponents().size())
778-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
779-
hasTrailingClosure, nullptr);
780-
781-
auto &component = keyPath->getComponents()[componentIndex];
782-
switch (component.getKind()) {
783-
case KeyPathExpr::Component::Kind::Subscript:
784-
case KeyPathExpr::Component::Kind::UnresolvedSubscript:
785-
targetLocator = cs.getConstraintLocator(callExpr, path[0]);
786-
argLabels = component.getSubscriptLabels();
787-
hasTrailingClosure = false; // key paths don't support trailing closures
788-
break;
789-
790-
case KeyPathExpr::Component::Kind::Invalid:
791-
case KeyPathExpr::Component::Kind::UnresolvedProperty:
792-
case KeyPathExpr::Component::Kind::Property:
793-
case KeyPathExpr::Component::Kind::OptionalForce:
794-
case KeyPathExpr::Component::Kind::OptionalChain:
795-
case KeyPathExpr::Component::Kind::OptionalWrap:
796-
case KeyPathExpr::Component::Kind::Identity:
797-
case KeyPathExpr::Component::Kind::TupleElement:
798-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
799-
hasTrailingClosure, nullptr);
800-
}
801-
} else {
802-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
803-
hasTrailingClosure, targetLocator);
804-
}
762+
auto argInfo = cs.getArgumentInfo(callLocator);
763+
if (!argInfo)
764+
return formUnknownCallee();
765+
766+
auto argLabels = argInfo->Labels;
767+
auto hasTrailingClosure = argInfo->HasTrailingClosure;
768+
auto calleeLocator = cs.getCalleeLocator(callLocator);
805769

806770
// Find the overload choice corresponding to the callee locator.
807771
// FIXME: This linearly walks the list of resolved overloads, which is
808772
// potentially very expensive.
809-
Optional<OverloadChoice> choice;
810-
ConstraintLocator *calleeLocator = nullptr;
811-
for (auto resolved = cs.getResolvedOverloadSets(); resolved;
812-
resolved = resolved->Previous) {
813-
// FIXME: Workaround null locators.
814-
if (!resolved->Locator) continue;
815-
816-
auto resolvedLocator = resolved->Locator;
817-
SmallVector<LocatorPathElt, 4> resolvedPath(
818-
resolvedLocator->getPath().begin(),
819-
resolvedLocator->getPath().end());
820-
if (!resolvedPath.empty() &&
821-
(resolvedPath.back().getKind() == ConstraintLocator::SubscriptMember ||
822-
resolvedPath.back().getKind() == ConstraintLocator::Member ||
823-
resolvedPath.back().getKind() == ConstraintLocator::UnresolvedMember ||
824-
resolvedPath.back().getKind() ==
825-
ConstraintLocator::ConstructorMember)) {
826-
resolvedPath.pop_back();
827-
resolvedLocator = cs.getConstraintLocator(
828-
resolvedLocator->getAnchor(),
829-
resolvedPath,
830-
resolvedLocator->getSummaryFlags());
831-
}
832-
833-
SourceRange range;
834-
resolvedLocator = simplifyLocator(cs, resolvedLocator, range);
835-
836-
if (resolvedLocator == targetLocator) {
837-
calleeLocator = resolved->Locator;
838-
choice = resolved->Choice;
839-
break;
840-
}
841-
}
842-
843-
// If we didn't find any matching overloads, we're done.
844-
if (!choice)
845-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
846-
hasTrailingClosure, nullptr);
847-
848-
// If there's a declaration, return it.
849-
if (auto *decl = choice->getDeclOrNull()) {
850-
return std::make_tuple(decl, hasAppliedSelf(cs, *choice), argLabels,
851-
hasTrailingClosure, calleeLocator);
852-
}
853-
854-
return std::make_tuple(nullptr, /*hasAppliedSelf=*/false, argLabels,
855-
hasTrailingClosure, calleeLocator);
773+
auto selectedOverload = cs.findSelectedOverloadFor(calleeLocator);
774+
775+
// If we didn't find any matching overloads, we're done. Just return the
776+
// argument info.
777+
if (!selectedOverload)
778+
return std::make_tuple(/*decl*/ nullptr, /*hasAppliedSelf*/ false,
779+
argLabels, hasTrailingClosure,
780+
/*calleeLocator*/ nullptr);
781+
782+
// Return the found declaration, assuming there is one.
783+
auto choice = selectedOverload->Choice;
784+
return std::make_tuple(choice.getDeclOrNull(), hasAppliedSelf(cs, choice),
785+
argLabels, hasTrailingClosure, calleeLocator);
856786
}
857787

858788
class ArgumentFailureTracker : public MatchCallArgumentListener {

test/Constraints/function_builder.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,18 @@ print(mbuilders.methodBuilder(13))
212212
// CHECK: ("propertyBuilder", 12)
213213
print(mbuilders.propertyBuilder)
214214

215+
// SR-11439: Operator builders
216+
infix operator ^^^
217+
func ^^^ (lhs: Int, @TupleBuilder rhs: (Int) -> (String, Int)) -> (String, Int) {
218+
return rhs(lhs)
219+
}
220+
221+
// CHECK: ("hello", 6)
222+
print(5 ^^^ {
223+
"hello"
224+
$0 + 1
225+
})
226+
215227
struct Tagged<Tag, Entity> {
216228
let tag: Tag
217229
let entity: Entity

test/Constraints/function_builder_diags.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,30 @@ func test_51167632() -> some P {
172172
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{10-10=<<#L: P#>>}}
173173
})
174174
}
175+
176+
struct SR11440 {
177+
typealias ReturnsTuple<T> = () -> (T, T)
178+
subscript<T, U>(@TupleBuilder x: ReturnsTuple<T>) -> (ReturnsTuple<U>) -> Void { //expected-note {{in call to 'subscript(_:)'}}
179+
return { _ in }
180+
}
181+
182+
func foo() {
183+
// This is okay, we apply the function builder for the subscript arg.
184+
self[{
185+
5
186+
5
187+
}]({
188+
(5, 5)
189+
})
190+
191+
// But we shouldn't perform the transform for the argument to the call
192+
// made on the function returned from the subscript.
193+
self[{ // expected-error {{generic parameter 'U' could not be inferred}}
194+
5
195+
5
196+
}]({
197+
5
198+
5
199+
})
200+
}
201+
}

0 commit comments

Comments
 (0)