Skip to content

Commit 9479192

Browse files
committed
[borrow-expr] Add simple support for borrow-expr but don't wire it up to anything.
1 parent cfe49a0 commit 9479192

File tree

9 files changed

+113
-9
lines changed

9 files changed

+113
-9
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,10 @@ ERROR(expected_expr_after_try, none,
13481348
"expected expression after 'try'", ())
13491349
ERROR(expected_expr_after_await, none,
13501350
"expected expression after 'await'", ())
1351+
ERROR(expected_expr_after_move, none,
1352+
"expected expression after '_move'", ())
1353+
ERROR(expected_expr_after_borrow, none,
1354+
"expected expression after '_borrow'", ())
13511355

13521356
// Cast expressions
13531357
ERROR(expected_type_after_is,none,

include/swift/AST/Expr.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,37 @@ class MoveExpr final : public IdentityExpr {
20762076
static bool classof(const Expr *e) { return e->getKind() == ExprKind::Move; }
20772077
};
20782078

2079+
/// BorrowExpr - A 'borrow' surrounding an lvalue/accessor expression at an
2080+
/// apply site marking the lvalue/accessor as being borrowed when passed to the
2081+
/// callee.
2082+
///
2083+
/// getSemanticsProvidingExpr() looks through this because it doesn't
2084+
/// provide the value and only very specific clients care where the
2085+
/// 'borrow' was written.
2086+
class BorrowExpr final : public IdentityExpr {
2087+
SourceLoc BorrowLoc;
2088+
2089+
public:
2090+
BorrowExpr(SourceLoc borrowLoc, Expr *sub, Type type = Type(),
2091+
bool implicit = false)
2092+
: IdentityExpr(ExprKind::Borrow, sub, type, implicit),
2093+
BorrowLoc(borrowLoc) {}
2094+
2095+
static BorrowExpr *createImplicit(ASTContext &ctx, SourceLoc borrowLoc,
2096+
Expr *sub, Type type = Type()) {
2097+
return new (ctx) BorrowExpr(borrowLoc, sub, type, /*implicit=*/true);
2098+
}
2099+
2100+
SourceLoc getLoc() const { return BorrowLoc; }
2101+
2102+
SourceLoc getStartLoc() const { return BorrowLoc; }
2103+
SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }
2104+
2105+
static bool classof(const Expr *e) {
2106+
return e->getKind() == ExprKind::Borrow;
2107+
}
2108+
};
2109+
20792110
/// TupleExpr - Parenthesized expressions like '(a: x+x)' and '(x, y, 4)'. Note
20802111
/// that expressions like '(4)' are represented with a ParenExpr.
20812112
class TupleExpr final : public Expr,

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ ABSTRACT_EXPR(Identity, Expr)
108108
EXPR(DotSelf, IdentityExpr)
109109
EXPR(Await, IdentityExpr)
110110
EXPR(Move, IdentityExpr)
111+
EXPR(Borrow, IdentityExpr)
111112
EXPR(UnresolvedMemberChainResult, IdentityExpr)
112113
EXPR_RANGE(Identity, Paren, UnresolvedMemberChainResult)
113114
ABSTRACT_EXPR(AnyTry, Expr)

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,6 +2191,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21912191
printRec(E->getSubExpr());
21922192
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21932193
}
2194+
void visitBorrowExpr(BorrowExpr *E) {
2195+
printCommon(E, "borrow_expr");
2196+
OS << '\n';
2197+
printRec(E->getSubExpr());
2198+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2199+
}
21942200
void visitUnresolvedMemberChainResultExpr(UnresolvedMemberChainResultExpr *E){
21952201
printCommon(E, "unresolved_member_chain_expr");
21962202
OS << '\n';

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4689,6 +4689,11 @@ void PrintAST::visitMoveExpr(MoveExpr *expr) {
46894689
visit(expr->getSubExpr());
46904690
}
46914691

4692+
void PrintAST::visitBorrowExpr(BorrowExpr *expr) {
4693+
Printer << "borrow ";
4694+
visit(expr->getSubExpr());
4695+
}
4696+
46924697
void PrintAST::visitInOutExpr(InOutExpr *expr) {
46934698
visit(expr->getSubExpr());
46944699
}

lib/AST/Expr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
370370
PASS_THROUGH_REFERENCE(DotSelf, getSubExpr);
371371
PASS_THROUGH_REFERENCE(Await, getSubExpr);
372372
PASS_THROUGH_REFERENCE(Move, getSubExpr);
373+
PASS_THROUGH_REFERENCE(Borrow, getSubExpr);
373374
PASS_THROUGH_REFERENCE(Try, getSubExpr);
374375
PASS_THROUGH_REFERENCE(ForceTry, getSubExpr);
375376
PASS_THROUGH_REFERENCE(OptionalTry, getSubExpr);
@@ -729,6 +730,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
729730

730731
case ExprKind::Await:
731732
case ExprKind::Move:
733+
case ExprKind::Borrow:
732734
case ExprKind::Try:
733735
case ExprKind::ForceTry:
734736
case ExprKind::OptionalTry:
@@ -914,6 +916,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
914916
case ExprKind::Paren:
915917
case ExprKind::Await:
916918
case ExprKind::Move:
919+
case ExprKind::Borrow:
917920
case ExprKind::UnresolvedMemberChainResult:
918921
case ExprKind::Try:
919922
case ExprKind::ForceTry:

lib/Parse/ParseExpr.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
370370
/// 'try' '?' expr-sequence-element(Mode)
371371
/// 'try' '!' expr-sequence-element(Mode)
372372
/// '_move' expr-sequence-element(Mode)
373+
/// 'borrow' expr-sequence-element(Mode)
373374
/// expr-unary(Mode)
374375
///
375376
/// 'try' is not actually allowed at an arbitrary position of a
@@ -405,17 +406,28 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
405406
return sub;
406407
}
407408

408-
if (Context.LangOpts.hasFeature(Feature::MoveOnly)
409-
&& Tok.isContextualKeyword("_move")) {
410-
Tok.setKind(tok::contextual_keyword);
411-
SourceLoc awaitLoc = consumeToken();
412-
ParserResult<Expr> sub =
413-
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
414-
if (!sub.hasCodeCompletion() && !sub.isNull()) {
415-
sub = makeParserResult(new (Context) MoveExpr(awaitLoc, sub.get()));
409+
if (Context.LangOpts.hasFeature(Feature::MoveOnly)) {
410+
if (Tok.isContextualKeyword("_move")) {
411+
Tok.setKind(tok::contextual_keyword);
412+
SourceLoc awaitLoc = consumeToken();
413+
ParserResult<Expr> sub =
414+
parseExprSequenceElement(diag::expected_expr_after_move, isExprBasic);
415+
if (!sub.hasCodeCompletion() && !sub.isNull()) {
416+
sub = makeParserResult(new (Context) MoveExpr(awaitLoc, sub.get()));
417+
}
418+
return sub;
416419
}
417420

418-
return sub;
421+
if (Tok.isContextualKeyword("_borrow")) {
422+
Tok.setKind(tok::contextual_keyword);
423+
SourceLoc awaitLoc = consumeToken();
424+
ParserResult<Expr> sub = parseExprSequenceElement(
425+
diag::expected_expr_after_borrow, isExprBasic);
426+
if (!sub.hasCodeCompletion() && !sub.isNull()) {
427+
sub = makeParserResult(new (Context) BorrowExpr(awaitLoc, sub.get()));
428+
}
429+
return sub;
430+
}
419431
}
420432

421433
SourceLoc tryLoc;

test/Parse/borrow_expr.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-move-only
2+
3+
var global: Int = 5
4+
func testGlobal() {
5+
let _ = _borrow global
6+
}
7+
8+
func testLet() {
9+
let t = String()
10+
let _ = _borrow t
11+
}
12+
13+
func testVar() {
14+
var t = String()
15+
t = String()
16+
let _ = _borrow t
17+
}
18+
19+

test/Sema/borrow_expr.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-move-only
2+
3+
class Klass {
4+
var k: Klass? = nil
5+
}
6+
7+
func useString(_ x: String) {}
8+
9+
var global: String = "5"
10+
func testGlobal() {
11+
useString(_borrow global)
12+
}
13+
14+
func testLet() {
15+
let t = String()
16+
useString(_borrow t)
17+
}
18+
19+
func testVar() {
20+
var t = String()
21+
t = String()
22+
useString(_borrow t)
23+
}

0 commit comments

Comments
 (0)