Skip to content

Commit 4850d54

Browse files
authored
Merge pull request #15287 from xedin/rdar-38309176
[CSApply] Don't try to force propagate l-value access in "shallow" mode
2 parents b506cba + cdf6cb3 commit 4850d54

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(
@@ -6450,8 +6460,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
64506460
// Overwrite the l-value access kind to be read-only if we're
64516461
// converting to a non-mutable pointer type.
64526462
auto *E = cast<InOutExpr>(expr->getValueProvidingExpr())->getSubExpr();
6453-
cs.propagateLValueAccessKind(E,
6454-
AccessKind::Read, /*overwrite*/ true);
6463+
cs.propagateLValueAccessKind(E, AccessKind::Read, IsShallow,
6464+
/*overwrite*/ true);
64556465
}
64566466

64576467
tc.requirePointerArgumentIntrinsics(expr->getLoc());
@@ -6554,7 +6564,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
65546564
// In an 'inout' operator like "i += 1", the operand is converted from
65556565
// an implicit lvalue to an inout argument.
65566566
assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
6557-
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite);
6567+
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite, IsShallow);
65586568
return cs.cacheType(new (tc.Context)
65596569
InOutExpr(expr->getStartLoc(), expr,
65606570
toIO->getObjectType(),
@@ -6573,7 +6583,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
65736583

65746584
if (performLoad) {
65756585
// Load from the lvalue.
6576-
cs.propagateLValueAccessKind(expr, AccessKind::Read);
6586+
cs.propagateLValueAccessKind(expr, AccessKind::Read, IsShallow);
65776587
expr = cs.cacheType(new (tc.Context)
65786588
LoadExpr(expr, fromLValue->getObjectType()));
65796589

@@ -6830,7 +6840,7 @@ ExprRewriter::coerceObjectArgumentToType(Expr *expr,
68306840

68316841
// Use InOutExpr to convert it to an explicit inout argument for the
68326842
// receiver.
6833-
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite);
6843+
cs.propagateLValueAccessKind(expr, AccessKind::ReadWrite, IsShallow);
68346844
return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr,
68356845
toInOutTy->getInOutObjectType(),
68366846
/*isImplicit*/ true));
@@ -8003,7 +8013,7 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
80038013
Expr *ConstraintSystem::applySolutionShallow(const Solution &solution,
80048014
Expr *expr,
80058015
bool suppressDiagnostics) {
8006-
ExprRewriter rewriter(*this, solution, suppressDiagnostics);
8016+
ExprRewriter rewriter(*this, solution, suppressDiagnostics, true);
80078017
rewriter.walkToExprPre(expr);
80088018
Expr *result = rewriter.walkToExprPost(expr);
80098019
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)