Skip to content

Commit a4a5d32

Browse files
committed
suppress notes from DI about @_compilerInitialized when reasonable
Since the only user of `@_compilerInitialized` is distributed actors, I decided to make DI's diagnostics saying that such a var was not initialized a second-tier note. If there is some other var associated with the same Memory that is _not_ compiler initialized AND is also _not_ initialized, then we suppress the suggestion to initialize the @_compilerInitialized thing, because something else is problematic. Only when there are @_compilerInitialized things that are still not initialized, do we emit a note talking about that.
1 parent af683dc commit a4a5d32

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ void LifetimeChecker::noteUninitializedMembers(const DIMemoryUse &Use) {
689689
AvailabilitySet Liveness =
690690
getLivenessAtInst(Use.Inst, Use.FirstElement, Use.NumElements);
691691

692+
SmallVector<std::function<void()>, 2> delayedNotes;
693+
bool emittedNote = false;
694+
692695
for (unsigned i = Use.FirstElement, e = Use.FirstElement+Use.NumElements;
693696
i != e; ++i) {
694697
if (Liveness.get(i) == DIKind::Yes) continue;
@@ -701,13 +704,34 @@ void LifetimeChecker::noteUninitializedMembers(const DIMemoryUse &Use) {
701704
auto *Decl = TheMemory.getPathStringToElement(i, Name);
702705
SILLocation Loc = Use.Inst->getLoc();
703706

704-
// If we found a non-implicit declaration, use its source location.
705-
if (Decl && !Decl->isImplicit())
706-
Loc = SILLocation(Decl);
707+
if (Decl) {
708+
// If we found a non-implicit declaration, use its source location.
709+
if (!Decl->isImplicit())
710+
Loc = SILLocation(Decl);
711+
712+
// If it's marked @_compilerInitialized, delay emission of the note.
713+
if (Decl->getAttrs().hasAttribute<CompilerInitializedAttr>()) {
714+
delayedNotes.push_back([=](){
715+
diagnose(Module, Loc, diag::stored_property_not_initialized,
716+
StringRef(Name));
717+
});
718+
continue;
719+
}
720+
}
707721

708722
diagnose(Module, Loc, diag::stored_property_not_initialized,
709723
StringRef(Name));
724+
emittedNote = true;
710725
}
726+
727+
// Drop the notes for @_compilerInitialized decls if we emitted a note for
728+
// other ones that do not have that attr.
729+
if (emittedNote)
730+
return;
731+
732+
// otherwise, emit delayed notes.
733+
for (auto &emitter : delayedNotes)
734+
emitter();
711735
}
712736

713737
/// Given a use that has at least one uninitialized element in it, produce a

test/SILOptimizer/definite_init.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,23 @@ func tuple_test() -> Int {
5656

5757
class CheckCompilerInitAttr {
5858
@_compilerInitialized let poster: Int
59-
init() {
59+
var whatever: Int // expected-note {{'self.whatever' not initialized}}
60+
61+
init(v1: Void) {
62+
whatever = 0
6063
poster = 10 // expected-error {{illegal assignment to '@_compilerInitialized' storage}}
6164
}
65+
66+
// NB: this case is testing whether we only get a note for `whatever` and not `poster`
67+
init(v2: Void) {} // expected-error {{return from initializer without initializing all stored properties}}
68+
}
69+
70+
class AgainCheckCompilerInitAttr {
71+
@_compilerInitialized let cleanup: Int // expected-note {{'self.cleanup' not initialized}}
72+
var whenever: Int
73+
74+
// NB: this case ensures we still get a note for `cleanup` because no other properties are uninitialized
75+
init() {
76+
whenever = 0
77+
} // expected-error {{return from initializer without initializing all stored properties}}
6278
}

0 commit comments

Comments
 (0)