Skip to content

Commit 7a904af

Browse files
committed
Don't crash when modifying a global observed variable.
The terrible hack in SILGen here is to not visit opaque accessors of global variables if they were added to the decls list by the parser. That needs to include the setter for an observed global variable, which we apparently did not have tests of. rdar://46472759
1 parent a061df5 commit 7a904af

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

lib/SILGen/SILGen.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -675,10 +675,10 @@ void SILGenModule::visitFuncDecl(FuncDecl *fd) { emitFunction(fd); }
675675
/// Emit a function now, if it's externally usable or has been referenced in
676676
/// the current TU, or remember how to emit it later if not.
677677
template<typename /*void (SILFunction*)*/ Fn>
678-
void emitOrDelayFunction(SILGenModule &SGM,
679-
SILDeclRef constant,
680-
Fn &&emitter,
681-
bool forceEmission = false) {
678+
static void emitOrDelayFunction(SILGenModule &SGM,
679+
SILDeclRef constant,
680+
Fn &&emitter,
681+
bool forceEmission = false) {
682682
auto emitAfter = SGM.lastEmittedFunction;
683683

684684
SILFunction *f = nullptr;
@@ -1312,7 +1312,8 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
13121312
case AccessorKind::Read:
13131313
return impl.getReadImpl() != ReadImplKind::Read;
13141314
case AccessorKind::Set:
1315-
return impl.getWriteImpl() != WriteImplKind::Set;
1315+
return impl.getWriteImpl() != WriteImplKind::Set &&
1316+
impl.getWriteImpl() != WriteImplKind::StoredWithObservers;
13161317
case AccessorKind::Modify:
13171318
return impl.getReadWriteImpl() != ReadWriteImplKind::Modify;
13181319
#define ACCESSOR(ID) \

test/SILGen/lazy_global_access.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,16 @@ func useProps() -> (Int, Int) {
2222
return (globalProp, Fooo.staticProp)
2323
}
2424

25+
// rdar://46472759
26+
// We used to crash tying to double-emit the setter.
27+
struct Bar {
28+
mutating func mutate() {}
29+
}
30+
func useGlobalBar() -> Bar {
31+
globalBar = Bar()
32+
globalBar.mutate()
33+
return globalBar
34+
}
35+
private var globalBar = Bar() {
36+
willSet {}
37+
}

0 commit comments

Comments
 (0)