Skip to content

Commit 4a60b6c

Browse files
committed
[Type checker] Don't fold the parentheses around call arguments into a TypeExpr.
TypeExpr formation from expressions is eager, and was pulling in the parentheses used to form a call argument, e.g., strideof(Int) would end up being a CallExpr whose argument was a TypeExpr containing the type "(Int)". This had the side effect of not requiring ".self" where it should (as reported in SR-899), e.g., the correct code for the above would be: strideof(Int.self) Don't pull the parentheses of a call argument into the TypeExpr, so we get a more sane AST. This would fix SR-899, but because SE-0090 is in limbo right now, we don't actually want to require the initial code to be considered well-formed right now. Therefore, put a hack into the checking for ".self" that ignores this specific case.
1 parent 73202fc commit 4a60b6c

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
102102
/// Keep track of InOutExprs
103103
SmallPtrSet<InOutExpr*, 2> AcceptableInOutExprs;
104104

105+
/// Keep track of the arguments to CallExprs.
106+
SmallPtrSet<Expr *, 2> CallArgs;
107+
105108
bool IsExprStmt;
106109

107110
public:
@@ -224,6 +227,11 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
224227
while (auto Conv = dyn_cast<ImplicitConversionExpr>(Base))
225228
Base = Conv->getSubExpr();
226229

230+
// Record call arguments.
231+
if (auto Call = dyn_cast<CallExpr>(Base)) {
232+
CallArgs.insert(Call->getArg());
233+
}
234+
227235
if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
228236
// Verify metatype uses.
229237
if (isa<TypeDecl>(DRE->getDecl())) {
@@ -485,6 +493,14 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
485493
isa<OpenExistentialExpr>(ParentExpr)) {
486494
return;
487495
}
496+
497+
// FIXME: As a specific hack, we white-list parenthesized
498+
// expressions that are call arguments. This allows some
499+
// ill-formed code to omit ".self" due to a historical bug. We
500+
// keep that code working until we have a decision on SE-0090,
501+
// rather than potentially breaking code twice.
502+
if (isa<ParenExpr>(ParentExpr) && CallArgs.count(ParentExpr) > 0)
503+
return;
488504
}
489505

490506
// Is this a protocol metatype?

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,12 +638,27 @@ namespace {
638638
/// node when visited.
639639
Expr *UnresolvedCtorRebindTarget = nullptr;
640640

641+
/// The expressions that are direct arguments of call expressions.
642+
llvm::SmallPtrSet<Expr *, 4> CallArgs;
643+
641644
public:
642645
PreCheckExpression(TypeChecker &tc, DeclContext *dc) : TC(tc), DC(dc) { }
643646

644647
bool walkToClosureExprPre(ClosureExpr *expr);
645648

646649
std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
650+
// If this is a call, record the argument expression.
651+
if (auto call = dyn_cast<CallExpr>(expr)) {
652+
CallArgs.insert(call->getArg());
653+
}
654+
655+
// If this is an unresolved member with a call argument (e.g.,
656+
// .some(x)), record the argument expression.
657+
if (auto unresolvedMember = dyn_cast<UnresolvedMemberExpr>(expr)) {
658+
if (auto arg = unresolvedMember->getArgument())
659+
CallArgs.insert(arg);
660+
}
661+
647662
// Local function used to finish up processing before returning. Every
648663
// return site should call through here.
649664
auto finish = [&](bool recursive, Expr *expr) {
@@ -875,6 +890,9 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) {
875890
/// as expressions due to the parser not knowing which identifiers are
876891
/// type names.
877892
TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
893+
// Don't try simplifying a call argument, because we don't want to
894+
// simplify away the required ParenExpr/TupleExpr.
895+
if (CallArgs.count(E) > 0) return nullptr;
878896

879897
// Fold 'T.Type' or 'T.Protocol' into a metatype when T is a TypeExpr.
880898
if (auto *MRE = dyn_cast<UnresolvedDotExpr>(E)) {

0 commit comments

Comments
 (0)