Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3dc470f
[Features] Add an experimental feature flag for init accessors.
hborla May 8, 2023
684ef9c
[AST] Add a new accessor kind for init accessors.
hborla May 10, 2023
d065d82
[Demangler] Demangle init accessors.
hborla May 11, 2023
429f190
[Parser] Parse init accessors when the experimental feature is enabled.
hborla May 12, 2023
ac66a06
[SIL] Add a new AssignOrInit instruction for init accessors.
hborla May 17, 2023
d35da62
[AST] Add a 'newValue' parameter to init accessors.
hborla May 17, 2023
eb3ed2b
[SILGen] Emit AssignOrInitInst for assignment to a computed property …
hborla May 17, 2023
9039d8b
[Sema] Add a request for gathering all computed properties in a nominal
hborla May 22, 2023
0028bdf
[DefiniteInitialization] Rename DIUseKind::AssignWrappedValue to DIUs…
hborla May 22, 2023
7512f6e
[SIL] Add an assignment mode to AssignOrInitInst that will be set by DI.
hborla May 22, 2023
df69020
[DefiniteInitialization] Lower AssignOrInit instructions to either ca…
hborla May 22, 2023
e5f7502
[AST] Add 'initializes' and 'accesses' attributes for init accessor
hborla May 23, 2023
404a523
[Parser] Parse 'initializes' and 'accesses' attributes on init access…
hborla May 24, 2023
c1a0000
[AST] InitAccessors: Add a way to retrieve referenced property declar…
xedin May 24, 2023
f96e1d7
[Parse] InitAccessors: Validate that init accessor declaration context
xedin May 25, 2023
d7f5419
[AST] InitAccessors: Add initializes/accesses attribute location vali…
xedin May 25, 2023
4a4bf3b
[Sema] InitAccessors/NFC: Add tests for invalid references in initial…
xedin May 25, 2023
fe90ddc
[DI] InitAccessors: Implement handling of initializes/accesses attrib…
xedin May 25, 2023
a090eb4
[Parse] InitAccessor: Reject init accessor declarations on subscripts
xedin May 26, 2023
dc9420e
[SILGen] InitAccessors: Add a way to check whether SILDeclRef points …
xedin May 27, 2023
2a64f28
[SIL] InitAccessors: Implement lowering of init accessor types
xedin May 27, 2023
003e460
[DI] Memory collector shouldn't assume that decls always have names
xedin May 29, 2023
d670067
[SILGen] InitAccessors: Add a way to check whether property is redire…
xedin May 29, 2023
00a9ccf
[SILGen] InitAccessors: Remap property references into argument refer…
xedin May 29, 2023
5bac6e8
[SILGen] NFC: Generalize `isCurrentFunction{{ReadAccess, InitAccessor…
xedin May 30, 2023
6c0e391
[SILGen] InitAccessor: Emit init accessor function
xedin May 30, 2023
7b140f8
[SILGen] InitAccessors: AssignOrInit instruction should reference ini…
xedin May 30, 2023
3b85840
[SIL/DI] InitAccessors: Get all required info from AssignOrInit inste…
xedin May 30, 2023
68866d7
[DI] InitAccessors: Handle `assign_or_init` without initializations
xedin May 30, 2023
2e8b0e7
[RawSILLowering] InitAccessors: Implement lowering of `assign_or_init…
xedin May 31, 2023
4dbaaf3
[AST] InitAccessors: Allow assignments to `let` properties
xedin May 31, 2023
69269e6
[Sema] InitAccessors: Mark init accesor as mutating "self" only for v…
xedin May 31, 2023
63e7561
[SIL] InitAccessors: Introduce a new `Out` kind to `MarkUninitialized…
xedin May 31, 2023
112d0d4
[DI] InitAccessors: Start marking `initializes(...)` properties as "out"
xedin Jun 1, 2023
73765c8
[SIL] InitAccessors: Fix reference type handling by DI and RawSIL low…
xedin Jun 1, 2023
78aee95
[SILVerifier] InitAccessors: Adjust verifier to map init accessor ref…
xedin Jun 1, 2023
fb15b6f
[Sema] InitAccessors: Mark properties with init accessor as computed
xedin Jun 1, 2023
22061e6
[Sema] InitAccessors: Verify that a property never appears both in in…
xedin Jun 2, 2023
ad95e91
[Sema/SIL] InitAccessors: Incorporate init accessors into memberwise …
xedin Jun 3, 2023
0e61a75
[Parser] InitAccessors: Properties in `initializes/accesses` should b…
xedin Jun 5, 2023
b22e8e6
[SIL] InitAccessors: Add tracking of properties that require assign i…
xedin Jun 5, 2023
c82559e
[DI/Lowering] InitAccessors: Implement lowering of property assignments
xedin Jun 5, 2023
85a8a05
[SILParse] InitAccessors: Print/parse "mode" of `assign_or_init` inst…
xedin Jun 5, 2023
d191ef8
[SIL/Parse] InitAccessors: Implement printing and parsing of previous…
xedin Jun 6, 2023
0d921e3
[Test] InitAccessors/NFC: Fix SIL test not to expecte %18 as a result
xedin Jun 6, 2023
a71b9c2
[Tests] InitAccessors/NFC: All init accessor tests require "asserts"
xedin Jun 6, 2023
5b19c0c
[Tests] InitAccessors/NFC: Switch test to validate output directly af…
xedin Jun 6, 2023
aaa7261
[Tests] InitAccessors/NFC: add interpreter tests for different config…
xedin Jun 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion include/swift/AST/AccessorKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@
ANY_ADDRESSOR(ID, KEYWORD)
#endif

/// INIT_ACCESSOR(ID, KEYWORD)
/// The given accessor is an init accessor.
///
/// Defaults to SINGLETON_ACCESSOR(ID, KEYWORD).
#ifndef INIT_ACCESSOR
#define INIT_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
#endif

// Suppress entries for accessors which can't be written in source code.
#ifndef SUPPRESS_ARTIFICIAL_ACCESSORS
#define SUPPRESS_ARTIFICIAL_ACCESSORS 0
Expand Down Expand Up @@ -174,11 +182,16 @@ IMMUTABLE_ADDRESSOR(Address, unsafeAddress)
/// of the type).
MUTABLE_ADDRESSOR(MutableAddress, unsafeMutableAddress)

/// This is an init accessor: a function that is called when DI
/// re-writes assignment to initialization.
INIT_ACCESSOR(Init, init)

#ifdef LAST_ACCESSOR
LAST_ACCESSOR(MutableAddress)
LAST_ACCESSOR(Init)
#undef LAST_ACCESSOR
#endif

#undef INIT_ACCESSOR
#undef IMMUTABLE_ADDRESSOR
#undef MUTABLE_ADDRESSOR
#undef ANY_ADDRESSOR
Expand Down
63 changes: 63 additions & 0 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class Decl;
class AbstractFunctionDecl;
class FuncDecl;
class ClassDecl;
class AccessorDecl;
class GenericFunctionType;
class LazyConformanceLoader;
class LazyMemberLoader;
Expand Down Expand Up @@ -1548,6 +1549,68 @@ class SpecializeAttr final
}
};

class InitializesAttr final
: public DeclAttribute,
private llvm::TrailingObjects<InitializesAttr, Identifier> {
friend TrailingObjects;

size_t numProperties;

InitializesAttr(SourceLoc atLoc, SourceRange range,
ArrayRef<Identifier> properties);

public:
static InitializesAttr *create(ASTContext &ctx,
SourceLoc atLoc, SourceRange range,
ArrayRef<Identifier> properties);

size_t numTrailingObjects(OverloadToken<Identifier>) const {
return numProperties;
}

unsigned getNumProperties() const { return numProperties; }

ArrayRef<Identifier> getProperties() const {
return {getTrailingObjects<Identifier>(), numProperties};
}

ArrayRef<VarDecl *> getPropertyDecls(AccessorDecl *attachedTo) const;

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Initializes;
}
};

class AccessesAttr final
: public DeclAttribute,
private llvm::TrailingObjects<AccessesAttr, Identifier> {
friend TrailingObjects;

size_t numProperties;

AccessesAttr(SourceLoc atLoc, SourceRange range,
ArrayRef<Identifier> properties);

public:
static AccessesAttr *create(ASTContext &ctx,
SourceLoc atLoc, SourceRange range,
ArrayRef<Identifier> properties);

size_t numTrailingObjects(OverloadToken<Identifier>) const {
return numProperties;
}

ArrayRef<Identifier> getProperties() const {
return {getTrailingObjects<Identifier>(), numProperties};
}

ArrayRef<VarDecl *> getPropertyDecls(AccessorDecl *attachedTo) const;

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Accesses;
}
};

/// The @_implements attribute, which treats a decl as the implementation for
/// some named protocol requirement (but otherwise not-visible by that name).
class ImplementsAttr : public DeclAttribute {
Expand Down
16 changes: 16 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "swift/Basic/Range.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/TrailingObjects.h"
#include <map>
#include <type_traits>

namespace swift {
Expand Down Expand Up @@ -184,6 +185,7 @@ enum class DescriptiveDeclKind : uint8_t {
DistributedMethod,
Getter,
Setter,
InitAccessor,
Addressor,
MutableAddressor,
ReadAccessor,
Expand Down Expand Up @@ -3980,6 +3982,16 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
/// Return a collection of the stored member variables of this type.
ArrayRef<VarDecl *> getStoredProperties() const;

/// Return a collection of all properties with init accessors in
/// this type.
ArrayRef<VarDecl *> getInitAccessorProperties() const;

/// Establish a mapping between properties that could be iniitalized
/// via other properties by means of init accessors. This mapping is
/// one-to-many because we allow intersecting `initializes(...)`.
void collectPropertiesInitializableByInitAccessors(
std::multimap<VarDecl *, VarDecl *> &result) const;

/// Return a collection of the stored member variables of this type, along
/// with placeholders for unimportable stored properties.
ArrayRef<Decl *> getStoredPropertiesAndMissingMemberPlaceholders() const;
Expand Down Expand Up @@ -7563,6 +7575,10 @@ class AccessorDecl final : public FuncDecl {
llvm_unreachable("bad accessor kind");
}

bool isInitAccessor() const {
return (getAccessorKind() == AccessorKind::Init);
}

/// \returns true if this is non-mutating due to applying a 'mutating'
/// attribute. For example a "mutating set" accessor.
bool isExplicitNonMutating() const;
Expand Down
11 changes: 11 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ ERROR(observing_accessor_in_subscript,none,
ERROR(getset_cannot_be_implied,none,
"variable with implied type cannot have implied getter/setter", ())

ERROR(init_accessor_expected_name,none,
"expected property name in init accessor effect", ())

// Import
ERROR(decl_expected_module_name,none,
"expected module name in import declaration", ())
Expand Down Expand Up @@ -2117,5 +2120,13 @@ ERROR(sil_markuncheckedreferencebinding_requires_attribute,none,
ERROR(sil_markuncheckedreferencebinding_invalid_attribute,none,
"Attribute '[%0]' can not be applied to mark_unchecked_reference_binding", (StringRef))

//------------------------------------------------------------------------------
// MARK: Init accessors
//------------------------------------------------------------------------------

ERROR(init_accessor_is_not_on_property,none,
"init accessors could only be associated with properties",
())

#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSIL.def
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ ERROR(ivar_not_initialized_at_superinit,none,
ERROR(ivar_not_initialized_at_implicit_superinit,none,
"property '%0' not initialized at implicitly generated super.init call",
(StringRef, bool))
ERROR(ivar_not_initialized_by_init_accessor,none,
"property %0 not initialized by init accessor",
(DeclName))

ERROR(self_use_before_fully_init,none,
"'self' used in %select{method call|property access}1 %0 before "
Expand Down
21 changes: 21 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5853,6 +5853,8 @@ ERROR(no_opaque_return_type_of,none,

ERROR(objc_observing_accessor, none,
"observing accessors are not allowed to be marked @objc", ())
ERROR(objc_init_accessor, none,
"init accessors cannot be marked @objc", ())
ERROR(objc_addressor, none,
"addressors are not allowed to be marked @objc", ())
ERROR(objc_coroutine_accessor, none,
Expand Down Expand Up @@ -7272,6 +7274,25 @@ NOTE(opt_out_from_missing_reflection_metadata_attr,none,
" unavailable extension",
(StringRef))

//------------------------------------------------------------------------------
// MARK: Init accessors
//------------------------------------------------------------------------------

ERROR(init_accessor_can_refer_only_to_properties,none,
"init accessor cannot refer to %0 %1; init accessors can refer only"
" to stored properties",
(DescriptiveDeclKind, DeclNameRef))

ERROR(init_accessor_initializes_attribute_on_other_declaration,none,
"initalizes(...) attribute could only be used with init accessors",
())
ERROR(init_accessor_accesses_attribute_on_other_declaration,none,
"accesses(...) attribute could only be used with init accessors",
())
ERROR(init_accessor_property_both_init_and_accessed,none,
"property %0 cannot be both initialized and accessed",
(DeclName))


#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
38 changes: 38 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,25 @@ class StoredPropertiesAndMissingMembersRequest :
bool isCached() const { return true; }
};

/// Request to obtain a list of computed properties with init accesors
/// in the given nominal type.
class InitAccessorPropertiesRequest :
public SimpleRequest<InitAccessorPropertiesRequest,
ArrayRef<VarDecl *>(NominalTypeDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

ArrayRef<VarDecl *>
evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const;

public:
bool isCached() const { return true; }
};

class StorageImplInfoRequest :
public SimpleRequest<StorageImplInfoRequest,
StorageImplInfo(AbstractStorageDecl *),
Expand Down Expand Up @@ -4270,6 +4289,25 @@ class IsNonUserModuleRequest
bool isCached() const { return true; }
};

class InitAccessorReferencedVariablesRequest
: public SimpleRequest<InitAccessorReferencedVariablesRequest,
ArrayRef<VarDecl *>(DeclAttribute *, AccessorDecl *,
ArrayRef<Identifier>),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

ArrayRef<VarDecl *> evaluate(Evaluator &evaluator, DeclAttribute *attr,
AccessorDecl *attachedTo,
ArrayRef<Identifier>) const;

public:
bool isCached() const { return true; }
};

#define SWIFT_TYPEID_ZONE TypeChecker
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"
Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ SWIFT_REQUEST(TypeChecker, StoredPropertiesAndMissingMembersRequest,
ArrayRef<Decl *>(NominalTypeDecl *), Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, StoredPropertiesRequest,
ArrayRef<VarDecl *>(NominalTypeDecl *), Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, InitAccessorPropertiesRequest,
ArrayRef<VarDecl *>(NominalTypeDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, StructuralTypeRequest, Type(TypeAliasDecl *), Cached,
NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SuperclassTypeRequest,
Expand Down Expand Up @@ -481,3 +484,7 @@ SWIFT_REQUEST(TypeChecker, IsNonUserModuleRequest,
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
unsigned(ExtensionDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, InitAccessorReferencedVariablesRequest,
ArrayRef<VarDecl *>(DeclAttribute *, AccessorDecl *,
ArrayRef<Identifier>),
Cached, NoLocationInfo)
1 change: 1 addition & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
EXPERIMENTAL_FEATURE(CodeItemMacros, true)
EXPERIMENTAL_FEATURE(TupleConformances, false)
EXPERIMENTAL_FEATURE(InitAccessors, false)

// Whether to enable @_used and @_section attributes
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ NODE(ImplErrorResult)
NODE(InOut)
NODE(InfixOperator)
CONTEXT_NODE(Initializer)
CONTEXT_NODE(InitAccessor)
NODE(Isolated)
NODE(KeyPathGetterThunkHelper)
NODE(KeyPathSetterThunkHelper)
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,10 @@ class Parser {
AccessorKind currentKind,
SourceLoc const& currentLoc);

ParserStatus parseInitAccessorEffects(ParsedAccessors &accessors,
AccessorKind currentKind,
DeclAttributes &Attributes);

/// Parse accessors provided as a separate list, for use in macro
/// expansions.
void parseTopLevelAccessors(
Expand Down
4 changes: 4 additions & 0 deletions include/swift/SIL/InstructionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ SILValue isPartialApplyOfReabstractionThunk(PartialApplyInst *PAI);
/// init or set function.
bool onlyUsedByAssignByWrapper(PartialApplyInst *PAI);

/// Returns true if \p PAI is only used by an \c assign_or_init
/// instruction as init or set function.
bool onlyUsedByAssignOrInit(PartialApplyInst *PAI);

/// Returns the runtime effects of \p inst.
///
/// Predicts which runtime calls are called in the generated code for `inst`.
Expand Down
14 changes: 13 additions & 1 deletion include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,14 @@ class SILBuilder {
getSILDebugLocation(Loc), Src, Dest, Initializer, Setter, mode));
}

AssignOrInitInst *createAssignOrInit(SILLocation Loc, SILValue Src,
SILValue Initializer,
SILValue Setter,
AssignOrInitInst::Mode Mode) {
return insert(new (getModule()) AssignOrInitInst(
getSILDebugLocation(Loc), Src, Initializer, Setter, Mode));
}

StoreBorrowInst *createStoreBorrow(SILLocation Loc, SILValue Src,
SILValue DestAddr) {
return insert(new (getModule())
Expand Down Expand Up @@ -1010,7 +1018,11 @@ class SILBuilder {
SILValue src) {
return createMarkUninitialized(Loc, src, MarkUninitializedInst::RootSelf);
}

MarkUninitializedInst *createMarkUninitializedOut(SILLocation Loc,
SILValue src) {
return createMarkUninitialized(Loc, src, MarkUninitializedInst::Out);
}

MarkFunctionEscapeInst *createMarkFunctionEscape(SILLocation Loc,
ArrayRef<SILValue> vars) {
return insert(
Expand Down
11 changes: 11 additions & 0 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,17 @@ void SILCloner<ImplClass>::visitAssignByWrapperInst(AssignByWrapperInst *Inst) {
getOpValue(Inst->getSetter()), Inst->getMode()));
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitAssignOrInitInst(AssignOrInitInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAssignOrInit(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getSrc()),
getOpValue(Inst->getInitializer()),
getOpValue(Inst->getSetter()), Inst->getMode()));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitMarkUninitializedInst(MarkUninitializedInst *Inst) {
Expand Down
3 changes: 3 additions & 0 deletions include/swift/SIL/SILDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,9 @@ struct SILDeclRef {
return kind == Kind::Initializer || kind == Kind::Destroyer;
}

/// True if the SILDeclRef references an init accessor declaration.
bool isInitAccessor() const;

/// True if the function should be treated as transparent.
bool isTransparent() const;
/// True if the function should have its body serialized.
Expand Down
Loading