Skip to content

Commit 21365cc

Browse files
authored
Merge pull request #25877 from slavapestov/dynamic-self-stored-property-init-diagnostic
Diagnose usages of 'Self' in stored property initializers
2 parents a8ea69e + 9915890 commit 21365cc

11 files changed

+168
-114
lines changed

include/swift/AST/AnyFunctionRef.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,20 @@ class AnyFunctionRef {
5252
}
5353
}
5454

55-
CaptureInfo &getCaptureInfo() const {
55+
const CaptureInfo &getCaptureInfo() const {
5656
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
5757
return AFD->getCaptureInfo();
5858
return TheFunction.get<AbstractClosureExpr *>()->getCaptureInfo();
5959
}
6060

61+
void setCaptureInfo(const CaptureInfo &captures) const {
62+
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
63+
AFD->setCaptureInfo(captures);
64+
return;
65+
}
66+
TheFunction.get<AbstractClosureExpr *>()->setCaptureInfo(captures);
67+
}
68+
6169
void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
6270
getCaptureInfo().getLocalCaptures(Result);
6371
}

include/swift/AST/CaptureInfo.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ class CaptureInfo {
126126
: Captures(nullptr), DynamicSelf(nullptr), OpaqueValue(nullptr), Count(0),
127127
GenericParamCaptures(0), Computed(0) { }
128128

129-
bool hasBeenComputed() { return Computed; }
129+
bool hasBeenComputed() const { return Computed; }
130130

131-
bool isTrivial() {
131+
bool isTrivial() const {
132132
return Count == 0 && !GenericParamCaptures && !DynamicSelf && !OpaqueValue;
133133
}
134134

include/swift/AST/Decl.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,9 @@ class PatternBindingEntry {
19321932
/// The initializer context used for this pattern binding entry.
19331933
llvm::PointerIntPair<DeclContext *, 1, bool> InitContextAndIsText;
19341934

1935+
/// Values captured by this initializer.
1936+
CaptureInfo Captures;
1937+
19351938
friend class PatternBindingInitializer;
19361939

19371940
public:
@@ -2025,6 +2028,9 @@ class PatternBindingEntry {
20252028
/// \param omitAccessors Whether the computation should omit the accessors
20262029
/// from the source range.
20272030
SourceRange getSourceRange(bool omitAccessors = false) const;
2031+
2032+
const CaptureInfo &getCaptureInfo() const { return Captures; }
2033+
void setCaptureInfo(const CaptureInfo &captures) { Captures = captures; }
20282034
};
20292035

20302036
/// This decl contains a pattern and optional initializer for a set
@@ -2122,6 +2128,18 @@ class PatternBindingDecl final : public Decl,
21222128

21232129
void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext);
21242130

2131+
DeclContext *getInitContext(unsigned i) const {
2132+
return getPatternList()[i].getInitContext();
2133+
}
2134+
2135+
const CaptureInfo &getCaptureInfo(unsigned i) const {
2136+
return getPatternList()[i].getCaptureInfo();
2137+
}
2138+
2139+
void setCaptureInfo(unsigned i, const CaptureInfo &captures) {
2140+
getMutablePatternList()[i].setCaptureInfo(captures);
2141+
}
2142+
21252143
/// Given that this PBD is the parent pattern for the specified VarDecl,
21262144
/// return the entry of the VarDecl in our PatternList. For example, in:
21272145
///
@@ -5847,8 +5865,8 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
58475865
/// Retrieve the source range of the function declaration name + patterns.
58485866
SourceRange getSignatureSourceRange() const;
58495867

5850-
CaptureInfo &getCaptureInfo() { return Captures; }
58515868
const CaptureInfo &getCaptureInfo() const { return Captures; }
5869+
void setCaptureInfo(const CaptureInfo &captures) { Captures = captures; }
58525870

58535871
/// Retrieve the Objective-C selector that names this method.
58545872
ObjCSelector getObjCSelector(DeclName preferredName = DeclName(),

include/swift/AST/DiagnosticsSema.def

+2
Original file line numberDiff line numberDiff line change
@@ -2595,6 +2595,8 @@ ERROR(dynamic_self_invalid_subscript,none,
25952595
"covariant 'Self' can only appear at the top level of subscript element type", ())
25962596
ERROR(dynamic_self_invalid_method,none,
25972597
"covariant 'Self' can only appear at the top level of method result type", ())
2598+
ERROR(dynamic_self_stored_property_init,none,
2599+
"covariant 'Self' type cannot be referenced from a stored property initializer", ())
25982600

25992601
//------------------------------------------------------------------------------
26002602
// MARK: Type Check Attributes

include/swift/AST/Expr.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -3427,8 +3427,8 @@ class AbstractClosureExpr : public DeclContext, public Expr {
34273427
Bits.AbstractClosureExpr.Discriminator = Discriminator;
34283428
}
34293429

3430-
CaptureInfo &getCaptureInfo() { return Captures; }
34313430
const CaptureInfo &getCaptureInfo() const { return Captures; }
3431+
void setCaptureInfo(CaptureInfo captures) { Captures = captures; }
34323432

34333433
/// Retrieve the parameters of this closure.
34343434
ParameterList *getParameters() { return parameterList; }

lib/SILGen/SILGen.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,7 @@ emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
11321132
auto *var = pbdEntry.getAnchoringVarDecl();
11331133
auto *init = pbdEntry.getInit();
11341134
auto *initDC = pbdEntry.getInitContext();
1135+
auto &captureInfo = pbdEntry.getCaptureInfo();
11351136
assert(!pbdEntry.isInitializerSubsumed());
11361137

11371138
// If this is the backing storage for a property with an attached wrapper
@@ -1148,12 +1149,23 @@ emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
11481149

11491150
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
11501151
emitOrDelayFunction(*this, constant,
1151-
[this,constant,init,initDC](SILFunction *f) {
1152+
[this,var,captureInfo,constant,init,initDC](SILFunction *f) {
11521153
preEmitFunction(constant, init, f, init);
11531154
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
11541155
f->createProfiler(init, constant, ForDefinition);
1155-
SILGenFunction(*this, *f, initDC)
1156-
.emitGeneratorFunction(constant, init, /*EmitProfilerIncrement=*/true);
1156+
SILGenFunction SGF(*this, *f, initDC);
1157+
1158+
// If this is a stored property initializer inside a type at global scope,
1159+
// it may close over a global variable. If we're emitting top-level code,
1160+
// then emit a "mark_function_escape" that lists the captured global
1161+
// variables so that definite initialization can reason about this
1162+
// escape point.
1163+
if (!var->getDeclContext()->isLocalContext() &&
1164+
TopLevelSGF && TopLevelSGF->B.hasValidInsertionPoint()) {
1165+
emitMarkFunctionEscapeForTopLevelCodeGlobals(var, captureInfo);
1166+
}
1167+
1168+
SGF.emitGeneratorFunction(constant, init, /*EmitProfilerIncrement=*/true);
11571169
postEmitFunction(constant, f);
11581170
});
11591171
}

0 commit comments

Comments
 (0)