Skip to content

Commit 15973e3

Browse files
authored
Merge pull request #73041 from jckarter/silgen-borrow-noncopyable-global-lets
SILGen: Emit references to noncopyable global storage directly as a borrow.
2 parents 2600aa5 + 4077c75 commit 15973e3

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3263,7 +3263,20 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
32633263
if (auto *declRef = dyn_cast<DeclRefExpr>(argExpr)) {
32643264
assert(!declRef->getType()->is<LValueType>() &&
32653265
"Shouldn't ever have an lvalue type here!");
3266-
return nullptr;
3266+
3267+
// Proceed if the storage references a global or static let.
3268+
// TODO: We should treat any storage reference as a borrow, it seems, but
3269+
// that currently disrupts what the move checker expects. It would also
3270+
// be valuable to borrow copyable global lets, but this is a targeted
3271+
// fix to allow noncopyable globals to work properly.
3272+
bool isGlobal = false;
3273+
if (auto vd = dyn_cast<VarDecl>(declRef->getDecl())) {
3274+
isGlobal = vd->isGlobalStorage();
3275+
}
3276+
3277+
if (!isGlobal) {
3278+
return nullptr;
3279+
}
32673280
}
32683281
}
32693282

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %target-swift-frontend -parse-as-library -DADDRESS_ONLY -emit-sil -verify %s
2+
// RUN: %target-swift-frontend -parse-as-library -DLOADABLE -emit-sil -verify %s
3+
// RUN: %target-swift-frontend -parse-as-library -DTRIVIAL -emit-sil -verify %s
4+
// RUN: %target-swift-frontend -parse-as-library -DEMPTY -emit-sil -verify %s
5+
6+
// RUN: %target-swift-frontend -DADDRESS_ONLY -emit-sil -verify %s
7+
// RUN: %target-swift-frontend -DLOADABLE -emit-sil -verify %s
8+
// RUN: %target-swift-frontend -DTRIVIAL -emit-sil -verify %s
9+
// RUN: %target-swift-frontend -DEMPTY -emit-sil -verify %s
10+
11+
struct Butt: ~Copyable {
12+
#if ADDRESS_ONLY
13+
var x: Any
14+
#elseif LOADABLE
15+
var x: AnyObject
16+
#elseif TRIVIAL
17+
var x: Int
18+
#elseif EMPTY
19+
#else
20+
#error("pick one")
21+
#endif
22+
23+
init() { fatalError() }
24+
25+
borrowing func method() {}
26+
}
27+
28+
func freefunc(_: borrowing Butt) {}
29+
30+
let global = Butt()
31+
32+
struct StaticHolder {
33+
static let staticMember = Butt()
34+
}
35+
36+
func foo() {
37+
freefunc(global)
38+
freefunc(StaticHolder.staticMember)
39+
global.method()
40+
StaticHolder.staticMember.method()
41+
}
42+
43+
func consume(_: consuming Butt) {}
44+
45+
func tryConsume() {
46+
// FIXME: gives different diagnostics for parse-as-library vs script global
47+
consume(global) // expected-error{{}} expected-note *{{}}
48+
consume(StaticHolder.staticMember) // expected-error{{cannot be consumed}} expected-note{{consumed here}}
49+
}
50+
51+
var globalVar = Butt()
52+
53+
func mutate(_: inout Butt) {}
54+
55+
func manipulateGlobalVar() {
56+
freefunc(globalVar)
57+
mutate(&globalVar)
58+
// FIXME: gives different diagnostics for parse-as-library vs script global
59+
consume(globalVar) // expected-error{{consume}}
60+
}

0 commit comments

Comments
 (0)