Skip to content

Commit 94aeacc

Browse files
authored
Merge pull request #10288 from DougGregor/coerce-to-rvalue
[4.0] Fold ConstraintSolver::coerceToRValue() into TypeChecker::coerceToRValue()
2 parents a3ab1ac + 0d29d3e commit 94aeacc

File tree

4 files changed

+67
-42
lines changed

4 files changed

+67
-42
lines changed

lib/Sema/CSApply.cpp

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7411,32 +7411,15 @@ namespace {
74117411
} // end anonymous namespace
74127412

74137413
Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
7414-
// Can't load from an inout value.
7415-
if (auto *iot = getType(expr)->getAs<InOutType>()) {
7416-
// Emit a fixit if we can find the & expression that turned this into an
7417-
// inout.
7418-
auto &tc = getTypeChecker();
7419-
if (auto addrOf =
7420-
dyn_cast<InOutExpr>(expr->getSemanticsProvidingExpr())) {
7421-
tc.diagnose(expr->getLoc(), diag::load_of_explicit_lvalue,
7422-
iot->getObjectType())
7423-
.fixItRemove(SourceRange(addrOf->getLoc()));
7424-
return coerceToRValue(addrOf->getSubExpr());
7425-
} else {
7426-
tc.diagnose(expr->getLoc(), diag::load_of_explicit_lvalue,
7427-
iot->getObjectType());
7428-
return expr;
7429-
}
7430-
}
7431-
7432-
// If we already have an rvalue, we're done, otherwise emit a load.
7433-
if (auto lvalueTy = getType(expr)->getAs<LValueType>()) {
7434-
propagateLValueAccessKind(expr, AccessKind::Read);
7435-
return cacheType(new (getASTContext())
7436-
LoadExpr(expr, lvalueTy->getObjectType()));
7437-
}
7438-
7439-
return expr;
7414+
auto &tc = getTypeChecker();
7415+
return tc.coerceToMaterializable(expr,
7416+
[&](Expr *expr) {
7417+
return getType(expr);
7418+
},
7419+
[&](Expr *expr, Type type) {
7420+
expr->setType(type);
7421+
cacheType(expr);
7422+
});
74407423
}
74417424

74427425
/// Emit the fixes computed as part of the solution, returning true if we were

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2854,47 +2854,64 @@ bool TypeChecker::isSubstitutableFor(Type type, ArchetypeType *archetype,
28542854
return true;
28552855
}
28562856

2857-
Expr *TypeChecker::coerceToMaterializable(Expr *expr) {
2857+
Expr *TypeChecker::coerceToMaterializable(Expr *expr,
2858+
llvm::function_ref<Type(Expr *)> getType,
2859+
llvm::function_ref<void(Expr *, Type)> setType) {
2860+
Type exprTy = getType(expr);
2861+
28582862
// If expr has no type, just assume it's the right expr.
2863+
if (!exprTy)
2864+
return expr;
2865+
28592866
// If the type is already materializable, then we're already done.
2860-
if (!expr->getType() || expr->getType()->isMaterializable())
2867+
if (exprTy->isMaterializable())
28612868
return expr;
28622869

28632870
// Load lvalues.
2864-
if (auto lvalue = expr->getType()->getAs<LValueType>()) {
2871+
if (auto lvalue = exprTy->getAs<LValueType>()) {
28652872
expr->propagateLValueAccessKind(AccessKind::Read);
2866-
return new (Context) LoadExpr(expr, lvalue->getObjectType());
2873+
auto result = new (Context) LoadExpr(expr, lvalue->getObjectType());
2874+
setType(result, lvalue->getObjectType());
2875+
return result;
28672876
}
28682877

28692878
// Walk into parenthesized expressions to update the subexpression.
28702879
if (auto paren = dyn_cast<IdentityExpr>(expr)) {
2871-
auto sub = coerceToMaterializable(paren->getSubExpr());
2880+
auto sub = coerceToMaterializable(paren->getSubExpr(), getType, setType);
28722881
paren->setSubExpr(sub);
2873-
paren->setType(sub->getType());
2882+
setType(paren, getType(sub));
28742883
return paren;
28752884
}
28762885

28772886
// Walk into 'try' and 'try!' expressions to update the subexpression.
28782887
if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
2879-
auto sub = coerceToMaterializable(tryExpr->getSubExpr());
2888+
auto sub = coerceToMaterializable(tryExpr->getSubExpr(), getType, setType);
28802889
tryExpr->setSubExpr(sub);
2881-
if (isa<OptionalTryExpr>(tryExpr) && !sub->getType()->hasError())
2882-
tryExpr->setType(OptionalType::get(sub->getType()));
2890+
if (isa<OptionalTryExpr>(tryExpr) && !getType(sub)->hasError())
2891+
setType(tryExpr, OptionalType::get(getType(sub)));
28832892
else
2884-
tryExpr->setType(sub->getType());
2893+
setType(tryExpr, getType(sub));
28852894
return tryExpr;
28862895
}
28872896

2897+
// Can't load from an inout value.
2898+
if (auto inoutExpr = dyn_cast<InOutExpr>(expr)) {
2899+
diagnose(expr->getLoc(), diag::load_of_explicit_lvalue,
2900+
exprTy->castTo<InOutType>()->getObjectType())
2901+
.fixItRemove(SourceRange(inoutExpr->getLoc()));
2902+
return coerceToMaterializable(inoutExpr->getSubExpr(), getType, setType);
2903+
}
2904+
28882905
// Walk into tuples to update the subexpressions.
28892906
if (auto tuple = dyn_cast<TupleExpr>(expr)) {
28902907
bool anyChanged = false;
28912908
for (auto &elt : tuple->getElements()) {
28922909
// Materialize the element.
2893-
auto oldType = elt->getType();
2894-
elt = coerceToMaterializable(elt);
2910+
auto oldType = getType(elt);
2911+
elt = coerceToMaterializable(elt, getType, setType);
28952912

28962913
// If the type changed at all, make a note of it.
2897-
if (elt->getType().getPointer() != oldType.getPointer()) {
2914+
if (getType(elt).getPointer() != oldType.getPointer()) {
28982915
anyChanged = true;
28992916
}
29002917
}
@@ -2904,11 +2921,11 @@ Expr *TypeChecker::coerceToMaterializable(Expr *expr) {
29042921
SmallVector<TupleTypeElt, 4> elements;
29052922
elements.reserve(tuple->getElements().size());
29062923
for (unsigned i = 0, n = tuple->getNumElements(); i != n; ++i) {
2907-
Type type = tuple->getElement(i)->getType();
2924+
Type type = getType(tuple->getElement(i));
29082925
Identifier name = tuple->getElementName(i);
29092926
elements.push_back(TupleTypeElt(type, name));
29102927
}
2911-
tuple->setType(TupleType::get(elements, Context));
2928+
setType(tuple, TupleType::get(elements, Context));
29122929
}
29132930

29142931
return tuple;

lib/Sema/TypeChecker.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1747,7 +1747,13 @@ class TypeChecker final : public LazyResolver {
17471747

17481748
/// \brief Coerce the given expression to materializable type, if it
17491749
/// isn't already.
1750-
Expr *coerceToMaterializable(Expr *expr);
1750+
Expr *coerceToMaterializable(Expr *expr,
1751+
llvm::function_ref<Type(Expr *)> getType
1752+
= [](Expr *expr) { return expr->getType(); },
1753+
llvm::function_ref<void(Expr *, Type)> setType
1754+
= [](Expr *expr, Type type) {
1755+
expr->setType(type);
1756+
});
17511757

17521758
/// Require that the library intrinsics for working with Optional<T>
17531759
/// exist.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend %s -emit-ir
2+
// REQUIRES: objc_interop
3+
4+
func f(_: AnyObject?) { }
5+
6+
class C {
7+
private var a: Int
8+
private var b: Int
9+
10+
func test() {
11+
f((self.a, self.b) as AnyObject)
12+
}
13+
14+
init() {
15+
a = 0
16+
b = 0
17+
}
18+
}
19+

0 commit comments

Comments
 (0)