Skip to content

Commit cdf6cb3

Browse files
committed
[CSApply] Don't try to force propagate l-value access in "shallow" mode
Some of the expressions call into `typeCheckExpressionShallow` while trying to apply solutions, we need to respect the fact that sub-expressions might be already properly type-checked while propagating l-value access kind. Resolves: rdar://problem/38309176
1 parent 7730dd3 commit cdf6cb3

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

lib/Sema/CSApply.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,15 @@ getImplicitMemberReferenceAccessSemantics(Expr *base, VarDecl *member,
251251
return member->getAccessSemanticsFromContext(DC);
252252
}
253253

254-
void ConstraintSystem::propagateLValueAccessKind(Expr *E,
255-
AccessKind accessKind,
254+
void ConstraintSystem::propagateLValueAccessKind(Expr *E, AccessKind accessKind,
255+
bool isShallow,
256256
bool allowOverwrite) {
257+
// If solver is set up in "shallow" mode we expect that some of the
258+
// sub-expressions are already type-checked which means that they
259+
// already have access kind set.
260+
if (isShallow && E->hasLValueAccessKind() && !allowOverwrite)
261+
return;
262+
257263
E->propagateLValueAccessKind(accessKind,
258264
[&](Expr *E) -> Type {
259265
return getType(E);
@@ -434,6 +440,7 @@ namespace {
434440
DeclContext *dc;
435441
const Solution &solution;
436442
bool SuppressDiagnostics;
443+
bool IsShallow;
437444

438445
/// Recognize used conformances from an imported type when we must emit
439446
/// the witness table.
@@ -885,7 +892,8 @@ namespace {
885892
// will handle this.
886893
if (record.OpaqueValue && record.OpaqueValue->hasLValueAccessKind())
887894
cs.propagateLValueAccessKind(record.ExistentialValue,
888-
record.OpaqueValue->getLValueAccessKind());
895+
record.OpaqueValue->getLValueAccessKind(),
896+
IsShallow);
889897

890898
// Form the open-existential expression.
891899
result = new (tc.Context) OpenExistentialExpr(
@@ -1846,9 +1854,9 @@ namespace {
18461854

18471855
public:
18481856
ExprRewriter(ConstraintSystem &cs, const Solution &solution,
1849-
bool suppressDiagnostics)
1850-
: cs(cs), dc(cs.DC), solution(solution),
1851-
SuppressDiagnostics(suppressDiagnostics) { }
1857+
bool suppressDiagnostics, bool shallow = false)
1858+
: cs(cs), dc(cs.DC), solution(solution),
1859+
SuppressDiagnostics(suppressDiagnostics), IsShallow(shallow) {}
18521860

18531861
ConstraintSystem &getConstraintSystem() const { return cs; }
18541862

@@ -3095,7 +3103,8 @@ namespace {
30953103
// case (when we turn the inout into an UnsafePointer) than to try to
30963104
// discover that we're in that case right now.
30973105
if (!cs.getType(expr->getSubExpr())->is<UnresolvedType>())
3098-
cs.propagateLValueAccessKind(expr->getSubExpr(), AccessKind::ReadWrite);
3106+
cs.propagateLValueAccessKind(expr->getSubExpr(), AccessKind::ReadWrite,
3107+
IsShallow);
30993108
auto objectTy = cs.getType(expr->getSubExpr())->getRValueType();
31003109

31013110
// The type is simply inout of whatever the lvalue's object type was.
@@ -3805,7 +3814,8 @@ namespace {
38053814
auto destTy = cs.computeAssignDestType(expr->getDest(), expr->getLoc());
38063815
if (!destTy)
38073816
return nullptr;
3808-
cs.propagateLValueAccessKind(expr->getDest(), AccessKind::Write);
3817+
cs.propagateLValueAccessKind(expr->getDest(), AccessKind::Write,
3818+
IsShallow);
38093819

38103820
// Convert the source to the simplified destination type.
38113821
auto locator =
@@ -4114,7 +4124,7 @@ namespace {
41144124

41154125
if (cs.getType(subExpr)->hasLValueType()) {
41164126
// Treat this like a read of the property.
4117-
cs.propagateLValueAccessKind(subExpr, AccessKind::Read);
4127+
cs.propagateLValueAccessKind(subExpr, AccessKind::Read, IsShallow);
41184128
}
41194129

41204130
// Check that we requested a property getter or setter.
@@ -6341,7 +6351,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
63416351

63426352
// Load from the lvalue. If we're loading the result of a force,
63436353
// swap the order so that we load first and force the result.
6344-
cs.propagateLValueAccessKind(expr, AccessKind::Read);
6354+
cs.propagateLValueAccessKind(expr, AccessKind::Read, IsShallow);
63456355
if (auto *forceExpr = dyn_cast<ForceValueExpr>(expr)) {
63466356
fromType = cs.getType(forceExpr->getSubExpr())->getRValueType();
63476357
auto *loadExpr = cs.cacheType(
@@ -6454,8 +6464,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
64546464
// Overwrite the l-value access kind to be read-only if we're
64556465
// converting to a non-mutable pointer type.
64566466
auto *E = cast<InOutExpr>(expr->getValueProvidingExpr())->getSubExpr();
6457-
cs.propagateLValueAccessKind(E,
6458-
AccessKind::Read, /*overwrite*/ true);
6467+
cs.propagateLValueAccessKind(E, AccessKind::Read, IsShallow,
6468+
/*overwrite*/ true);
64596469
}
64606470

64616471
tc.requirePointerArgumentIntrinsics(expr->getLoc());
@@ -6558,7 +6568,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
65586568
// In an 'inout' operator like "i += 1", the operand is converted from
65596569
// an implicit lvalue to an inout argument.
65606570
assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
6561-
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite);
6571+
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite, IsShallow);
65626572
return cs.cacheType(new (tc.Context)
65636573
InOutExpr(expr->getStartLoc(), expr,
65646574
toIO->getObjectType(),
@@ -6577,7 +6587,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
65776587

65786588
if (performLoad) {
65796589
// Load from the lvalue.
6580-
cs.propagateLValueAccessKind(expr, AccessKind::Read);
6590+
cs.propagateLValueAccessKind(expr, AccessKind::Read, IsShallow);
65816591
expr = cs.cacheType(new (tc.Context)
65826592
LoadExpr(expr, fromLValue->getObjectType()));
65836593

@@ -6834,7 +6844,7 @@ ExprRewriter::coerceObjectArgumentToType(Expr *expr,
68346844

68356845
// Use InOutExpr to convert it to an explicit inout argument for the
68366846
// receiver.
6837-
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite);
6847+
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite, IsShallow);
68386848
return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr,
68396849
toInOutTy->getInOutObjectType(),
68406850
/*isImplicit*/ true));
@@ -8007,7 +8017,7 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
80078017
Expr *ConstraintSystem::applySolutionShallow(const Solution &solution,
80088018
Expr *expr,
80098019
bool suppressDiagnostics) {
8010-
ExprRewriter rewriter(*this, solution, suppressDiagnostics);
8020+
ExprRewriter rewriter(*this, solution, suppressDiagnostics, true);
80118021
rewriter.walkToExprPre(expr);
80128022
Expr *result = rewriter.walkToExprPost(expr);
80138023
if (result)

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,8 +2031,7 @@ class ConstraintSystem {
20312031
/// Call Expr::propagateLValueAccessKind on the given expression,
20322032
/// using a custom accessor for the type on the expression that
20332033
/// reads the type from the ConstraintSystem expression type map.
2034-
void propagateLValueAccessKind(Expr *E,
2035-
AccessKind accessKind,
2034+
void propagateLValueAccessKind(Expr *E, AccessKind accessKind, bool isShallow,
20362035
bool allowOverwrite = false);
20372036

20382037
/// Call Expr::isTypeReference on the given expression, using a
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift %s
2+
3+
func foo(_ msg: Int) {}
4+
func foo(_ msg: Double) {}
5+
6+
func rdar38309176(_ errors: inout [String]) {
7+
foo("error: \(errors[0])") // expected-error {{cannot invoke 'foo' with an argument list of type '(String)'}}
8+
// expected-note@-1 {{overloads for 'foo' exist with these partially matching parameter lists: (Int), (Double)}}
9+
}

0 commit comments

Comments
 (0)