Skip to content

Commit d48881b

Browse files
authored
Merge pull request #10276 from DougGregor/coerce-to-rvalue
2 parents 4d65801 + 622e3a6 commit d48881b

File tree

6 files changed

+57
-47
lines changed

6 files changed

+57
-47
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,6 @@ NOTE(previous_precedence_group_decl,none,
733733

734734
ERROR(tuple_conversion_not_expressible,none,
735735
"cannot express tuple conversion %0 to %1", (Type, Type))
736-
ERROR(load_of_explicit_lvalue,none,
737-
"%0 variable is not being passed by reference", (Type))
738736

739737
//------------------------------------------------------------------------------
740738
// Expression Type Checking Errors

lib/Sema/CSApply.cpp

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

72877287
Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
7288-
// Can't load from an inout value.
7289-
if (auto *iot = getType(expr)->getAs<InOutType>()) {
7290-
// Emit a fixit if we can find the & expression that turned this into an
7291-
// inout.
7292-
auto &tc = getTypeChecker();
7293-
if (auto addrOf =
7294-
dyn_cast<InOutExpr>(expr->getSemanticsProvidingExpr())) {
7295-
tc.diagnose(expr->getLoc(), diag::load_of_explicit_lvalue,
7296-
iot->getObjectType())
7297-
.fixItRemove(SourceRange(addrOf->getLoc()));
7298-
return coerceToRValue(addrOf->getSubExpr());
7299-
} else {
7300-
tc.diagnose(expr->getLoc(), diag::load_of_explicit_lvalue,
7301-
iot->getObjectType());
7302-
return expr;
7303-
}
7304-
}
7305-
7306-
// If we already have an rvalue, we're done, otherwise emit a load.
7307-
if (auto lvalueTy = getType(expr)->getAs<LValueType>()) {
7308-
propagateLValueAccessKind(expr, AccessKind::Read);
7309-
return cacheType(new (getASTContext())
7310-
LoadExpr(expr, lvalueTy->getObjectType()));
7311-
}
7312-
7313-
return expr;
7288+
auto &tc = getTypeChecker();
7289+
return tc.coerceToRValue(expr,
7290+
[&](Expr *expr) {
7291+
return getType(expr);
7292+
},
7293+
[&](Expr *expr, Type type) {
7294+
expr->setType(type);
7295+
cacheType(expr);
7296+
});
73147297
}
73157298

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

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,39 +2856,43 @@ bool TypeChecker::isSubstitutableFor(Type type, ArchetypeType *archetype,
28562856
return true;
28572857
}
28582858

2859-
Expr *TypeChecker::coerceToRValue(Expr *expr) {
2859+
Expr *TypeChecker::coerceToRValue(Expr *expr,
2860+
llvm::function_ref<Type(Expr *)> getType,
2861+
llvm::function_ref<void(Expr *, Type)> setType) {
2862+
Type exprTy = getType(expr);
2863+
28602864
// If expr has no type, just assume it's the right expr.
2861-
if (!expr->getType())
2865+
if (!exprTy)
28622866
return expr;
2863-
2864-
Type exprTy = expr->getType();
2865-
2867+
28662868
// If the type is already materializable, then we're already done.
28672869
if (!exprTy->hasLValueType())
28682870
return expr;
28692871

28702872
// Load lvalues.
28712873
if (auto lvalue = exprTy->getAs<LValueType>()) {
28722874
expr->propagateLValueAccessKind(AccessKind::Read);
2873-
return new (Context) LoadExpr(expr, lvalue->getObjectType());
2875+
auto result = new (Context) LoadExpr(expr, lvalue->getObjectType());
2876+
setType(result, lvalue->getObjectType());
2877+
return result;
28742878
}
28752879

28762880
// Walk into parenthesized expressions to update the subexpression.
28772881
if (auto paren = dyn_cast<IdentityExpr>(expr)) {
2878-
auto sub = coerceToRValue(paren->getSubExpr());
2882+
auto sub = coerceToRValue(paren->getSubExpr(), getType, setType);
28792883
paren->setSubExpr(sub);
2880-
paren->setType(sub->getType());
2884+
setType(paren, getType(sub));
28812885
return paren;
28822886
}
28832887

28842888
// Walk into 'try' and 'try!' expressions to update the subexpression.
28852889
if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
2886-
auto sub = coerceToRValue(tryExpr->getSubExpr());
2890+
auto sub = coerceToRValue(tryExpr->getSubExpr(), getType, setType);
28872891
tryExpr->setSubExpr(sub);
2888-
if (isa<OptionalTryExpr>(tryExpr) && !sub->getType()->hasError())
2889-
tryExpr->setType(OptionalType::get(sub->getType()));
2892+
if (isa<OptionalTryExpr>(tryExpr) && !getType(sub)->hasError())
2893+
setType(tryExpr, OptionalType::get(getType(sub)));
28902894
else
2891-
tryExpr->setType(sub->getType());
2895+
setType(tryExpr, getType(sub));
28922896
return tryExpr;
28932897
}
28942898

@@ -2897,11 +2901,11 @@ Expr *TypeChecker::coerceToRValue(Expr *expr) {
28972901
bool anyChanged = false;
28982902
for (auto &elt : tuple->getElements()) {
28992903
// Materialize the element.
2900-
auto oldType = elt->getType();
2901-
elt = coerceToRValue(elt);
2904+
auto oldType = getType(elt);
2905+
elt = coerceToRValue(elt, getType, setType);
29022906

29032907
// If the type changed at all, make a note of it.
2904-
if (elt->getType().getPointer() != oldType.getPointer()) {
2908+
if (getType(elt).getPointer() != oldType.getPointer()) {
29052909
anyChanged = true;
29062910
}
29072911
}
@@ -2911,11 +2915,11 @@ Expr *TypeChecker::coerceToRValue(Expr *expr) {
29112915
SmallVector<TupleTypeElt, 4> elements;
29122916
elements.reserve(tuple->getElements().size());
29132917
for (unsigned i = 0, n = tuple->getNumElements(); i != n; ++i) {
2914-
Type type = tuple->getElement(i)->getType();
2918+
Type type = getType(tuple->getElement(i));
29152919
Identifier name = tuple->getElementName(i);
29162920
elements.push_back(TupleTypeElt(type, name));
29172921
}
2918-
tuple->setType(TupleType::get(elements, Context));
2922+
setType(tuple, TupleType::get(elements, Context));
29192923
}
29202924

29212925
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 *coerceToRValue(Expr *expr);
1750+
Expr *coerceToRValue(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+
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

88
// REQUIRES: asserts
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
9+
// RUN: not %target-swift-frontend %s -emit-ir
1010
&_ is Character

0 commit comments

Comments
 (0)