Skip to content

Commit 2b7d0f9

Browse files
committed
[Type checker] Extract default argument information from the callee declaration.
Rather than relying on the embedding of default argument information into tuple types (which is gross), make sure that the various clients (type checker, type checker diagnostics, constraint application) can dig out the callee declaration and retrieve that information from there.
1 parent 95b28cb commit 2b7d0f9

File tree

8 files changed

+296
-69
lines changed

8 files changed

+296
-69
lines changed

include/swift/AST/Expr.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3196,7 +3196,15 @@ class CallExpr : public ApplyExpr {
31963196
SourceLoc FnLoc = getFn()->getLoc();
31973197
return FnLoc.isValid() ? FnLoc : getArg()->getLoc();
31983198
}
3199-
3199+
3200+
/// Retrieve the expression that direct represents the callee.
3201+
///
3202+
/// The "direct" callee is the expression representing the callee
3203+
/// after looking through top-level constructs that don't affect the
3204+
/// identity of the callee, e.g., extra parentheses, optional
3205+
/// unwrapping (?)/forcing (!), etc.
3206+
Expr *getDirectCallee() const;
3207+
32003208
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Call; }
32013209
};
32023210

lib/AST/Expr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,25 @@ ValueDecl *ApplyExpr::getCalledValue() const {
10351035
return ::getCalledValue(Fn);
10361036
}
10371037

1038+
Expr *CallExpr::getDirectCallee() const {
1039+
auto fn = getFn();
1040+
while (true) {
1041+
fn = fn->getSemanticsProvidingExpr();
1042+
1043+
if (auto force = dyn_cast<ForceValueExpr>(fn)) {
1044+
fn = force->getSubExpr();
1045+
continue;
1046+
}
1047+
1048+
if (auto bind = dyn_cast<BindOptionalExpr>(fn)) {
1049+
fn = bind->getSubExpr();
1050+
continue;
1051+
}
1052+
1053+
return fn;
1054+
}
1055+
}
1056+
10381057
RebindSelfInConstructorExpr::RebindSelfInConstructorExpr(Expr *SubExpr,
10391058
VarDecl *Self)
10401059
: Expr(ExprKind::RebindSelfInConstructor, /*Implicit=*/true,

lib/Sema/CSApply.cpp

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/Basic/StringExtras.h"
2424
#include "llvm/ADT/APFloat.h"
2525
#include "llvm/ADT/APInt.h"
26+
#include "llvm/ADT/Fixnum.h"
2627
#include "llvm/ADT/SmallString.h"
2728
#include "llvm/Support/SaveAndRestore.h"
2829

@@ -1111,10 +1112,15 @@ namespace {
11111112
///
11121113
/// \param arg The argument expression.
11131114
/// \param paramType The parameter type.
1115+
/// \param applyOrLevel For function applications, the ApplyExpr that forms
1116+
/// the call. Otherwise, a specific level describing which parameter level
1117+
/// we're applying.
11141118
/// \param locator Locator used to describe where in this expression we are.
11151119
///
11161120
/// \returns the coerced expression, which will have type \c ToType.
11171121
Expr *coerceCallArguments(Expr *arg, Type paramType,
1122+
llvm::PointerUnion<ApplyExpr *, llvm::Fixnum<2>>
1123+
applyOrLevel,
11181124
ConstraintLocatorBuilder locator);
11191125

11201126
/// \brief Coerce the given object argument (e.g., for the base of a
@@ -1184,7 +1190,7 @@ namespace {
11841190
}
11851191

11861192
// Coerce the index argument.
1187-
index = coerceCallArguments(index, indexTy,
1193+
index = coerceCallArguments(index, indexTy, /*level=*/llvm::Fixnum<2>(1),
11881194
locator.withPathElement(
11891195
ConstraintLocator::SubscriptIndex));
11901196
if (!index)
@@ -3778,11 +3784,11 @@ resolveLocatorToDecl(ConstraintSystem &cs, ConstraintLocator *locator,
37783784
}
37793785

37803786

3781-
/// \brief Given a constraint locator, find the owner of default arguments for
3782-
/// that tuple, i.e., a FuncDecl.
3787+
/// \brief Given a constraint locator, find the declaration reference
3788+
/// to the callee, it is a call to a declaration.
37833789
static ConcreteDeclRef
3784-
findDefaultArgsOwner(ConstraintSystem &cs, const Solution &solution,
3785-
ConstraintLocator *locator) {
3790+
findCalleeDeclRef(ConstraintSystem &cs, const Solution &solution,
3791+
ConstraintLocator *locator) {
37863792
if (locator->getPath().empty() || !locator->getAnchor())
37873793
return nullptr;
37883794

@@ -4043,8 +4049,8 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
40434049
SmallVector<TupleTypeElt, 4> fromTupleExprFields(
40444050
fromTuple->getElements().size());
40454051
SmallVector<Expr *, 2> callerDefaultArgs;
4046-
ConcreteDeclRef defaultArgsOwner =
4047-
findDefaultArgsOwner(cs, solution, cs.getConstraintLocator(locator));
4052+
ConcreteDeclRef callee =
4053+
findCalleeDeclRef(cs, solution, cs.getConstraintLocator(locator));
40484054

40494055
for (unsigned i = 0, n = toTuple->getNumElements(); i != n; ++i) {
40504056
const auto &toElt = toTuple->getElement(i);
@@ -4058,7 +4064,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
40584064

40594065
// Create a caller-side default argument, if we need one.
40604066
if (auto defArg = getCallerDefaultArg(tc, dc, expr->getLoc(),
4061-
defaultArgsOwner, i).first) {
4067+
callee, i).first) {
40624068
callerDefaultArgs.push_back(defArg);
40634069
sources[i] = TupleShuffleExpr::CallerDefaultInitialize;
40644070
}
@@ -4218,7 +4224,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
42184224
auto shuffle = new (tc.Context) TupleShuffleExpr(
42194225
expr, mapping,
42204226
TupleShuffleExpr::SourceIsTuple,
4221-
defaultArgsOwner,
4227+
callee,
42224228
tc.Context.AllocateCopy(variadicArgs),
42234229
callerDefaultArgsCopy,
42244230
toSugarType);
@@ -4299,8 +4305,8 @@ Expr *ExprRewriter::coerceScalarToTuple(Expr *expr, TupleType *toTuple,
42994305
SmallVector<int, 4> elements;
43004306
SmallVector<unsigned, 1> variadicArgs;
43014307
SmallVector<Expr*, 4> callerDefaultArgs;
4302-
ConcreteDeclRef defaultArgsOwner =
4303-
findDefaultArgsOwner(cs, solution, cs.getConstraintLocator(locator));
4308+
ConcreteDeclRef callee =
4309+
findCalleeDeclRef(cs, solution, cs.getConstraintLocator(locator));
43044310

43054311
i = 0;
43064312
for (auto &field : toTuple->getElements()) {
@@ -4324,7 +4330,7 @@ Expr *ExprRewriter::coerceScalarToTuple(Expr *expr, TupleType *toTuple,
43244330

43254331
// Create a caller-side default argument, if we need one.
43264332
if (auto defArg = getCallerDefaultArg(tc, dc, expr->getLoc(),
4327-
defaultArgsOwner, i).first) {
4333+
callee, i).first) {
43284334
// Record the caller-side default argument expression.
43294335
// FIXME: Do we need to record what this was synthesized from?
43304336
elements.push_back(TupleShuffleExpr::CallerDefaultInitialize);
@@ -4342,7 +4348,7 @@ Expr *ExprRewriter::coerceScalarToTuple(Expr *expr, TupleType *toTuple,
43424348
return new (tc.Context) TupleShuffleExpr(expr,
43434349
tc.Context.AllocateCopy(elements),
43444350
TupleShuffleExpr::SourceIsScalar,
4345-
defaultArgsOwner,
4351+
callee,
43464352
tc.Context.AllocateCopy(variadicArgs),
43474353
tc.Context.AllocateCopy(callerDefaultArgs),
43484354
destSugarTy);
@@ -4525,14 +4531,56 @@ Expr *ExprRewriter::coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type ob
45254531
return expr;
45264532
}
45274533

4528-
Expr *ExprRewriter::coerceCallArguments(Expr *arg, Type paramType,
4529-
ConstraintLocatorBuilder locator) {
4534+
/// Determine whether the given expression is a reference to an
4535+
/// unbound instance member of a type.
4536+
static bool isReferenceToMetatypeMember(Expr *expr) {
4537+
expr = expr->getSemanticsProvidingExpr();
4538+
if (auto dotIgnored = dyn_cast<DotSyntaxBaseIgnoredExpr>(expr))
4539+
return dotIgnored->getLHS()->getType()->is<AnyMetatypeType>();
4540+
if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(expr))
4541+
return dotSyntax->getBase()->getType()->is<AnyMetatypeType>();
4542+
return false;
4543+
}
4544+
4545+
Expr *ExprRewriter::coerceCallArguments(
4546+
Expr *arg, Type paramType,
4547+
llvm::PointerUnion<ApplyExpr *, llvm::Fixnum<2>> applyOrLevel,
4548+
ConstraintLocatorBuilder locator) {
45304549

45314550
bool allParamsMatch = arg->getType()->isEqual(paramType);
4532-
4551+
4552+
// Find the callee declaration.
4553+
ConcreteDeclRef callee =
4554+
findCalleeDeclRef(cs, solution, cs.getConstraintLocator(locator));
4555+
4556+
// Determine the level,
4557+
unsigned level = 0;
4558+
if (applyOrLevel.is<llvm::Fixnum<2>>()) {
4559+
// Level specified by caller.
4560+
level = applyOrLevel.get<llvm::Fixnum<2>>();
4561+
} else if (callee) {
4562+
// Determine the level based on the application itself.
4563+
auto apply = applyOrLevel.get<ApplyExpr *>();
4564+
4565+
// Only calls to members of types can have level > 0.
4566+
auto calleeDecl = callee.getDecl();
4567+
if (calleeDecl->getDeclContext()->isTypeContext()) {
4568+
// Level 1 if we're not applying "self".
4569+
if (auto call = dyn_cast<CallExpr>(apply)) {
4570+
if (!calleeDecl->isInstanceMember() ||
4571+
!isReferenceToMetatypeMember(call->getDirectCallee()))
4572+
level = 1;
4573+
} else if (isa<PrefixUnaryExpr>(apply) ||
4574+
isa<PostfixUnaryExpr>(apply) ||
4575+
isa<BinaryExpr>(apply)) {
4576+
level = 1;
4577+
}
4578+
}
4579+
}
4580+
45334581
// Determine the parameter bindings.
4534-
auto params = decomposeArgParamType(paramType);
4535-
auto args = decomposeArgParamType(arg->getType());
4582+
auto params = decomposeParamType(paramType, callee.getDecl(), level);
4583+
auto args = decomposeArgType(arg->getType());
45364584

45374585
// Quickly test if any further fix-ups for the argument types are necessary.
45384586
// FIXME: This hack is only necessary to work around some problems we have
@@ -4614,8 +4662,6 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, Type paramType,
46144662
SmallVector<Expr*, 4> fromTupleExpr(argTuple? argTuple->getNumElements() : 1);
46154663
SmallVector<unsigned, 4> variadicArgs;
46164664
SmallVector<Expr *, 2> callerDefaultArgs;
4617-
ConcreteDeclRef defaultArgsOwner =
4618-
findDefaultArgsOwner(cs, solution, cs.getConstraintLocator(locator));
46194665
Type sliceType = nullptr;
46204666
SmallVector<int, 4> sources;
46214667
for (unsigned paramIdx = 0, numParams = parameterBindings.size();
@@ -4673,8 +4719,7 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, Type paramType,
46734719
Expr *defArg;
46744720
DefaultArgumentKind defArgKind;
46754721
std::tie(defArg, defArgKind) = getCallerDefaultArg(tc, dc, arg->getLoc(),
4676-
defaultArgsOwner,
4677-
paramIdx);
4722+
callee, paramIdx);
46784723

46794724
// Note that we'll be doing a shuffle involving default arguments.
46804725
anythingShuffled = true;
@@ -4793,7 +4838,7 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, Type paramType,
47934838
auto shuffle = new (tc.Context) TupleShuffleExpr(
47944839
arg, mapping,
47954840
isSourceScalar,
4796-
defaultArgsOwner,
4841+
callee,
47974842
tc.Context.AllocateCopy(variadicArgs),
47984843
callerDefaultArgsCopy,
47994844
paramType);
@@ -5768,8 +5813,8 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
57685813
// the function.
57695814
if (auto fnType = fn->getType()->getAs<FunctionType>()) {
57705815
auto origArg = apply->getArg();
5771-
57725816
Expr *arg = coerceCallArguments(origArg, fnType->getInput(),
5817+
apply,
57735818
locator.withPathElement(
57745819
ConstraintLocator::ApplyArgument));
57755820
if (!arg) {
@@ -6547,14 +6592,23 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
65476592
if (!witness)
65486593
return nullptr;
65496594

6595+
// Form a syntactic expression that describes the reference to the
6596+
// witness.
6597+
// FIXME: Egregious hack.
6598+
Expr *unresolvedDot = new (Context) UnresolvedDotExpr(
6599+
base, SourceLoc(),
6600+
witness->getFullName(),
6601+
DeclNameLoc(base->getEndLoc()),
6602+
/*Implicit=*/true);
6603+
auto dotLocator = cs.getConstraintLocator(unresolvedDot);
6604+
65506605
// Form a reference to the witness itself.
6551-
auto locator = cs.getConstraintLocator(base);
65526606
Type openedFullType, openedType;
65536607
std::tie(openedFullType, openedType)
65546608
= cs.getTypeOfMemberReference(base->getType(), witness,
65556609
/*isTypeReference=*/false,
65566610
/*isDynamicResult=*/false,
6557-
locator);
6611+
dotLocator);
65586612

65596613
// Form the call argument.
65606614
// FIXME: Standardize all callers to always provide all argument names,
@@ -6626,7 +6680,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
66266680
base->getStartLoc(),
66276681
witness,
66286682
DeclNameLoc(base->getEndLoc()),
6629-
openedType, locator, locator,
6683+
openedType, dotLocator, dotLocator,
66306684
/*Implicit=*/true,
66316685
AccessSemantics::Ordinary,
66326686
/*isDynamic=*/false);

0 commit comments

Comments
 (0)