Skip to content

Commit 4f25c55

Browse files
authored
Merge pull request swiftlang#21317 from xedin/rdar-46497155
[CSDiag] Account for expression sanitizer mutating AST
2 parents 6594e81 + 5239edf commit 4f25c55

File tree

3 files changed

+107
-35
lines changed

3 files changed

+107
-35
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,27 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
423423
const CalleeCandidateInfo &candidates,
424424
TCCOptions options = TCCOptions());
425425

426+
void getPossibleTypesOfExpressionWithoutApplying(
427+
Expr *&expr, DeclContext *dc, SmallPtrSetImpl<TypeBase *> &types,
428+
FreeTypeVariableBinding allowFreeTypeVariables =
429+
FreeTypeVariableBinding::Disallow,
430+
ExprTypeCheckListener *listener = nullptr) {
431+
CS.TC.getPossibleTypesOfExpressionWithoutApplying(
432+
expr, dc, types, allowFreeTypeVariables, listener);
433+
CS.cacheExprTypes(expr);
434+
}
435+
436+
Type getTypeOfExpressionWithoutApplying(
437+
Expr *&expr, DeclContext *dc, ConcreteDeclRef &referencedDecl,
438+
FreeTypeVariableBinding allowFreeTypeVariables =
439+
FreeTypeVariableBinding::Disallow,
440+
ExprTypeCheckListener *listener = nullptr) {
441+
auto type = CS.TC.getTypeOfExpressionWithoutApplying(expr, dc, referencedDecl,
442+
allowFreeTypeVariables, listener);
443+
CS.cacheExprTypes(expr);
444+
return type;
445+
}
446+
426447
/// Diagnose common failures due to applications of an argument list to an
427448
/// ApplyExpr or SubscriptExpr.
428449
bool diagnoseParameterErrors(CalleeCandidateInfo &CCI,
@@ -452,6 +473,10 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
452473
Type contextualType,
453474
ContextualTypePurpose CTP);
454475

476+
bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
477+
CalleeCandidateInfo &CCI,
478+
ArrayRef<Identifier> argLabels);
479+
455480
private:
456481
/// Validate potential contextual type for type-checking one of the
457482
/// sub-expressions, usually correct/valid types are the ones which
@@ -3194,10 +3219,9 @@ decomposeArgType(Type argType, ArrayRef<Identifier> argLabels) {
31943219
return result;
31953220
}
31963221

3197-
static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
3198-
CalleeCandidateInfo &CCI,
3199-
ArrayRef<Identifier> argLabels,
3200-
ConstraintSystem &CS) {
3222+
bool FailureDiagnosis::diagnoseImplicitSelfErrors(
3223+
Expr *fnExpr, Expr *argExpr, CalleeCandidateInfo &CCI,
3224+
ArrayRef<Identifier> argLabels) {
32013225
// If candidate list is empty it means that problem is somewhere else,
32023226
// since we need to have candidates which might be shadowing other funcs.
32033227
if (CCI.empty() || !CCI[0].getDecl())
@@ -3251,8 +3275,7 @@ static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
32513275
for (unsigned i = 0, e = argTuple->getNumElements(); i < e; ++i) {
32523276
ConcreteDeclRef ref = nullptr;
32533277
auto *el = argTuple->getElement(i);
3254-
auto typeResult =
3255-
TC.getTypeOfExpressionWithoutApplying(el, CS.DC, ref);
3278+
auto typeResult = getTypeOfExpressionWithoutApplying(el, CS.DC, ref);
32563279
if (!typeResult)
32573280
return false;
32583281
auto flags = ParameterTypeFlags().withInOut(typeResult->is<InOutType>());
@@ -4226,7 +4249,7 @@ bool FailureDiagnosis::diagnoseParameterErrors(CalleeCandidateInfo &CCI,
42264249
}
42274250

42284251
// Try to diagnose errors related to the use of implicit self reference.
4229-
if (diagnoseImplicitSelfErrors(fnExpr, argExpr, CCI, argLabels, CS))
4252+
if (diagnoseImplicitSelfErrors(fnExpr, argExpr, CCI, argLabels))
42304253
return true;
42314254

42324255
if (diagnoseInstanceMethodAsCurriedMemberOnType(CCI, fnExpr, argExpr))
@@ -4368,7 +4391,7 @@ bool FailureDiagnosis::diagnoseSubscriptErrors(SubscriptExpr *SE,
43684391
ConcreteDeclRef decl = nullptr;
43694392
message = diag::cannot_subscript_with_index;
43704393

4371-
if (CS.TC.getTypeOfExpressionWithoutApplying(expr, CS.DC, decl))
4394+
if (getTypeOfExpressionWithoutApplying(expr, CS.DC, decl))
43724395
return false;
43734396

43744397
// If we are down to a single candidate but with an unresolved
@@ -4932,7 +4955,7 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
49324955
if (currentType->hasTypeVariable() || currentType->hasUnresolvedType()) {
49334956
auto contextualType = CS.getContextualType();
49344957
CallResultListener listener(contextualType);
4935-
CS.TC.getPossibleTypesOfExpressionWithoutApplying(
4958+
getPossibleTypesOfExpressionWithoutApplying(
49364959
fnExpr, CS.DC, possibleTypes, FreeTypeVariableBinding::UnresolvedType,
49374960
&listener);
49384961

@@ -5037,9 +5060,9 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
50375060
auto &TC = CS.TC;
50385061
auto *DC = CS.DC;
50395062

5040-
auto typeCheckExpr = [](TypeChecker &TC, Expr *expr, DeclContext *DC,
5041-
SmallPtrSetImpl<TypeBase *> &types) {
5042-
TC.getPossibleTypesOfExpressionWithoutApplying(
5063+
auto typeCheckExpr = [&](TypeChecker &TC, Expr *expr, DeclContext *DC,
5064+
SmallPtrSetImpl<TypeBase *> &types) {
5065+
getPossibleTypesOfExpressionWithoutApplying(
50435066
expr, DC, types, FreeTypeVariableBinding::Disallow);
50445067
};
50455068

@@ -5165,14 +5188,14 @@ bool FailureDiagnosis::diagnoseSubscriptMisuse(ApplyExpr *callExpr) {
51655188
// unresolved result let's not re-typecheck the function expression,
51665189
// because it might produce unrelated diagnostics due to lack of
51675190
// contextual information.
5168-
static bool shouldTypeCheckFunctionExpr(TypeChecker &TC, DeclContext *DC,
5191+
static bool shouldTypeCheckFunctionExpr(FailureDiagnosis &FD, DeclContext *DC,
51695192
Expr *fnExpr) {
51705193
if (!isa<UnresolvedDotExpr>(fnExpr))
51715194
return true;
51725195

51735196
SmallPtrSet<TypeBase *, 4> fnTypes;
5174-
TC.getPossibleTypesOfExpressionWithoutApplying(fnExpr, DC, fnTypes,
5175-
FreeTypeVariableBinding::UnresolvedType);
5197+
FD.getPossibleTypesOfExpressionWithoutApplying(
5198+
fnExpr, DC, fnTypes, FreeTypeVariableBinding::UnresolvedType);
51765199

51775200
if (fnTypes.size() == 1) {
51785201
// Some member types depend on the arguments to produce a result type,
@@ -5232,7 +5255,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
52325255
auto *fnExpr = callExpr->getFn();
52335256
auto originalFnType = CS.getType(callExpr->getFn());
52345257

5235-
if (shouldTypeCheckFunctionExpr(CS.TC, CS.DC, fnExpr)) {
5258+
if (shouldTypeCheckFunctionExpr(*this, CS.DC, fnExpr)) {
52365259

52375260
// If we are misusing a subscript, diagnose that and provide a fixit.
52385261
// We diagnose this here to have enough context to offer an appropriate fixit.
@@ -5269,7 +5292,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
52695292
fnExpr = callExpr->getFn();
52705293

52715294
SmallPtrSet<TypeBase *, 4> types;
5272-
CS.TC.getPossibleTypesOfExpressionWithoutApplying(fnExpr, CS.DC, types);
5295+
getPossibleTypesOfExpressionWithoutApplying(fnExpr, CS.DC, types);
52735296

52745297
auto isFunctionType = [getFuncType](Type type) -> bool {
52755298
return type && getFuncType(type)->is<AnyFunctionType>();
@@ -5309,7 +5332,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
53095332
"unexpected declaration reference");
53105333

53115334
ConcreteDeclRef decl = nullptr;
5312-
Type type = CS.TC.getTypeOfExpressionWithoutApplying(
5335+
Type type = getTypeOfExpressionWithoutApplying(
53135336
fnExpr, CS.DC, decl, FreeTypeVariableBinding::UnresolvedType,
53145337
&listener);
53155338

@@ -5893,7 +5916,7 @@ bool FailureDiagnosis::visitAssignExpr(AssignExpr *assignExpr) {
58935916
ExprTypeSaverAndEraser eraser(srcExpr);
58945917

58955918
ConcreteDeclRef ref = nullptr;
5896-
auto type = CS.TC.getTypeOfExpressionWithoutApplying(srcExpr, CS.DC, ref);
5919+
auto type = getTypeOfExpressionWithoutApplying(srcExpr, CS.DC, ref);
58975920

58985921
if (type && !type->isEqual(contextualType))
58995922
return diagnoseContextualConversionError(
@@ -6391,7 +6414,7 @@ bool FailureDiagnosis::diagnoseClosureExpr(
63916414
// diagnose situations where contextual type expected one result
63926415
// type but actual closure produces a different one without explicitly
63936416
// declaring it (e.g. by using anonymous parameters).
6394-
auto type = CS.TC.getTypeOfExpressionWithoutApplying(
6417+
auto type = getTypeOfExpressionWithoutApplying(
63956418
closure, CS.DC, decl, FreeTypeVariableBinding::Disallow);
63966419

63976420
if (type && resultTypeProcessor(type, expectedResultType))
@@ -6900,7 +6923,7 @@ bool FailureDiagnosis::visitKeyPathExpr(KeyPathExpr *KPE) {
69006923
KeyPathListener listener(klass, parentType, rootType);
69016924
ConcreteDeclRef concreteDecl;
69026925

6903-
auto derivedType = CS.TC.getTypeOfExpressionWithoutApplying(
6926+
auto derivedType = getTypeOfExpressionWithoutApplying(
69046927
expr, CS.DC, concreteDecl, FreeTypeVariableBinding::Disallow,
69056928
&listener);
69066929

@@ -8043,7 +8066,7 @@ diagnoseAmbiguousMultiStatementClosure(ClosureExpr *closure) {
80438066
// successfully type-checked its type cleanup is going to be disabled
80448067
// (we are allowing unresolved types), and as a side-effect it might
80458068
// also be transformed e.g. OverloadedDeclRefExpr -> DeclRefExpr.
8046-
auto type = CS.TC.getTypeOfExpressionWithoutApplying(
8069+
auto type = getTypeOfExpressionWithoutApplying(
80478070
resultExpr, CS.DC, decl, FreeTypeVariableBinding::UnresolvedType);
80488071
if (type)
80498072
resultType = type;

lib/Sema/CSGen.cpp

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3366,6 +3366,20 @@ namespace {
33663366
assert(!isa<ImplicitConversionExpr>(expr) &&
33673367
"ImplicitConversionExpr should be eliminated in walkToExprPre");
33683368

3369+
auto buildMemberRef = [&](Type memberType, Expr *base, SourceLoc dotLoc,
3370+
ConcreteDeclRef member, DeclNameLoc memberLoc,
3371+
bool implicit) -> Expr * {
3372+
auto *memberRef = new (TC.Context)
3373+
MemberRefExpr(base, dotLoc, member, memberLoc, implicit);
3374+
3375+
if (memberType) {
3376+
memberRef->setType(memberType);
3377+
return CS.cacheType(memberRef);
3378+
}
3379+
3380+
return memberRef;
3381+
};
3382+
33693383
// A DotSyntaxCallExpr is a member reference that has already been
33703384
// type-checked down to a call; turn it back into an overloaded
33713385
// member reference expression.
@@ -3375,21 +3389,23 @@ namespace {
33753389
memberLoc);
33763390
if (memberAndFunctionRef.first) {
33773391
assert(!isa<ImplicitConversionExpr>(dotCall->getBase()));
3378-
return new (TC.Context) MemberRefExpr(dotCall->getBase(),
3379-
dotCall->getDotLoc(),
3380-
memberAndFunctionRef.first,
3381-
memberLoc, expr->isImplicit());
3392+
return buildMemberRef(dotCall->getType(),
3393+
dotCall->getBase(),
3394+
dotCall->getDotLoc(),
3395+
memberAndFunctionRef.first,
3396+
memberLoc, expr->isImplicit());
33823397
}
33833398
}
33843399

33853400
if (auto *dynamicMember = dyn_cast<DynamicMemberRefExpr>(expr)) {
33863401
if (auto memberRef = dynamicMember->getMember()) {
33873402
assert(!isa<ImplicitConversionExpr>(dynamicMember->getBase()));
3388-
return new (TC.Context) MemberRefExpr(dynamicMember->getBase(),
3389-
dynamicMember->getDotLoc(),
3390-
memberRef,
3391-
dynamicMember->getNameLoc(),
3392-
expr->isImplicit());
3403+
return buildMemberRef(dynamicMember->getType(),
3404+
dynamicMember->getBase(),
3405+
dynamicMember->getDotLoc(),
3406+
memberRef,
3407+
dynamicMember->getNameLoc(),
3408+
expr->isImplicit());
33933409
}
33943410
}
33953411

@@ -3403,10 +3419,11 @@ namespace {
34033419
memberLoc);
34043420
if (memberAndFunctionRef.first) {
34053421
assert(!isa<ImplicitConversionExpr>(dotIgnored->getLHS()));
3406-
return new (TC.Context) MemberRefExpr(dotIgnored->getLHS(),
3407-
dotIgnored->getDotLoc(),
3408-
memberAndFunctionRef.first,
3409-
memberLoc, expr->isImplicit());
3422+
return buildMemberRef(dotIgnored->getType(),
3423+
dotIgnored->getLHS(),
3424+
dotIgnored->getDotLoc(),
3425+
memberAndFunctionRef.first,
3426+
memberLoc, expr->isImplicit());
34103427
}
34113428
}
34123429
return expr;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P {
4+
func isEqual(_ other: P) -> Bool
5+
}
6+
7+
struct A {
8+
var value: P? = nil
9+
}
10+
11+
struct B {
12+
func foo() throws -> A {}
13+
}
14+
15+
struct E {
16+
func getB(_ flag: inout Bool) throws -> B {
17+
return B()
18+
}
19+
}
20+
21+
func foo(arr: [E], other: P) -> Bool {
22+
return arr.compactMap { i in
23+
// expected-error@-1 {{unable to infer complex closure return type; add explicit type to disambiguate}} {{29-29=-> B? }}
24+
var flag = false
25+
return try? i.getB(&flag)
26+
}.compactMap { u -> P? in
27+
guard let a = try? u.foo() else { return nil }
28+
return a.value!
29+
}.contains {
30+
$0.isEqual(other)
31+
}
32+
}

0 commit comments

Comments
 (0)