Skip to content

Commit 314093f

Browse files
committed
SILGen: add RValue emission for BorrowExpr
1 parent e39a31a commit 314093f

File tree

6 files changed

+54
-6
lines changed

6 files changed

+54
-6
lines changed

lib/AST/ASTVerifier.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,24 @@ class Verifier : public ASTWalker {
25082508
verifyCheckedBase(E);
25092509
}
25102510

2511+
void verifyChecked(BorrowExpr *E) {
2512+
PrettyStackTraceExpr debugStack(Ctx, "verifying BorrowExpr", E);
2513+
2514+
auto toType = E->getType();
2515+
auto fromType = E->getSubExpr()->getType();
2516+
2517+
// FIXME: doesStorageProduceLValue should not return false for a 'let',
2518+
// so that you can borrow from it.
2519+
if (!fromType->hasLValueType())
2520+
error("borrow source must be an l-value", E);
2521+
2522+
// Result type can be either l-value or r-value.
2523+
// Ensure underlying type matches.
2524+
if (fromType->getRValueType()->getCanonicalType() !=
2525+
toType->getRValueType()->getCanonicalType())
2526+
error("borrow should not be performing a cast", E);
2527+
}
2528+
25112529
void verifyChecked(ABISafeConversionExpr *E) {
25122530
PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E);
25132531

lib/SILGen/SILGenExpr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ namespace {
468468

469469
RValue visitStringLiteralExpr(StringLiteralExpr *E, SGFContext C);
470470
RValue visitLoadExpr(LoadExpr *E, SGFContext C);
471+
RValue visitBorrowExpr(BorrowExpr *E, SGFContext C);
471472
RValue visitDerivedToBaseExpr(DerivedToBaseExpr *E, SGFContext C);
472473
RValue visitMetatypeConversionExpr(MetatypeConversionExpr *E,
473474
SGFContext C);
@@ -1103,6 +1104,24 @@ RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
11031104
C.withFollowingSideEffects());
11041105
}
11051106

1107+
RValue RValueEmitter::visitBorrowExpr(BorrowExpr *E, SGFContext C_Ignored) {
1108+
// NOTE: You should NOT add an evaluation scope here!
1109+
//
1110+
// The callers of this visitor should have established a scope already that
1111+
// encompasses the use of the borrowed RValue that we return.
1112+
ASSERT(SGF.isInFormalEvaluationScope() && "emit borrow_expr without scope?");
1113+
1114+
auto accessKind =
1115+
SGF.getTypeLowering(E->getType()).isAddress()
1116+
? SGFAccessKind::BorrowedAddressRead
1117+
: SGFAccessKind::BorrowedObjectRead;
1118+
1119+
LValue lv = SGF.emitLValue(E->getSubExpr(), accessKind);
1120+
auto substFormalType = lv.getSubstFormalType();
1121+
ManagedValue mv = SGF.emitBorrowedLValue(E, std::move(lv));
1122+
return RValue(SGF, E, substFormalType, mv);
1123+
}
1124+
11061125
SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc, SILType ty,
11071126
HasDynamicLifetime_t dynamic,
11081127
IsLexical_t isLexical,

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,16 @@ bool TypeChecker::checkedCastMaySucceed(Type t1, Type t2, DeclContext *dc) {
11311131
return (kind != CheckedCastKind::Unresolved);
11321132
}
11331133

1134+
Expr *
1135+
TypeChecker::addImplicitBorrowExpr(ASTContext &Ctx, Expr *E,
1136+
std::function<Type(Expr *)> getType,
1137+
std::function<void(Expr *, Type)> setType) {
1138+
auto objectType = getType(E)->getRValueType();
1139+
auto *BE = BorrowExpr::createImplicit(Ctx, E->getLoc(), E, objectType);
1140+
setType(BE, objectType);
1141+
return BE;
1142+
}
1143+
11341144
Expr *
11351145
TypeChecker::addImplicitLoadExpr(ASTContext &Context, Expr *expr,
11361146
std::function<Type(Expr *)> getType,

lib/Sema/TypeChecker.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,12 @@ Expr *addImplicitLoadExpr(
882882
std::function<void(Expr *, Type)> setType =
883883
[](Expr *E, Type type) { E->setType(type); });
884884

885+
Expr *addImplicitBorrowExpr(
886+
ASTContext &Context, Expr *expr,
887+
std::function<Type(Expr *)> getType = [](Expr *E) { return E->getType(); },
888+
std::function<void(Expr *, Type)> setType =
889+
[](Expr *E, Type type) { E->setType(type); });
890+
885891
/// Determine whether the given type either conforms to, or itself an
886892
/// existential subtype of, the given protocol.
887893
///

test/ASTGen/exprs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func asyncFunc(_ arg: String) async throws -> Int {
8383
return 1
8484
}
8585
func testUnaryExprs() async throws {
86-
let str = String()
86+
var str = String()
8787
let foo = try await asyncFunc(_borrow str)
8888
let bar = copy foo
8989
let baz = consume foo

test/Parse/borrow_expr.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ func testGlobal() {
55
let _ = _borrow global
66
}
77

8-
func testLet() {
9-
let t = String()
10-
let _ = _borrow t
11-
}
12-
138
func testVar() {
149
var t = String()
1510
t = String()

0 commit comments

Comments
 (0)