Skip to content

Commit 274a43b

Browse files
authored
Merge pull request #66283 from xedin/init-accessors
[Parse/Sema/SIL] Implementation of init accessors feature (under a flag)
2 parents 39a5000 + aaa7261 commit 274a43b

File tree

79 files changed

+2828
-53
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2828
-53
lines changed

include/swift/AST/AccessorKinds.def

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@
100100
ANY_ADDRESSOR(ID, KEYWORD)
101101
#endif
102102

103+
/// INIT_ACCESSOR(ID, KEYWORD)
104+
/// The given accessor is an init accessor.
105+
///
106+
/// Defaults to SINGLETON_ACCESSOR(ID, KEYWORD).
107+
#ifndef INIT_ACCESSOR
108+
#define INIT_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
109+
#endif
110+
103111
// Suppress entries for accessors which can't be written in source code.
104112
#ifndef SUPPRESS_ARTIFICIAL_ACCESSORS
105113
#define SUPPRESS_ARTIFICIAL_ACCESSORS 0
@@ -174,11 +182,16 @@ IMMUTABLE_ADDRESSOR(Address, unsafeAddress)
174182
/// of the type).
175183
MUTABLE_ADDRESSOR(MutableAddress, unsafeMutableAddress)
176184

185+
/// This is an init accessor: a function that is called when DI
186+
/// re-writes assignment to initialization.
187+
INIT_ACCESSOR(Init, init)
188+
177189
#ifdef LAST_ACCESSOR
178-
LAST_ACCESSOR(MutableAddress)
190+
LAST_ACCESSOR(Init)
179191
#undef LAST_ACCESSOR
180192
#endif
181193

194+
#undef INIT_ACCESSOR
182195
#undef IMMUTABLE_ADDRESSOR
183196
#undef MUTABLE_ADDRESSOR
184197
#undef ANY_ADDRESSOR

include/swift/AST/Attr.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Decl;
5555
class AbstractFunctionDecl;
5656
class FuncDecl;
5757
class ClassDecl;
58+
class AccessorDecl;
5859
class GenericFunctionType;
5960
class LazyConformanceLoader;
6061
class LazyMemberLoader;
@@ -1548,6 +1549,68 @@ class SpecializeAttr final
15481549
}
15491550
};
15501551

1552+
class InitializesAttr final
1553+
: public DeclAttribute,
1554+
private llvm::TrailingObjects<InitializesAttr, Identifier> {
1555+
friend TrailingObjects;
1556+
1557+
size_t numProperties;
1558+
1559+
InitializesAttr(SourceLoc atLoc, SourceRange range,
1560+
ArrayRef<Identifier> properties);
1561+
1562+
public:
1563+
static InitializesAttr *create(ASTContext &ctx,
1564+
SourceLoc atLoc, SourceRange range,
1565+
ArrayRef<Identifier> properties);
1566+
1567+
size_t numTrailingObjects(OverloadToken<Identifier>) const {
1568+
return numProperties;
1569+
}
1570+
1571+
unsigned getNumProperties() const { return numProperties; }
1572+
1573+
ArrayRef<Identifier> getProperties() const {
1574+
return {getTrailingObjects<Identifier>(), numProperties};
1575+
}
1576+
1577+
ArrayRef<VarDecl *> getPropertyDecls(AccessorDecl *attachedTo) const;
1578+
1579+
static bool classof(const DeclAttribute *DA) {
1580+
return DA->getKind() == DAK_Initializes;
1581+
}
1582+
};
1583+
1584+
class AccessesAttr final
1585+
: public DeclAttribute,
1586+
private llvm::TrailingObjects<AccessesAttr, Identifier> {
1587+
friend TrailingObjects;
1588+
1589+
size_t numProperties;
1590+
1591+
AccessesAttr(SourceLoc atLoc, SourceRange range,
1592+
ArrayRef<Identifier> properties);
1593+
1594+
public:
1595+
static AccessesAttr *create(ASTContext &ctx,
1596+
SourceLoc atLoc, SourceRange range,
1597+
ArrayRef<Identifier> properties);
1598+
1599+
size_t numTrailingObjects(OverloadToken<Identifier>) const {
1600+
return numProperties;
1601+
}
1602+
1603+
ArrayRef<Identifier> getProperties() const {
1604+
return {getTrailingObjects<Identifier>(), numProperties};
1605+
}
1606+
1607+
ArrayRef<VarDecl *> getPropertyDecls(AccessorDecl *attachedTo) const;
1608+
1609+
static bool classof(const DeclAttribute *DA) {
1610+
return DA->getKind() == DAK_Accesses;
1611+
}
1612+
};
1613+
15511614
/// The @_implements attribute, which treats a decl as the implementation for
15521615
/// some named protocol requirement (but otherwise not-visible by that name).
15531616
class ImplementsAttr : public DeclAttribute {

include/swift/AST/Decl.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "swift/Basic/Range.h"
4848
#include "llvm/ADT/DenseSet.h"
4949
#include "llvm/Support/TrailingObjects.h"
50+
#include <map>
5051
#include <type_traits>
5152

5253
namespace swift {
@@ -184,6 +185,7 @@ enum class DescriptiveDeclKind : uint8_t {
184185
DistributedMethod,
185186
Getter,
186187
Setter,
188+
InitAccessor,
187189
Addressor,
188190
MutableAddressor,
189191
ReadAccessor,
@@ -3986,6 +3988,16 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
39863988
/// Return a collection of the stored member variables of this type.
39873989
ArrayRef<VarDecl *> getStoredProperties() const;
39883990

3991+
/// Return a collection of all properties with init accessors in
3992+
/// this type.
3993+
ArrayRef<VarDecl *> getInitAccessorProperties() const;
3994+
3995+
/// Establish a mapping between properties that could be iniitalized
3996+
/// via other properties by means of init accessors. This mapping is
3997+
/// one-to-many because we allow intersecting `initializes(...)`.
3998+
void collectPropertiesInitializableByInitAccessors(
3999+
std::multimap<VarDecl *, VarDecl *> &result) const;
4000+
39894001
/// Return a collection of the stored member variables of this type, along
39904002
/// with placeholders for unimportable stored properties.
39914003
ArrayRef<Decl *> getStoredPropertiesAndMissingMemberPlaceholders() const;
@@ -7569,6 +7581,10 @@ class AccessorDecl final : public FuncDecl {
75697581
llvm_unreachable("bad accessor kind");
75707582
}
75717583

7584+
bool isInitAccessor() const {
7585+
return (getAccessorKind() == AccessorKind::Init);
7586+
}
7587+
75727588
/// \returns true if this is non-mutating due to applying a 'mutating'
75737589
/// attribute. For example a "mutating set" accessor.
75747590
bool isExplicitNonMutating() const;

include/swift/AST/DiagnosticsParse.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ ERROR(observing_accessor_in_subscript,none,
309309
ERROR(getset_cannot_be_implied,none,
310310
"variable with implied type cannot have implied getter/setter", ())
311311

312+
ERROR(init_accessor_expected_name,none,
313+
"expected property name in init accessor effect", ())
314+
312315
// Import
313316
ERROR(decl_expected_module_name,none,
314317
"expected module name in import declaration", ())
@@ -2117,5 +2120,13 @@ ERROR(sil_markuncheckedreferencebinding_requires_attribute,none,
21172120
ERROR(sil_markuncheckedreferencebinding_invalid_attribute,none,
21182121
"Attribute '[%0]' can not be applied to mark_unchecked_reference_binding", (StringRef))
21192122

2123+
//------------------------------------------------------------------------------
2124+
// MARK: Init accessors
2125+
//------------------------------------------------------------------------------
2126+
2127+
ERROR(init_accessor_is_not_on_property,none,
2128+
"init accessors could only be associated with properties",
2129+
())
2130+
21202131
#define UNDEFINE_DIAGNOSTIC_MACROS
21212132
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsSIL.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ ERROR(ivar_not_initialized_at_superinit,none,
189189
ERROR(ivar_not_initialized_at_implicit_superinit,none,
190190
"property '%0' not initialized at implicitly generated super.init call",
191191
(StringRef, bool))
192+
ERROR(ivar_not_initialized_by_init_accessor,none,
193+
"property %0 not initialized by init accessor",
194+
(DeclName))
192195

193196
ERROR(self_use_before_fully_init,none,
194197
"'self' used in %select{method call|property access}1 %0 before "

include/swift/AST/DiagnosticsSema.def

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5856,6 +5856,8 @@ ERROR(no_opaque_return_type_of,none,
58565856

58575857
ERROR(objc_observing_accessor, none,
58585858
"observing accessors are not allowed to be marked @objc", ())
5859+
ERROR(objc_init_accessor, none,
5860+
"init accessors cannot be marked @objc", ())
58595861
ERROR(objc_addressor, none,
58605862
"addressors are not allowed to be marked @objc", ())
58615863
ERROR(objc_coroutine_accessor, none,
@@ -7275,6 +7277,25 @@ NOTE(opt_out_from_missing_reflection_metadata_attr,none,
72757277
" unavailable extension",
72767278
(StringRef))
72777279

7280+
//------------------------------------------------------------------------------
7281+
// MARK: Init accessors
7282+
//------------------------------------------------------------------------------
7283+
7284+
ERROR(init_accessor_can_refer_only_to_properties,none,
7285+
"init accessor cannot refer to %0 %1; init accessors can refer only"
7286+
" to stored properties",
7287+
(DescriptiveDeclKind, DeclNameRef))
7288+
7289+
ERROR(init_accessor_initializes_attribute_on_other_declaration,none,
7290+
"initalizes(...) attribute could only be used with init accessors",
7291+
())
7292+
ERROR(init_accessor_accesses_attribute_on_other_declaration,none,
7293+
"accesses(...) attribute could only be used with init accessors",
7294+
())
7295+
ERROR(init_accessor_property_both_init_and_accessed,none,
7296+
"property %0 cannot be both initialized and accessed",
7297+
(DeclName))
7298+
72787299

72797300
#define UNDEFINE_DIAGNOSTIC_MACROS
72807301
#include "DefineDiagnosticMacros.h"

include/swift/AST/TypeCheckRequests.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,25 @@ class StoredPropertiesAndMissingMembersRequest :
16711671
bool isCached() const { return true; }
16721672
};
16731673

1674+
/// Request to obtain a list of computed properties with init accesors
1675+
/// in the given nominal type.
1676+
class InitAccessorPropertiesRequest :
1677+
public SimpleRequest<InitAccessorPropertiesRequest,
1678+
ArrayRef<VarDecl *>(NominalTypeDecl *),
1679+
RequestFlags::Cached> {
1680+
public:
1681+
using SimpleRequest::SimpleRequest;
1682+
1683+
private:
1684+
friend SimpleRequest;
1685+
1686+
ArrayRef<VarDecl *>
1687+
evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const;
1688+
1689+
public:
1690+
bool isCached() const { return true; }
1691+
};
1692+
16741693
class StorageImplInfoRequest :
16751694
public SimpleRequest<StorageImplInfoRequest,
16761695
StorageImplInfo(AbstractStorageDecl *),
@@ -4270,6 +4289,25 @@ class IsNonUserModuleRequest
42704289
bool isCached() const { return true; }
42714290
};
42724291

4292+
class InitAccessorReferencedVariablesRequest
4293+
: public SimpleRequest<InitAccessorReferencedVariablesRequest,
4294+
ArrayRef<VarDecl *>(DeclAttribute *, AccessorDecl *,
4295+
ArrayRef<Identifier>),
4296+
RequestFlags::Cached> {
4297+
public:
4298+
using SimpleRequest::SimpleRequest;
4299+
4300+
private:
4301+
friend SimpleRequest;
4302+
4303+
ArrayRef<VarDecl *> evaluate(Evaluator &evaluator, DeclAttribute *attr,
4304+
AccessorDecl *attachedTo,
4305+
ArrayRef<Identifier>) const;
4306+
4307+
public:
4308+
bool isCached() const { return true; }
4309+
};
4310+
42734311
#define SWIFT_TYPEID_ZONE TypeChecker
42744312
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
42754313
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ SWIFT_REQUEST(TypeChecker, StoredPropertiesAndMissingMembersRequest,
306306
ArrayRef<Decl *>(NominalTypeDecl *), Cached, NoLocationInfo)
307307
SWIFT_REQUEST(TypeChecker, StoredPropertiesRequest,
308308
ArrayRef<VarDecl *>(NominalTypeDecl *), Cached, NoLocationInfo)
309+
SWIFT_REQUEST(TypeChecker, InitAccessorPropertiesRequest,
310+
ArrayRef<VarDecl *>(NominalTypeDecl *),
311+
Cached, NoLocationInfo)
309312
SWIFT_REQUEST(TypeChecker, StructuralTypeRequest, Type(TypeAliasDecl *), Cached,
310313
NoLocationInfo)
311314
SWIFT_REQUEST(TypeChecker, SuperclassTypeRequest,
@@ -481,3 +484,7 @@ SWIFT_REQUEST(TypeChecker, IsNonUserModuleRequest,
481484
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
482485
unsigned(ExtensionDecl *),
483486
Cached, NoLocationInfo)
487+
SWIFT_REQUEST(TypeChecker, InitAccessorReferencedVariablesRequest,
488+
ArrayRef<VarDecl *>(DeclAttribute *, AccessorDecl *,
489+
ArrayRef<Identifier>),
490+
Cached, NoLocationInfo)

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
120120
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
121121
EXPERIMENTAL_FEATURE(CodeItemMacros, true)
122122
EXPERIMENTAL_FEATURE(TupleConformances, false)
123+
EXPERIMENTAL_FEATURE(InitAccessors, false)
123124

124125
// Whether to enable @_used and @_section attributes
125126
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ NODE(ImplErrorResult)
143143
NODE(InOut)
144144
NODE(InfixOperator)
145145
CONTEXT_NODE(Initializer)
146+
CONTEXT_NODE(InitAccessor)
146147
NODE(Isolated)
147148
NODE(KeyPathGetterThunkHelper)
148149
NODE(KeyPathSetterThunkHelper)

include/swift/Parse/Parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,10 @@ class Parser {
12661266
AccessorKind currentKind,
12671267
SourceLoc const& currentLoc);
12681268

1269+
ParserStatus parseInitAccessorEffects(ParsedAccessors &accessors,
1270+
AccessorKind currentKind,
1271+
DeclAttributes &Attributes);
1272+
12691273
/// Parse accessors provided as a separate list, for use in macro
12701274
/// expansions.
12711275
void parseTopLevelAccessors(

include/swift/SIL/InstructionUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ SILValue isPartialApplyOfReabstractionThunk(PartialApplyInst *PAI);
145145
/// init or set function.
146146
bool onlyUsedByAssignByWrapper(PartialApplyInst *PAI);
147147

148+
/// Returns true if \p PAI is only used by an \c assign_or_init
149+
/// instruction as init or set function.
150+
bool onlyUsedByAssignOrInit(PartialApplyInst *PAI);
151+
148152
/// Returns the runtime effects of \p inst.
149153
///
150154
/// Predicts which runtime calls are called in the generated code for `inst`.

include/swift/SIL/SILBuilder.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,14 @@ class SILBuilder {
956956
getSILDebugLocation(Loc), Src, Dest, Initializer, Setter, mode));
957957
}
958958

959+
AssignOrInitInst *createAssignOrInit(SILLocation Loc, SILValue Src,
960+
SILValue Initializer,
961+
SILValue Setter,
962+
AssignOrInitInst::Mode Mode) {
963+
return insert(new (getModule()) AssignOrInitInst(
964+
getSILDebugLocation(Loc), Src, Initializer, Setter, Mode));
965+
}
966+
959967
StoreBorrowInst *createStoreBorrow(SILLocation Loc, SILValue Src,
960968
SILValue DestAddr) {
961969
return insert(new (getModule())
@@ -1010,7 +1018,11 @@ class SILBuilder {
10101018
SILValue src) {
10111019
return createMarkUninitialized(Loc, src, MarkUninitializedInst::RootSelf);
10121020
}
1013-
1021+
MarkUninitializedInst *createMarkUninitializedOut(SILLocation Loc,
1022+
SILValue src) {
1023+
return createMarkUninitialized(Loc, src, MarkUninitializedInst::Out);
1024+
}
1025+
10141026
MarkFunctionEscapeInst *createMarkFunctionEscape(SILLocation Loc,
10151027
ArrayRef<SILValue> vars) {
10161028
return insert(

include/swift/SIL/SILCloner.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,17 @@ void SILCloner<ImplClass>::visitAssignByWrapperInst(AssignByWrapperInst *Inst) {
13521352
getOpValue(Inst->getSetter()), Inst->getMode()));
13531353
}
13541354

1355+
template <typename ImplClass>
1356+
void SILCloner<ImplClass>::visitAssignOrInitInst(AssignOrInitInst *Inst) {
1357+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1358+
recordClonedInstruction(
1359+
Inst, getBuilder().createAssignOrInit(
1360+
getOpLocation(Inst->getLoc()),
1361+
getOpValue(Inst->getSrc()),
1362+
getOpValue(Inst->getInitializer()),
1363+
getOpValue(Inst->getSetter()), Inst->getMode()));
1364+
}
1365+
13551366
template<typename ImplClass>
13561367
void
13571368
SILCloner<ImplClass>::visitMarkUninitializedInst(MarkUninitializedInst *Inst) {

include/swift/SIL/SILDeclRef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ struct SILDeclRef {
382382
return kind == Kind::Initializer || kind == Kind::Destroyer;
383383
}
384384

385+
/// True if the SILDeclRef references an init accessor declaration.
386+
bool isInitAccessor() const;
387+
385388
/// True if the function should be treated as transparent.
386389
bool isTransparent() const;
387390
/// True if the function should have its body serialized.

0 commit comments

Comments
 (0)