Skip to content

Commit f7ea907

Browse files
authored
Merge pull request #73056 from jckarter/silgen-borrow-noncopyable-global-lets-6.0
[6.0] SILGen: Emit references to noncopyable global storage directly as a borrow.
2 parents 4ccf315 + aab7350 commit f7ea907

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
@@ -3327,7 +3327,20 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
33273327
if (auto *declRef = dyn_cast<DeclRefExpr>(argExpr)) {
33283328
assert(!declRef->getType()->is<LValueType>() &&
33293329
"Shouldn't ever have an lvalue type here!");
3330-
return nullptr;
3330+
3331+
// Proceed if the storage references a global or static let.
3332+
// TODO: We should treat any storage reference as a borrow, it seems, but
3333+
// that currently disrupts what the move checker expects. It would also
3334+
// be valuable to borrow copyable global lets, but this is a targeted
3335+
// fix to allow noncopyable globals to work properly.
3336+
bool isGlobal = false;
3337+
if (auto vd = dyn_cast<VarDecl>(declRef->getDecl())) {
3338+
isGlobal = vd->isGlobalStorage();
3339+
}
3340+
3341+
if (!isGlobal) {
3342+
return nullptr;
3343+
}
33313344
}
33323345
}
33333346

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)