Skip to content

Commit 6ce4eb2

Browse files
committed
[Type checker] Use DotSyntaxCallExpr consistently for instance members.
When building a curry thunk for unapplied references to instance methods, the type checker would build a CallExpr rather than a DotSyntaxCallExpr to work around various issues with source locations. Fix the underlying issues with source locations in DotSyntaxCallExpr so we can consistently build DotSyntaxCallExpr here, and assert that we don't do this again: * DotSyntaxCallExpr wasn't able to reason about having just one of its children having source location information; fix it. * @dynamicCallable support was passing the declaration source location for the call expression, which was nowhere in the expression itself. The above mistake was covering for this one.
1 parent 2762405 commit 6ce4eb2

File tree

3 files changed

+60
-36
lines changed

3 files changed

+60
-36
lines changed

include/swift/AST/Expr.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4574,16 +4574,10 @@ class DotSyntaxCallExpr : public SelfApplyExpr {
45744574

45754575
SourceLoc getDotLoc() const { return DotLoc; }
45764576

4577-
SourceLoc getLoc() const {
4578-
return isImplicit() ? getBase()->getStartLoc() : getFn()->getLoc();
4579-
}
4580-
SourceLoc getStartLoc() const {
4581-
return getBase()->getStartLoc();
4582-
}
4583-
SourceLoc getEndLoc() const {
4584-
return isImplicit() ? getBase()->getEndLoc() : getFn()->getEndLoc();
4585-
}
4586-
4577+
SourceLoc getLoc() const;
4578+
SourceLoc getStartLoc() const;
4579+
SourceLoc getEndLoc() const;
4580+
45874581
static bool classof(const Expr *E) {
45884582
return E->getKind() == ExprKind::DotSyntaxCall;
45894583
}

lib/AST/Expr.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,12 @@ CallExpr::CallExpr(Expr *fn, Expr *arg, bool Implicit,
16561656
Bits.CallExpr.HasArgLabelLocs = !argLabelLocs.empty();
16571657
Bits.CallExpr.HasTrailingClosure = hasTrailingClosure;
16581658
initializeCallArguments(argLabels, argLabelLocs);
1659+
1660+
#ifndef NDEBUG
1661+
Expr *calleeFn = fn->getSemanticsProvidingExpr();
1662+
if (auto *calleeDRE = dyn_cast<DeclRefExpr>(calleeFn))
1663+
assert(!calleeDRE->getDecl()->isInstanceMember());
1664+
#endif
16591665
}
16601666

16611667
CallExpr *CallExpr::create(ASTContext &ctx, Expr *fn, Expr *arg,
@@ -1729,6 +1735,33 @@ Expr *CallExpr::getDirectCallee() const {
17291735
}
17301736
}
17311737

1738+
SourceLoc DotSyntaxCallExpr::getLoc() const {
1739+
if (isImplicit()) {
1740+
SourceLoc baseLoc = getBase()->getLoc();
1741+
return baseLoc.isValid() ? baseLoc : getFn()->getLoc();
1742+
}
1743+
1744+
return getFn()->getLoc();
1745+
}
1746+
1747+
SourceLoc DotSyntaxCallExpr::getStartLoc() const {
1748+
if (isImplicit()) {
1749+
SourceLoc baseLoc = getBase()->getStartLoc();
1750+
return baseLoc.isValid() ? baseLoc : getFn()->getStartLoc();
1751+
}
1752+
1753+
return getBase()->getStartLoc();
1754+
}
1755+
1756+
SourceLoc DotSyntaxCallExpr::getEndLoc() const {
1757+
if (isImplicit()) {
1758+
SourceLoc fnLoc = getFn()->getEndLoc();
1759+
return fnLoc.isValid() ? fnLoc : getBase()->getEndLoc();
1760+
}
1761+
1762+
return getFn()->getEndLoc();
1763+
}
1764+
17321765
void ExplicitCastExpr::setCastType(Type type) {
17331766
CastTy->setType(MetatypeType::get(type));
17341767
}

lib/Sema/CSApply.cpp

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,24 @@ namespace {
916916

917917
Expr *selfOpenedRef = selfParamRef;
918918

919+
// If the 'self' parameter has non-trivial ownership, adjust the
920+
// argument accordingly.
921+
switch (selfParam.getValueOwnership()) {
922+
case ValueOwnership::Default:
923+
case ValueOwnership::InOut:
924+
break;
925+
926+
case ValueOwnership::Owned:
927+
case ValueOwnership::Shared:
928+
// Ensure that the argument type matches up exactly.
929+
auto selfArgTy = ParenType::get(context,
930+
selfParam.getPlainType(),
931+
selfParam.getParameterFlags());
932+
selfOpenedRef->setType(selfArgTy);
933+
cs.cacheType(selfOpenedRef);
934+
break;
935+
}
936+
919937
if (selfParamTy->hasOpenedExistential()) {
920938
// If we're opening an existential:
921939
// - the type of 'ref' inside the closure is written in terms of the
@@ -931,31 +949,10 @@ namespace {
931949
}
932950

933951
// (Self) -> ...
934-
ApplyExpr *selfCall;
935-
936-
// We build either a CallExpr or a DotSyntaxCallExpr depending on whether
937-
// the base is implicit or not. This helps maintain some invariants around
938-
// source ranges.
939-
if (selfParamRef->isImplicit()) {
940-
selfCall =
941-
CallExpr::createImplicit(context, ref, selfOpenedRef, {},
942-
[&](Expr *E) { return cs.getType(E); });
943-
selfCall->setType(refTy->getResult());
944-
cs.cacheType(selfCall);
945-
946-
// FIXME: This is a holdover from the old tuple-based function call
947-
// representation.
948-
auto selfArgTy = ParenType::get(context,
949-
selfParam.getPlainType(),
950-
selfParam.getParameterFlags());
951-
selfCall->getArg()->setType(selfArgTy);
952-
cs.cacheType(selfCall->getArg());
953-
} else {
954-
selfCall = new (context) DotSyntaxCallExpr(ref, SourceLoc(), selfOpenedRef);
955-
selfCall->setImplicit(false);
956-
selfCall->setType(refTy->getResult());
957-
cs.cacheType(selfCall);
958-
}
952+
ApplyExpr *selfCall = new (context) DotSyntaxCallExpr(
953+
ref, SourceLoc(), selfOpenedRef);
954+
selfCall->setType(refTy->getResult());
955+
cs.cacheType(selfCall);
959956

960957
if (selfParamRef->isSuperExpr())
961958
selfCall->setIsSuper(true);
@@ -7132,7 +7129,7 @@ ExprRewriter::buildDynamicCallable(ApplyExpr *apply, SelectedOverload selected,
71327129

71337130
// Construct expression referencing the `dynamicallyCall` method.
71347131
auto member = buildMemberRef(fn, SourceLoc(), selected,
7135-
DeclNameLoc(method->getNameLoc()), loc, loc,
7132+
DeclNameLoc(), loc, loc,
71367133
/*implicit=*/true, AccessSemantics::Ordinary);
71377134

71387135
// Construct argument to the method (either an array or dictionary

0 commit comments

Comments
 (0)