Merge pull request #17604 from Azoy/moar-random-improvements
[stdlib] Remove _random() customization point
diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake
index 6be8b08..04e9b27 100644
--- a/cmake/modules/SwiftSource.cmake
+++ b/cmake/modules/SwiftSource.cmake
@@ -257,9 +257,9 @@
"-Xfrontend" "${GROUP_INFO_JSON_FILE}")
endif()
- # Force swift 3 compatibility mode for Standard Library.
+ # Force swift 4 compatibility mode for Standard Library.
if (SWIFTFILE_IS_STDLIB)
- list(APPEND swift_flags "-swift-version" "3")
+ list(APPEND swift_flags "-swift-version" "4")
endif()
# Force swift 4 compatibility mode for overlays.
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index bb8d6bd..ab3cb49 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -3168,6 +3168,21 @@
llvm::ArrayRef<GenericParamDescriptor> getGenericParams() const;
+ bool isSynthesizedRelatedEntity() const {
+ return getTypeContextDescriptorFlags().isSynthesizedRelatedEntity();
+ }
+
+ /// Return the tag used to discriminate declarations synthesized by the
+ /// Clang importer and give them stable identities.
+ StringRef getSynthesizedDeclRelatedEntityTag() const {
+ if (!isSynthesizedRelatedEntity())
+ return {};
+ // The tag name comes after the null terminator for the name.
+ const char *nameBegin = Name.get();
+ auto *nameEnd = nameBegin + strlen(nameBegin) + 1;
+ return nameEnd;
+ }
+
/// Return the offset of the start of generic arguments in the nominal
/// type's metadata. The returned value is measured in sizeof(void*).
int32_t getGenericArgumentOffset() const;
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0a82e16..e59acda 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -1189,6 +1189,12 @@
///
/// Meaningful for all type-descriptor kinds.
IsReflectable = 2,
+
+ /// Set if the type is a Clang-importer-synthesized related entity. After
+ /// the null terminator for the type name is another null-terminated string
+ /// containing the tag that discriminates the entity from other synthesized
+ /// declarations associated with the same declaration.
+ IsSynthesizedRelatedEntity = 3,
/// Set if the context descriptor is includes metadata for dynamically
/// constructing a class's vtables at metadata instantiation time.
@@ -1221,6 +1227,10 @@
FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTypedef, isCTypedef, setIsCTypedef)
FLAGSET_DEFINE_FLAG_ACCESSORS(IsReflectable, isReflectable, setIsReflectable)
+ FLAGSET_DEFINE_FLAG_ACCESSORS(IsSynthesizedRelatedEntity,
+ isSynthesizedRelatedEntity,
+ setIsSynthesizedRelatedEntity)
+
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
class_hasVTable,
class_setHasVTable)
diff --git a/include/swift/AST/ASTWalker.h b/include/swift/AST/ASTWalker.h
index b112e72..69519f8 100644
--- a/include/swift/AST/ASTWalker.h
+++ b/include/swift/AST/ASTWalker.h
@@ -201,6 +201,16 @@
/// params in AbstractFunctionDecl and NominalTypeDecl.
virtual bool shouldWalkIntoGenericParams() { return false; }
+ /// This method configures whether the walker should walk into the
+ /// initializers of lazy variables. These initializers are semantically
+ /// different from other initializers in their context and so sometimes
+ /// should not be visited.
+ ///
+ /// Note that visiting the body of the lazy getter will find a
+ /// LazyInitializerExpr with the initializer as its sub-expression.
+ /// However, ASTWalker does not walk into LazyInitializerExprs on its own.
+ virtual bool shouldWalkIntoLazyInitializers() { return true; }
+
/// walkToParameterListPre - This method is called when first visiting a
/// ParameterList, before walking into its parameters. If it returns false,
/// the subtree is skipped.
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 553f334..f8b6fc2 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -27,6 +27,7 @@
#include "swift/AST/GenericParamKey.h"
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/LayoutConstraint.h"
+#include "swift/AST/StorageImpl.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Witness.h"
@@ -306,7 +307,7 @@
NumElements : 32
);
- SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
+ SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1+1+1,
AlreadyInLookupTable : 1,
/// Whether we have already checked whether this declaration is a
@@ -315,10 +316,16 @@
/// Whether the decl can be accessed by swift users; for instance,
/// a.storage for lazy var a is a decl that cannot be accessed.
- IsUserAccessible : 1
+ IsUserAccessible : 1,
+
+ /// Whether the "IsObjC" bit has been computed yet.
+ IsObjCComputed : 1,
+
+ /// Whether this declaration is exposed to Objective-C.
+ IsObjC : 1
);
- SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1+4,
+ SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1+1+1,
/// Whether we are overridden later
Overridden : 1,
@@ -328,11 +335,14 @@
/// Whether the setter is mutating.
IsSetterMutating : 1,
- /// The storage kind.
- StorageKind : 4
+ /// Whether this represents physical storage.
+ HasStorage : 1,
+
+ /// Whether this storage supports semantic mutation in some way.
+ SupportsMutation : 1
);
- SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+4+1+1+1,
+ SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+4+1+1+1+1,
/// \brief Whether this property is a type property (currently unfortunately
/// called 'static').
IsStatic : 1,
@@ -351,7 +361,11 @@
/// \brief Whether this is a property used in expressions in the debugger.
/// It is up to the debugger to instruct SIL how to access this variable.
- IsDebuggerVar : 1
+ IsDebuggerVar : 1,
+
+ /// \brief Whether this is a property defined in the debugger's REPL.
+ /// FIXME: Remove this once LLDB has proper support for resilience.
+ IsREPLVar : 1
);
SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1 + NumDefaultArgumentKindBits,
@@ -450,14 +464,7 @@
HasStubImplementation : 1
);
- SWIFT_INLINE_BITFIELD(TypeDecl, ValueDecl, 1,
- /// Whether we have already checked the inheritance clause.
- ///
- /// FIXME: Is this too fine-grained?
- CheckedInheritanceClause : 1
- );
-
- SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl);
+ SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, ValueDecl);
SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16,
: NumPadBits,
@@ -466,7 +473,7 @@
Index : 16
);
- SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl);
+ SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, ValueDecl);
SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+1,
/// Whether the typealias forwards perfectly to its underlying type.
@@ -581,7 +588,7 @@
Associativity : 2
);
- SWIFT_INLINE_BITFIELD(AssociatedTypeDecl, TypeDecl, 1+1,
+ SWIFT_INLINE_BITFIELD(AssociatedTypeDecl, ValueDecl, 1+1,
ComputedOverridden : 1,
HasOverridden : 1
);
@@ -593,7 +600,7 @@
NumPathElements : 8
);
- SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1+1,
+ SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1,
/// An encoding of the default and maximum access level for this extension.
///
/// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
@@ -601,11 +608,6 @@
/// default, and 'private' is never used. 0 represents an uncomputed value.
DefaultAndMaxAccessLevel : 3,
- /// Whether we have already checked the inheritance clause.
- ///
- /// FIXME: Is this too fine-grained?
- CheckedInheritanceClause : 1,
-
/// Whether there is are lazily-loaded conformances for this extension.
HasLazyConformances : 1
);
@@ -1673,16 +1675,6 @@
return hasValidationStarted() && !isBeingValidated();
}
- /// Whether we already type-checked the inheritance clause.
- bool checkedInheritanceClause() const {
- return Bits.ExtensionDecl.CheckedInheritanceClause;
- }
-
- /// Note that we have already type-checked the inheritance clause.
- void setCheckedInheritanceClause(bool checked = true) {
- Bits.ExtensionDecl.CheckedInheritanceClause = checked;
- }
-
bool hasDefaultAccessLevel() const {
return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
}
@@ -1814,13 +1806,14 @@
enum class Flags {
Checked = 1 << 0,
- Removed = 1 << 1
+ Removed = 1 << 1,
+ Lazy = 1 << 2,
};
// When the initializer is removed we don't actually clear the pointer
// because we might need to get initializer's source range. Since the
// initializer is ASTContext-allocated it is safe.
- llvm::PointerIntPair<Expr *, 2, OptionSet<Flags>> InitCheckedAndRemoved;
+ llvm::PointerIntPair<Expr *, 3, OptionSet<Flags>> InitAndFlags;
/// The initializer context used for this pattern binding entry.
DeclContext *InitContext = nullptr;
@@ -1829,26 +1822,35 @@
public:
PatternBindingEntry(Pattern *P, Expr *E, DeclContext *InitContext)
- : ThePattern(P), InitCheckedAndRemoved(E, {}), InitContext(InitContext) {}
+ : ThePattern(P), InitAndFlags(E, {}), InitContext(InitContext) {}
Pattern *getPattern() const { return ThePattern; }
void setPattern(Pattern *P) { ThePattern = P; }
Expr *getInit() const {
- return (InitCheckedAndRemoved.getInt().contains(Flags::Removed))
- ? nullptr : InitCheckedAndRemoved.getPointer();
+ return (InitAndFlags.getInt().contains(Flags::Removed))
+ ? nullptr : InitAndFlags.getPointer();
+ }
+ Expr *getNonLazyInit() const {
+ return isInitializerLazy() ? nullptr : getInit();
}
SourceRange getOrigInitRange() const;
void setInit(Expr *E);
/// Retrieve the initializer as it was written in the source.
- Expr *getInitAsWritten() const { return InitCheckedAndRemoved.getPointer(); }
+ Expr *getInitAsWritten() const { return InitAndFlags.getPointer(); }
bool isInitializerChecked() const {
- return InitCheckedAndRemoved.getInt().contains(Flags::Checked);
+ return InitAndFlags.getInt().contains(Flags::Checked);
}
void setInitializerChecked() {
- InitCheckedAndRemoved.setInt(
- InitCheckedAndRemoved.getInt() | Flags::Checked);
+ InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Checked);
+ }
+
+ bool isInitializerLazy() const {
+ return InitAndFlags.getInt().contains(Flags::Lazy);
+ }
+ void setInitializerLazy() {
+ InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Lazy);
}
// Return the first variable initialized by this pattern.
@@ -1929,6 +1931,9 @@
Expr *getInit(unsigned i) const {
return getPatternList()[i].getInit();
}
+ Expr *getNonLazyInit(unsigned i) const {
+ return getPatternList()[i].getNonLazyInit();
+ }
SourceRange getOrigInitRange(unsigned i) const {
return getPatternList()[i].getOrigInitRange();
@@ -1966,6 +1971,14 @@
void setInitializerChecked(unsigned i) {
getMutablePatternList()[i].setInitializerChecked();
}
+
+ bool isInitializerLazy(unsigned i) const {
+ return getPatternList()[i].isInitializerLazy();
+ }
+
+ void setInitializerLazy(unsigned i) {
+ getMutablePatternList()[i].setInitializerLazy();
+ }
/// Does this binding declare something that requires storage?
bool hasStorage() const;
@@ -2170,6 +2183,8 @@
Bits.ValueDecl.AlreadyInLookupTable = false;
Bits.ValueDecl.CheckedRedeclaration = false;
Bits.ValueDecl.IsUserAccessible = true;
+ Bits.ValueDecl.IsObjCComputed = false;
+ Bits.ValueDecl.IsObjC = false;
}
// MemberLookupTable borrows a bit from this type
@@ -2190,7 +2205,7 @@
/// Determine whether we have already checked whether this
/// declaration is a redeclaration.
bool alreadyCheckedRedeclaration() const {
- return Bits.ValueDecl.CheckedRedeclaration;
+ return Bits.ValueDecl.CheckedRedeclaration;
}
/// Set whether we have already checked this declaration as a
@@ -2405,10 +2420,9 @@
/// This can be true even if there is no 'objc' attribute on the declaration.
/// In that case it was inferred by the type checker and set with a call to
/// markAsObjC().
- bool isObjC() const {
- return getAttrs().hasAttribute<ObjCAttr>();
- }
-
+ bool isObjC() const;
+
+ /// Note whether this declaration is known to be exposed to Objective-C.
void setIsObjC(bool Value);
/// Is this declaration marked with 'final'?
@@ -2477,10 +2491,7 @@
TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
Identifier name, SourceLoc NameLoc,
MutableArrayRef<TypeLoc> inherited) :
- ValueDecl(K, context, name, NameLoc), Inherited(inherited)
- {
- Bits.TypeDecl.CheckedInheritanceClause = false;
- }
+ ValueDecl(K, context, name, NameLoc), Inherited(inherited) {}
public:
Identifier getName() const { return getFullName().getBaseIdentifier(); }
@@ -2504,16 +2515,6 @@
/// Retrieve one of the types listed in the "inherited" clause.
Type getInheritedType(unsigned index) const;
- /// Whether we already type-checked the inheritance clause.
- bool checkedInheritanceClause() const {
- return Bits.TypeDecl.CheckedInheritanceClause;
- }
-
- /// Note that we have already type-checked the inheritance clause.
- void setCheckedInheritanceClause(bool checked = true) {
- Bits.TypeDecl.CheckedInheritanceClause = checked;
- }
-
void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }
static bool classof(const Decl *D) {
@@ -3726,6 +3727,15 @@
bool existentialTypeSupportedSlow(LazyResolver *resolver);
+ struct {
+ /// The superclass type and a bit to indicate whether the
+ /// superclass was computed yet or not.
+ llvm::PointerIntPair<Type, 1, bool> Superclass;
+ } LazySemanticInfo;
+
+ friend class SuperclassTypeRequest;
+ friend class TypeChecker;
+
public:
ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
Identifier Name, MutableArrayRef<TypeLoc> Inherited,
@@ -3736,6 +3746,19 @@
/// Retrieve the set of protocols inherited from this protocol.
llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
+ /// Determine whether this protocol has a superclass.
+ bool hasSuperclass() const { return (bool)getSuperclass(); }
+
+ /// Retrieve the superclass of this protocol, or null if there is no superclass.
+ Type getSuperclass() const;
+
+ /// Retrieve the ClassDecl for the superclass of this protocol, or null if there
+ /// is no superclass.
+ ClassDecl *getSuperclassDecl() const;
+
+ /// Set the superclass of this protocol.
+ void setSuperclass(Type superclass);
+
/// Retrieve the set of AssociatedTypeDecl members of this protocol; this
/// saves loading the set of members in cases where there's no possibility of
/// a protocol having nested types (ObjC protocols).
@@ -3953,71 +3976,6 @@
}
};
-// Note that the values of these enums line up with %select values in
-// diagnostics.
-enum class AccessorKind {
-#define ACCESSOR(ID) ID,
-#define LAST_ACCESSOR(ID) Last = ID
-#include "swift/AST/AccessorKinds.def"
-};
-
-const unsigned NumAccessorKinds = unsigned(AccessorKind::Last) + 1;
-
-static inline IntRange<AccessorKind> allAccessorKinds() {
- return IntRange<AccessorKind>(AccessorKind(0),
- AccessorKind(NumAccessorKinds));
-}
-
-/// The safety semantics of this addressor.
-enum class AddressorKind : uint8_t {
- /// \brief This is not an addressor.
- NotAddressor,
- /// \brief This is an unsafe addressor; it simply returns an address.
- Unsafe,
- /// \brief This is an owning addressor; it returns an AnyObject
- /// which should be released when the caller is done with the object.
- Owning,
- /// \brief This is an owning addressor; it returns a Builtin.NativeObject
- /// which should be released when the caller is done with the object.
- NativeOwning,
- /// \brief This is a pinning addressor; it returns a Builtin.NativeObject?
- /// which should be unpinned when the caller is done with the object.
- NativePinning,
-};
-
-/// Whether an access to storage is for reading, writing, or both.
-enum class AccessKind : uint8_t {
- /// The access is just to read the current value.
- Read,
-
- /// The access is just to overwrite the current value.
- Write,
-
- /// The access may require either reading or writing the current value.
- ReadWrite
-};
-
-/// The way to actually evaluate an access to storage.
-enum class AccessStrategy : uint8_t {
- /// The decl is a VarDecl with its own backing storage; evaluate its
- /// address directly.
- Storage,
-
- /// The decl is a VarDecl with storage defined by a property behavior;
- /// this access may initialize or reassign the storage based on dataflow.
- BehaviorStorage,
-
- /// The decl has addressors; call the appropriate addressor for the
- /// access kind. These calls are currently always direct.
- Addressor,
-
- /// Directly call the getter, setter, or materializeForSet accessor.
- DirectToAccessor,
-
- /// Indirectly call the getter, setter, or materializeForSet accessor.
- DispatchToAccessor,
-};
-
/// Information about a behavior instantiated by a storage declaration.
///
/// TODO: Accessors, composed behaviors
@@ -4054,75 +4012,6 @@
/// SubscriptDecl, representing potentially settable memory locations.
class AbstractStorageDecl : public ValueDecl {
public:
- enum StorageKindTy {
- /// There are bits stored in memory for this object, and they are accessed
- /// directly. This is not valid for a SubscriptDecl.
- Stored,
-
- /// This is a stored property with trivial accessors which simply get and
- /// set the underlying storage. This is not valid for a SubscriptDecl.
- ///
- /// These accessors are used for several different purposes:
- /// 1) In an @objc variable, these accessors are dynamically dispatched
- /// to and may be overridden.
- /// 2) When a stored property satisfies a protocol requirement, these
- /// accessors end up as entries in the witness table.
- /// 3) When a stored property is accessed outside of the storage
- /// declaration's resilience domain, when the owning type or
- /// global variable is resilient.
- StoredWithTrivialAccessors,
-
- /// This is a stored property with either a didSet specifier or a
- /// willSet specifier (or both). Sema synthesizes a setter which
- /// calls them at the appropriate points.
- StoredWithObservers,
-
- /// There are bits stored in memory for this object, but they are
- /// not allocated directly within the container; instead, there
- /// are accessors which return the address of the memory. The
- /// value is accessed directly through the returned address.
- ///
- /// This is legal on both VarDecls and SubscriptDecls.
- ///
- /// There is always at least an 'address' accessor; if the object
- /// is mutable, there will also be a 'mutableAddress' accessor.
- Addressed,
-
- /// Like Addressed, this object has address accessors. Like
- /// StoredWithTrivialAccessors, accessors have been synthesized
- /// which simply read and write through the addresses returned by
- /// the addressors.
- AddressedWithTrivialAccessors,
-
- /// Like Addressed, this object has address accessors. Like
- /// StoredWithObservers, it also has either a willSet specifier or
- /// a didSet specifier. Accessors have been synthesized, like
- /// with StoredWithObservers but using the address returned from
- /// the appropriate accessor instead.
- AddressedWithObservers,
-
- /// This is an override of an object which adds either a didSet
- /// specifier or a willSet specifier (or both). Sema synthesizes
- /// a setter which calls them at the appropriate points around
- /// delegating to the superclass's setter.
- InheritedWithObservers,
-
- /// There is no memory associated with this decl anywhere. It is
- /// accessed by calling a getter and setter. If the setter is
- /// absent, then the value is only loadable, but not storable.
- Computed,
-
- /// This object was specified with non-trivial getter and
- /// mutableAddress accessors. If it is accessed in a read-only
- /// manner, the getter is called; otherwise, mutableAddress is
- /// called.
- ///
- /// This turns out to the be the right thing for certain core data
- /// structures which, when they store a bridged object, cannot
- /// return the address at which the object is stored.
- ComputedWithMutableAddress,
- };
-
static const size_t MaxNumAccessors = 255;
private:
AbstractStorageDecl *OverriddenDecl;
@@ -4135,7 +4024,14 @@
using AccessorIndex = uint8_t;
static const AccessorIndex InvalidIndex = 0;
+ /// The range of the braces around the accessor clause.
SourceRange Braces;
+
+ /// The implementation info for the accessors. If there's no
+ /// AccessorRecord for a storage decl, the decl is just stored.
+ StorageImplInfo ImplInfo;
+
+ /// The number of accessors currently stored in this record.
AccessorIndex NumAccessors;
/// The storage capacity of this record for accessors. Always includes
@@ -4148,14 +4044,19 @@
/// or the index+1 of the accessor in the accessors array.
AccessorIndex AccessorIndices[NumAccessorKinds];
- AccessorRecord(SourceRange braces, ArrayRef<AccessorDecl*> accessors,
+ AccessorRecord(SourceRange braces, StorageImplInfo implInfo,
+ ArrayRef<AccessorDecl*> accessors,
AccessorIndex accessorsCapacity);
public:
static AccessorRecord *create(ASTContext &ctx, SourceRange braces,
+ StorageImplInfo implInfo,
ArrayRef<AccessorDecl*> accessors);
SourceRange getBracesRange() const { return Braces; }
+ const StorageImplInfo &getImplInfo() const { return ImplInfo; }
+ void overwriteImplInfo(StorageImplInfo newInfo) { ImplInfo = newInfo; }
+
inline AccessorDecl *getAccessor(AccessorKind kind) const;
ArrayRef<AccessorDecl *> getAllAccessors() const {
@@ -4176,21 +4077,33 @@
llvm::PointerIntPair<BehaviorRecord*, 3, OptionalEnum<AccessLevel>>
BehaviorInfo;
- void setStorageKind(StorageKindTy K) {
- Bits.AbstractStorageDecl.StorageKind = unsigned(K);
- }
-
void configureAccessor(AccessorDecl *accessor);
+ void setFieldsFromImplInfo(StorageImplInfo implInfo) {
+ Bits.AbstractStorageDecl.HasStorage = implInfo.hasStorage();
+ Bits.AbstractStorageDecl.SupportsMutation = implInfo.supportsMutation();
+ }
protected:
AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
- SourceLoc NameLoc)
+ SourceLoc NameLoc, bool supportsMutation)
: ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) {
- Bits.AbstractStorageDecl.StorageKind = Stored;
+ Bits.AbstractStorageDecl.HasStorage = true;
+ Bits.AbstractStorageDecl.SupportsMutation = supportsMutation;
Bits.AbstractStorageDecl.IsGetterMutating = false;
Bits.AbstractStorageDecl.IsSetterMutating = true;
Bits.AbstractStorageDecl.Overridden = false;
}
+
+ void setSupportsMutationIfStillStored(bool supportsMutation) {
+ if (auto ptr = Accessors.getPointer()) {
+ auto impl = ptr->getImplInfo();
+ if (!impl.isSimpleStored()) return;
+ impl = StorageImplInfo::getSimpleStored(supportsMutation);
+ ptr->overwriteImplInfo(impl);
+ }
+ Bits.AbstractStorageDecl.SupportsMutation = supportsMutation;
+ }
+
public:
/// \brief Should this declaration be treated as if annotated with transparent
@@ -4201,113 +4114,49 @@
/// is a member. Currently only variables can be static.
inline bool isStatic() const; // defined in this header
- /// \brief Determine whether this variable is computed, which means it
- /// has no storage but does have a user-defined getter or setter.
- ///
- StorageKindTy getStorageKind() const {
- return (StorageKindTy) Bits.AbstractStorageDecl.StorageKind;
+ /// \brief Determine how this storage is implemented.
+ StorageImplInfo getImplInfo() const {
+ if (auto ptr = Accessors.getPointer())
+ return ptr->getImplInfo();
+ return StorageImplInfo::getSimpleStored(supportsMutation());
}
+ ReadImplKind getReadImpl() const {
+ return getImplInfo().getReadImpl();
+ }
+ WriteImplKind getWriteImpl() const {
+ return getImplInfo().getWriteImpl();
+ }
+ ReadWriteImplKind getReadWriteImpl() const {
+ return getImplInfo().getReadWriteImpl();
+ }
+
+ /// Overwrite the registered implementation-info. This should be
+ /// used carefully.
+ void overwriteImplInfo(StorageImplInfo implInfo);
+
/// \brief Return true if this is a VarDecl that has storage associated with
/// it.
bool hasStorage() const {
- switch (getStorageKind()) {
- case Stored:
- case StoredWithTrivialAccessors:
- case StoredWithObservers:
- return true;
- case InheritedWithObservers:
- case Computed:
- case ComputedWithMutableAddress:
- case Addressed:
- case AddressedWithTrivialAccessors:
- case AddressedWithObservers:
- return false;
- }
- llvm_unreachable("bad storage kind");
+ return Bits.AbstractStorageDecl.HasStorage;
}
- /// \brief Return true if this is a VarDecl that has storage associated with
- /// it which can be trivially accessed.
- bool hasTrivialStorage() const {
- switch (getStorageKind()) {
- case Stored:
- case StoredWithTrivialAccessors:
- return true;
- case StoredWithObservers:
- case InheritedWithObservers:
- case Computed:
- case ComputedWithMutableAddress:
- case Addressed:
- case AddressedWithTrivialAccessors:
- case AddressedWithObservers:
- return false;
- }
- llvm_unreachable("bad storage kind");
- }
-
- /// \brief Return true if this object has a getter (and, if mutable,
- /// a setter and a materializeForSet).
- bool hasAccessorFunctions() const {
- switch (getStorageKind()) {
- case Addressed:
- case Stored:
- return false;
- case StoredWithTrivialAccessors:
- case StoredWithObservers:
- case InheritedWithObservers:
- case Computed:
- case ComputedWithMutableAddress:
- case AddressedWithTrivialAccessors:
- case AddressedWithObservers:
- return true;
- }
- llvm_unreachable("bad storage kind");
- }
-
- /// \brief Return true if this object has observing accessors.
+ /// \brief Return true if this storage has the basic accessors/capability
+ /// to be mutated. This is generally constant after the accessors are
+ /// installed by the parser/importer/whatever.
///
- /// It's generally not appropriate to use this predicate directly in
- /// a condition; instead, you should be switching on the storage kind.
- bool hasObservers() const {
- switch (getStorageKind()) {
- case Stored:
- case StoredWithTrivialAccessors:
- case Computed:
- case ComputedWithMutableAddress:
- case Addressed:
- case AddressedWithTrivialAccessors:
- return false;
- case StoredWithObservers:
- case InheritedWithObservers:
- case AddressedWithObservers:
- return true;
- }
- llvm_unreachable("bad storage kind");
+ /// Note that this is different from the mutability of the declaration
+ /// in the user language: sometimes we can assign to declarations that
+ /// don't support mutation (e.g. to initialize them), and sometimes we
+ /// can't mutate things that do support mutation (e.g. because their
+ /// setter is private).
+ bool supportsMutation() const {
+ return Bits.AbstractStorageDecl.SupportsMutation;
}
- /// \brief Return true if this object has either an addressor or a
- /// mutable addressor.
- ///
- /// It's generally not appropriate to use this predicate directly in
- /// a condition; instead, you should be switching on the storage
- /// kind. Only use this for diagnostic, AST exploration, or
- /// assertion purposes.
- bool hasAddressors() const {
- switch (getStorageKind()) {
- case Stored:
- case StoredWithTrivialAccessors:
- case StoredWithObservers:
- case InheritedWithObservers:
- case Computed:
- return false;
- case ComputedWithMutableAddress:
- case Addressed:
- case AddressedWithTrivialAccessors:
- case AddressedWithObservers:
- return true;
- }
- llvm_unreachable("bad storage kind");
+ /// Are there any accessors for this declaration, including implicit ones?
+ bool hasAnyAccessors() const {
+ return !getAllAccessors().empty();
}
/// \brief Return true if reading this storage requires the ability to
@@ -4328,26 +4177,22 @@
Bits.AbstractStorageDecl.IsSetterMutating = isMutating;
}
- AccessorDecl *getAccessorFunction(AccessorKind kind) const {
+ AccessorDecl *getAccessor(AccessorKind kind) const {
if (auto info = Accessors.getPointer())
return info->getAccessor(kind);
return nullptr;
}
- ArrayRef<AccessorDecl*> getAllAccessorFunctions() const {
+ ArrayRef<AccessorDecl*> getAllAccessors() const {
if (const auto *info = Accessors.getPointer())
return info->getAllAccessors();
return {};
}
- void setAccessors(StorageKindTy storageKind,
+ void setAccessors(StorageImplInfo storageImpl,
SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
SourceLoc rbraceLoc);
- /// \brief Add trivial accessors to this Stored or Addressed object.
- void addTrivialAccessors(AccessorDecl *Get, AccessorDecl *Set,
- AccessorDecl *MaterializeForSet);
-
/// \brief Add a setter to an existing Computed var.
///
/// This should only be used by the ClangImporter.
@@ -4356,10 +4201,14 @@
/// \brief Add a behavior to a property.
void addBehavior(TypeRepr *Type, Expr *Param);
- /// \brief Set a materializeForSet accessor for this declaration.
- ///
- /// This should only be used by Sema.
- void setMaterializeForSetFunc(AccessorDecl *materializeForSet);
+ /// \brief Add a synthesized getter.
+ void setSynthesizedGetter(AccessorDecl *getter);
+
+ /// \brief Add a synthesized setter.
+ void setSynthesizedSetter(AccessorDecl *setter);
+
+ /// \brief Add a synthesized materializeForSet accessor.
+ void setSynthesizedMaterializeForSet(AccessorDecl *materializeForSet);
SourceRange getBracesRange() const {
if (auto info = Accessors.getPointer())
@@ -4369,12 +4218,12 @@
/// \brief Retrieve the getter used to access the value of this variable.
AccessorDecl *getGetter() const {
- return getAccessorFunction(AccessorKind::Get);
+ return getAccessor(AccessorKind::Get);
}
/// \brief Retrieve the setter used to mutate the value of this variable.
AccessorDecl *getSetter() const {
- return getAccessorFunction(AccessorKind::Set);
+ return getAccessor(AccessorKind::Set);
}
AccessLevel getSetterFormalAccess() const {
@@ -4393,18 +4242,18 @@
/// \brief Retrieve the materializeForSet function, if this
/// declaration has one.
AccessorDecl *getMaterializeForSetFunc() const {
- return getAccessorFunction(AccessorKind::MaterializeForSet);
+ return getAccessor(AccessorKind::MaterializeForSet);
}
/// \brief Return the decl for the immutable addressor if it exists.
AccessorDecl *getAddressor() const {
- return getAccessorFunction(AccessorKind::Address);
+ return getAccessor(AccessorKind::Address);
}
/// \brief Return the decl for the 'mutableAddress' accessors if
/// it exists; this is only valid on a declaration with addressors.
AccessorDecl *getMutableAddressor() const {
- return getAccessorFunction(AccessorKind::MutableAddress);
+ return getAccessor(AccessorKind::MutableAddress);
}
/// \brief Return the appropriate addressor for the given access kind.
@@ -4417,13 +4266,13 @@
/// \brief Return the decl for the willSet specifier if it exists, this is
/// only valid on a declaration with Observing storage.
AccessorDecl *getWillSetFunc() const {
- return getAccessorFunction(AccessorKind::WillSet);
+ return getAccessor(AccessorKind::WillSet);
}
/// \brief Return the decl for the didSet specifier if it exists, this is
/// only valid on a declaration with Observing storage.
AccessorDecl *getDidSetFunc() const {
- return getAccessorFunction(AccessorKind::DidSet);
+ return getAccessor(AccessorKind::DidSet);
}
/// Given that this is an Objective-C property or subscript declaration,
@@ -4550,12 +4399,13 @@
VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList,
SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC)
- : AbstractStorageDecl(Kind, DC, Name, NameLoc)
+ : AbstractStorageDecl(Kind, DC, Name, NameLoc, !isImmutableSpecifier(Sp))
{
Bits.VarDecl.IsStatic = IsStatic;
Bits.VarDecl.Specifier = static_cast<unsigned>(Sp);
Bits.VarDecl.IsCaptureList = IsCaptureList;
Bits.VarDecl.IsDebuggerVar = false;
+ Bits.VarDecl.IsREPLVar = false;
Bits.VarDecl.HasNonPatternBindingInit = false;
setType(Ty);
}
@@ -4669,9 +4519,7 @@
Specifier getSpecifier() const {
return static_cast<Specifier>(Bits.VarDecl.Specifier);
}
- void setSpecifier(Specifier Spec) {
- Bits.VarDecl.Specifier = static_cast<unsigned>(Spec);
- }
+ void setSpecifier(Specifier Spec);
/// Is the type of this parameter 'inout'?
///
@@ -4692,7 +4540,10 @@
StaticSpellingKind getCorrectStaticSpelling() const;
bool isImmutable() const {
- switch (getSpecifier()) {
+ return isImmutableSpecifier(getSpecifier());
+ }
+ static bool isImmutableSpecifier(Specifier sp) {
+ switch (sp) {
case Specifier::Let:
case Specifier::Shared:
case Specifier::Owned:
@@ -4742,6 +4593,13 @@
void setDebuggerVar(bool IsDebuggerVar) {
Bits.VarDecl.IsDebuggerVar = IsDebuggerVar;
}
+
+ /// Is this a special debugger REPL variable?
+ /// FIXME: Remove this once LLDB has proper support for resilience.
+ bool isREPLVar() const { return Bits.VarDecl.IsREPLVar; }
+ void setREPLVar(bool IsREPLVar) {
+ Bits.VarDecl.IsREPLVar = IsREPLVar;
+ }
/// Return the Objective-C runtime name for this property.
Identifier getObjCPropertyName() const;
@@ -4934,7 +4792,8 @@
SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
GenericParamList *GenericParams)
: GenericContext(DeclContextKind::SubscriptDecl, Parent),
- AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
+ AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc,
+ /*supports mutation (will be overwritten)*/ true),
ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
setIndices(Indices);
setGenericParams(GenericParams);
diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def
index 8246eab..4c33af6 100644
--- a/include/swift/AST/DiagnosticsCommon.def
+++ b/include/swift/AST/DiagnosticsCommon.def
@@ -93,6 +93,24 @@
ERROR(function_type_no_parens,none,
"single argument function types require parentheses", ())
+//------------------------------------------------------------------------------
+// MARK: Circular reference diagnostics
+//------------------------------------------------------------------------------
+ERROR(circular_reference, none,
+ "circular reference", ())
+
+ERROR(redundant_type_alias_define, none,
+ "redundant type alias declaration", ())
+
+NOTE(circular_reference_through, none,
+ "through reference here", ())
+
+ERROR(circular_class_inheritance,none,
+ "%0 inherits from itself", (Identifier))
+
+ERROR(circular_enum_inheritance,none,
+ "%0 has a raw type that depends on itself", (Identifier))
+
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index cc6ba01..ef58c27 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -283,9 +283,9 @@
ERROR(observingproperty_with_getset,none,
"%select{willSet|didSet}0 variable must not also have a "
"%select{get|set}1 specifier", (unsigned, unsigned))
-ERROR(observingproperty_without_mutableaddress,none,
- "%select{willSet|didSet}0 variable with addressor must provide a "
- "'mutableAddress' accessor", (unsigned))
+ERROR(observingproperty_with_address,none,
+ "variable with addressor may not have %select{willSet|didSet}0",
+ (unsigned))
ERROR(observingproperty_in_subscript,none,
"%select{willSet|didSet}0 is not allowed in subscripts", (unsigned))
ERROR(getset_init,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 5fd05de..a461fae 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1826,7 +1826,7 @@
"generic parameter base", (Identifier))
ERROR(circular_protocol_def,none,
- "circular protocol inheritance %0", (StringRef))
+ "protocol %0 refines itself", (Identifier))
ERROR(objc_protocol_inherits_non_objc_protocol,none,
"@objc protocol %0 cannot refine non-@objc protocol %1", (Type, Type))
WARNING(protocol_composition_with_postfix,none,
@@ -2155,8 +2155,6 @@
NOTE(superclass_here,none,"superclass is declared here", ())
ERROR(superclass_of_open_not_open,none,
"superclass %0 of open class must be open", (Type))
-ERROR(circular_class_inheritance,none,
- "circular class inheritance %0", (StringRef))
ERROR(inheritance_from_final_class,none,
"inheritance from a final class %0", (Identifier))
ERROR(inheritance_from_unspecialized_objc_generic_class,none,
@@ -2199,8 +2197,6 @@
// Enum raw types
ERROR(multiple_enum_raw_types,none,
"multiple enum raw types %0 and %1", (Type, Type))
-ERROR(circular_enum_inheritance,none,
- "circular enum raw types %0", (StringRef))
ERROR(raw_type_not_first,none,
"raw type %0 must appear first in the enum inheritance clause", (Type))
ERROR(raw_type_not_literal_convertible,none,
@@ -2799,12 +2795,19 @@
// Partial application of foreign functions not supported
ERROR(partial_application_of_function_invalid,none,
"partial application of %select{"
- "function with 'inout' parameters|"
"'mutating' method|"
"'super.init' initializer chain|"
"'self.init' initializer delegation"
"}0 is not allowed",
(unsigned))
+WARNING(partial_application_of_function_invalid_swift4,none,
+ "partial application of %select{"
+ "'mutating' method|"
+ "'super.init' initializer chain|"
+ "'self.init' initializer delegation"
+ "}0 is not allowed; calling the function has undefined behavior and will "
+ "be an error in future Swift versions",
+ (unsigned))
ERROR(self_assignment_var,none,
"assigning a variable to itself", ())
@@ -4062,18 +4065,6 @@
(Identifier, unsigned))
//------------------------------------------------------------------------------
-// MARK: Circular reference diagnostics
-//------------------------------------------------------------------------------
-ERROR(circular_reference, none,
- "circular reference", ())
-
-ERROR(redundant_type_alias_define, none,
- "redundant type alias declaration", ())
-
-NOTE(circular_reference_through, none,
- "through reference here", ())
-
-//------------------------------------------------------------------------------
// MARK: Debug diagnostics
//------------------------------------------------------------------------------
diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h
index 985b4c7..78cb3ce 100644
--- a/include/swift/AST/Evaluator.h
+++ b/include/swift/AST/Evaluator.h
@@ -37,12 +37,23 @@
namespace swift {
+using llvm::ArrayRef;
using llvm::Optional;
using llvm::None;
class DiagnosticEngine;
+class Evaluator;
class UnifiedStatsReporter;
+/// An "abstract" request function pointer, which is the storage type
+/// used for each of the
+using AbstractRequestFunction = void(void);
+
+/// Form the specific request function for the given request type.
+template<typename Request>
+using RequestFunction =
+ typename Request::OutputType(const Request &, Evaluator &);
+
/// Pretty stack trace handler for an arbitrary request.
template<typename Request>
class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry {
@@ -59,7 +70,7 @@
};
/// Report that a request of the given kind is being evaluated, so it
-/// can be recoded by the stats reporter.
+/// can be recorded by the stats reporter.
template<typename Request>
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
const Request &request) { }
@@ -138,6 +149,18 @@
/// non-null.
UnifiedStatsReporter *stats = nullptr;
+ /// A vector containing the abstract request functions that can compute
+ /// the result of a particular request within a given zone. The
+ /// \c uint8_t is the zone number of the request, and the array is
+ /// indexed by the index of the request type within that zone. Each
+ /// entry is a function pointer that will be reinterpret_cast'd to
+ ///
+ /// RequestType::OutputType (*)(const RequestType &request,
+ /// Evaluator &evaluator);
+ /// and called to satisfy the request.
+ std::vector<std::pair<uint8_t, ArrayRef<AbstractRequestFunction *>>>
+ requestFunctionsByZone;
+
/// A vector containing all of the active evaluation requests, which
/// is treated as a stack and is used to detect cycles.
llvm::SetVector<AnyRequest> activeRequests;
@@ -156,6 +179,19 @@
/// so all clients must cope with cycles.
llvm::DenseMap<AnyRequest, std::vector<AnyRequest>> dependencies;
+ /// Retrieve the request function for the given zone and request IDs.
+ AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID,
+ uint8_t requestID) const;
+
+ /// Retrieve the request function for the given request type.
+ template<typename Request>
+ auto getRequestFunction() const -> RequestFunction<Request> * {
+ auto abstractFn = getAbstractRequestFunction(TypeID<Request>::zoneID,
+ TypeID<Request>::localID);
+ assert(abstractFn && "No request function for request");
+ return reinterpret_cast<RequestFunction<Request> *>(abstractFn);
+ }
+
public:
/// Construct a new evaluator that can emit cyclic-dependency
/// diagnostics through the given diagnostics engine.
@@ -165,6 +201,13 @@
/// statistics will be recorded.
void setStatsReporter(UnifiedStatsReporter *stats) { this->stats = stats; }
+ /// Register the set of request functions for the given zone.
+ ///
+ /// These functions will be called to evaluate any requests within that
+ /// zone.
+ void registerRequestFunctions(uint8_t zoneID,
+ ArrayRef<AbstractRequestFunction *> functions);
+
/// Evaluate the given request and produce its result,
/// consulting/populating the cache as required.
template<typename Request>
@@ -247,7 +290,7 @@
/// Update statistics.
if (stats) reportEvaluatedRequest(*stats, request);
- return request(*this);
+ return getRequestFunction<Request>()(request, *this);
}
/// Get the result of a request, consulting an external cache
@@ -260,17 +303,8 @@
if (auto cached = request.getCachedResult())
return *cached;
- // Clear out the dependencies on this request; we're going to recompute
- // them now anyway.
- dependencies[request].clear();
-
- PrettyStackTraceRequest<Request> prettyStackTrace(request);
-
- /// Update statistics.
- if (stats) reportEvaluatedRequest(*stats, request);
-
- // Service the request.
- auto result = request(*this);
+ // Compute the result.
+ auto result = getResultUncached(request);
// Cache the result.
request.cacheResult(result);
@@ -293,12 +327,8 @@
return known->second.castTo<typename Request::OutputType>();
}
- // Clear out the dependencies on this request; we're going to recompute
- // them now anyway.
- dependencies[request].clear();
-
- // Evaluate the request.
- auto result = request(*this);
+ // Compute the result.
+ auto result = getResultUncached(request);
// Cache the result.
cache.insert({anyRequest, result});
@@ -314,7 +344,7 @@
llvm::raw_ostream &out,
llvm::DenseSet<AnyRequest> &visitedAnywhere,
llvm::SmallVectorImpl<AnyRequest> &visitedAlongPath,
- llvm::ArrayRef<AnyRequest> highlightPath,
+ ArrayRef<AnyRequest> highlightPath,
std::string &prefixStr,
bool lastChild) const;
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 7ae0df4..edfa810 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -104,15 +104,19 @@
Last_CheckedCastKind = Swift3BridgingDowncast,
};
+/// What are the high-level semantics of this access?
enum class AccessSemantics : uint8_t {
- /// On a property or subscript reference, this is a direct access to
- /// the underlying storage. On a function reference, this is a
- /// non-polymorphic access to a particular implementation.
+ /// On a storage reference, this is a direct access to the underlying
+ /// physical storage, bypassing any observers. The declaration must be
+ /// a variable with storage.
+ ///
+ /// On a function reference, this is a non-polymorphic access to a
+ /// particular implementation.
DirectToStorage,
- /// On a property or subscript reference, this is a direct,
- /// non-polymorphic access to the getter/setter accessors.
- DirectToAccessor,
+ /// On a storage reference, this is a direct access to the concrete
+ /// implementation of this storage, bypassing any possibility of override.
+ DirectToImplementation,
/// On a property or subscript reference, this is an access to a property
/// behavior that may be an initialization. Reads always go through the
@@ -4612,6 +4616,28 @@
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
};
+/// A LazyInitializerExpr is used to embed an existing typechecked
+/// expression --- like the initializer of a lazy variable --- into an
+/// untypechecked AST.
+class LazyInitializerExpr : public Expr {
+ Expr *SubExpr;
+public:
+ LazyInitializerExpr(Expr *subExpr)
+ : Expr(ExprKind::LazyInitializer, /*implicit*/ true),
+ SubExpr(subExpr) {}
+
+ SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
+ SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
+ SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
+ SourceLoc getLoc() const { return SubExpr->getLoc(); }
+
+ Expr *getSubExpr() const { return SubExpr; }
+
+ static bool classof(const Expr *E) {
+ return E->getKind() == ExprKind::LazyInitializer;
+ }
+};
+
/// Produces the Objective-C selector of the referenced method.
///
/// \code
diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def
index 30b3c9f..9dd9137 100644
--- a/include/swift/AST/ExprNodes.def
+++ b/include/swift/AST/ExprNodes.def
@@ -182,6 +182,7 @@
EXPR(Assign, Expr)
EXPR(CodeCompletion, Expr)
UNCHECKED_EXPR(UnresolvedPattern, Expr)
+EXPR(LazyInitializer, Expr)
EXPR(EditorPlaceholder, Expr)
EXPR(ObjCSelector, Expr)
EXPR(KeyPath, Expr)
diff --git a/include/swift/AST/Initializer.h b/include/swift/AST/Initializer.h
index c3ce60d..754056a 100644
--- a/include/swift/AST/Initializer.h
+++ b/include/swift/AST/Initializer.h
@@ -99,6 +99,11 @@
unsigned getBindingIndex() const { return SpareBits; }
+ /// If this initializes a single @lazy variable, return it.
+ VarDecl *getInitializedLazyVar() const;
+
+ /// If this initializes a single @lazy variable, lazily create a self
+ /// declaration for it to refer to.
ParamDecl *getImplicitSelfDecl();
static bool classof(const DeclContext *DC) {
diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h
index a630968..560b9c5 100644
--- a/include/swift/AST/LazyResolver.h
+++ b/include/swift/AST/LazyResolver.h
@@ -71,17 +71,6 @@
/// Resolve the "is Objective-C" bit for the given declaration.
virtual void resolveIsObjC(ValueDecl *VD) = 0;
- /// Retrieve the superclass of the given class.
- virtual Type getSuperclass(const ClassDecl *classDecl) = 0;
-
- /// Resolve the raw type of the given enum.
- virtual Type getRawType(EnumDecl *enumDecl) = 0;
-
- /// Get a specific inherited type from the given declaration.
- virtual Type getInheritedType(
- llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
- unsigned index) = 0;
-
/// Resolve the trailing where clause of the given protocol in-place.
virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;
diff --git a/include/swift/AST/SimpleRequest.h b/include/swift/AST/SimpleRequest.h
index cf41659..4b483b1 100644
--- a/include/swift/AST/SimpleRequest.h
+++ b/include/swift/AST/SimpleRequest.h
@@ -56,7 +56,7 @@
/// important one takes an evaluator and the input values, then computes the
/// final result:
/// \code
-/// Output operator()(Evaluator &evaluator, Inputs...) const;
+/// Output evaluate(Evaluator &evaluator, Inputs...) const;
/// \endcode
///
/// The \c Derived class will also need to implement an operation to break a
@@ -105,8 +105,8 @@
template<size_t ...Indices>
Output callDerived(Evaluator &evaluator,
llvm::index_sequence<Indices...>) const {
- static_assert(sizeof...(Indices) > 0, "Subclass must define operator()");
- return asDerived()(evaluator, std::get<Indices>(storage)...);
+ static_assert(sizeof...(Indices) > 0, "Subclass must define evaluate()");
+ return asDerived().evaluate(evaluator, std::get<Indices>(storage)...);
}
template<size_t ...Indices>
@@ -130,8 +130,11 @@
explicit SimpleRequest(const Inputs& ...inputs)
: storage(inputs...) { }
- OutputType operator()(Evaluator &evaluator) const {
- return callDerived(evaluator, llvm::index_sequence_for<Inputs...>());
+ /// Request evaluation function that will be registered with the evaluator.
+ static OutputType evaluateRequest(const Derived &request,
+ Evaluator &evaluator) {
+ return request.callDerived(evaluator,
+ llvm::index_sequence_for<Inputs...>());
}
void diagnoseCycle(DiagnosticEngine &diags) const {
diff --git a/include/swift/AST/StorageImpl.h b/include/swift/AST/StorageImpl.h
new file mode 100644
index 0000000..ee4097d
--- /dev/null
+++ b/include/swift/AST/StorageImpl.h
@@ -0,0 +1,362 @@
+//===--- StorageImpl.h - Storage declaration access impl --------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types for describing the implementation of an
+// AbstractStorageDecl.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_STORAGEIMPL_H
+#define SWIFT_STORAGEIMPL_H
+
+#include "swift/Basic/Range.h"
+
+namespace swift {
+
+// Note that the values of these enums line up with %select values in
+// diagnostics.
+enum class AccessorKind {
+#define ACCESSOR(ID) ID,
+#define LAST_ACCESSOR(ID) Last = ID
+#include "swift/AST/AccessorKinds.def"
+};
+
+const unsigned NumAccessorKinds = unsigned(AccessorKind::Last) + 1;
+
+static inline IntRange<AccessorKind> allAccessorKinds() {
+ return IntRange<AccessorKind>(AccessorKind(0),
+ AccessorKind(NumAccessorKinds));
+}
+
+/// The safety semantics of this addressor.
+enum class AddressorKind : uint8_t {
+ /// \brief This is not an addressor.
+ NotAddressor,
+ /// \brief This is an unsafe addressor; it simply returns an address.
+ Unsafe,
+ /// \brief This is an owning addressor; it returns an AnyObject
+ /// which should be released when the caller is done with the object.
+ Owning,
+ /// \brief This is an owning addressor; it returns a Builtin.NativeObject
+ /// which should be released when the caller is done with the object.
+ NativeOwning,
+ /// \brief This is a pinning addressor; it returns a Builtin.NativeObject?
+ /// which should be unpinned when the caller is done with the object.
+ NativePinning,
+};
+
+/// Whether an access to storage is for reading, writing, or both.
+enum class AccessKind : uint8_t {
+ /// The access is just to read the current value.
+ Read,
+
+ /// The access is just to overwrite the current value.
+ Write,
+
+ /// The access may require either reading or writing the current value.
+ ReadWrite
+};
+
+/// Produce the aggregate access kind of the combination of two accesses.
+inline AccessKind combineAccessKinds(AccessKind a, AccessKind b) {
+ // If they're the same, use that; otherwise, all combinations combine
+ // ReadWrite.
+ return (a == b ? a : AccessKind::ReadWrite);
+}
+
+class AccessStrategy {
+public:
+ enum Kind : uint8_t {
+ /// The declaration is a VarDecl with its own physical storage; access
+ /// that storage directly.
+ Storage,
+
+ /// The decl is a VarDecl with storage defined by a property behavior;
+ /// this access may initialize or reassign the storage based on dataflow.
+ BehaviorStorage,
+
+ /// Directly call an accessor of some sort. The strategy includes
+ /// an accessor kind.
+ DirectToAccessor,
+
+ /// Dispatch to an accessor of some sort. The strategy includes an
+ /// accessor kind.
+ DispatchToAccessor,
+
+ /// The access is a ReadWrite access and should be implemented by
+ /// separately performing a Read into a temporary variable followed by
+ /// a Write access back into the storage.
+ MaterializeToTemporary,
+ };
+
+private:
+ Kind TheKind;
+ Kind FirstKind;
+ AccessorKind FirstAccessor;
+ Kind SecondKind;
+ AccessorKind SecondAccessor;
+
+ AccessStrategy(Kind kind)
+ : TheKind(kind) {
+ assert(kind == Storage || kind == BehaviorStorage);
+ }
+
+ AccessStrategy(Kind kind, AccessorKind accessor)
+ : TheKind(kind), FirstAccessor(accessor) {
+ // Generally used for one of the accessor strategies, but also used
+ // for constructing a first or second strategy.
+ }
+
+ AccessStrategy(AccessStrategy readStrategy, AccessStrategy writeStrategy)
+ : TheKind(MaterializeToTemporary),
+ FirstKind(readStrategy.TheKind),
+ FirstAccessor(readStrategy.FirstAccessor),
+ SecondKind(writeStrategy.TheKind),
+ SecondAccessor(writeStrategy.FirstAccessor) {
+ assert(readStrategy.TheKind != MaterializeToTemporary);
+ assert(writeStrategy.TheKind != MaterializeToTemporary);
+ }
+
+public:
+ static AccessStrategy getStorage() {
+ return { Storage };
+ }
+
+ static AccessStrategy getBehaviorStorage() {
+ return { BehaviorStorage };
+ }
+
+ static AccessStrategy getAccessor(AccessorKind accessor, bool dispatched) {
+ return { dispatched ? DispatchToAccessor : DirectToAccessor, accessor };
+ }
+
+ static AccessStrategy getMaterializeToTemporary(AccessStrategy read,
+ AccessStrategy write) {
+ return { read, write };
+ }
+
+ Kind getKind() const { return TheKind; }
+
+ AccessorKind getAccessor() const {
+ assert(TheKind == DirectToAccessor || TheKind == DispatchToAccessor);
+ return FirstAccessor;
+ }
+
+ AccessStrategy getReadStrategy() const {
+ assert(TheKind == MaterializeToTemporary);
+ return { FirstKind, FirstAccessor };
+ }
+ AccessStrategy getWriteStrategy() const {
+ assert(TheKind == MaterializeToTemporary);
+ return { SecondKind, SecondAccessor };
+ }
+};
+
+/// How are read accesses implemented?
+enum class ReadImplKind {
+ /// There's storage.
+ Stored,
+
+ /// The superclass's read implementation is directly inherited.
+ Inherited,
+
+ /// There's a getter.
+ Get,
+
+ /// There's an immutable addressor.
+ Address,
+};
+enum { NumReadImplKindBits = 2 };
+
+StringRef getReadImplKindName(ReadImplKind kind);
+
+/// How are simple write accesses implemented?
+enum class WriteImplKind {
+ /// It's immutable.
+ Immutable,
+
+ /// There's storage.
+ Stored,
+
+ /// There are observers on top of the storage.
+ /// TODO: maybe add a StoredWithDidSet here and to ReadWriteImplKind?
+ StoredWithObservers,
+
+ /// There are observers on top of the superclass's write implementation.
+ InheritedWithObservers,
+
+ /// There's a setter.
+ Set,
+
+ /// There's a mutable addressor.
+ MutableAddress,
+};
+enum { NumWriteImplKindBits = 3 };
+
+StringRef getWriteImplKindName(WriteImplKind kind);
+
+/// How are read-write accesses implemented?
+enum class ReadWriteImplKind {
+ /// It's immutable.
+ Immutable,
+
+ /// There's storage.
+ Stored,
+
+ /// There's a materializeForSet. (This is currently only used for opaque
+ /// declarations.)
+ MaterializeForSet,
+
+ /// There's a mutable addressor.
+ MutableAddress,
+
+ /// Do a read into a temporary and then a write back.
+ MaterializeToTemporary,
+};
+enum { NumReadWriteImplKindBits = 3 };
+
+StringRef getReadWriteImplKindName(ReadWriteImplKind kind);
+
+class StorageImplInfo {
+ using IntType = uint16_t;
+ static_assert(NumReadImplKindBits + NumWriteImplKindBits
+ + NumReadWriteImplKindBits <= 16,
+ "bit count exceeds IntType range");
+ IntType Read : NumReadImplKindBits;
+ IntType Write : NumWriteImplKindBits;
+ IntType ReadWrite : NumReadWriteImplKindBits;
+
+public:
+ /// A convenience constructor for building immutable storage.
+ StorageImplInfo(ReadImplKind readImpl)
+ : StorageImplInfo(readImpl, WriteImplKind::Immutable,
+ ReadWriteImplKind::Immutable) {}
+
+ /// The primary constructor.
+ StorageImplInfo(ReadImplKind readImpl,
+ WriteImplKind writeImpl,
+ ReadWriteImplKind readWriteImpl)
+ : Read(IntType(readImpl)),
+ Write(IntType(writeImpl)),
+ ReadWrite(IntType(readWriteImpl)) {
+#ifndef NDEBUG
+ assert((writeImpl == WriteImplKind::Immutable)
+ == (readWriteImpl == ReadWriteImplKind::Immutable) &&
+ "write and read-write disagree about immutability");
+
+ switch (writeImpl) {
+ case WriteImplKind::Immutable:
+ // No other consistency checks are required if the storage is immutable.
+ return;
+
+ case WriteImplKind::Stored:
+ assert(readImpl == ReadImplKind::Stored);
+ assert(readWriteImpl == ReadWriteImplKind::Stored);
+ return;
+
+ case WriteImplKind::StoredWithObservers:
+ assert(readImpl == ReadImplKind::Stored);
+ assert(readWriteImpl == ReadWriteImplKind::MaterializeToTemporary);
+ return;
+
+ case WriteImplKind::InheritedWithObservers:
+ assert(readImpl == ReadImplKind::Inherited);
+ assert(readWriteImpl == ReadWriteImplKind::MaterializeToTemporary);
+ return;
+
+ case WriteImplKind::Set:
+ assert(readImpl == ReadImplKind::Get);
+ assert(readWriteImpl == ReadWriteImplKind::MaterializeToTemporary ||
+ readWriteImpl == ReadWriteImplKind::MaterializeForSet);
+ return;
+
+ case WriteImplKind::MutableAddress:
+ assert(readImpl == ReadImplKind::Get ||
+ readImpl == ReadImplKind::Address);
+ assert(readWriteImpl == ReadWriteImplKind::MutableAddress);
+ return;
+ }
+ llvm_unreachable("bad write impl kind");
+#endif
+ }
+
+ static StorageImplInfo getSimpleStored(bool supportsMutation) {
+ return { ReadImplKind::Stored,
+ supportsMutation ? WriteImplKind::Stored
+ : WriteImplKind::Immutable,
+ supportsMutation ? ReadWriteImplKind::Stored
+ : ReadWriteImplKind::Immutable };
+ }
+
+ static StorageImplInfo getOpaque(bool supportsMutation) {
+ return (supportsMutation ? getMutableOpaque() : getImmutableOpaque());
+ }
+
+ /// Describe the implementation of a immutable property implemented opaquely.
+ static StorageImplInfo getImmutableOpaque() {
+ return { ReadImplKind::Get };
+ }
+
+ /// Describe the implementation of a mutable property implemented opaquely.
+ static StorageImplInfo getMutableOpaque() {
+ return { ReadImplKind::Get, WriteImplKind::Set,
+ ReadWriteImplKind::MaterializeForSet };
+ }
+
+ static StorageImplInfo getComputed(bool supportsMutation) {
+ return (supportsMutation ? getMutableComputed() : getImmutableComputed());
+ }
+
+ /// Describe the implementation of an immutable property implemented
+ /// with just a getter.
+ static StorageImplInfo getImmutableComputed() {
+ return { ReadImplKind::Get };
+ }
+
+ /// Describe the implementation of a mutable property implemented with
+ /// getter and setter.
+ static StorageImplInfo getMutableComputed() {
+ return { ReadImplKind::Get, WriteImplKind::Set,
+ ReadWriteImplKind::MaterializeToTemporary };
+ }
+
+ /// Does this implementation description require storage?
+ bool hasStorage() const {
+ return getReadImpl() == ReadImplKind::Stored;
+ }
+
+ /// Does this describe a simply-stored variable?
+ bool isSimpleStored() const {
+ return getReadImpl() == ReadImplKind::Stored &&
+ (getWriteImpl() == WriteImplKind::Stored ||
+ getWriteImpl() == WriteImplKind::Immutable);
+ }
+
+ /// Does this describe storage that supports mutation?
+ bool supportsMutation() const {
+ return getWriteImpl() != WriteImplKind::Immutable;
+ }
+
+ ReadImplKind getReadImpl() const {
+ return ReadImplKind(Read);
+ }
+ WriteImplKind getWriteImpl() const {
+ return WriteImplKind(Write);
+ }
+ ReadWriteImplKind getReadWriteImpl() const {
+ return ReadWriteImplKind(ReadWrite);
+ }
+};
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/Sema/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h
similarity index 86%
rename from include/swift/Sema/TypeCheckRequests.h
rename to include/swift/AST/TypeCheckRequests.h
index 2da1459..f2400b9 100644
--- a/include/swift/Sema/TypeCheckRequests.h
+++ b/include/swift/AST/TypeCheckRequests.h
@@ -46,15 +46,14 @@
public:
using SimpleRequest::SimpleRequest;
- using SimpleRequest::operator();
private:
friend class SimpleRequest;
// Evaluation.
- Type operator()(Evaluator &evaluator,
- llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
- unsigned index) const;
+ Type evaluate(Evaluator &evaluator,
+ llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
+ unsigned index) const;
public:
// Cycle handling
@@ -73,16 +72,15 @@
public SimpleRequest<SuperclassTypeRequest,
CacheKind::SeparatelyCached,
Type,
- ClassDecl *> {
+ NominalTypeDecl *> {
public:
using SimpleRequest::SimpleRequest;
- using SimpleRequest::operator();
private:
friend class SimpleRequest;
// Evaluation.
- Type operator()(Evaluator &evaluator, ClassDecl *classDecl) const;
+ Type evaluate(Evaluator &evaluator, NominalTypeDecl *classDecl) const;
public:
// Cycle handling
@@ -104,13 +102,12 @@
EnumDecl *> {
public:
using SimpleRequest::SimpleRequest;
- using SimpleRequest::operator();
private:
friend class SimpleRequest;
// Evaluation.
- Type operator()(Evaluator &evaluator, EnumDecl *enumDecl) const;
+ Type evaluate(Evaluator &evaluator, EnumDecl *enumDecl) const;
public:
// Cycle handling
@@ -124,8 +121,11 @@
void cacheResult(Type value) const;
};
-#define SWIFT_TYPEID_ZONE 10
-#define SWIFT_TYPEID_HEADER "swift/Sema/TypeCheckerTypeIDZone.def"
+/// The zone number for the type checker.
+#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
+
+#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE
+#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"
// Set up reporting of evaluated requests.
@@ -135,7 +135,7 @@
const RequestType &request) { \
++stats.getFrontendCounters().RequestType; \
}
-#include "swift/Sema/TypeCheckerTypeIDZone.def"
+#include "swift/AST/TypeCheckerTypeIDZone.def"
#undef SWIFT_TYPEID
} // end namespace swift
diff --git a/include/swift/Sema/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def
similarity index 92%
rename from include/swift/Sema/TypeCheckerTypeIDZone.def
rename to include/swift/AST/TypeCheckerTypeIDZone.def
index f931845..44732e6 100644
--- a/include/swift/Sema/TypeCheckerTypeIDZone.def
+++ b/include/swift/AST/TypeCheckerTypeIDZone.def
@@ -1,4 +1,4 @@
-//===--- ArithmeticEvaluatorTypeIDZone.def - --------------------*- C++ -*-===//
+//===--- TypeCheckerTypeIDZone.def ------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Basic/DefineTypeIDZone.h b/include/swift/Basic/DefineTypeIDZone.h
index fe23539..734505b 100644
--- a/include/swift/Basic/DefineTypeIDZone.h
+++ b/include/swift/Basic/DefineTypeIDZone.h
@@ -46,15 +46,15 @@
};
// Second pass: create specializations of TypeID for these types.
-#define SWIFT_TYPEID_NAMED(Type, Name) \
-template<> struct TypeID<Type> { \
- static const uint64_t value = \
- formTypeID(SWIFT_TYPEID_ZONE, \
- TypeIDZoneTypes<SWIFT_TYPEID_ZONE>::Name); \
- \
- static llvm::StringRef getName() { \
- return #Name; \
- } \
+#define SWIFT_TYPEID_NAMED(Type, Name) \
+template<> struct TypeID<Type> { \
+ static const uint8_t zoneID = SWIFT_TYPEID_ZONE; \
+ static const uint8_t localID = \
+ TypeIDZoneTypes<SWIFT_TYPEID_ZONE>::Name; \
+ \
+ static const uint64_t value = formTypeID(zoneID, localID); \
+ \
+ static llvm::StringRef getName() { return #Name; } \
};
#define SWIFT_TYPEID_TEMPLATE1_NAMED(Template, Name, Param1, Arg1) \
diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def
index ad90a8a..1337cf3 100644
--- a/include/swift/Basic/Statistics.def
+++ b/include/swift/Basic/Statistics.def
@@ -197,7 +197,7 @@
/// All type check requests go into the Sema area.
#define SWIFT_TYPEID(NAME) FRONTEND_STATISTIC(Sema, NAME)
-#include "swift/Sema/TypeCheckerTypeIDZone.def"
+#include "swift/AST/TypeCheckerTypeIDZone.def"
#undef SWIFT_TYPEID
/// The next 10 statistics count 5 kinds of SIL entities present
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index bb0cfc9..ec3327d 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -172,6 +172,7 @@
SPECIAL_CASE_ID(NSOpenGLGetVersion)
SPECIAL_CASE_ID(ToIntMax)
SPECIAL_CASE_ID(ToUIntMax)
+SPECIAL_CASE_ID(UIApplicationMain)
#undef SPECIAL_CASE_ID
#undef DIFF_ITEM_KEY_KIND_INT
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 3d5feef..b4cf170 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -889,7 +889,7 @@
TypeLoc elementTy, ParameterList *indices,
SmallVectorImpl<Decl *> &decls);
- AbstractStorageDecl::StorageKindTy
+ StorageImplInfo
classify(Parser &P, AbstractStorageDecl *storage, bool invalid,
ParseDeclOptions flags, SourceLoc staticLoc,
const DeclAttributes &attrs,
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 2173e25..a87f538 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -1138,12 +1138,13 @@
Demangle::NodePointer
buildNominalTypeMangling(ContextDescriptorRef descriptor,
Demangle::NodeFactory &nodeFactory) {
- std::vector<std::pair<Demangle::Node::Kind, std::string>>
+ std::vector<std::pair<Demangle::Node::Kind, Demangle::NodePointer>>
nameComponents;
ContextDescriptorRef parent = descriptor;
while (parent) {
std::string nodeName;
+ std::string relatedTag;
Demangle::Node::Kind nodeKind;
auto getTypeName = [&]() -> bool {
@@ -1151,7 +1152,16 @@
reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
(parent.getLocalBuffer());
auto nameAddress = resolveRelativeField(parent, typeBuffer->Name);
- return Reader->readString(RemoteAddress(nameAddress), nodeName);
+ if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
+ return false;
+
+ if (typeBuffer->isSynthesizedRelatedEntity()) {
+ nameAddress += nodeName.size() + 1;
+ if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
+ return false;
+ }
+
+ return true;
};
bool isTypeContext = false;
@@ -1210,8 +1220,17 @@
else if (typeFlags.isCTypedef())
nodeKind = Demangle::Node::Kind::TypeAlias;
}
+
+ auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
+ nodeName);
+ if (!relatedTag.empty()) {
+ auto relatedNode =
+ nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
+ relatedNode->addChild(nameNode, nodeFactory);
+ nameNode = relatedNode;
+ }
- nameComponents.emplace_back(nodeKind, nodeName);
+ nameComponents.emplace_back(nodeKind, nameNode);
parent = readParentContextDescriptor(parent);
}
@@ -1224,13 +1243,11 @@
auto moduleInfo = std::move(nameComponents.back());
nameComponents.pop_back();
auto demangling =
- nodeFactory.createNode(Node::Kind::Module, moduleInfo.second);
+ nodeFactory.createNode(Node::Kind::Module, moduleInfo.second->getText());
for (auto &component : reversed(nameComponents)) {
- auto name = nodeFactory.createNode(Node::Kind::Identifier,
- component.second);
auto parent = nodeFactory.createNode(component.first);
parent->addChild(demangling, nodeFactory);
- parent->addChild(name, nodeFactory);
+ parent->addChild(component.second, nodeFactory);
demangling = parent;
}
diff --git a/include/swift/SIL/MemAccessUtils.h b/include/swift/SIL/MemAccessUtils.h
index 3cc5dca..d493cf7 100644
--- a/include/swift/SIL/MemAccessUtils.h
+++ b/include/swift/SIL/MemAccessUtils.h
@@ -357,7 +357,8 @@
/// through any Nested access to find the original storage.
///
/// This is identical to findAccessedStorage(), but never returns Nested
-/// storage.
+/// storage and may return invalid storage for nested access when the outer
+/// access has Unsafe enforcement.
AccessedStorage findAccessedStorageNonNested(SILValue sourceAddr);
/// Return true if the given address operand is used by a memory operation that
@@ -368,6 +369,8 @@
/// Return true if the given address producer may be the source of a formal
/// access (a read or write of a potentially aliased, user visible variable).
///
+/// `storage` must be a valid AccessedStorage object.
+///
/// If this returns false, then the address can be safely accessed without
/// a begin_access marker. To determine whether to emit begin_access:
/// storage = findAccessedStorage(address)
diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def
index 91c37b9..f75c361 100644
--- a/include/swift/SILOptimizer/PassManager/Passes.def
+++ b/include/swift/SILOptimizer/PassManager/Passes.def
@@ -58,6 +58,8 @@
"Access Enforcement Optimization")
PASS(AccessEnforcementSelection, "access-enforcement-selection",
"Access Enforcement Selection")
+PASS(AccessEnforcementWMO, "access-enforcement-wmo",
+ "Access Enforcement Whole Module Optimization")
PASS(AccessSummaryDumper, "access-summary-dump",
"Dump Address Parameter Access Summary")
PASS(AccessedStorageDumper, "accessed-storage-dump",
diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h
index 9f05f11..6a42f50 100644
--- a/include/swift/Sema/IDETypeChecking.h
+++ b/include/swift/Sema/IDETypeChecking.h
@@ -36,9 +36,7 @@
class DeclName;
/// \brief Typecheck a declaration parsed during code completion.
- ///
- /// \returns true on success, false on error.
- bool typeCheckCompletionDecl(Decl *D);
+ void typeCheckCompletionDecl(Decl *D);
/// \brief Check if T1 is convertible to T2.
///
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 8585e61..ff747b1 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -575,7 +575,9 @@
/// Sets the accessors for \p storage based on \p rawStorageKind.
void configureStorage(AbstractStorageDecl *storage,
- unsigned rawStorageKind,
+ uint8_t rawReadImpl,
+ uint8_t rawWriteImpl,
+ uint8_t rawReadWriteImpl,
AccessorRecord &accessors);
public:
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 108f1d5..9e194af 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 422; // Last change: {strong_retain,copy}_unowned
+const uint16_t VERSION_MINOR = 425; // Last change: access impls
using DeclIDField = BCFixed<31>;
@@ -112,13 +112,38 @@
using FileSizeField = BCVBR<16>;
using FileModTimeField = BCVBR<16>;
-enum class StorageKind : uint8_t {
- Stored, StoredWithTrivialAccessors, StoredWithObservers,
- InheritedWithObservers,
- Computed, ComputedWithMutableAddress,
- Addressed, AddressedWithTrivialAccessors, AddressedWithObservers,
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum class ReadImplKind : uint8_t {
+ Stored = 0,
+ Get,
+ Inherited,
+ Address
};
-using StorageKindField = BCFixed<4>;
+using ReadImplKindField = BCFixed<3>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum class WriteImplKind : uint8_t {
+ Immutable = 0,
+ Stored,
+ StoredWithObservers,
+ InheritedWithObservers,
+ Set,
+ MutableAddress,
+};
+using WriteImplKindField = BCFixed<3>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum class ReadWriteImplKind : uint8_t {
+ Immutable = 0,
+ Stored,
+ MaterializeForSet,
+ MutableAddress,
+ MaterializeToTemporary,
+};
+using ReadWriteImplKindField = BCFixed<3>;
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
@@ -861,8 +886,9 @@
IdentifierIDField, // name
DeclContextIDField, // context decl
BCFixed<1>, // implicit flag
+ BCFixed<1>, // isObjC
GenericEnvironmentIDField, // generic environment
- AccessLevelField, // access level
+ AccessLevelField, // access level
BCVBR<4>, // number of conformances
BCArray<TypeIDField> // inherited types
// Trailed by the generic parameters (if any), the members record, and
@@ -874,9 +900,10 @@
IdentifierIDField, // name
DeclContextIDField, // context decl
BCFixed<1>, // implicit flag
+ BCFixed<1>, // isObjC
GenericEnvironmentIDField, // generic environment
TypeIDField, // raw type
- AccessLevelField, // access level
+ AccessLevelField, // access level
BCVBR<4>, // number of conformances
BCVBR<4>, // number of inherited types
BCArray<TypeIDField> // inherited types, followed by dependency types
@@ -886,15 +913,15 @@
using ClassLayout = BCRecordLayout<
CLASS_DECL,
- IdentifierIDField, // name
- DeclContextIDField,// context decl
- BCFixed<1>, // implicit?
- BCFixed<1>, // explicitly objc?
- BCFixed<1>, // requires stored property initial values?
- BCFixed<1>, // inherits convenience initializers from its superclass?
+ IdentifierIDField, // name
+ DeclContextIDField, // context decl
+ BCFixed<1>, // implicit?
+ BCFixed<1>, // explicitly objc?
+ BCFixed<1>, // requires stored property initial values?
+ BCFixed<1>, // inherits convenience initializers from its superclass?
GenericEnvironmentIDField, // generic environment
- TypeIDField, // superclass
- AccessLevelField, // access level
+ TypeIDField, // superclass
+ AccessLevelField, // access level
BCVBR<4>, // number of conformances
BCArray<TypeIDField> // inherited types
// Trailed by the generic parameters (if any), the members record, and
@@ -910,7 +937,8 @@
BCFixed<1>, // objc?
BCFixed<1>, // existential-type-supported?
GenericEnvironmentIDField, // generic environment
- AccessLevelField, // access level
+ TypeIDField, // superclass
+ AccessLevelField, // access level
BCArray<DeclIDField> // inherited types
// Trailed by the generic parameters (if any), the members record, and
// the default witness table record
@@ -957,7 +985,9 @@
BCFixed<1>, // HasNonPatternBindingInit?
BCFixed<1>, // is getter mutating?
BCFixed<1>, // is setter mutating?
- StorageKindField, // StorageKind
+ ReadImplKindField, // read implementation
+ WriteImplKindField, // write implementation
+ ReadWriteImplKindField, // read-write implementation
AccessorCountField, // number of accessors
TypeIDField, // interface type
DeclIDField, // overridden decl
@@ -981,7 +1011,7 @@
BCFixed<1>, // implicit?
BCFixed<1>, // is 'static' or 'class'?
StaticSpellingKindField, // spelling of 'static' or 'class'
- BCFixed<1>, // explicitly objc?
+ BCFixed<1>, // isObjC?
SelfAccessKindField, // self access kind
BCFixed<1>, // has dynamic self?
BCFixed<1>, // has forced static dispatch?
@@ -1010,7 +1040,7 @@
BCFixed<1>, // implicit?
BCFixed<1>, // is 'static' or 'class'?
StaticSpellingKindField, // spelling of 'static' or 'class'
- BCFixed<1>, // explicitly objc?
+ BCFixed<1>, // isObjC?
SelfAccessKindField, // self access kind
BCFixed<1>, // has dynamic self?
BCFixed<1>, // has forced static dispatch?
@@ -1094,7 +1124,9 @@
BCFixed<1>, // objc?
BCFixed<1>, // is getter mutating?
BCFixed<1>, // is setter mutating?
- StorageKindField, // StorageKind
+ ReadImplKindField, // read implementation
+ WriteImplKindField, // write implementation
+ ReadWriteImplKindField, // read-write implementation
AccessorCountField, // number of accessors
GenericEnvironmentIDField, // generic environment
TypeIDField, // interface type
diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h
index 1bb3d80..abe7243 100644
--- a/include/swift/Subsystems.h
+++ b/include/swift/Subsystems.h
@@ -46,6 +46,7 @@
class DelayedParsingCallbacks;
class DiagnosticConsumer;
class DiagnosticEngine;
+ class Evaluator;
class FileUnit;
class GenericEnvironment;
class GenericParamList;
@@ -342,6 +343,13 @@
struct Implementation;
Implementation &Impl;
};
+
+ /// Register the type checker's request functions with the evaluator.
+ ///
+ /// Clients that form an ASTContext and will perform any semantic
+ /// queries should call this function after forming the ASTContext.
+ void registerTypeCheckerRequestFunctions(Evaluator &evaluator);
+
} // end namespace swift
#endif // SWIFT_SUBSYSTEMS_H
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index 9961d5b..c8c8bf6 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -48,17 +48,17 @@
#ifndef NDEBUG
#define syntax_assert_child_kind(Raw, Cursor, ExpectedKind) \
- ({ \
+ do { \
if (auto &__Child = Raw->getChild(Cursor)) \
assert(__Child->getKind() == ExpectedKind); \
- })
+ } while (false)
#else
-#define syntax_assert_child_kind(Raw, Cursor, ExpectedKind) ({});
+#define syntax_assert_child_kind(Raw, Cursor, ExpectedKind)
#endif
#ifndef NDEBUG
#define syntax_assert_child_token(Raw, CursorName, ...) \
- ({ \
+ do { \
bool __Found = false; \
if (auto &__Token = Raw->getChild(Cursor::CursorName)) { \
assert(__Token->isToken()); \
@@ -73,14 +73,14 @@
", expected one of {" #__VA_ARGS__ "}"); \
} \
} \
- })
+ } while (false)
#else
-#define syntax_assert_child_token(Raw, CursorName, ...) ({});
+#define syntax_assert_child_token(Raw, CursorName, ...)
#endif
#ifndef NDEBUG
#define syntax_assert_child_token_text(Raw, CursorName, TokenKind, ...) \
- ({ \
+ do { \
bool __Found = false; \
if (auto &__Child = Raw->getChild(Cursor::CursorName)) { \
assert(__Child->isToken()); \
@@ -96,19 +96,19 @@
", expected one of {" #__VA_ARGS__ "}"); \
} \
} \
- })
+ } while (false)
#else
-#define syntax_assert_child_token_text(Raw, CursorName, TokenKind, ...) ({});
+#define syntax_assert_child_token_text(Raw, CursorName, TokenKind, ...)
#endif
#ifndef NDEBUG
#define syntax_assert_token_is(Tok, Kind, Text) \
- ({ \
+ do { \
assert(Tok.getTokenKind() == Kind); \
assert(Tok.getText() == Text); \
- })
+ } while (false)
#else
-#define syntax_assert_token_is(Tok, Kind, Text) ({});
+#define syntax_assert_token_is(Tok, Kind, Text)
#endif
namespace swift {
@@ -222,7 +222,7 @@
friend TrailingObjects;
union {
- uint64_t Clear;
+ uint64_t OpaqueBits;
struct {
/// The kind of syntax this node represents.
unsigned Kind : bitmax(NumSyntaxKindBits, 8);
@@ -231,7 +231,7 @@
/// Whether this piece of syntax was constructed with manually managed
/// memory.
unsigned ManualMemory : 1;
- };
+ } Common;
enum { NumRawSyntaxBits = bitmax(NumSyntaxKindBits, 8) + 1 + 1 };
// For "layout" nodes.
@@ -243,7 +243,7 @@
unsigned NumChildren : 32;
/// Number of bytes this node takes up spelled out in the source code
unsigned TextLength : 32;
- };
+ } Layout;
// For "token" nodes.
struct {
@@ -256,17 +256,19 @@
unsigned NumLeadingTrivia : 16;
/// Number of trailing trivia pieces.
unsigned NumTrailingTrivia : 16;
- };
+ } Token;
} Bits;
size_t numTrailingObjects(OverloadToken<RC<RawSyntax>>) const {
- return isToken() ? 0 : Bits.NumChildren;
+ return isToken() ? 0 : Bits.Layout.NumChildren;
}
size_t numTrailingObjects(OverloadToken<OwnedString>) const {
return isToken() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<TriviaPiece>) const {
- return isToken() ? Bits.NumLeadingTrivia + Bits.NumTrailingTrivia : 0;
+ return isToken()
+ ? Bits.Token.NumLeadingTrivia + Bits.Token.NumTrailingTrivia
+ : 0;
}
/// Constructor for creating layout nodes
@@ -282,12 +284,12 @@
~RawSyntax();
void Release() const {
- if (Bits.ManualMemory)
+ if (Bits.Common.ManualMemory)
return;
return llvm::ThreadSafeRefCountedBase<RawSyntax>::Release();
}
void Retain() const {
- if (Bits.ManualMemory)
+ if (Bits.Common.ManualMemory)
return;
return llvm::ThreadSafeRefCountedBase<RawSyntax>::Retain();
}
@@ -326,10 +328,12 @@
/// @}
SourcePresence getPresence() const {
- return static_cast<SourcePresence>(Bits.Presence);
+ return static_cast<SourcePresence>(Bits.Common.Presence);
}
- SyntaxKind getKind() const { return static_cast<SyntaxKind>(Bits.Kind); }
+ SyntaxKind getKind() const {
+ return static_cast<SyntaxKind>(Bits.Common.Kind);
+ }
/// Returns true if the node is "missing" in the source (i.e. it was
/// expected (or optional) but not written.
@@ -365,7 +369,7 @@
/// Get the kind of the token.
tok getTokenKind() const {
assert(isToken());
- return static_cast<tok>(Bits.TokenKind);
+ return static_cast<tok>(Bits.Token.TokenKind);
}
/// Return the text of the token.
@@ -377,13 +381,13 @@
/// Return the leading trivia list of the token.
ArrayRef<TriviaPiece> getLeadingTrivia() const {
assert(isToken());
- return {getTrailingObjects<TriviaPiece>(), Bits.NumLeadingTrivia};
+ return {getTrailingObjects<TriviaPiece>(), Bits.Token.NumLeadingTrivia};
}
/// Return the trailing trivia list of the token.
ArrayRef<TriviaPiece> getTrailingTrivia() const {
assert(isToken());
- return {getTrailingObjects<TriviaPiece>() + Bits.NumLeadingTrivia,
- Bits.NumTrailingTrivia};
+ return {getTrailingObjects<TriviaPiece>() + Bits.Token.NumLeadingTrivia,
+ Bits.Token.NumTrailingTrivia};
}
/// Return \c true if this is the given kind of token.
@@ -427,13 +431,13 @@
ArrayRef<RC<RawSyntax>> getLayout() const {
if (isToken())
return {};
- return {getTrailingObjects<RC<RawSyntax>>(), Bits.NumChildren};
+ return {getTrailingObjects<RC<RawSyntax>>(), Bits.Layout.NumChildren};
}
size_t getNumChildren() const {
if (isToken())
return 0;
- return Bits.NumChildren;
+ return Bits.Layout.NumChildren;
}
/// Get a child based on a particular node's "Cursor", indicating
@@ -454,7 +458,7 @@
accumulateAbsolutePosition(Pos);
return Pos.getOffset();
} else {
- return Bits.TextLength;
+ return Bits.Layout.TextLength;
}
}
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index a27148e..37166e6 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -213,31 +213,55 @@
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
}
-static StringRef
-getAbstractStorageDeclKindString(AbstractStorageDecl::StorageKindTy value) {
- switch (value) {
- case AbstractStorageDecl::Stored:
- return "stored";
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- return "stored_with_trivial_accessors";
- case AbstractStorageDecl::StoredWithObservers:
- return "stored_with_observers";
- case AbstractStorageDecl::InheritedWithObservers:
- return "inherited_with_observers";
- case AbstractStorageDecl::Addressed:
- return "addressed";
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- return "addressed_with_trivial_accessors";
- case AbstractStorageDecl::AddressedWithObservers:
- return "addressed_with_observers";
- case AbstractStorageDecl::ComputedWithMutableAddress:
- return "computed_with_mutable_address";
- case AbstractStorageDecl::Computed:
- return "computed";
- }
- llvm_unreachable("Unhandled AbstractStorageDecl in switch.");
+StringRef swift::getReadImplKindName(ReadImplKind kind) {
+ switch (kind) {
+ case ReadImplKind::Stored:
+ return "stored";
+ case ReadImplKind::Inherited:
+ return "inherited";
+ case ReadImplKind::Get:
+ return "getter";
+ case ReadImplKind::Address:
+ return "addressor";
+ }
+ llvm_unreachable("bad kind");
}
+
+StringRef swift::getWriteImplKindName(WriteImplKind kind) {
+ switch (kind) {
+ case WriteImplKind::Immutable:
+ return "immutable";
+ case WriteImplKind::Stored:
+ return "stored";
+ case WriteImplKind::StoredWithObservers:
+ return "stored_with_observers";
+ case WriteImplKind::InheritedWithObservers:
+ return "inherited_with_observers";
+ case WriteImplKind::Set:
+ return "setter";
+ case WriteImplKind::MutableAddress:
+ return "mutable_addressor";
+ }
+ llvm_unreachable("bad kind");
+}
+
+StringRef swift::getReadWriteImplKindName(ReadWriteImplKind kind) {
+ switch (kind) {
+ case ReadWriteImplKind::Immutable:
+ return "immutable";
+ case ReadWriteImplKind::Stored:
+ return "stored";
+ case ReadWriteImplKind::MaterializeForSet:
+ return "materialize_for_set";
+ case ReadWriteImplKind::MutableAddress:
+ return "mutable_addressor";
+ case ReadWriteImplKind::MaterializeToTemporary:
+ return "materialize_to_temporary";
+ }
+ llvm_unreachable("bad kind");
+}
+
static StringRef getImportKindString(ImportKind value) {
switch (value) {
case ImportKind::Module: return "module";
@@ -339,7 +363,7 @@
switch (value) {
case AccessSemantics::Ordinary: return "ordinary";
case AccessSemantics::DirectToStorage: return "direct_to_storage";
- case AccessSemantics::DirectToAccessor: return "direct_to_accessor";
+ case AccessSemantics::DirectToImplementation: return "direct_to_impl";
case AccessSemantics::BehaviorInitialization: return "behavior_init";
}
@@ -794,48 +818,35 @@
PrintWithColorRAII(OS, DeclModifierColor) << " let";
if (VD->hasNonPatternBindingInit())
PrintWithColorRAII(OS, DeclModifierColor) << " non_pattern_init";
- PrintWithColorRAII(OS, DeclModifierColor)
- << " storage_kind="
- << getAbstractStorageDeclKindString(VD->getStorageKind());
if (VD->getAttrs().hasAttribute<LazyAttr>())
PrintWithColorRAII(OS, DeclModifierColor) << " lazy";
-
+ printStorageImpl(VD);
printAccessors(VD);
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
+ void printStorageImpl(AbstractStorageDecl *D) {
+ auto impl = D->getImplInfo();
+ PrintWithColorRAII(OS, DeclModifierColor)
+ << " readImpl="
+ << getReadImplKindName(impl.getReadImpl());
+ if (!impl.supportsMutation()) {
+ PrintWithColorRAII(OS, DeclModifierColor)
+ << " immutable";
+ } else {
+ PrintWithColorRAII(OS, DeclModifierColor)
+ << " writeImpl="
+ << getWriteImplKindName(impl.getWriteImpl());
+ PrintWithColorRAII(OS, DeclModifierColor)
+ << " readWriteImpl="
+ << getReadWriteImplKindName(impl.getReadWriteImpl());
+ }
+ }
+
void printAccessors(AbstractStorageDecl *D) {
- if (FuncDecl *Get = D->getGetter()) {
+ for (auto accessor : D->getAllAccessors()) {
OS << "\n";
- printRec(Get);
- }
- if (FuncDecl *Set = D->getSetter()) {
- OS << "\n";
- printRec(Set);
- }
- if (FuncDecl *MaterializeForSet = D->getMaterializeForSetFunc()) {
- OS << "\n";
- printRec(MaterializeForSet);
- }
- if (D->hasObservers()) {
- if (FuncDecl *WillSet = D->getWillSetFunc()) {
- OS << "\n";
- printRec(WillSet);
- }
- if (FuncDecl *DidSet = D->getDidSetFunc()) {
- OS << "\n";
- printRec(DidSet);
- }
- }
- if (D->hasAddressors()) {
- if (FuncDecl *addressor = D->getAddressor()) {
- OS << "\n";
- printRec(addressor);
- }
- if (FuncDecl *mutableAddressor = D->getMutableAddressor()) {
- OS << "\n";
- printRec(mutableAddressor);
- }
+ printRec(accessor);
}
}
@@ -907,8 +918,7 @@
void visitSubscriptDecl(SubscriptDecl *SD) {
printCommon(SD, "subscript_decl");
- OS << " storage_kind="
- << getAbstractStorageDeclKindString(SD->getStorageKind());
+ printStorageImpl(SD);
printAccessors(SD);
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
@@ -2514,6 +2524,11 @@
printSemanticExpr(E->getSemanticExpr());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
+ void visitLazyInitializerExpr(LazyInitializerExpr *E) {
+ printCommon(E, "lazy_initializer_expr") << '\n';
+ printRec(E->getSubExpr());
+ PrintWithColorRAII(OS, ParenthesisColor) << ')';
+ }
void visitObjCSelectorExpr(ObjCSelectorExpr *E) {
printCommon(E, "objc_selector_expr");
OS << " kind=" << getObjCSelectorExprKindString(E->getSelectorKind());
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 749a60f..7429005 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -740,6 +740,16 @@
Options.ExcludeAttrList.push_back(DAK_Final);
}
+ // If the declaration is implicitly @objc, print the attribute now.
+ if (Options.PrintImplicitAttrs) {
+ if (auto VD = dyn_cast<ValueDecl>(D)) {
+ if (VD->isObjC() && !VD->getAttrs().hasAttribute<ObjCAttr>()) {
+ Printer.printAttrName("@objc");
+ Printer << " ";
+ }
+ }
+ }
+
D->getAttrs().print(Printer, Options, D);
Options.ExcludeAttrList.resize(originalExcludeAttrCount);
@@ -1400,57 +1410,54 @@
llvm_unreachable("bad addressor kind");
}
-static StringRef getAddressorLabel(AccessorDecl *addressor) {
- switch (addressor->getAddressorKind()) {
- case AddressorKind::NotAddressor:
- llvm_unreachable("addressor claims not to be an addressor");
- case AddressorKind::Unsafe:
- return "unsafeAddress";
- case AddressorKind::Owning:
- return "addressWithOwner";
- case AddressorKind::NativeOwning:
- return "addressWithNativeOwner";
- case AddressorKind::NativePinning:
- return "addressWithPinnedNativeOwner";
- }
- llvm_unreachable("bad addressor kind");
-}
+static StringRef getAccessorLabel(AccessorDecl *accessor) {
+ switch (accessor->getAccessorKind()) {
+#define SINGLETON_ACCESSOR(ID, KEYWORD) \
+ case AccessorKind::ID: return #KEYWORD;
+#define ACCESSOR(ID)
+#include "swift/AST/AccessorKinds.def"
-static StringRef getMutableAddressorLabel(AccessorDecl *addressor) {
- switch (addressor->getAddressorKind()) {
- case AddressorKind::NotAddressor:
- llvm_unreachable("addressor claims not to be an addressor");
- case AddressorKind::Unsafe:
- return "unsafeMutableAddress";
- case AddressorKind::Owning:
- return "mutableAddressWithOwner";
- case AddressorKind::NativeOwning:
- return "mutableAddressWithNativeOwner";
- case AddressorKind::NativePinning:
- return "mutableAddressWithPinnedNativeOwner";
+ case AccessorKind::Address:
+ switch (accessor->getAddressorKind()) {
+ case AddressorKind::NotAddressor: llvm_unreachable("bad combination");
+#define IMMUTABLE_ADDRESSOR(ID, KEYWORD) \
+ case AddressorKind::ID: return #KEYWORD;
+#define ACCESSOR(ID)
+#include "swift/AST/AccessorKinds.def"
+ }
+ llvm_unreachable("bad addressor kind");
+
+ case AccessorKind::MutableAddress:
+ switch (accessor->getAddressorKind()) {
+ case AddressorKind::NotAddressor: llvm_unreachable("bad combination");
+#define MUTABLE_ADDRESSOR(ID, KEYWORD) \
+ case AddressorKind::ID: return #KEYWORD;
+#define ACCESSOR(ID)
+#include "swift/AST/AccessorKinds.def"
+ }
+ llvm_unreachable("bad addressor kind");
}
- llvm_unreachable("bad addressor kind");
+ llvm_unreachable("bad accessor kind");
}
void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
if (isa<VarDecl>(ASD) && !Options.PrintPropertyAccessors)
return;
- auto storageKind = ASD->getStorageKind();
-
// Never print anything for stored properties.
- if (storageKind == AbstractStorageDecl::Stored)
+ if (ASD->getAllAccessors().empty())
return;
+ auto impl = ASD->getImplInfo();
+
// Treat StoredWithTrivialAccessors the same as Stored unless
// we're printing for SIL, in which case we want to distinguish it
// from a pure stored property.
- if (storageKind == AbstractStorageDecl::StoredWithTrivialAccessors) {
- if (!Options.PrintForSIL) return;
-
- // Don't print an accessor for a let; the parser can't handle it.
- if (isa<VarDecl>(ASD) && cast<VarDecl>(ASD)->isLet())
- return;
+ if (impl.isSimpleStored()) {
+ if (Options.PrintForSIL) {
+ Printer << " { get " << (impl.supportsMutation() ? "set }" : "}");
+ }
+ return;
}
// We sometimes want to print the accessors abstractly
@@ -1496,22 +1503,23 @@
// Honor !Options.PrintGetSetOnRWProperties in the only remaining
// case where we could end up printing { get set }.
- if (storageKind == AbstractStorageDecl::StoredWithTrivialAccessors ||
- storageKind == AbstractStorageDecl::Computed) {
- if (!Options.PrintGetSetOnRWProperties &&
- !Options.FunctionDefinitions &&
- ASD->getSetter() &&
- !ASD->getGetter()->isMutating() &&
- !ASD->getSetter()->isExplicitNonMutating()) {
- return;
- }
+ if ((impl.getReadImpl() == ReadImplKind::Stored ||
+ impl.getReadImpl() == ReadImplKind::Get) &&
+ (impl.getWriteImpl() == WriteImplKind::Stored ||
+ impl.getWriteImpl() == WriteImplKind::Set) &&
+ (impl.getReadWriteImpl() == ReadWriteImplKind::MaterializeToTemporary) &&
+ !Options.PrintGetSetOnRWProperties &&
+ !Options.FunctionDefinitions &&
+ !ASD->getGetter()->isMutating() &&
+ !ASD->getSetter()->isExplicitNonMutating()) {
+ return;
}
// Otherwise, print all the concrete defining accessors.
bool PrintAccessorBody = Options.FunctionDefinitions || Options.FunctionBody;
- auto PrintAccessor = [&](AccessorDecl *Accessor, StringRef Label) {
+ auto PrintAccessor = [&](AccessorDecl *Accessor) {
if (!Accessor)
return;
if (!PrintAccessorBody) {
@@ -1527,7 +1535,7 @@
}
}
Printer << " ";
- Printer.printKeyword(Label); // Contextual keyword get, set, ...
+ Printer.printKeyword(getAccessorLabel(Accessor));
} else {
Printer.printNewline();
IndentRAII IndentMore(*this);
@@ -1536,59 +1544,49 @@
}
};
- auto PrintAddressor = [&](AccessorDecl *accessor) {
- if (!accessor) return;
- PrintAccessor(accessor, getAddressorLabel(accessor));
- };
-
- auto PrintMutableAddressor = [&](AccessorDecl *accessor) {
- if (!accessor) return;
- PrintAccessor(accessor, getMutableAddressorLabel(accessor));
- };
-
Printer << " {";
- switch (storageKind) {
- case AbstractStorageDecl::Stored:
- llvm_unreachable("filtered out above!");
-
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- case AbstractStorageDecl::Computed:
- if (ASD->getGetter() && !ASD->getSetter() && PrintAccessorBody &&
- !Options.FunctionDefinitions) {
- // Omit the 'get' keyword. Directly print getter
- if (auto BodyFunc = Options.FunctionBody) {
- Printer.printNewline();
- IndentRAII IndentBody(*this);
- indent();
- Printer << BodyFunc(ASD->getGetter());
- }
- } else {
- PrintAccessor(ASD->getGetter(), "get");
- PrintAccessor(ASD->getSetter(), "set");
+ if (impl.getReadImpl() == ReadImplKind::Get && ASD->getGetter() &&
+ !ASD->supportsMutation() &&
+ PrintAccessorBody && !Options.FunctionDefinitions) {
+ // Omit the 'get' keyword. Directly print getter
+ if (auto BodyFunc = Options.FunctionBody) {
+ Printer.printNewline();
+ IndentRAII IndentBody(*this);
+ indent();
+ Printer << BodyFunc(ASD->getGetter());
+ }
+ } else {
+ switch (impl.getReadImpl()) {
+ case ReadImplKind::Stored:
+ case ReadImplKind::Inherited:
+ break;
+ case ReadImplKind::Get:
+ PrintAccessor(ASD->getGetter());
+ break;
+ case ReadImplKind::Address:
+ PrintAccessor(ASD->getAddressor());
+ break;
}
- break;
-
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::InheritedWithObservers:
- PrintAccessor(ASD->getWillSetFunc(), "willSet");
- PrintAccessor(ASD->getDidSetFunc(), "didSet");
- break;
-
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
- PrintAddressor(ASD->getAddressor());
- PrintMutableAddressor(ASD->getMutableAddressor());
- if (ASD->hasObservers()) {
- PrintAccessor(ASD->getWillSetFunc(), "willSet");
- PrintAccessor(ASD->getDidSetFunc(), "didSet");
+ switch (impl.getWriteImpl()) {
+ case WriteImplKind::Immutable:
+ break;
+ case WriteImplKind::Stored:
+ llvm_unreachable("simply-stored variable should have been filtered out");
+ case WriteImplKind::StoredWithObservers:
+ case WriteImplKind::InheritedWithObservers:
+ PrintAccessor(ASD->getWillSetFunc());
+ PrintAccessor(ASD->getDidSetFunc());
+ break;
+ case WriteImplKind::Set:
+ PrintAccessor(ASD->getSetter());
+ // FIXME: ReadWriteImplKind::Modify
+ break;
+ case WriteImplKind::MutableAddress:
+ PrintAccessor(ASD->getMutableAddressor());
+ PrintAccessor(ASD->getWillSetFunc());
+ PrintAccessor(ASD->getDidSetFunc());
+ break;
}
- break;
-
- case AbstractStorageDecl::ComputedWithMutableAddress:
- PrintAccessor(ASD->getGetter(), "get");
- PrintMutableAddressor(ASD->getMutableAddressor());
- break;
}
if (PrintAccessorBody) {
Printer.printNewline();
@@ -2403,22 +2401,12 @@
switch (auto kind = decl->getAccessorKind()) {
case AccessorKind::Get:
case AccessorKind::Address:
- recordDeclLoc(decl,
- [&]{
- Printer << (kind == AccessorKind::Get
- ? "get" : getAddressorLabel(decl));
- });
- Printer << " {";
- break;
case AccessorKind::DidSet:
case AccessorKind::MaterializeForSet:
case AccessorKind::MutableAddress:
recordDeclLoc(decl,
[&]{
- Printer << (kind == AccessorKind::DidSet ? "didSet" :
- kind == AccessorKind::MaterializeForSet
- ? "materializeForSet"
- : getMutableAddressorLabel(decl));
+ Printer << getAccessorLabel(decl);
});
Printer << " {";
break;
@@ -2426,7 +2414,7 @@
case AccessorKind::WillSet:
recordDeclLoc(decl,
[&]{
- Printer << (decl->isSetter() ? "set" : "willSet");
+ Printer << getAccessorLabel(decl);
auto params = decl->getParameterLists().back();
if (params->size() != 0 && !params->get(0)->isImplicit()) {
@@ -3018,20 +3006,18 @@
// Stored variables in Swift source will be picked up by the
// PatternBindingDecl.
if (auto *VD = dyn_cast<VarDecl>(this)) {
- if (!VD->hasClangNode() && VD->hasStorage() &&
- VD->getStorageKind() != VarDecl::StoredWithObservers)
+ if (!VD->hasClangNode() && VD->getImplInfo().isSimpleStored())
return false;
}
- // Skip pattern bindings that consist of just one computed variable.
+ // Skip pattern bindings that consist of just one variable with
+ // interesting accessors.
if (auto pbd = dyn_cast<PatternBindingDecl>(this)) {
if (pbd->getPatternList().size() == 1) {
auto pattern =
pbd->getPatternList()[0].getPattern()->getSemanticsProvidingPattern();
if (auto named = dyn_cast<NamedPattern>(pattern)) {
- auto StorageKind = named->getDecl()->getStorageKind();
- if (StorageKind == VarDecl::Computed ||
- StorageKind == VarDecl::StoredWithObservers)
+ if (!named->getDecl()->getImplInfo().isSimpleStored())
return false;
}
}
diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp
index 50e589d..b13f137 100644
--- a/lib/AST/ASTScope.cpp
+++ b/lib/AST/ASTScope.cpp
@@ -171,22 +171,7 @@
/// Determine whether the given abstract storage declaration has accessors.
static bool hasAccessors(AbstractStorageDecl *asd) {
- switch (asd->getStorageKind()) {
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithObservers:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::Computed:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::StoredWithObservers:
- return asd->getBracesRange().isValid();
-
- case AbstractStorageDecl::Stored:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- return false;
- }
-
- llvm_unreachable("Unhandled ContinuationKind in switch.");
+ return asd->getBracesRange().isValid();
}
void ASTScope::expand() const {
@@ -561,39 +546,12 @@
case ASTScopeKind::Accessors: {
// Add children for all of the explicitly-written accessors.
- SmallVector<ASTScope *, 4> accessors;
- auto addAccessor = [&](FuncDecl *accessor) {
- if (!accessor) return;
- if (accessor->isImplicit()) return;
- if (accessor->getStartLoc().isInvalid()) return;
-
+ for (auto accessor : abstractStorageDecl->getAllAccessors()) {
+ if (accessor->isImplicit() || accessor->getStartLoc().isInvalid())
+ continue;
if (auto accessorChild = createIfNeeded(this, accessor))
- accessors.push_back(accessorChild);
- };
-
- addAccessor(abstractStorageDecl->getGetter());
- addAccessor(abstractStorageDecl->getSetter());
- addAccessor(abstractStorageDecl->getMaterializeForSetFunc());
- if (abstractStorageDecl->hasAddressors()) {
- addAccessor(abstractStorageDecl->getAddressor());
- addAccessor(abstractStorageDecl->getMutableAddressor());
+ addChild(accessorChild);
}
- if (abstractStorageDecl->hasObservers()) {
- addAccessor(abstractStorageDecl->getDidSetFunc());
- addAccessor(abstractStorageDecl->getWillSetFunc());
- }
-
- // Sort the accessors, because they can come in any order.
- std::sort(accessors.begin(), accessors.end(),
- [&](ASTScope *s1, ASTScope *s2) {
- return ctx.SourceMgr.isBeforeInBuffer(s1->getSourceRange().Start,
- s2->getSourceRange().Start);
- });
-
- // Add the accessors.
- for (auto accessor : accessors)
- addChild(accessor);
-
break;
}
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 3ba4ae2..4b70ec6 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1624,7 +1624,7 @@
if (auto *baseIOT = E->getBase()->getType()->getAs<InOutType>()) {
if (!baseIOT->getObjectType()->is<ArchetypeType>()) {
auto *VD = dyn_cast<VarDecl>(E->getMember().getDecl());
- if (!VD || !VD->hasAccessorFunctions()) {
+ if (!VD || VD->getAllAccessors().empty()) {
Out << "member_ref_expr on value of inout type\n";
E->dump(Out);
abort();
@@ -2151,6 +2151,13 @@
verifyCheckedBase(VD);
}
+ bool shouldWalkIntoLazyInitializers() override {
+ // We don't want to walk into lazy initializers because they should
+ // have been reparented to their synthesized getter, which will
+ // invalidate various invariants.
+ return false;
+ }
+
void verifyChecked(PatternBindingDecl *binding) {
// Look at all of the VarDecls being bound.
for (auto entry : binding->getPatternList())
@@ -2194,20 +2201,18 @@
abort();
}
}
- if (ASD->hasAddressors()) {
- if (auto addressor = ASD->getAddressor()) {
- if (addressor->isMutating() != ASD->isGetterMutating()) {
- Out << "AbstractStorageDecl::isGetterMutating is out of sync"
- " with whether immutable addressor is mutating";
- abort();
- }
+ if (auto addressor = ASD->getAddressor()) {
+ if (addressor->isMutating() != ASD->isGetterMutating()) {
+ Out << "AbstractStorageDecl::isGetterMutating is out of sync"
+ " with whether immutable addressor is mutating";
+ abort();
}
- if (auto addressor = ASD->getMutableAddressor()) {
- if (addressor->isMutating() != ASD->isSetterMutating()) {
- Out << "AbstractStorageDecl::isSetterMutating is out of sync"
- " with whether mutable addressor is mutating";
- abort();
- }
+ }
+ if (auto addressor = ASD->getMutableAddressor()) {
+ if (addressor->isMutating() != ASD->isSetterMutating()) {
+ Out << "AbstractStorageDecl::isSetterMutating is out of sync"
+ " with whether mutable addressor is mutating";
+ abort();
}
}
@@ -2958,8 +2963,7 @@
}
}
- auto storedAccessor =
- storageDecl->getAccessorFunction(FD->getAccessorKind());
+ auto storedAccessor = storageDecl->getAccessor(FD->getAccessorKind());
if (storedAccessor != FD) {
Out << "storage declaration has different accessor for this kind\n";
abort();
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index 4fedbe7..8a6f844 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -158,7 +158,9 @@
PBD->setPattern(idx, Pat, entry.getInitContext());
else
return true;
- if (entry.getInit()) {
+ if (entry.getInit() &&
+ (!entry.isInitializerLazy() ||
+ Walker.shouldWalkIntoLazyInitializers())) {
#ifndef NDEBUG
PrettyStackTraceDecl debugStack("walking into initializer for", PBD);
#endif
@@ -942,6 +944,11 @@
return E;
}
+ Expr *visitLazyInitializerExpr(LazyInitializerExpr *E) {
+ // Initializer is totally opaque for most visitation purposes.
+ return E;
+ }
+
Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {
Expr *sub = doIt(E->getSubExpr());
if (!sub) return nullptr;
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 0d4e183..7ad584b 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -52,6 +52,7 @@
SubstitutionMap.cpp
SwiftNameTranslation.cpp
Type.cpp
+ TypeCheckRequests.cpp
TypeJoinMeet.cpp
TypeRefinementContext.cpp
TypeRepr.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index fb393e3..17b0e75 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -35,6 +35,7 @@
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/ResilienceExpansion.h"
#include "swift/AST/Stmt.h"
+#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/SwiftNameTranslation.h"
#include "clang/Lex/MacroInfo.h"
@@ -909,7 +910,6 @@
ExtendedType(extendedType),
Inherited(inherited)
{
- Bits.ExtensionDecl.CheckedInheritanceClause = false;
Bits.ExtensionDecl.DefaultAndMaxAccessLevel = 0;
Bits.ExtensionDecl.HasLazyConformances = false;
setTrailingWhereClause(trailingWhereClause);
@@ -959,12 +959,8 @@
Type ExtensionDecl::getInheritedType(unsigned index) const {
ASTContext &ctx = getASTContext();
- if (auto lazyResolver = ctx.getLazyResolver()) {
- return lazyResolver->getInheritedType(const_cast<ExtensionDecl *>(this),
- index);
- }
-
- return getInherited()[index].getType();
+ return ctx.evaluator(InheritedTypeRequest{const_cast<ExtensionDecl *>(this),
+ index});
}
bool ExtensionDecl::isConstrainedExtension() const {
@@ -1073,10 +1069,9 @@
if (SelfParam)
return SelfParam;
- if (auto singleVar = getBinding()->getSingleVar()) {
- auto *DC = singleVar->getDeclContext();
- if (singleVar->getAttrs().hasAttribute<LazyAttr>() &&
- DC->isTypeContext()) {
+ if (auto singleVar = getInitializedLazyVar()) {
+ auto DC = singleVar->getDeclContext();
+ if (DC->isTypeContext()) {
bool isInOut = !DC->getDeclaredInterfaceType()->hasReferenceSemantics();
SelfParam = ParamDecl::createSelf(SourceLoc(), DC,
singleVar->isStatic(),
@@ -1088,6 +1083,14 @@
return SelfParam;
}
+VarDecl *PatternBindingInitializer::getInitializedLazyVar() const {
+ if (auto var = getBinding()->getSingleVar()) {
+ if (var->getAttrs().hasAttribute<LazyAttr>())
+ return var;
+ }
+ return nullptr;
+}
+
static bool patternContainsVarDeclBinding(const Pattern *P, const VarDecl *VD) {
bool Result = false;
P->forEachVariable([&](VarDecl *FoundVD) {
@@ -1118,17 +1121,17 @@
}
SourceRange PatternBindingEntry::getOrigInitRange() const {
- auto Init = InitCheckedAndRemoved.getPointer();
+ auto Init = InitAndFlags.getPointer();
return Init ? Init->getSourceRange() : SourceRange();
}
void PatternBindingEntry::setInit(Expr *E) {
- auto F = InitCheckedAndRemoved.getInt();
+ auto F = InitAndFlags.getInt();
if (E) {
- InitCheckedAndRemoved.setInt(F - Flags::Removed);
- InitCheckedAndRemoved.setPointer(E);
+ InitAndFlags.setInt(F - Flags::Removed);
+ InitAndFlags.setPointer(E);
} else {
- InitCheckedAndRemoved.setInt(F | Flags::Removed);
+ InitAndFlags.setInt(F | Flags::Removed);
}
}
@@ -1343,135 +1346,173 @@
AccessSemantics
ValueDecl::getAccessSemanticsFromContext(const DeclContext *UseDC,
bool isAccessOnSelf) const {
- // If we're inside a @_transparent function, use the most conservative
- // access pattern, since we may be inlined from a different resilience
- // domain.
- ResilienceExpansion expansion = UseDC->getResilienceExpansion();
+ // All accesses have ordinary semantics except those to variables
+ // with storage from within their own accessors. In Swift 5 and later,
+ // the access must also be a member access on 'self'.
- if (auto *var = dyn_cast<AbstractStorageDecl>(this)) {
- auto isMember = var->getDeclContext()->isTypeContext();
- if (isAccessOnSelf)
- assert(isMember && "Access on self, but var isn't a member");
-
- // Within a variable's own didSet/willSet specifier, access its storage
- // directly if either:
- // 1) It's a 'plain variable' (i.e a variable that's not a member).
- // 2) It's an access to the member on the implicit 'self' declaration.
- // If it's a member access on some other base, we want to call the setter
- // as we might be accessing the member on a *different* instance.
- // 3) We're not in Swift 5 mode (or higher), as in earlier versions of Swift
- // we always performed direct accesses.
- // This prevents assignments from becoming infinite loops in most cases.
- if (!isMember || isAccessOnSelf ||
- !UseDC->getASTContext().isSwiftVersionAtLeast(5))
- if (auto *UseFD = dyn_cast<AccessorDecl>(UseDC))
- if (var->hasStorage() && var->hasAccessorFunctions() &&
- UseFD->getStorage() == var)
- return AccessSemantics::DirectToStorage;
-
- // "StoredWithTrivialAccessors" are generally always accessed indirectly,
- // but if we know that the trivial accessor will always produce the same
- // thing as the getter/setter (i.e., it can't be overridden), then just do a
- // direct access.
- //
- // This is true in structs and for final properties.
- // TODO: What about static properties?
- switch (var->getStorageKind()) {
- case AbstractStorageDecl::Stored:
- case AbstractStorageDecl::Addressed:
- // The storage is completely trivial. Always do direct access.
- return AccessSemantics::DirectToStorage;
-
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithTrivialAccessors: {
- // If the property is defined in a non-final class or a protocol, the
- // accessors are dynamically dispatched, and we cannot do direct access.
- if (isPolymorphic(var))
- return AccessSemantics::Ordinary;
-
- // If the property is resilient from the given context,
- // we cannot do direct access.
- if (var->isResilient(UseDC->getParentModule(), expansion))
- return AccessSemantics::Ordinary;
-
- // We know enough about the property to perform direct access.
- return AccessSemantics::DirectToStorage;
- }
-
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::Computed:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::AddressedWithObservers:
- // Property is not trivially backed by storage, do not perform
- // direct access.
- break;
+ // The condition most likely to fast-path us is not being in an accessor,
+ // so we check that first.
+ if (auto *accessor = dyn_cast<AccessorDecl>(UseDC)) {
+ if (auto *var = dyn_cast<VarDecl>(this)) {
+ if (accessor->getStorage() == var && var->hasStorage() &&
+ (isAccessOnSelf || !var->getDeclContext()->isTypeContext() ||
+ !var->getASTContext().isSwiftVersionAtLeast(5)))
+ return AccessSemantics::DirectToStorage;
}
}
+ // Otherwise, it's a semantically normal access. The client should be
+ // able to figure out the most efficient way to do this access.
return AccessSemantics::Ordinary;
}
+static AccessStrategy
+getDirectReadAccessStrategy(const AbstractStorageDecl *storage) {
+ switch (storage->getReadImpl()) {
+ case ReadImplKind::Stored:
+ return AccessStrategy::getStorage();
+ case ReadImplKind::Inherited:
+ // TODO: maybe add a specific strategy for this?
+ return AccessStrategy::getAccessor(AccessorKind::Get,
+ /*dispatch*/ false);
+ case ReadImplKind::Get:
+ return AccessStrategy::getAccessor(AccessorKind::Get,
+ /*dispatch*/ false);
+ case ReadImplKind::Address:
+ return AccessStrategy::getAccessor(AccessorKind::Address,
+ /*dispatch*/ false);
+ }
+ llvm_unreachable("bad impl kind");
+}
+
+static AccessStrategy
+getDirectWriteAccessStrategy(const AbstractStorageDecl *storage) {
+ switch (storage->getWriteImpl()) {
+ case WriteImplKind::Immutable:
+ assert(isa<VarDecl>(storage) && cast<VarDecl>(storage)->isLet() &&
+ "mutation of a immutable variable that isn't a let");
+ return AccessStrategy::getStorage();
+ case WriteImplKind::Stored:
+ return AccessStrategy::getStorage();
+ case WriteImplKind::StoredWithObservers:
+ // TODO: maybe add a specific strategy for this?
+ return AccessStrategy::getAccessor(AccessorKind::Set,
+ /*dispatch*/ false);
+ case WriteImplKind::InheritedWithObservers:
+ // TODO: maybe add a specific strategy for this?
+ return AccessStrategy::getAccessor(AccessorKind::Set,
+ /*dispatch*/ false);
+ case WriteImplKind::Set:
+ return AccessStrategy::getAccessor(AccessorKind::Set,
+ /*dispatch*/ false);
+ case WriteImplKind::MutableAddress:
+ return AccessStrategy::getAccessor(AccessorKind::MutableAddress,
+ /*dispatch*/ false);
+ }
+ llvm_unreachable("bad impl kind");
+}
+
+static AccessStrategy
+getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
+ switch (storage->getReadWriteImpl()) {
+ case ReadWriteImplKind::Immutable:
+ assert(isa<VarDecl>(storage) && cast<VarDecl>(storage)->isLet() &&
+ "mutation of a immutable variable that isn't a let");
+ return AccessStrategy::getStorage();
+ case ReadWriteImplKind::Stored:
+ return AccessStrategy::getStorage();
+ case ReadWriteImplKind::MaterializeForSet:
+ return AccessStrategy::getAccessor(AccessorKind::MaterializeForSet,
+ /*dispatch*/ false);
+ case ReadWriteImplKind::MutableAddress:
+ return AccessStrategy::getAccessor(AccessorKind::MutableAddress,
+ /*dispatch*/ false);
+ case ReadWriteImplKind::MaterializeToTemporary:
+ return AccessStrategy::getMaterializeToTemporary(
+ getDirectReadAccessStrategy(storage),
+ getDirectWriteAccessStrategy(storage));
+ }
+ llvm_unreachable("bad impl kind");
+}
+
+static AccessStrategy
+getOpaqueReadAccessStrategy(const AbstractStorageDecl *storage, bool dispatch) {
+ return AccessStrategy::getAccessor(AccessorKind::Get, dispatch);
+}
+
+static AccessStrategy
+getOpaqueWriteAccessStrategy(const AbstractStorageDecl *storage, bool dispatch){
+ return AccessStrategy::getAccessor(AccessorKind::Set, dispatch);
+}
+
+static bool hasDispatchedMaterializeForSet(const AbstractStorageDecl *storage) {
+ // If the declaration is dynamic, there's no materializeForSet.
+ if (storage->isDynamic())
+ return false;
+
+ // If the declaration was imported from C, we won't gain anything
+ // from using materializeForSet, and furthermore, it might not
+ // exist.
+ if (storage->hasClangNode())
+ return false;
+
+ // If the declaration is not in type context, there's no
+ // materializeForSet.
+ auto dc = storage->getDeclContext();
+ if (!dc->isTypeContext())
+ return false;
+
+ // @objc protocols count also don't have materializeForSet declarations.
+ if (auto proto = dyn_cast<ProtocolDecl>(dc)) {
+ if (proto->isObjC())
+ return false;
+ }
+
+ // Otherwise it should have a materializeForSet if we might be
+ // accessing it opaquely.
+ return true;
+}
+
+static AccessStrategy
+getOpaqueAccessStrategy(const AbstractStorageDecl *storage,
+ AccessKind accessKind, bool dispatch) {
+ switch (accessKind) {
+ case AccessKind::Read:
+ return getOpaqueReadAccessStrategy(storage, dispatch);
+ case AccessKind::Write:
+ return getOpaqueWriteAccessStrategy(storage, dispatch);
+ case AccessKind::ReadWrite:
+ if (hasDispatchedMaterializeForSet(storage))
+ return AccessStrategy::getAccessor(AccessorKind::MaterializeForSet,
+ dispatch);
+ return AccessStrategy::getMaterializeToTemporary(
+ getOpaqueReadAccessStrategy(storage, dispatch),
+ getOpaqueWriteAccessStrategy(storage, dispatch));
+ }
+ llvm_unreachable("bad access kind");
+}
+
AccessStrategy
AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
AccessKind accessKind,
DeclContext *accessFromDC) const {
switch (semantics) {
case AccessSemantics::DirectToStorage:
- switch (getStorageKind()) {
- case Stored:
- case StoredWithTrivialAccessors:
- case StoredWithObservers:
- return AccessStrategy::Storage;
-
- case Addressed:
- case AddressedWithTrivialAccessors:
- case AddressedWithObservers:
- case ComputedWithMutableAddress:
- return AccessStrategy::Addressor;
-
- case InheritedWithObservers:
- case Computed:
- llvm_unreachable("cannot have direct-to-storage access to "
- "computed storage");
- }
- llvm_unreachable("bad storage kind");
-
- case AccessSemantics::DirectToAccessor:
- assert(hasAccessorFunctions() &&
- "direct-to-accessors access to storage without accessors?");
- return AccessStrategy::DirectToAccessor;
+ assert(hasStorage());
+ return AccessStrategy::getStorage();
case AccessSemantics::Ordinary:
- switch (auto storageKind = getStorageKind()) {
- case Stored:
- return AccessStrategy::Storage;
- case Addressed:
- return AccessStrategy::Addressor;
-
- case StoredWithObservers:
- case InheritedWithObservers:
- case AddressedWithObservers:
- // An observing property backed by its own storage (i.e. which
- // doesn't override anything) has a trivial getter implementation,
- // but its setter is interesting.
- if (accessKind != AccessKind::Read ||
- storageKind == InheritedWithObservers) {
- if (isPolymorphic(this))
- return AccessStrategy::DispatchToAccessor;
- return AccessStrategy::DirectToAccessor;
- }
-
- // Fall through to the trivial-implementation case.
- LLVM_FALLTHROUGH;
-
- case StoredWithTrivialAccessors:
- case AddressedWithTrivialAccessors: {
+ // Skip these checks for local variables, both because they're unnecessary
+ // and because we won't necessarily have computed access.
+ if (!getDeclContext()->isLocalContext()) {
// If the property is defined in a non-final class or a protocol, the
// accessors are dynamically dispatched, and we cannot do direct access.
if (isPolymorphic(this))
- return AccessStrategy::DispatchToAccessor;
+ return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ true);
+ // If the storage is resilient to the given use DC (perhaps because
+ // it's @_transparent and we have to be careful about it being inlined
+ // across module lines), we cannot use direct access.
// If we end up here with a stored property of a type that's resilient
// from some resilience domain, we cannot do direct access.
//
@@ -1485,46 +1526,38 @@
bool resilient;
if (accessFromDC)
resilient = isResilient(accessFromDC->getParentModule(),
- ResilienceExpansion::Maximal);
+ accessFromDC->getResilienceExpansion());
else
resilient = isResilient();
-
+
if (resilient)
- return AccessStrategy::DirectToAccessor;
-
- if (storageKind == StoredWithObservers ||
- storageKind == StoredWithTrivialAccessors) {
- return AccessStrategy::Storage;
- } else {
- assert(storageKind == AddressedWithObservers ||
- storageKind == AddressedWithTrivialAccessors);
- return AccessStrategy::Addressor;
- }
+ return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ false);
}
- case ComputedWithMutableAddress:
- if (isPolymorphic(this))
- return AccessStrategy::DispatchToAccessor;
- if (accessKind == AccessKind::Read)
- return AccessStrategy::DirectToAccessor;
- return AccessStrategy::Addressor;
+ LLVM_FALLTHROUGH;
- case Computed:
- if (isPolymorphic(this))
- return AccessStrategy::DispatchToAccessor;
- return AccessStrategy::DirectToAccessor;
+ case AccessSemantics::DirectToImplementation:
+ switch (accessKind) {
+ case AccessKind::Read:
+ return getDirectReadAccessStrategy(this);
+ case AccessKind::Write:
+ return getDirectWriteAccessStrategy(this);
+ case AccessKind::ReadWrite:
+ return getDirectReadWriteAccessStrategy(this);
}
- llvm_unreachable("bad storage kind");
+ llvm_unreachable("bad access kind");
+
case AccessSemantics::BehaviorInitialization:
// Behavior initialization writes to the property as if it has storage.
// SIL definite initialization will introduce the logical accesses.
- // Reads or inouts still go through the getter.
+ // Reads or inouts go through the ordinary path.
switch (accessKind) {
case AccessKind::Write:
- return AccessStrategy::BehaviorStorage;
- case AccessKind::ReadWrite:
+ return AccessStrategy::getBehaviorStorage();
case AccessKind::Read:
- return AccessStrategy::DispatchToAccessor;
+ case AccessKind::ReadWrite:
+ return getAccessStrategy(AccessSemantics::Ordinary,
+ accessKind, accessFromDC);
}
}
llvm_unreachable("bad access semantics");
@@ -1946,19 +1979,25 @@
return CanType();
}
-void ValueDecl::setIsObjC(bool Value) {
- bool CurrentValue = isObjC();
- if (CurrentValue == Value)
- return;
+bool ValueDecl::isObjC() const {
+ if (Bits.ValueDecl.IsObjCComputed)
+ return Bits.ValueDecl.IsObjC;
- if (!Value) {
- for (auto *Attr : getAttrs()) {
- if (auto *OA = dyn_cast<ObjCAttr>(Attr))
- OA->setInvalid();
- }
- } else {
- getAttrs().add(ObjCAttr::createUnnamedImplicit(getASTContext()));
+ // Fallback: look for an @objc attribute.
+ // FIXME: This should become an error, eventually.
+ return getAttrs().hasAttribute<ObjCAttr>();
+}
+
+void ValueDecl::setIsObjC(bool value) {
+ assert(!Bits.ValueDecl.IsObjCComputed || Bits.ValueDecl.IsObjC == value);
+
+ if (Bits.ValueDecl.IsObjCComputed) {
+ assert(Bits.ValueDecl.IsObjC == value);
+ return;
}
+
+ Bits.ValueDecl.IsObjCComputed = true;
+ Bits.ValueDecl.IsObjC = value;
}
bool ValueDecl::canBeAccessedByDynamicLookup() const {
@@ -2323,12 +2362,8 @@
Type TypeDecl::getInheritedType(unsigned index) const {
ASTContext &ctx = getASTContext();
- if (auto lazyResolver = ctx.getLazyResolver()) {
- return lazyResolver->getInheritedType(const_cast<TypeDecl *>(this),
- index);
- }
-
- return getInherited()[index].getType();
+ return ctx.evaluator(InheritedTypeRequest{const_cast<TypeDecl *>(this),
+ index});
}
Type TypeDecl::getDeclaredInterfaceType() const {
@@ -2823,11 +2858,7 @@
Type EnumDecl::getRawType() const {
ASTContext &ctx = getASTContext();
- if (auto lazyResolver = ctx.getLazyResolver()) {
- return lazyResolver->getRawType(const_cast<EnumDecl *>(this));
- }
-
- return LazySemanticInfo.RawType.getPointer();
+ return ctx.evaluator(EnumRawTypeRequest{const_cast<EnumDecl *>(this)});
}
StructDecl::StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
@@ -2888,8 +2919,9 @@
DD->setGenericEnvironment(getGenericEnvironmentOfContext());
// Mark DD as ObjC, as all dtors are.
- DD->setIsObjC(true);
- recordObjCMethod(DD);
+ DD->setIsObjC(getASTContext().LangOpts.EnableObjCInterop);
+ if (getASTContext().LangOpts.EnableObjCInterop)
+ recordObjCMethod(DD);
// Assign DD the interface type (Self) -> () -> ()
ArrayRef<AnyFunctionType::Param> noParams;
@@ -3277,6 +3309,23 @@
return result;
}
+Type ProtocolDecl::getSuperclass() const {
+ ASTContext &ctx = getASTContext();
+ return ctx.evaluator(SuperclassTypeRequest{const_cast<ProtocolDecl *>(this)});
+}
+
+ClassDecl *ProtocolDecl::getSuperclassDecl() const {
+ if (auto superclass = getSuperclass())
+ return superclass->getClassOrBoundGenericClass();
+ return nullptr;
+}
+
+void ProtocolDecl::setSuperclass(Type superclass) {
+ assert((!superclass || !superclass->hasArchetype())
+ && "superclass must be interface type");
+ LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
+}
+
bool ProtocolDecl::walkInheritedProtocols(
llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const {
auto self = const_cast<ProtocolDecl *>(this);
@@ -3728,18 +3777,16 @@
llvm_unreachable("bad accessor kind");
}
-void AbstractStorageDecl::setAccessors(StorageKindTy storageKind,
+void AbstractStorageDecl::overwriteImplInfo(StorageImplInfo implInfo) {
+ setFieldsFromImplInfo(implInfo);
+ Accessors.getPointer()->overwriteImplInfo(implInfo);
+}
+
+void AbstractStorageDecl::setAccessors(StorageImplInfo implInfo,
SourceLoc lbraceLoc,
ArrayRef<AccessorDecl *> accessors,
SourceLoc rbraceLoc) {
- assert(getStorageKind() == Stored && "StorageKind already set");
-
- // The only situation where we allow the incoming storage kind to be
- // Stored is when there are no accessors. This happens when the program
- // has {} as the accessor clause (or unparsable contents).
- assert((storageKind != Stored || accessors.empty()) &&
- "cannot combine Stored storage kind with any accessors");
- setStorageKind(storageKind);
+ setFieldsFromImplInfo(implInfo);
// This method is called after we've already recorded an accessors clause
// only on recovery paths and only when that clause was empty.
@@ -3752,7 +3799,7 @@
} else {
record = AccessorRecord::create(getASTContext(),
SourceRange(lbraceLoc, rbraceLoc),
- accessors);
+ implInfo, accessors);
Accessors.setPointer(record);
}
@@ -3772,6 +3819,7 @@
AbstractStorageDecl::AccessorRecord *
AbstractStorageDecl::AccessorRecord::create(ASTContext &ctx,
SourceRange braces,
+ StorageImplInfo storageInfo,
ArrayRef<AccessorDecl*> accessors) {
// Silently cap the number of accessors we store at a number that should
// be easily sufficient for all the valid cases, including space for adding
@@ -3811,13 +3859,15 @@
auto accessorsCapacity = AccessorIndex(accessors.size() + numMissingOpaque);
void *mem = ctx.Allocate(totalSizeToAlloc<AccessorDecl*>(accessorsCapacity),
alignof(AccessorRecord));
- return new (mem) AccessorRecord(braces, accessors, accessorsCapacity);
+ return new (mem) AccessorRecord(braces, storageInfo,
+ accessors, accessorsCapacity);
}
AbstractStorageDecl::AccessorRecord::AccessorRecord(SourceRange braces,
+ StorageImplInfo implInfo,
ArrayRef<AccessorDecl *> accessors,
AccessorIndex accessorsCapacity)
- : Braces(braces), NumAccessors(accessors.size()),
+ : Braces(braces), ImplInfo(implInfo), NumAccessors(accessors.size()),
AccessorsCapacity(accessorsCapacity), AccessorIndices{} {
// Copy the complete accessors list into place.
@@ -3860,57 +3910,55 @@
}
void AbstractStorageDecl::setComputedSetter(AccessorDecl *setter) {
- assert(getStorageKind() == Computed && "Not a computed variable");
+ assert(getImplInfo().getReadImpl() == ReadImplKind::Get);
+ assert(!getImplInfo().supportsMutation());
assert(getGetter() && "sanity check: missing getter");
assert(!getSetter() && "already has a setter");
assert(hasClangNode() && "should only be used for ObjC properties");
assert(isAccessor(setter, AccessorKind::Set, this));
assert(setter && "should not be called for readonly properties");
+ overwriteImplInfo(StorageImplInfo::getMutableComputed());
Accessors.getPointer()->addOpaqueAccessor(setter);
configureAccessor(setter);
}
-void AbstractStorageDecl::setMaterializeForSetFunc(AccessorDecl *accessor) {
- assert(hasAccessorFunctions() && "No accessors for declaration!");
- assert(getSetter() && "declaration is not settable");
- assert(!getMaterializeForSetFunc() && "already has a materializeForSet");
- assert(isAccessor(accessor, AccessorKind::MaterializeForSet, this));
+void
+AbstractStorageDecl::setSynthesizedGetter(AccessorDecl *accessor) {
+ assert(!getGetter() && "declaration doesn't already have getter!");
+ assert(isAccessor(accessor, AccessorKind::Get, this));
+
+ auto accessors = Accessors.getPointer();
+ if (!accessors) {
+ accessors = AccessorRecord::create(getASTContext(), SourceRange(),
+ getImplInfo(), {});
+ Accessors.setPointer(accessors);
+ }
+
+ accessors->addOpaqueAccessor(accessor);
+ configureAccessor(accessor);
+}
+
+void
+AbstractStorageDecl::setSynthesizedSetter(AccessorDecl *accessor) {
+ assert(getGetter() && "declaration doesn't already have getter!");
+ assert(supportsMutation() && "adding setter to immutable storage");
+ assert(isAccessor(accessor, AccessorKind::Set, this));
Accessors.getPointer()->addOpaqueAccessor(accessor);
configureAccessor(accessor);
}
-/// \brief Turn this into a StoredWithTrivialAccessors var, specifying the
-/// accessors (getter and setter) that go with it.
-void AbstractStorageDecl::addTrivialAccessors(AccessorDecl *getter,
- AccessorDecl *setter,
- AccessorDecl *materializeForSet) {
- assert((getStorageKind() == Stored ||
- getStorageKind() == Addressed) && "StorageKind already set");
- assert(getter);
+void
+AbstractStorageDecl::setSynthesizedMaterializeForSet(AccessorDecl *accessor) {
+ assert(getGetter() && "declaration doesn't already have getter!");
+ assert(getSetter() && "declaration doesn't already have setter!");
+ assert(supportsMutation() && "adding materializeForSet to immutable storage");
+ assert(!getMaterializeForSetFunc() && "already has a materializeForSet");
+ assert(isAccessor(accessor, AccessorKind::MaterializeForSet, this));
- if (getStorageKind() == Addressed) {
- setStorageKind(AddressedWithTrivialAccessors);
- } else {
- setStorageKind(StoredWithTrivialAccessors);
- if (!Accessors.getPointer()) {
- Accessors.setPointer(AccessorRecord::create(getASTContext(),
- SourceRange(), {}));
- }
- }
-
- auto record = Accessors.getPointer();
- assert(record);
-
- auto collect = [&](AccessorDecl *accessor) {
- record->addOpaqueAccessor(accessor);
- configureAccessor(accessor);
- };
-
- collect(getter);
- if (setter) collect(setter);
- if (materializeForSet) collect(materializeForSet);
+ Accessors.getPointer()->addOpaqueAccessor(accessor);
+ configureAccessor(accessor);
}
void AbstractStorageDecl::addBehavior(TypeRepr *Type,
@@ -4020,30 +4068,6 @@
return SourceLoc();
}
-static bool isSettable(const AbstractStorageDecl *decl) {
- switch (decl->getStorageKind()) {
- case AbstractStorageDecl::Stored:
- return true;
-
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- return decl->getSetter() != nullptr;
-
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- return decl->getMutableAddressor() != nullptr;
-
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::AddressedWithObservers:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- return true;
-
- case AbstractStorageDecl::Computed:
- return decl->getSetter() != nullptr;
- }
- llvm_unreachable("bad storage kind");
-}
-
Type VarDecl::getType() const {
if (!typeInContext) {
const_cast<VarDecl *>(this)->typeInContext =
@@ -4076,7 +4100,7 @@
// If this is a 'var' decl, then we're settable if we have storage or a
// setter.
if (!isImmutable())
- return ::isSettable(this);
+ return supportsMutation();
// If the decl has a value bound to it but has no PBD, then it is
// initialized.
@@ -4139,7 +4163,7 @@
}
bool SubscriptDecl::isSettable() const {
- return ::isSettable(this);
+ return supportsMutation();
}
SourceRange VarDecl::getSourceRange() const {
@@ -4230,6 +4254,11 @@
return false;
}
+void VarDecl::setSpecifier(Specifier specifier) {
+ Bits.VarDecl.Specifier = static_cast<unsigned>(specifier);
+ setSupportsMutationIfStillStored(!isImmutableSpecifier(specifier));
+}
+
bool VarDecl::isAnonClosureParam() const {
auto name = getName();
if (name.empty())
@@ -5670,11 +5699,7 @@
Type ClassDecl::getSuperclass() const {
ASTContext &ctx = getASTContext();
- if (auto lazyResolver = ctx.getLazyResolver()) {
- return lazyResolver->getSuperclass(this);
- }
-
- return LazySemanticInfo.Superclass.getPointer();
+ return ctx.evaluator(SuperclassTypeRequest{const_cast<ClassDecl *>(this)});
}
ClassDecl *ClassDecl::getSuperclassDecl() const {
diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp
index 93f5ba7..12d4aa5 100644
--- a/lib/AST/Evaluator.cpp
+++ b/lib/AST/Evaluator.cpp
@@ -32,6 +32,32 @@
return result;
}
+AbstractRequestFunction *
+Evaluator::getAbstractRequestFunction(uint8_t zoneID, uint8_t requestID) const {
+ for (const auto &zone : requestFunctionsByZone) {
+ if (zone.first == zoneID) {
+ if (requestID < zone.second.size())
+ return zone.second[requestID];
+
+ return nullptr;
+ }
+ }
+
+ return nullptr;
+}
+
+void Evaluator::registerRequestFunctions(
+ uint8_t zoneID,
+ ArrayRef<AbstractRequestFunction *> functions) {
+#ifndef NDEBUG
+ for (const auto &zone : requestFunctionsByZone) {
+ assert(zone.first != zoneID);
+ }
+#endif
+
+ requestFunctionsByZone.push_back({zoneID, functions});
+}
+
Evaluator::Evaluator(DiagnosticEngine &diags,
CycleDiagnosticKind shouldDiagnoseCycles)
: diags(diags), shouldDiagnoseCycles(shouldDiagnoseCycles) { }
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5ec9569..683bcd6 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -379,6 +379,7 @@
NON_LVALUE_EXPR(ObjCSelector)
NON_LVALUE_EXPR(KeyPath)
NON_LVALUE_EXPR(EnumIsCase)
+ NON_LVALUE_EXPR(LazyInitializer)
#define UNCHECKED_EXPR(KIND, BASE) \
NON_LVALUE_EXPR(KIND)
@@ -413,6 +414,7 @@
NO_REFERENCE(ObjectLiteral);
NO_REFERENCE(MagicIdentifierLiteral);
NO_REFERENCE(DiscardAssignment);
+ NO_REFERENCE(LazyInitializer);
SIMPLE_REFERENCE(DeclRef, getDeclRef);
SIMPLE_REFERENCE(SuperRef, getSelf);
@@ -684,6 +686,7 @@
switch (getKind()) {
case ExprKind::Error:
case ExprKind::CodeCompletion:
+ case ExprKind::LazyInitializer:
return false;
case ExprKind::NilLiteral:
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 9c4511c..7e5d364 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -130,12 +130,6 @@
ProtocolConformanceRef conformance,
Identifier name,
LazyResolver *resolver) {
- // For an archetype, retrieve the nested type with the appropriate
- // name. There are no conformance tables.
- if (auto archetype = type->getAs<ArchetypeType>()) {
- return archetype->getNestedType(name);
- }
-
// Find the named requirement.
AssociatedTypeDecl *assocType = nullptr;
auto members = conformance.getRequirement()->lookupDirect(name);
@@ -149,8 +143,15 @@
if (!assocType)
return nullptr;
- if (conformance.isAbstract())
+ if (conformance.isAbstract()) {
+ // For an archetype, retrieve the nested type with the appropriate
+ // name. There are no conformance tables.
+ if (auto archetype = type->getAs<ArchetypeType>()) {
+ return archetype->getNestedType(name);
+ }
+
return DependentMemberType::get(type, assocType);
+ }
auto concrete = conformance.getConcrete();
if (!concrete->hasTypeWitness(assocType, resolver)) {
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
new file mode 100644
index 0000000..ba9f13f
--- /dev/null
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -0,0 +1,147 @@
+//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+#include "swift/AST/TypeCheckRequests.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/DiagnosticsCommon.h"
+#include "swift/AST/TypeLoc.h"
+#include "swift/AST/Types.h"
+
+using namespace swift;
+
+namespace swift {
+// Implement the type checker type zone (zone 10).
+#define SWIFT_TYPEID_ZONE 10
+#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
+#include "swift/Basic/ImplementTypeIDZone.h"
+
+}
+
+void swift::simple_display(
+ llvm::raw_ostream &out,
+ const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value) {
+ if (auto type = value.dyn_cast<TypeDecl *>()) {
+ type->dumpRef(out);
+ return;
+ }
+
+ auto ext = value.get<ExtensionDecl *>();
+ out << "extension of ";
+ ext->getAsNominalTypeOrNominalTypeExtensionContext()->dumpRef(out);
+}
+
+//----------------------------------------------------------------------------//
+// Inherited type computation.
+//----------------------------------------------------------------------------//
+
+TypeLoc &InheritedTypeRequest::getTypeLoc(
+ llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
+ unsigned index) const {
+ if (auto typeDecl = decl.dyn_cast<TypeDecl *>())
+ return typeDecl->getInherited()[index];
+
+ return decl.get<ExtensionDecl *>()->getInherited()[index];
+}
+
+void InheritedTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+ const auto &storage = getStorage();
+ auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+ diags.diagnose(typeLoc.getLoc(), diag::circular_reference);
+}
+
+void InheritedTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
+ const auto &storage = getStorage();
+ auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+ diags.diagnose(typeLoc.getLoc(), diag::circular_reference_through);
+}
+
+Optional<Type> InheritedTypeRequest::getCachedResult() const {
+ const auto &storage = getStorage();
+ auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+ if (typeLoc.wasValidated())
+ return typeLoc.getType();
+
+ return None;
+}
+
+void InheritedTypeRequest::cacheResult(Type value) const {
+ const auto &storage = getStorage();
+ auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+ typeLoc.setType(value);
+}
+
+//----------------------------------------------------------------------------//
+// Superclass computation.
+//----------------------------------------------------------------------------//
+void SuperclassTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+ // FIXME: Improve this diagnostic.
+ auto nominalDecl = std::get<0>(getStorage());
+ diags.diagnose(nominalDecl, diag::circular_class_inheritance,
+ nominalDecl->getName());
+}
+
+void SuperclassTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
+ auto nominalDecl = std::get<0>(getStorage());
+ // FIXME: Customize this further.
+ diags.diagnose(nominalDecl, diag::circular_reference_through);
+}
+
+Optional<Type> SuperclassTypeRequest::getCachedResult() const {
+ auto nominalDecl = std::get<0>(getStorage());
+
+ if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+ if (classDecl->LazySemanticInfo.Superclass.getInt())
+ return classDecl->LazySemanticInfo.Superclass.getPointer();
+
+ if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+ if (protocolDecl->LazySemanticInfo.Superclass.getInt())
+ return protocolDecl->LazySemanticInfo.Superclass.getPointer();
+
+ return None;
+}
+
+void SuperclassTypeRequest::cacheResult(Type value) const {
+ auto nominalDecl = std::get<0>(getStorage());
+
+ if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+ classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+
+ if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+ protocolDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+}
+
+//----------------------------------------------------------------------------//
+// Enum raw type computation.
+//----------------------------------------------------------------------------//
+void EnumRawTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+ // FIXME: Improve this diagnostic.
+ auto enumDecl = std::get<0>(getStorage());
+ diags.diagnose(enumDecl, diag::circular_enum_inheritance, enumDecl->getName());
+}
+
+void EnumRawTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
+ auto enumDecl = std::get<0>(getStorage());
+ // FIXME: Customize this further.
+ diags.diagnose(enumDecl, diag::circular_reference_through);
+}
+
+Optional<Type> EnumRawTypeRequest::getCachedResult() const {
+ auto enumDecl = std::get<0>(getStorage());
+ if (enumDecl->LazySemanticInfo.RawType.getInt())
+ return enumDecl->LazySemanticInfo.RawType.getPointer();
+
+ return None;
+}
+
+void EnumRawTypeRequest::cacheResult(Type value) const {
+ auto enumDecl = std::get<0>(getStorage());
+ enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
+}
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 699c756..fcb21b1 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -188,10 +188,13 @@
static void makeComputed(AbstractStorageDecl *storage,
AccessorDecl *getter, AccessorDecl *setter) {
assert(getter);
- AccessorDecl *buffer[] = { getter, setter };
- auto accessors = llvm::makeArrayRef(buffer).slice(0, setter ? 2 : 1);
- storage->setAccessors(AbstractStorageDecl::Computed,
- SourceLoc(), accessors, SourceLoc());
+ if (setter) {
+ storage->setAccessors(StorageImplInfo::getMutableComputed(),
+ SourceLoc(), {getter, setter}, SourceLoc());
+ } else {
+ storage->setAccessors(StorageImplInfo::getImmutableComputed(),
+ SourceLoc(), {getter}, SourceLoc());
+ }
}
#ifndef NDEBUG
@@ -1198,6 +1201,7 @@
auto call = CallExpr::createImplicit(context, zeroInitializerRef, {}, {});
call->setType(selfType);
+ call->setThrows(false);
auto assign = new (context) AssignExpr(lhs, SourceLoc(), call,
/*implicit*/ true);
@@ -1423,7 +1427,7 @@
auto varGetter = makeStructRawValueGetter(
Impl, structDecl, var, var);
- var->addTrivialAccessors(varGetter, nullptr, nullptr);
+ var->setSynthesizedGetter(varGetter);
assert(var->hasStorage());
// Create constructors to initialize that value from a value of the
@@ -1641,9 +1645,9 @@
thunk->setAccess(getOverridableAccessLevel(dc));
- auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>();
- assert(objcAttr);
- thunk->getAttrs().add(objcAttr->clone(C));
+ if (auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>())
+ thunk->getAttrs().add(objcAttr->clone(C));
+ thunk->setIsObjC(getter->isObjC());
// FIXME: Should we record thunks?
return thunk;
@@ -1711,9 +1715,9 @@
thunk->setAccess(getOverridableAccessLevel(dc));
- auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>();
- assert(objcAttr);
- thunk->getAttrs().add(objcAttr->clone(C));
+ if (auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>())
+ thunk->getAttrs().add(objcAttr->clone(C));
+ thunk->setIsObjC(setter->isObjC());
return thunk;
}
@@ -2634,7 +2638,6 @@
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(decl,
AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
structDecl->computeType();
- structDecl->setCheckedInheritanceClause();
structDecl->setAddedImplicitInitializers();
auto options = getDefaultMakeStructRawValuedOptions();
@@ -2776,7 +2779,6 @@
SmallVector<TypeLoc, 2> inheritedTypes;
inheritedTypes.push_back(TypeLoc::withoutLoc(underlyingType));
enumDecl->setInherited(C.AllocateCopy(inheritedTypes));
- enumDecl->setCheckedInheritanceClause();
if (errorWrapper) {
addSynthesizedProtocolAttrs(Impl, enumDecl,
@@ -3811,7 +3813,11 @@
/// The importer should use this rather than adding the attribute directly.
void addObjCAttribute(ValueDecl *decl, Optional<ObjCSelector> name) {
auto &ctx = Impl.SwiftContext;
- decl->getAttrs().add(ObjCAttr::create(ctx, name, /*implicitName=*/true));
+ if (name) {
+ decl->getAttrs().add(ObjCAttr::create(ctx, name,
+ /*implicitName=*/true));
+ }
+ decl->setIsObjC(true);
// If the declaration we attached the 'objc' attribute to is within a
// class, record it in the class.
@@ -4378,7 +4384,6 @@
inheritedTypes);
result->setValidationStarted();
result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
- result->setCheckedInheritanceClause();
result->setMemberLoader(&Impl, 0);
return result;
@@ -4516,7 +4521,6 @@
importObjCProtocols(result, decl->getReferencedProtocols(),
inheritedTypes);
result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
- result->setCheckedInheritanceClause();
// Compute the requirement signature.
if (!result->isRequirementSignatureComputed())
@@ -4563,7 +4567,6 @@
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
result->setCircularityCheck(CircularityCheck::Checked);
result->setSuperclass(Type());
- result->setCheckedInheritanceClause();
result->setAddedImplicitInitializers(); // suppress all initializers
addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
result->addImplicitDestructor();
@@ -4720,7 +4723,6 @@
importObjCProtocols(result, decl->getReferencedProtocols(),
inheritedTypes);
result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
- result->setCheckedInheritanceClause();
// Add inferred attributes.
#define INFERRED_ATTRIBUTES(ModuleName, ClassName, AttributeSet) \
@@ -5144,7 +5146,6 @@
SmallVector<TypeLoc, 4> inheritedTypes;
inheritedTypes.push_back(TypeLoc::withoutLoc(superclass));
theClass->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
- theClass->setCheckedInheritanceClause();
}
addSynthesizedProtocolAttrs(Impl, theClass, {KnownProtocolKind::CFObject});
@@ -5305,7 +5306,6 @@
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
structDecl->computeType();
- structDecl->setCheckedInheritanceClause();
structDecl->setAddedImplicitInitializers();
// Import the type of the underlying storage
@@ -5584,7 +5584,6 @@
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
structDecl->computeType();
- structDecl->setCheckedInheritanceClause();
structDecl->setAddedImplicitInitializers();
makeStructRawValued(Impl, structDecl, underlyingType,
@@ -6515,7 +6514,8 @@
auto swiftSel = Impl.importSelector(sel);
for (auto found : classDecl->lookupDirect(swiftSel, true)) {
if (auto foundFunc = dyn_cast<FuncDecl>(found))
- return foundFunc;
+ if (foundFunc->hasClangNode())
+ return foundFunc;
}
}
@@ -8224,7 +8224,6 @@
auto ext = ExtensionDecl::create(SwiftContext, SourceLoc(), swiftTyLoc, {},
getClangModuleForDecl(decl), nullptr);
ext->setValidationStarted();
- ext->setCheckedInheritanceClause();
ext->setMemberLoader(this, reinterpret_cast<uintptr_t>(declSubmodule));
if (auto protoDecl = ext->getAsProtocolExtensionContext()) {
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 0784305..3c34aec 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -152,6 +152,7 @@
Context.reset(ASTContext::get(Invocation.getLangOptions(),
Invocation.getSearchPathOptions(), SourceMgr,
Diagnostics));
+ registerTypeCheckerRequestFunctions(Context->evaluator);
if (setUpModuleLoaders())
return true;
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 89ff552..95aeda1 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1338,14 +1338,12 @@
/// to the \c Consumer.
bool DeliveredResults = false;
- bool typecheckContext(DeclContext *DC) {
+ void typeCheckContext(DeclContext *DC) {
// Nothing to type check in module context.
if (DC->isModuleScopeContext())
- return true;
+ return;
- // Type check the parent context.
- if (!typecheckContext(DC->getParent()))
- return false;
+ typeCheckContext(DC->getParent());
// Type-check this context.
switch (DC->getContextKind()) {
@@ -1353,31 +1351,38 @@
case DeclContextKind::Initializer:
case DeclContextKind::Module:
case DeclContextKind::SerializedLocal:
+ case DeclContextKind::TopLevelCodeDecl:
// Nothing to do for these.
- return true;
+ break;
- case DeclContextKind::AbstractFunctionDecl:
- return typeCheckAbstractFunctionBodyUntil(
- cast<AbstractFunctionDecl>(DC),
+ case DeclContextKind::AbstractFunctionDecl: {
+ auto *AFD = cast<AbstractFunctionDecl>(DC);
+
+ // FIXME: This shouldn't be necessary, but we crash otherwise.
+ if (auto *AD = dyn_cast<AccessorDecl>(AFD))
+ typeCheckCompletionDecl(AD->getStorage());
+
+ typeCheckAbstractFunctionBodyUntil(
+ AFD,
P.Context.SourceMgr.getCodeCompletionLoc());
+ break;
+ }
case DeclContextKind::ExtensionDecl:
- return typeCheckCompletionDecl(cast<ExtensionDecl>(DC));
+ typeCheckCompletionDecl(cast<ExtensionDecl>(DC));
+ break;
case DeclContextKind::GenericTypeDecl:
- return typeCheckCompletionDecl(cast<GenericTypeDecl>(DC));
+ typeCheckCompletionDecl(cast<GenericTypeDecl>(DC));
+ break;
case DeclContextKind::FileUnit:
llvm_unreachable("module scope context handled above");
case DeclContextKind::SubscriptDecl:
- return typeCheckCompletionDecl(cast<SubscriptDecl>(DC));
-
- case DeclContextKind::TopLevelCodeDecl:
- return typeCheckTopLevelCodeDecl(cast<TopLevelCodeDecl>(DC));
+ typeCheckCompletionDecl(cast<SubscriptDecl>(DC));
+ break;
}
-
- llvm_unreachable("Unhandled DeclContextKind in switch.");
}
Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
@@ -5186,8 +5191,16 @@
CurDeclContext = DC;
}
- if (!typecheckContext(CurDeclContext))
- return;
+ // The only time we have to explicitly check a TopLevelCodeDecl
+ // is when we're directly inside of one. In this case,
+ // performTypeChecking() did not type check it for us.
+ auto *DC = CurDeclContext;
+ while (isa<AbstractClosureExpr>(DC))
+ DC = DC->getParent();
+ if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(DC))
+ typeCheckTopLevelCodeDecl(TLCD);
+ else
+ typeCheckContext(CurDeclContext);
Optional<Type> ExprType;
ConcreteDeclRef ReferencedDecl = nullptr;
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index 36ee0b7..f6bbaa6 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -1612,7 +1612,7 @@
return false;
if (auto ASD = dyn_cast<AbstractStorageDecl>(D)) {
- auto accessors = ASD->getAllAccessorFunctions();
+ auto accessors = ASD->getAllAccessors();
Found.insert(accessors.begin(), accessors.end());
}
return true;
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index 03f149e..61b2c02 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -801,9 +801,9 @@
else
SR = VD->getSourceRange();
SN.Range = charSourceRangeFromSourceRange(SM, SR);
- if (VD->hasAccessorFunctions())
- SN.BodyRange = innerCharSourceRangeFromSourceRange(SM,
- VD->getBracesRange());
+ auto bracesRange = VD->getBracesRange();
+ if (bracesRange.isValid())
+ SN.BodyRange = innerCharSourceRangeFromSourceRange(SM, bracesRange);
SourceLoc NRStart = VD->getNameLoc();
SourceLoc NREnd = NRStart.getAdvancedLoc(VD->getName().getLength());
SN.NameRange = CharSourceRange(SM, NRStart, NREnd);
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 257c601..1b900bd 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -2250,7 +2250,7 @@
/*generics*/ nullptr,
Context.TheBuiltinModule);
SwiftRootClass->computeType();
- SwiftRootClass->setIsObjC(true);
+ SwiftRootClass->setIsObjC(Context.LangOpts.EnableObjCInterop);
SwiftRootClass->getAttrs().add(ObjCAttr::createNullary(Context, objcName,
/*isNameImplicit=*/true));
SwiftRootClass->setImplicit();
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index e0ee36d..0fce67f 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2136,6 +2136,12 @@
bool inFixedBuffer = false;
bool indirectForDebugInfo = false;
+ // FIXME: Remove this once LLDB has proper support for resilience.
+ bool isREPLVar = false;
+ if (auto *decl = var->getDecl())
+ if (decl->isREPLVar())
+ isREPLVar = true;
+
if (var->isInitializedObject()) {
assert(ti.isFixedSize(expansion));
StructLayout *Layout = StaticObjectLayouts[var].get();
@@ -2155,7 +2161,7 @@
fixedSize = Layout->getSize();
fixedAlignment = Layout->getAlignment();
assert(fixedAlignment >= TargetInfo.HeapObjectAlignment);
- } else if (ti.isFixedSize(expansion)) {
+ } else if (isREPLVar || ti.isFixedSize(expansion)) {
// Allocate static storage.
auto &fixedTI = cast<FixedTypeInfo>(ti);
storageType = fixedTI.getStorageType();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 3f9cdda..6ec7f07 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -481,11 +481,21 @@
}
void addName() {
+ SmallString<32> nameBuf;
StringRef name;
-
+
+ // Use the original name with tag for synthesized decls. The tag comes
+ // after the null terminator for the name.
+ if (auto *synthesizedTypeAttr =
+ Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+ nameBuf.append(synthesizedTypeAttr->originalTypeName);
+ nameBuf.push_back('\0');
+ nameBuf.append(synthesizedTypeAttr->getManglingName());
+
+ name = nameBuf;
// Try to use the Clang name if there is one.
- if (auto namedClangDecl =
- Mangle::ASTMangler::getClangDeclForMangling(Type)) {
+ } else if (auto namedClangDecl =
+ Mangle::ASTMangler::getClangDeclForMangling(Type)) {
name = namedClangDecl->getName();
} else {
name = Type->getName().str();
@@ -565,22 +575,18 @@
/// Flags to indicate Clang-imported declarations so we mangle them
/// consistently at runtime.
void getClangImportedFlags(TypeContextDescriptorFlags &flags) const {
- auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type);
- if (!clangDecl)
- return;
-
- if (isa<clang::TagDecl>(clangDecl)) {
- flags.setIsCTag(true);
- return;
+ if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+ flags.setIsSynthesizedRelatedEntity(true);
}
- if (isa<clang::TypedefNameDecl>(clangDecl)
- || isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
- flags.setIsCTypedef(true);
- return;
+ if (auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type)) {
+ if (isa<clang::TagDecl>(clangDecl)) {
+ flags.setIsCTag(true);
+ } else if (isa<clang::TypedefNameDecl>(clangDecl)
+ || isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
+ flags.setIsCTypedef(true);
+ }
}
-
- return;
}
// Subclasses should provide:
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index a9f6fc0..4553214 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1859,9 +1859,15 @@
auto expansion = IGM.getResilienceExpansionForLayout(var);
+ // FIXME: Remove this once LLDB has proper support for resilience.
+ bool isREPLVar = false;
+ if (auto *decl = var->getDecl())
+ if (decl->isREPLVar())
+ isREPLVar = true;
+
// If the global is fixed-size in all resilience domains that can see it,
// we allocated storage for it statically, and there's nothing to do.
- if (ti.isFixedSize(expansion))
+ if (isREPLVar || ti.isFixedSize(expansion))
return;
// Otherwise, the static storage for the global consists of a fixed-size
@@ -1889,9 +1895,15 @@
Address addr = IGM.getAddrOfSILGlobalVariable(var, ti,
NotForDefinition);
+ // FIXME: Remove this once LLDB has proper support for resilience.
+ bool isREPLVar = false;
+ if (auto *decl = var->getDecl())
+ if (decl->isREPLVar())
+ isREPLVar = true;
+
// If the global is fixed-size in all resilience domains that can see it,
// we allocated storage for it statically, and there's nothing to do.
- if (ti.isFixedSize(expansion)) {
+ if (isREPLVar || ti.isFixedSize(expansion)) {
setLoweredAddress(i, addr);
return;
}
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 3bccbb5..154447a 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -871,8 +871,11 @@
auto isNullOrImplicit = [](const Decl *D) -> bool {
return !D || D->isImplicit();
};
+
+ bool usedPseudoAccessors = false;
if (isa<VarDecl>(D) && isNullOrImplicit(StoreD->getGetter()) &&
isNullOrImplicit(StoreD->getSetter())) {
+ usedPseudoAccessors = true;
auto VarD = cast<VarDecl>(D);
// No actual getter or setter, pass 'pseudo' accessors.
// We create accessor entities so we can implement the functionality
@@ -885,33 +888,19 @@
return false;
if (!reportPseudoSetterDecl(VarD))
return false;
- } else {
- if (auto FD = StoreD->getGetter())
- SourceEntityWalker::walk(cast<Decl>(FD));
+ }
+
+ for (auto accessor : StoreD->getAllAccessors()) {
+ // Don't include the implicit getter and setter if we added pseudo
+ // accessors above.
+ if (usedPseudoAccessors &&
+ (accessor->getAccessorKind() == AccessorKind::Get ||
+ accessor->getAccessorKind() == AccessorKind::Set))
+ continue;
+
+ SourceEntityWalker::walk(cast<Decl>(accessor));
if (Cancelled)
return false;
- if (auto FD = StoreD->getSetter())
- SourceEntityWalker::walk(cast<Decl>(FD));
- if (Cancelled)
- return false;
- }
- if (StoreD->hasObservers()) {
- if (auto FD = StoreD->getWillSetFunc())
- SourceEntityWalker::walk(cast<Decl>(FD));
- if (Cancelled)
- return false;
- if (auto FD = StoreD->getDidSetFunc())
- SourceEntityWalker::walk(cast<Decl>(FD));
- if (Cancelled)
- return false;
- }
- if (StoreD->hasAddressors()) {
- if (auto FD = StoreD->getAddressor())
- SourceEntityWalker::walk(cast<Decl>(FD));
- if (Cancelled)
- return false;
- if (auto FD = StoreD->getMutableAddressor())
- SourceEntityWalker::walk(cast<Decl>(FD));
}
} else if (auto NTD = dyn_cast<NominalTypeDecl>(D)) {
if (!reportInheritedTypeRefs(NTD->getInherited(), NTD))
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 39dbb03..c507d36 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -675,6 +675,23 @@
}
return false;
}
+ case SpecialCaseId::UIApplicationMain: {
+ // If the first argument is CommandLine.argc, replace the second argument
+ // with CommandLine.unsafeArgv
+ CallArgInfo &FirstArg = AllArgs[0];
+ // handle whitespace/line splits around the first arg when matching
+ auto FirstArgSplit =
+ SM.extractText(FirstArg.getEntireCharRange(SM)).rsplit('.');
+ if (!FirstArgSplit.second.empty() &&
+ FirstArgSplit.first.trim() == "CommandLine" &&
+ FirstArgSplit.second.trim() == "argc") {
+ CallArgInfo &SecondArg = AllArgs[1];
+ Editor.replace(SecondArg.getEntireCharRange(SM),
+ "CommandLine.unsafeArgv");
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/lib/Migrator/overlay3.json b/lib/Migrator/overlay3.json
index 19c5d66..d0820c4 100644
--- a/lib/Migrator/overlay3.json
+++ b/lib/Migrator/overlay3.json
@@ -1316,4 +1316,9 @@
"RightComment": "compactMap",
"ModuleName": "Swift"
},
+ {
+ "DiffItemKind": "SpecialCaseDiffItem",
+ "Usr": "c:@F@UIApplicationMain",
+ "SpecialCaseId": "UIApplicationMain"
+ }
]
diff --git a/lib/Migrator/overlay4.json b/lib/Migrator/overlay4.json
index 19c5d66..d0820c4 100644
--- a/lib/Migrator/overlay4.json
+++ b/lib/Migrator/overlay4.json
@@ -1316,4 +1316,9 @@
"RightComment": "compactMap",
"ModuleName": "Swift"
},
+ {
+ "DiffItemKind": "SpecialCaseDiffItem",
+ "Usr": "c:@F@UIApplicationMain",
+ "SpecialCaseId": "UIApplicationMain"
+ }
]
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index acf9390..2e5b7f0 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4540,7 +4540,7 @@
storage->setAccessors(storageKind, LBLoc, Accessors, RBLoc);
}
-AbstractStorageDecl::StorageKindTy
+StorageImplInfo
Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
bool invalid, ParseDeclOptions flags,
SourceLoc staticLoc,
@@ -4631,6 +4631,18 @@
}
}
+ // Disallow observers with addressors.
+ if (Address || MutableAddress) {
+ if (WillSet) {
+ P.diagnose(WillSet->getLoc(), diag::observingproperty_with_address, 0);
+ ignoreInvalidAccessor(WillSet);
+ }
+ if (DidSet) {
+ P.diagnose(DidSet->getLoc(), diag::observingproperty_with_address, 1);
+ ignoreInvalidAccessor(DidSet);
+ }
+ }
+
// If this is a willSet/didSet observing property, record this and we're done.
if (WillSet || DidSet) {
if (Get) {
@@ -4644,23 +4656,6 @@
ignoreInvalidAccessor(Set);
}
- AbstractStorageDecl::StorageKindTy storageKind;
- if (Address) {
- if (!MutableAddress) {
- P.diagnose(WillSet ? WillSet->getLoc() : DidSet->getLoc(),
- diag::observingproperty_without_mutableaddress,
- bool(DidSet));
- createImplicitAccessor(AccessorKind::MutableAddress,
- AddressorKind::Unsafe, nullptr);
- }
-
- storageKind = AbstractStorageDecl::AddressedWithObservers;
- } else if (attrs.hasAttribute<OverrideAttr>()) {
- storageKind = AbstractStorageDecl::InheritedWithObservers;
- } else {
- storageKind = AbstractStorageDecl::StoredWithObservers;
- }
-
// Observing properties will have getters and setters synthesized by sema.
// Create their prototypes now.
createImplicitAccessor(AccessorKind::Get,
@@ -4675,13 +4670,27 @@
createImplicitAccessor(AccessorKind::Set,
AddressorKind::NotAddressor, argList);
- return storageKind;
+ if (attrs.hasAttribute<OverrideAttr>()) {
+ return StorageImplInfo(ReadImplKind::Inherited,
+ WriteImplKind::InheritedWithObservers,
+ ReadWriteImplKind::MaterializeToTemporary);
+ } else {
+ return StorageImplInfo(ReadImplKind::Stored,
+ WriteImplKind::StoredWithObservers,
+ ReadWriteImplKind::MaterializeToTemporary);
+ }
}
// If we have addressors, at this point mark it as addressed.
if (Address) {
assert(!Get && !Set);
- return AbstractStorageDecl::Addressed;
+ if (MutableAddress) {
+ return StorageImplInfo(ReadImplKind::Address,
+ WriteImplKind::MutableAddress,
+ ReadWriteImplKind::MutableAddress);
+ } else {
+ return StorageImplInfo(ReadImplKind::Address);
+ }
}
// If this is a get+mutableAddress property, synthesize an implicit
@@ -4695,7 +4704,9 @@
createImplicitAccessor(AccessorKind::Set,
AddressorKind::NotAddressor, argList);
- return AbstractStorageDecl::ComputedWithMutableAddress;
+ return StorageImplInfo(ReadImplKind::Get,
+ WriteImplKind::MutableAddress,
+ ReadWriteImplKind::MutableAddress);
}
// Otherwise, this must be a get/set property. The set is optional,
@@ -4718,17 +4729,19 @@
}
}
+ assert(!Set || Get);
+
if (Set || Get) {
if (attrs.hasAttribute<SILStoredAttr>())
// Turn this into a stored property with trivial accessors.
- return AbstractStorageDecl::StoredWithTrivialAccessors;
+ return StorageImplInfo::getSimpleStored(Set != nullptr);
else
// Turn this into a computed variable.
- return AbstractStorageDecl::Computed;
+ return StorageImplInfo::getComputed(Set != nullptr);
} else {
// Otherwise this decl is invalid and the accessors have been rejected above.
// Make sure to at least record the braces range in the AST.
- return AbstractStorageDecl::Stored;
+ return StorageImplInfo::getSimpleStored(/*mutable*/ true);
}
}
@@ -4925,6 +4938,11 @@
// global, record it.
PBDEntries.back().setInitContext(initContext);
+ // If the attributes include @lazy, flag that on each initializer.
+ if (Attributes.hasAttribute<LazyAttr>()) {
+ PBDEntries.back().setInitializerLazy();
+ }
+
// If we are doing second pass of code completion, we don't want to
// suddenly cut off parsing and throw away the declaration.
if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) {
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index d3f0714..2522604 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -1301,7 +1301,7 @@
(accessorKind = getAccessorKind(Id.str())).hasValue()) {
auto storageDecl = dyn_cast<AbstractStorageDecl>(VD);
auto accessor = (storageDecl
- ? storageDecl->getAccessorFunction(*accessorKind)
+ ? storageDecl->getAccessor(*accessorKind)
: nullptr);
if (!accessor) {
P.diagnose(IdLoc, diag::referenced_value_no_accessor, 0);
@@ -1312,8 +1312,7 @@
// Update values for this accessor kind.
for (unsigned I = 0, E = values.size(); I < E; I++)
if (auto otherDecl = dyn_cast<AbstractStorageDecl>(values[I]))
- if (auto otherAccessor =
- otherDecl->getAccessorFunction(*accessorKind))
+ if (auto otherAccessor = otherDecl->getAccessor(*accessorKind))
values[I] = otherAccessor;
ParseState = 1;
} else if (!ParseState && Id.str() == "allocator") {
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index a70ccab..fc54291 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -754,7 +754,17 @@
if (HadError) return;
if (decl == Result) return;
if (!Result) {
- Result = cast<NominalTypeDecl>(decl);
+ // A synthesized type from the Clang importer may resolve to a
+ // compatibility alias.
+ if (auto resultAlias = dyn_cast<TypeAliasDecl>(decl)) {
+ if (resultAlias->isCompatibilityAlias()) {
+ Result = resultAlias->getUnderlyingTypeLoc().getType()
+ ->getAnyNominal();
+ }
+ } else {
+ Result = dyn_cast<NominalTypeDecl>(decl);
+ }
+ HadError |= !Result;
} else {
HadError = true;
Result = nullptr;
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 6c61fa5..cc07bc9 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -775,6 +775,10 @@
if (isThunk() || isForeign)
return SubclassScope::NotApplicable;
+ // Default arg generators only need to be visible in Swift 3.
+ if (isDefaultArgGenerator() && !context->getASTContext().isSwiftVersion3())
+ return SubclassScope::NotApplicable;
+
auto *classType = context->getAsClassOrClassExtensionContext();
if (!classType || classType->isFinal())
return SubclassScope::NotApplicable;
diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp
index 1509b15..f32b86f 100644
--- a/lib/SIL/SILProfiler.cpp
+++ b/lib/SIL/SILProfiler.cpp
@@ -140,8 +140,8 @@
ASTWalker &Walker) {
if (PBD && !PBD->isStatic())
for (auto E : PBD->getPatternList())
- if (E.getInit())
- E.getInit()->walk(Walker);
+ if (auto init = E.getNonLazyInit())
+ init->walk(Walker);
}
/// Special logic for handling closure visitation.
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 5fc4e78..df4a5a7 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -216,19 +216,7 @@
require(fieldTy == componentTy,
"property decl should be a member of the base with the same type "
"as the component");
- switch (property->getStorageKind()) {
- case AbstractStorageDecl::Stored:
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- break;
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithObservers:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::Computed:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::InheritedWithObservers:
- require(false, "property must be stored");
- }
+ require(property->hasStorage(), "property must be stored");
auto propertyTy = loweredBaseTy.getFieldType(property, M);
require(propertyTy.getObjectType()
== loweredComponentTy.getObjectType(),
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index 416ea7e..244f018 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -89,60 +89,35 @@
CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture) {
auto decl = capture.getDecl();
if (auto *var = dyn_cast<VarDecl>(decl)) {
- switch (var->getStorageKind()) {
- case VarDecl::StoredWithTrivialAccessors:
- llvm_unreachable("stored local variable with trivial accessors?");
+ assert(var->hasStorage() &&
+ "should not have attempted to directly capture this variable");
- case VarDecl::InheritedWithObservers:
- llvm_unreachable("inherited local variable?");
+ // If this is a non-address-only stored 'let' constant, we can capture it
+ // by value. If it is address-only, then we can't load it, so capture it
+ // by its address (like a var) instead.
+ if (var->isImmutable() &&
+ (!SILModuleConventions(M).useLoweredAddresses() ||
+ !getTypeLowering(var->getType()).isAddressOnly()))
+ return CaptureKind::Constant;
- case VarDecl::Computed:
- llvm_unreachable("computed captured property should have been lowered "
- "away");
-
- case VarDecl::StoredWithObservers:
- case VarDecl::Addressed:
- case VarDecl::AddressedWithTrivialAccessors:
- case VarDecl::AddressedWithObservers:
- case VarDecl::ComputedWithMutableAddress:
- // Computed captures should have been lowered away.
- assert(capture.isDirect()
- && "computed captured property should have been lowered away");
-
- // If captured directly, the variable is captured by box or pointer.
- assert(var->hasStorage());
- return capture.isNoEscape() ?
- CaptureKind::StorageAddress : CaptureKind::Box;
-
- case VarDecl::Stored:
- // If this is a non-address-only stored 'let' constant, we can capture it
- // by value. If it is address-only, then we can't load it, so capture it
- // by its address (like a var) instead.
- if (var->isImmutable() &&
- (!SILModuleConventions(M).useLoweredAddresses() ||
- !getTypeLowering(var->getType()).isAddressOnly()))
- return CaptureKind::Constant;
-
- // In-out parameters are captured by address.
- if (var->isInOut()) {
- return CaptureKind::StorageAddress;
- }
-
- // Reference storage types can appear in a capture list, which means
- // we might allocate boxes to store the captures. However, those boxes
- // have the same lifetime as the closure itself, so we must capture
- // the box itself and not the payload, even if the closure is noescape,
- // otherwise they will be destroyed when the closure is formed.
- if (var->getType()->is<ReferenceStorageType>()) {
- return CaptureKind::Box;
- }
-
- // If we're capturing into a non-escaping closure, we can generally just
- // capture the address of the value as no-escape.
- return capture.isNoEscape() ?
- CaptureKind::StorageAddress : CaptureKind::Box;
+ // In-out parameters are captured by address.
+ if (var->isInOut()) {
+ return CaptureKind::StorageAddress;
}
- llvm_unreachable("bad storage kind");
+
+ // Reference storage types can appear in a capture list, which means
+ // we might allocate boxes to store the captures. However, those boxes
+ // have the same lifetime as the closure itself, so we must capture
+ // the box itself and not the payload, even if the closure is noescape,
+ // otherwise they will be destroyed when the closure is formed.
+ if (var->getType()->is<ReferenceStorageType>()) {
+ return CaptureKind::Box;
+ }
+
+ // If we're capturing into a non-escaping closure, we can generally just
+ // capture the address of the value as no-escape.
+ return capture.isNoEscape() ?
+ CaptureKind::StorageAddress : CaptureKind::Box;
}
// "Captured" local types require no context.
@@ -2080,57 +2055,76 @@
// If the capture is of a computed property, grab the transitive captures
// of its accessors.
if (auto capturedVar = dyn_cast<VarDecl>(capture.getDecl())) {
- switch (capturedVar->getStorageKind()) {
- case VarDecl::StoredWithTrivialAccessors:
- llvm_unreachable("stored local variable with trivial accessors?");
+ if (!capture.isDirect()) {
+ auto impl = capturedVar->getImplInfo();
- case VarDecl::InheritedWithObservers:
- llvm_unreachable("inherited local variable?");
-
- case VarDecl::StoredWithObservers:
- case VarDecl::Addressed:
- case VarDecl::AddressedWithTrivialAccessors:
- case VarDecl::AddressedWithObservers:
- case VarDecl::ComputedWithMutableAddress:
- // Directly capture storage if we're supposed to.
- if (capture.isDirect())
- goto capture_value;
-
- // Otherwise, transitively capture the accessors.
- LLVM_FALLTHROUGH;
-
- case VarDecl::Computed: {
- collectFunctionCaptures(capturedVar->getGetter());
- if (auto setter = capturedVar->getSetter())
- collectFunctionCaptures(setter);
- continue;
- }
-
- case VarDecl::Stored: {
- // We can always capture the storage in these cases.
- Type captureType = capturedVar->getType();
- if (auto *metatypeType = captureType->getAs<MetatypeType>())
- captureType = metatypeType->getInstanceType();
-
- if (auto *selfType = captureType->getAs<DynamicSelfType>()) {
- captureType = selfType->getSelfType();
-
- // We're capturing a 'self' value with dynamic 'Self' type;
- // handle it specially.
- if (!selfCapture &&
- captureType->getClassOrBoundGenericClass()) {
- selfCapture = capture;
- continue;
- }
+ switch (impl.getReadImpl()) {
+ case ReadImplKind::Stored:
+ // Will capture storage later.
+ break;
+ case ReadImplKind::Address:
+ collectFunctionCaptures(capturedVar->getAddressor());
+ break;
+ case ReadImplKind::Get:
+ collectFunctionCaptures(capturedVar->getGetter());
+ break;
+ case ReadImplKind::Inherited:
+ llvm_unreachable("inherited local variable?");
}
- // Otherwise just fall through.
- goto capture_value;
+ switch (impl.getWriteImpl()) {
+ case WriteImplKind::Immutable:
+ case WriteImplKind::Stored:
+ break;
+ case WriteImplKind::StoredWithObservers:
+ case WriteImplKind::Set:
+ collectFunctionCaptures(capturedVar->getSetter());
+ break;
+ case WriteImplKind::MutableAddress:
+ collectFunctionCaptures(capturedVar->getMutableAddressor());
+ break;
+ case WriteImplKind::InheritedWithObservers:
+ llvm_unreachable("inherited local variable");
+ }
+
+ switch (impl.getReadWriteImpl()) {
+ case ReadWriteImplKind::Immutable:
+ case ReadWriteImplKind::Stored:
+ break;
+ case ReadWriteImplKind::MaterializeToTemporary:
+ // We've already processed the read and write operations.
+ break;
+ case ReadWriteImplKind::MutableAddress:
+ collectFunctionCaptures(capturedVar->getMutableAddressor());
+ break;
+ case ReadWriteImplKind::MaterializeForSet:
+ llvm_unreachable("local variable with materializeForSet?");
+ }
}
+
+ if (!capturedVar->hasStorage())
+ continue;
+
+ // We can always capture the storage in these cases.
+ Type captureType = capturedVar->getType();
+ if (auto *metatypeType = captureType->getAs<MetatypeType>())
+ captureType = metatypeType->getInstanceType();
+
+ if (auto *selfType = captureType->getAs<DynamicSelfType>()) {
+ captureType = selfType->getSelfType();
+
+ // We're capturing a 'self' value with dynamic 'Self' type;
+ // handle it specially.
+ if (!selfCapture &&
+ captureType->getClassOrBoundGenericClass()) {
+ selfCapture = capture;
+ continue;
+ }
}
+
+ // Fall through to capture the storage.
}
- capture_value:
// Collect non-function captures.
captures.insert(capture);
}
diff --git a/lib/SILGen/ASTVisitor.h b/lib/SILGen/ASTVisitor.h
index 1012b0f..72553ab 100644
--- a/lib/SILGen/ASTVisitor.h
+++ b/lib/SILGen/ASTVisitor.h
@@ -65,6 +65,11 @@
return static_cast<ImplClass*>(this)->visit(E->getSubExpr(),
std::forward<Args>(AA)...);
}
+
+ ExprRetTy visitLazyInitializerExpr(LazyInitializerExpr *E, Args...AA) {
+ return static_cast<ImplClass*>(this)->visit(E->getSubExpr(),
+ std::forward<Args>(AA)...);
+ }
};
template <typename ImplClass,
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index daf92b9..9039c3d 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -16,6 +16,7 @@
#include "swift/Strings.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/GenericEnvironment.h"
+#include "swift/AST/Initializer.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/PrettyStackTrace.h"
@@ -731,9 +732,9 @@
PrettyStackTraceSILFunction X("silgen emitFunction", f);
auto accessor = dyn_cast<AccessorDecl>(fd);
if (accessor && accessor->isMaterializeForSet())
- SILGenFunction(*this, *f).emitMaterializeForSet(accessor);
+ SILGenFunction(*this, *f, accessor).emitMaterializeForSet(accessor);
else
- SILGenFunction(*this, *f).emitFunction(fd);
+ SILGenFunction(*this, *f, fd).emitFunction(fd);
postEmitFunction(constant, f);
}, /*forceEmission=*/ForCoverageMapping);
}
@@ -772,7 +773,7 @@
*this, constant, [this, constant, decl](SILFunction *f) {
preEmitFunction(constant, decl, f, decl);
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
- SILGenFunction(*this, *f).emitClassConstructorAllocator(decl);
+ SILGenFunction(*this, *f, decl).emitClassConstructorAllocator(decl);
postEmitFunction(constant, f);
});
@@ -788,7 +789,8 @@
initF);
initF->setProfiler(
getOrCreateProfilerForConstructors(declCtx, decl));
- SILGenFunction(*this, *initF).emitClassConstructorInitializer(decl);
+ SILGenFunction(*this, *initF, decl)
+ .emitClassConstructorInitializer(decl);
postEmitFunction(initConstant, initF);
},
/*forceEmission=*/ForCoverageMapping);
@@ -800,7 +802,7 @@
preEmitFunction(constant, decl, f, decl);
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl));
- SILGenFunction(*this, *f).emitValueConstructor(decl);
+ SILGenFunction(*this, *f, decl).emitValueConstructor(decl);
postEmitFunction(constant, f);
});
}
@@ -813,7 +815,7 @@
SILFunction *f = getFunction(constant, ForDefinition);
preEmitFunction(constant, decl, f, decl);
PrettyStackTraceSILFunction X("silgen enum constructor", f);
- SILGenFunction(*this, *f).emitEnumConstructor(decl);
+ SILGenFunction(*this, *f, decl->getDeclContext()).emitEnumConstructor(decl);
postEmitFunction(constant, f);
}
@@ -832,7 +834,7 @@
preEmitFunction(constant, ce, f, ce);
PrettyStackTraceSILFunction X("silgen closureexpr", f);
- SILGenFunction(*this, *f).emitClosure(ce);
+ SILGenFunction(*this, *f, ce).emitClosure(ce);
postEmitFunction(constant, f);
return f;
}
@@ -848,7 +850,7 @@
if (!pbd) continue;
for (auto entry : pbd->getPatternList())
- if (entry.getInit())
+ if (entry.getNonLazyInit())
return true;
}
@@ -887,7 +889,7 @@
preEmitFunction(dealloc, dd, f, dd);
PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f);
f->createProfiler(dd, ForDefinition);
- SILGenFunction(*this, *f).emitObjCDestructor(dealloc);
+ SILGenFunction(*this, *f, dd).emitObjCDestructor(dealloc);
postEmitFunction(dealloc, f);
}
@@ -903,7 +905,7 @@
SILFunction *f = getFunction(ivarInitializer, ForDefinition);
preEmitFunction(ivarInitializer, dd, f, dd);
PrettyStackTraceSILFunction X("silgen emitDestructor ivar initializer", f);
- SILGenFunction(*this, *f).emitIVarInitializer(ivarInitializer);
+ SILGenFunction(*this, *f, cd).emitIVarInitializer(ivarInitializer);
postEmitFunction(ivarInitializer, f);
}
@@ -914,7 +916,7 @@
SILFunction *f = getFunction(ivarDestroyer, ForDefinition);
preEmitFunction(ivarDestroyer, dd, f, dd);
PrettyStackTraceSILFunction X("silgen emitDestructor ivar destroyer", f);
- SILGenFunction(*this, *f).emitIVarDestroyer(ivarDestroyer);
+ SILGenFunction(*this, *f, cd).emitIVarDestroyer(ivarDestroyer);
postEmitFunction(ivarDestroyer, f);
}
}
@@ -928,7 +930,7 @@
SILFunction *f = getFunction(ivarDestroyer, ForDefinition);
preEmitFunction(ivarDestroyer, dd, f, dd);
PrettyStackTraceSILFunction X("silgen emitDestructor ivar destroyer", f);
- SILGenFunction(*this, *f).emitIVarDestroyer(ivarDestroyer);
+ SILGenFunction(*this, *f, dd).emitIVarDestroyer(ivarDestroyer);
postEmitFunction(ivarDestroyer, f);
}
@@ -945,7 +947,7 @@
SILFunction *f = getFunction(destroyer, ForDefinition);
preEmitFunction(destroyer, dd, f, dd);
PrettyStackTraceSILFunction X("silgen emitDestroyingDestructor", f);
- SILGenFunction(*this, *f).emitDestroyingDestructor(dd);
+ SILGenFunction(*this, *f, dd).emitDestroyingDestructor(dd);
f->setDebugScope(new (M) SILDebugScope(dd, f));
postEmitFunction(destroyer, f);
}
@@ -957,14 +959,15 @@
preEmitFunction(deallocator, dd, f, dd);
PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f);
f->createProfiler(dd, ForDefinition);
- SILGenFunction(*this, *f).emitDeallocatingDestructor(dd);
+ SILGenFunction(*this, *f, dd).emitDeallocatingDestructor(dd);
f->setDebugScope(new (M) SILDebugScope(dd, f));
postEmitFunction(deallocator, f);
}
}
void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
- DefaultArgumentKind kind) {
+ DefaultArgumentKind kind,
+ DeclContext *initDC) {
switch (kind) {
case DefaultArgumentKind::None:
llvm_unreachable("No default argument here?");
@@ -986,10 +989,11 @@
return;
}
- emitOrDelayFunction(*this, constant, [this,constant,arg](SILFunction *f) {
+ emitOrDelayFunction(*this, constant,
+ [this,constant,arg,initDC](SILFunction *f) {
preEmitFunction(constant, arg, f, arg);
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
- SILGenFunction SGF(*this, *f);
+ SILGenFunction SGF(*this, *f, initDC);
SGF.emitGeneratorFunction(constant, arg);
postEmitFunction(constant, f);
});
@@ -1000,9 +1004,12 @@
const PatternBindingEntry &pbdEntry = pbd->getPatternList()[i];
auto *var = pbdEntry.getAnchoringVarDecl();
auto *init = pbdEntry.getInit();
+ auto *initDC = pbdEntry.getInitContext();
+ assert(!pbdEntry.isInitializerLazy());
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
- emitOrDelayFunction(*this, constant, [this,constant,init,var](SILFunction *f) {
+ emitOrDelayFunction(*this, constant,
+ [this,constant,init,initDC,var](SILFunction *f) {
preEmitFunction(constant, init, f, init);
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
@@ -1010,7 +1017,7 @@
f->setProfiler(
getOrCreateProfilerForConstructors(var->getDeclContext(), nullptr));
- SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
+ SILGenFunction(*this, *f, initDC).emitGeneratorFunction(constant, init);
postEmitFunction(constant, f);
});
}
@@ -1033,7 +1040,8 @@
SILLocation(binding), IsNotBare, IsNotTransparent,
IsNotSerialized);
f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f));
- SILGenFunction(*this, *f).emitLazyGlobalInitializer(binding, pbdEntry);
+ auto dc = binding->getDeclContext();
+ SILGenFunction(*this, *f, dc).emitLazyGlobalInitializer(binding, pbdEntry);
f->verify();
return f;
@@ -1047,7 +1055,7 @@
[this,accessor,global,onceToken,onceFunc](SILFunction *f){
preEmitFunction(accessor, global, f, global);
PrettyStackTraceSILFunction X("silgen emitGlobalAccessor", f);
- SILGenFunction(*this, *f)
+ SILGenFunction(*this, *f, global->getDeclContext())
.emitGlobalAccessor(global, onceToken, onceFunc);
postEmitFunction(accessor, f);
});
@@ -1059,7 +1067,8 @@
for (auto param : *paramList) {
if (auto defaultArg = param->getDefaultValue())
emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index),
- defaultArg, param->getDefaultArgumentKind());
+ defaultArg, param->getDefaultArgumentKind(),
+ param->getDefaultArgumentInitContext());
++index;
}
}
@@ -1078,7 +1087,7 @@
PrettyStackTraceSILFunction X("silgen emitObjCMethodThunk", f);
f->setBare(IsBare);
f->setThunk(IsThunk);
- SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+ SILGenFunction(*this, *f, method).emitNativeToForeignThunk(thunk);
postEmitFunction(thunk, f);
}
@@ -1104,7 +1113,8 @@
PrettyStackTraceSILFunction X("silgen objc property getter thunk", f);
f->setBare(IsBare);
f->setThunk(IsThunk);
- SILGenFunction(*this, *f).emitNativeToForeignThunk(getter);
+ SILGenFunction(*this, *f, prop->getGetter())
+ .emitNativeToForeignThunk(getter);
postEmitFunction(getter, f);
}
@@ -1120,7 +1130,7 @@
PrettyStackTraceSILFunction X("silgen objc property setter thunk", f);
f->setBare(IsBare);
f->setThunk(IsThunk);
- SILGenFunction(*this, *f).emitNativeToForeignThunk(setter);
+ SILGenFunction(*this, *f, prop->getSetter()).emitNativeToForeignThunk(setter);
postEmitFunction(setter, f);
}
@@ -1139,7 +1149,7 @@
PrettyStackTraceSILFunction X("silgen objc constructor thunk", f);
f->setBare(IsBare);
f->setThunk(IsThunk);
- SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+ SILGenFunction(*this, *f, constructor).emitNativeToForeignThunk(thunk);
postEmitFunction(thunk, f);
}
@@ -1155,14 +1165,14 @@
PrettyStackTraceSILFunction X("silgen objc destructor thunk", f);
f->setBare(IsBare);
f->setThunk(IsThunk);
- SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+ SILGenFunction(*this, *f, destructor).emitNativeToForeignThunk(thunk);
postEmitFunction(thunk, f);
}
void SILGenModule::visitPatternBindingDecl(PatternBindingDecl *pd) {
assert(!TopLevelSGF && "script mode PBDs should be in TopLevelCodeDecls");
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i)
- if (pd->getInit(i))
+ if (pd->getNonLazyInit(i))
emitGlobalInitialization(pd, i);
}
@@ -1173,13 +1183,15 @@
if (vd->hasStorage())
addGlobalVariable(vd);
- if (vd->getStorageKind() == AbstractStorageDecl::StoredWithTrivialAccessors) {
+ if (vd->getImplInfo().isSimpleStored()) {
// If the global variable has storage, it might also have synthesized
// accessors. Emit them here, since they won't appear anywhere else.
if (auto getter = vd->getGetter())
emitFunction(getter);
if (auto setter = vd->getSetter())
emitFunction(setter);
+ if (auto materializeForSet = vd->getMaterializeForSetFunc())
+ emitFunction(materializeForSet);
}
tryEmitPropertyDescriptor(vd);
@@ -1187,9 +1199,12 @@
bool
TypeConverter::canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl) {
- switch (auto strategy = decl->getAccessStrategy(AccessSemantics::Ordinary,
- AccessKind::ReadWrite,
- M.getSwiftModule())) {
+ auto strategy = decl->getAccessStrategy(AccessSemantics::Ordinary,
+ decl->supportsMutation()
+ ? AccessKind::ReadWrite
+ : AccessKind::Read,
+ M.getSwiftModule());
+ switch (strategy.getKind()) {
case AccessStrategy::Storage: {
// If the stored value would need to be reabstracted in fully opaque
// context, then we have to treat the component as computed.
@@ -1208,9 +1223,9 @@
return storageTy.getAddressType() == opaqueTy.getAddressType();
}
- case AccessStrategy::Addressor:
case AccessStrategy::DirectToAccessor:
case AccessStrategy::DispatchToAccessor:
+ case AccessStrategy::MaterializeToTemporary:
return false;
case AccessStrategy::BehaviorStorage:
llvm_unreachable("should not occur");
@@ -1488,7 +1503,7 @@
// Assign a debug scope pointing into the void to the top level function.
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
- sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel);
+ sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel, sf);
sgm.TopLevelSGF->MagicFunctionName = sgm.SwiftModule->getName();
auto moduleCleanupLoc = CleanupLocation::getModuleCleanupLocation();
sgm.TopLevelSGF->prepareEpilog(Type(), true, moduleCleanupLoc);
@@ -1599,7 +1614,7 @@
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
// Create the argc and argv arguments.
- SILGenFunction SGF(sgm, *toplevel);
+ SILGenFunction SGF(sgm, *toplevel, sf);
auto entry = SGF.B.getInsertionBB();
auto paramTypeIter =
SGF.F.getConventions().getParameterSILTypes().begin();
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index e00ec3a..a6e61ee 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -248,7 +248,7 @@
/// Emits the default argument generator with the given expression.
void emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
- DefaultArgumentKind kind);
+ DefaultArgumentKind kind, DeclContext *DC);
/// Emits the stored property initializer for the given pattern.
void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 0410c0f..db9437f 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -5298,7 +5298,7 @@
if (auto genericFnType = dyn_cast<GenericFunctionType>(origAccessType))
genericSig = genericFnType.getGenericSignature();
- return MaterializedLValue(ManagedValue::forUnmanaged(address),
+ return MaterializedLValue(ManagedValue::forLValue(address),
origSelfType, genericSig,
optionalCallback, callbackStorage);
}
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 9575a81..68bbb0e 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -584,7 +584,7 @@
// Build it if necessary.
if (thunk->empty()) {
thunk->setGenericEnvironment(genericEnv);
- SILGenFunction thunkSGF(SGM, *thunk);
+ SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
auto loc = RegularLocation::getAutoGeneratedLocation();
// Not retaining the closure in the reabstraction thunk is safe if we hold
// another reference for the is_escaping sentinel.
@@ -938,7 +938,7 @@
// Build it if necessary.
if (thunk->empty()) {
- SILGenFunction thunkSGF(SGM, *thunk);
+ SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
thunk->setGenericEnvironment(genericEnv);
auto loc = RegularLocation::getAutoGeneratedLocation();
buildBlockToFuncThunkBody(thunkSGF, loc, blockType, funcType,
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 9d37d5b..e1358da 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -940,7 +940,7 @@
if (pbd->isStatic()) continue;
for (auto entry : pbd->getPatternList()) {
- auto init = entry.getInit();
+ auto init = entry.getNonLazyInit();
if (!init) continue;
// Cleanup after this initialization.
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index 6045189..e816a99 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -1141,7 +1141,7 @@
// If an initial value expression was specified by the decl, emit it into
// the initialization. Otherwise, mark it uninitialized for DI to resolve.
- if (auto *Init = entry.getInit()) {
+ if (auto *Init = entry.getNonLazyInit()) {
FullExpr Scope(Cleanups, CleanupLocation(Init));
emitExprInto(Init, initialization.get(), SILLocation(PBD));
} else {
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 703d4aa..14dc138 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -708,22 +708,29 @@
return ManagedValue();
}
- switch (var->getAccessStrategy(semantics, accessKind)) {
+ auto strategy = var->getAccessStrategy(semantics, accessKind, FunctionDC);
+
+ switch (strategy.getKind()) {
case AccessStrategy::Storage:
// The only kind of stored variable that should make it to here is
// a global variable. Just invoke its accessor function to get its
// address.
return emitGlobalVariableRef(loc, var);
- case AccessStrategy::Addressor: {
+ case AccessStrategy::DirectToAccessor:
+ case AccessStrategy::DispatchToAccessor: {
+ auto accessor = strategy.getAccessor();
+ if (accessor != AccessorKind::Address &&
+ accessor != AccessorKind::MutableAddress)
+ return ManagedValue();
+
LValue lvalue =
emitLValueForAddressedNonMemberVarDecl(loc, var, formalRValueType,
accessKind, semantics);
return emitAddressOfLValue(loc, std::move(lvalue), accessKind);
}
- case AccessStrategy::DirectToAccessor:
- case AccessStrategy::DispatchToAccessor:
+ case AccessStrategy::MaterializeToTemporary:
return ManagedValue();
case AccessStrategy::BehaviorStorage:
@@ -1047,7 +1054,7 @@
? Result : Result.copyUnmanaged(*this, loc));
}
- assert(var->hasAccessorFunctions() && "Unknown rvalue case");
+ assert(var->getGetter() && "Unknown rvalue case");
SILDeclRef getter = SGM.getGetterDeclRef(var);
@@ -1074,7 +1081,8 @@
selfSource = ArgumentSource(loc, std::move(metatypeRV));
}
- bool isDirectAccessorUse = (semantics == AccessSemantics::DirectToAccessor);
+ bool isDirectAccessorUse =
+ (semantics == AccessSemantics::DirectToImplementation);
return emitGetAccessor(loc, getter,
SGM.getNonMemberVarDeclSubstitutions(var),
std::move(selfSource),
@@ -1109,19 +1117,27 @@
static SILDeclRef getRValueAccessorDeclRef(SILGenFunction &SGF,
AbstractStorageDecl *storage,
AccessStrategy strategy) {
- switch (strategy) {
+ switch (strategy.getKind()) {
case AccessStrategy::BehaviorStorage:
llvm_unreachable("shouldn't load an rvalue via behavior storage!");
case AccessStrategy::Storage:
llvm_unreachable("should already have been filtered out!");
- case AccessStrategy::DirectToAccessor:
- case AccessStrategy::DispatchToAccessor:
- return SGF.SGM.getGetterDeclRef(storage);
+ case AccessStrategy::MaterializeToTemporary:
+ llvm_unreachable("never used for read accesses");
- case AccessStrategy::Addressor:
- return SGF.SGM.getAddressorDeclRef(storage, AccessKind::Read);
+ case AccessStrategy::DirectToAccessor:
+ case AccessStrategy::DispatchToAccessor: {
+ auto accessor = strategy.getAccessor();
+ assert(accessor == AccessorKind::Get || accessor == AccessorKind::Address);
+ if (accessor == AccessorKind::Get) {
+ return SGF.SGM.getGetterDeclRef(storage);
+ } else {
+ return SGF.SGM.getAddressorDeclRef(storage, AccessKind::Read);
+ }
+ }
+
}
llvm_unreachable("should already have been filtered out!");
}
@@ -1136,26 +1152,18 @@
AbstractionPattern origFormalType,
CanType substFormalType,
SGFContext C) {
- bool isDirectUse = (strategy == AccessStrategy::DirectToAccessor);
-
- switch (strategy) {
- case AccessStrategy::BehaviorStorage:
- llvm_unreachable("shouldn't load an rvalue via behavior storage!");
-
- case AccessStrategy::Storage:
- llvm_unreachable("should already have been filtered out!");
+ assert(strategy.getKind() == AccessStrategy::DirectToAccessor ||
+ strategy.getKind() == AccessStrategy::DispatchToAccessor);
+ bool isDirectUse = (strategy.getKind() == AccessStrategy::DirectToAccessor);
// The easy path here is if we don't need to use an addressor.
- case AccessStrategy::DirectToAccessor:
- case AccessStrategy::DispatchToAccessor: {
+ if (strategy.getAccessor() == AccessorKind::Get) {
return SGF.emitGetAccessor(loc, accessor, substitutions,
std::move(baseRV), isSuper, isDirectUse,
std::move(subscriptRV), C);
}
- case AccessStrategy::Addressor:
- break;
- }
+ assert(strategy.getAccessor() == AccessorKind::Address);
auto &storageTL = SGF.getTypeLowering(origFormalType, substFormalType);
SILType storageType = storageTL.getLoweredType().getAddressType();
@@ -1208,10 +1216,10 @@
AccessSemantics semantics, Type propTy, SGFContext C,
bool isBaseGuaranteed) {
AccessStrategy strategy =
- storage->getAccessStrategy(semantics, AccessKind::Read);
+ storage->getAccessStrategy(semantics, AccessKind::Read, FunctionDC);
// If we should call an accessor of some kind, do so.
- if (strategy != AccessStrategy::Storage) {
+ if (strategy.getKind() != AccessStrategy::Storage) {
auto accessor = getRValueAccessorDeclRef(*this, storage, strategy);
ArgumentSource baseRV = prepareAccessorBaseArg(loc, base,
baseFormalType,
@@ -2471,8 +2479,9 @@
// Check that we have a stored access strategy. If we don't bail.
AccessStrategy strategy =
- Field->getAccessStrategy(Expr->getAccessSemantics(), AccessKind::Read);
- if (strategy != AccessStrategy::Storage)
+ Field->getAccessStrategy(Expr->getAccessSemantics(), AccessKind::Read,
+ SGF.FunctionDC);
+ if (strategy.getKind() != AccessStrategy::Storage)
return None;
if (isa<StructDecl>(Base))
@@ -3102,7 +3111,6 @@
SILLocation loc,
AbstractStorageDecl *property,
SubstitutionMap subs,
- AccessStrategy strategy,
GenericEnvironment *genericEnv,
ArrayRef<IndexTypePair> indexes,
CanType baseType,
@@ -3171,7 +3179,7 @@
thunk->setGenericEnvironment(genericEnv);
}
- SILGenFunction subSGF(SGM, *thunk);
+ SILGenFunction subSGF(SGM, *thunk, SGM.SwiftModule);
auto entry = thunk->begin();
auto resultArgTy = result.getSILStorageType();
auto baseArgTy = params[0].getSILStorageType();
@@ -3216,11 +3224,10 @@
return thunk;
}
-SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
+static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
SILLocation loc,
AbstractStorageDecl *property,
SubstitutionMap subs,
- AccessStrategy strategy,
GenericEnvironment *genericEnv,
ArrayRef<IndexTypePair> indexes,
CanType baseType,
@@ -3297,7 +3304,7 @@
thunk->setGenericEnvironment(genericEnv);
}
- SILGenFunction subSGF(SGM, *thunk);
+ SILGenFunction subSGF(SGM, *thunk, SGM.SwiftModule);
auto entry = thunk->begin();
auto valueArgTy = params[0].getSILStorageType();
auto baseArgTy = params[1].getSILStorageType();
@@ -3356,16 +3363,19 @@
}
}
+ auto semantics = AccessSemantics::Ordinary;
+ auto strategy = property->getAccessStrategy(semantics, AccessKind::Write);
+
LValueOptions lvOptions;
if (auto var = dyn_cast<VarDecl>(property)) {
lv.addMemberVarComponent(subSGF, loc, var, subs, lvOptions,
/*super*/ false, AccessKind::Write,
- AccessSemantics::Ordinary, strategy, propertyType);
+ semantics, strategy, propertyType);
} else {
auto sub = cast<SubscriptDecl>(property);
lv.addMemberSubscriptComponent(subSGF, loc, sub, subs, lvOptions,
/*super*/ false, AccessKind::Write,
- AccessSemantics::Ordinary, strategy, propertyType,
+ semantics, strategy, propertyType,
std::move(indexValue));
}
@@ -3453,7 +3463,7 @@
return;
}
- SILGenFunction subSGF(SGM, *equals);
+ SILGenFunction subSGF(SGM, *equals, SGM.SwiftModule);
equals->setGenericEnvironment(genericEnv);
auto entry = equals->begin();
auto lhsPtr = entry->createFunctionArgument(params[0].getSILStorageType());
@@ -3617,7 +3627,7 @@
return;
}
- SILGenFunction subSGF(SGM, *hash);
+ SILGenFunction subSGF(SGM, *hash, SGM.SwiftModule);
hash->setGenericEnvironment(genericEnv);
auto entry = hash->begin();
auto indexPtr = entry->createFunctionArgument(params[0].getSILStorageType());
@@ -3709,11 +3719,19 @@
getIdForKeyPathComponentComputedProperty(SILGenModule &SGM,
AbstractStorageDecl *storage,
AccessStrategy strategy) {
- switch (strategy) {
+ switch (strategy.getKind()) {
case AccessStrategy::Storage:
// Identify reabstracted stored properties by the property itself.
return cast<VarDecl>(storage);
- case AccessStrategy::Addressor:
+ case AccessStrategy::MaterializeToTemporary:
+ // Use the read strategy. But try to avoid turning e.g. an
+ // observed property into a stored property.
+ strategy = strategy.getReadStrategy();
+ if (strategy.getKind() != AccessStrategy::Storage ||
+ !storage->getGetter()) {
+ return getIdForKeyPathComponentComputedProperty(SGM, storage, strategy);
+ }
+ LLVM_FALLTHROUGH;
case AccessStrategy::DirectToAccessor: {
// Identify the property using its (unthunked) getter. For a
// computed property, this should be stable ABI; for a resilient public
@@ -3799,8 +3817,9 @@
CanType baseTy,
bool forPropertyDescriptor) {
auto strategy = storage->getAccessStrategy(AccessSemantics::Ordinary,
- AccessKind::ReadWrite,
- M.getSwiftModule());
+ storage->supportsMutation()
+ ? AccessKind::ReadWrite
+ : AccessKind::Read);
if (auto var = dyn_cast<VarDecl>(storage)) {
CanType componentTy;
@@ -3818,12 +3837,35 @@
if (Types.canStorageUseStoredKeyPathComponent(var)) {
return KeyPathPatternComponent::forStoredProperty(var, componentTy);
- } else {
+ }
+
+ switch (strategy.getKind()) {
+ case AccessStrategy::BehaviorStorage:
+ llvm_unreachable("key path for behavior storage?");
+ case AccessStrategy::Storage: {
+ // If the stored value would need to be reabstracted in fully opaque
+ // context, then we have to treat the component as computed.
+ auto componentObjTy = componentTy->getWithoutSpecifierType();
+ if (genericEnv)
+ componentObjTy = genericEnv->mapTypeIntoContext(componentObjTy);
+ auto storageTy = Types.getSubstitutedStorageType(var, componentObjTy);
+ auto opaqueTy = Types
+ .getLoweredType(AbstractionPattern::getOpaque(), componentObjTy);
+
+ if (storageTy.getAddressType() == opaqueTy.getAddressType()) {
+ return KeyPathPatternComponent::forStoredProperty(var, componentTy);
+ }
+ LLVM_FALLTHROUGH;
+ }
+ case AccessStrategy::MaterializeToTemporary:
+ case AccessStrategy::DirectToAccessor:
+ case AccessStrategy::DispatchToAccessor: {
+ // We need thunks to bring the getter and setter to the right signature
+ // expected by the key path runtime.
auto id = getIdForKeyPathComponentComputedProperty(*this, var,
strategy);
auto getter = getOrCreateKeyPathGetter(*this, loc,
var, subs,
- strategy,
needsGenericContext ? genericEnv : nullptr,
{},
baseTy, componentTy);
@@ -3831,7 +3873,6 @@
if (var->isSettable(var->getDeclContext())) {
auto setter = getOrCreateKeyPathSetter(*this, loc,
var, subs,
- strategy,
needsGenericContext ? genericEnv : nullptr,
{},
baseTy, componentTy);
@@ -3842,6 +3883,7 @@
getter, {}, nullptr, nullptr, componentTy);
}
}
+ }
}
if (auto decl = dyn_cast<SubscriptDecl>(storage)) {
@@ -3875,7 +3917,6 @@
auto id = getIdForKeyPathComponentComputedProperty(*this, decl, strategy);
auto getter = getOrCreateKeyPathGetter(*this, loc,
decl, subs,
- strategy,
needsGenericContext ? genericEnv : nullptr,
indexTypes,
baseTy, componentTy);
@@ -3884,7 +3925,6 @@
if (decl->isSettable()) {
auto setter = getOrCreateKeyPathSetter(*this, loc,
decl, subs,
- strategy,
needsGenericContext ? genericEnv : nullptr,
indexTypes,
baseTy, componentTy);
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 3590262..d0d5b89 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -30,10 +30,12 @@
// SILGenFunction Class implementation
//===----------------------------------------------------------------------===//
-SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F)
- : SGM(SGM), F(F), silConv(SGM.M), StartOfPostmatter(F.end()),
- B(*this), OpenedArchetypesTracker(&F),
+SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F,
+ DeclContext *DC)
+ : SGM(SGM), F(F), silConv(SGM.M), FunctionDC(DC),
+ StartOfPostmatter(F.end()), B(*this), OpenedArchetypesTracker(&F),
CurrentSILLoc(F.getLocation()), Cleanups(*this) {
+ assert(DC && "creating SGF without a DeclContext?");
B.setInsertionPoint(createBasicBlock());
B.setCurrentDebugScope(F.getDebugScope());
B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 50c389f..d7c69d8 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -167,6 +167,9 @@
/// The SILModuleConventions for this SIL module.
SILModuleConventions silConv;
+ /// The DeclContext corresponding to the function currently being emitted.
+ DeclContext * const FunctionDC;
+
/// The name of the function currently being emitted, as presented to user
/// code by #function.
DeclName MagicFunctionName;
@@ -380,7 +383,7 @@
/// Get the PGO node's parent.
Optional<ASTNode> getPGOParent(ASTNode Node) const;
- SILGenFunction(SILGenModule &SGM, SILFunction &F);
+ SILGenFunction(SILGenModule &SGM, SILFunction &F, DeclContext *DC);
~SILGenFunction();
/// Return a stable reference to the current cleanup.
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index e2afa61..f85301f 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -490,6 +490,15 @@
return addr;
}
+static ManagedValue enterAccessScope(SILGenFunction &SGF, SILLocation loc,
+ ManagedValue addr, LValueTypeData typeData,
+ AccessKind accessKind,
+ SILAccessEnforcement enforcement) {
+ return ManagedValue::forLValue(
+ enterAccessScope(SGF, loc, addr.getLValueAddress(), typeData,
+ accessKind, enforcement));
+}
+
// Find the base of the formal access at `address`. If the base requires an
// access marker, then create a begin_access on `address`. Return the
// address to be used for the access.
@@ -503,11 +512,8 @@
return address;
const AccessedStorage &storage = findAccessedStorage(address);
- if (!storage) {
- llvm::dbgs() << "Bad memory access source: " << address;
- llvm_unreachable("Unexpected access source.");
- }
- if (!isPossibleFormalAccessBase(storage, &SGF.F))
+ // Unsafe access may have invalid storage (e.g. a RawPointer).
+ if (storage && !isPossibleFormalAccessBase(storage, &SGF.F))
return address;
auto BAI =
@@ -979,7 +985,7 @@
static LValueOptions getBaseOptions(LValueOptions options,
AccessStrategy strategy) {
- return (strategy == AccessStrategy::Storage
+ return (strategy.getKind() == AccessStrategy::Storage
? options.forProjectedBaseLValue()
: options.forComputedBaseLValue());
}
@@ -1310,11 +1316,15 @@
// of whether the base is trivial because even a trivial base
// may be value-dependent on something non-trivial.
if (base) {
- SILValue temporary = materialized.temporary.getValue();
- materialized.temporary = ManagedValue::forUnmanaged(
+ SILValue temporary = materialized.temporary.getLValueAddress();
+ materialized.temporary = ManagedValue::forLValue(
SGF.B.createMarkDependence(loc, temporary, base.getValue()));
}
}
+ // Enter an access scope for the temporary.
+ materialized.temporary =
+ enterAccessScope(SGF, loc, materialized.temporary, getTypeData(),
+ accessKind, SILAccessEnforcement::Unsafe);
// TODO: maybe needsWriteback should be a thin function pointer
// to which we pass the base? That would let us use direct
@@ -1487,22 +1497,15 @@
// It could be overridden by a computed property in a subclass, but
// that's not likely enough to be worth the strictness here.
if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
- switch (storage->getStorageKind()) {
- case AbstractStorageDecl::Stored:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- return;
+ auto impl = storage->getImplInfo();
// TODO: Stored properties with didSet accessors that don't look at the
// oldValue could also be addressed.
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::AddressedWithObservers:
- break;
-
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::Computed:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- break;
+ if ((impl.getReadImpl() == ReadImplKind::Stored ||
+ impl.getReadImpl() == ReadImplKind::Address) &&
+ (impl.getWriteImpl() == WriteImplKind::Immutable ||
+ impl.getWriteImpl() == WriteImplKind::Stored ||
+ impl.getWriteImpl() == WriteImplKind::MutableAddress)) {
+ return;
}
}
@@ -1628,6 +1631,7 @@
IsSuper,
IsDirectAccessorUse, std::move(args.subscripts), SubstFieldType);
}
+
switch (cast<AccessorDecl>(addressor.getDecl())->getAddressorKind()) {
case AddressorKind::NotAddressor:
llvm_unreachable("not an addressor!");
@@ -1635,13 +1639,13 @@
// For unsafe addressors, we have no owner pointer to manage.
case AddressorKind::Unsafe:
assert(!result.second);
- return result.first;
+ break;
// For owning addressors, we can just let the owner get released
// at an appropriate point.
case AddressorKind::Owning:
case AddressorKind::NativeOwning:
- return result.first;
+ break;
// For pinning addressors, we have to push a writeback.
case AddressorKind::NativePinning: {
@@ -1649,10 +1653,16 @@
component(new UnpinPseudoComponent(getTypeData()));
pushWriteback(SGF, loc, std::move(component), result.second,
MaterializedLValue());
- return result.first;
+ break;
}
}
- llvm_unreachable("bad addressor kind");
+
+ // Enter an unsafe access scope for the access.
+ auto addr = result.first;
+ addr = enterAccessScope(SGF, loc, addr, getTypeData(), accessKind,
+ SILAccessEnforcement::Unsafe);
+
+ return addr;
}
void dump(raw_ostream &OS, unsigned indent) const override {
@@ -2285,13 +2295,22 @@
AccessSemantics semantics) {
LValue lv;
- switch (var->getAccessStrategy(semantics, accessKind)) {
+ auto strategy = var->getAccessStrategy(semantics, accessKind, SGF.FunctionDC);
+ switch (strategy.getKind()) {
case AccessStrategy::DispatchToAccessor:
llvm_unreachable("can't polymorphically access non-member variable");
// If it's a computed variable, push a reference to the getter and setter.
- case AccessStrategy::DirectToAccessor: {
+ case AccessStrategy::DirectToAccessor:
+ if (strategy.getAccessor() == AccessorKind::Address ||
+ strategy.getAccessor() == AccessorKind::MutableAddress) {
+ addNonMemberVarDeclAddressorComponent(SGF.SGM, var, formalRValueType, lv);
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case AccessStrategy::MaterializeToTemporary: {
+ // FIXME: this is not correct for all materialization-based strategies.
auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
lv.add<GetterSetterComponent>(var, /*isSuper=*/false, /*direct*/ true,
SGF.SGM.getNonMemberVarDeclSubstitutions(var),
@@ -2299,11 +2318,6 @@
break;
}
- case AccessStrategy::Addressor: {
- addNonMemberVarDeclAddressorComponent(SGF.SGM, var, formalRValueType, lv);
- break;
- }
-
case AccessStrategy::Storage: {
// If it's a physical value (e.g. a local variable in memory), push its
// address.
@@ -2421,23 +2435,31 @@
static AccessKind getBaseAccessKind(AbstractStorageDecl *member,
AccessKind accessKind,
AccessStrategy strategy) {
- switch (strategy) {
+ switch (strategy.getKind()) {
// Assume that the member only partially projects the enclosing value.
case AccessStrategy::Storage:
return (accessKind == AccessKind::Read
? AccessKind::Read : AccessKind::ReadWrite);
- case AccessStrategy::Addressor:
- return getBaseAccessKindForAccessor(
- member->getAddressorForAccess(accessKind));
+ case AccessStrategy::MaterializeToTemporary: {
+ assert(accessKind == AccessKind::ReadWrite);
+ auto writeBaseKind = getBaseAccessKind(member, AccessKind::Write,
+ strategy.getWriteStrategy());
+
+ // Fast path for the common case that the write will need to mutate
+ // the base.
+ if (writeBaseKind == AccessKind::ReadWrite)
+ return writeBaseKind;
+
+ auto readBaseKind = getBaseAccessKind(member, AccessKind::Read,
+ strategy.getReadStrategy());
+ return combineAccessKinds(readBaseKind, writeBaseKind);
+ }
case AccessStrategy::DirectToAccessor:
case AccessStrategy::DispatchToAccessor:
- if (accessKind == AccessKind::Read) {
- return getBaseAccessKindForAccessor(member->getGetter());
- } else {
- return getBaseAccessKindForAccessor(member->getSetter());
- }
+ return getBaseAccessKindForAccessor(
+ member->getAccessor(strategy.getAccessor()));
case AccessStrategy::BehaviorStorage:
// We should only access the behavior storage for initialization purposes.
@@ -2454,7 +2476,7 @@
// that can be an lvalue is a VarDecl.
VarDecl *var = cast<VarDecl>(e->getMember().getDecl());
AccessStrategy strategy =
- var->getAccessStrategy(e->getAccessSemantics(), accessKind);
+ var->getAccessStrategy(e->getAccessSemantics(), accessKind, SGF.FunctionDC);
LValue lv = visitRec(e->getBase(),
getBaseAccessKind(var, accessKind, strategy),
@@ -2470,6 +2492,38 @@
return lv;
}
+static bool isDirectAccessorUse(AccessStrategy strategy) {
+ switch (strategy.getKind()) {
+ case AccessStrategy::Storage:
+ case AccessStrategy::BehaviorStorage:
+ // This is only necessary to support because of the recursive use in
+ // MaterializeToTemporary.
+ //llvm_unreachable("not an accessor use");
+ return false;
+
+ case AccessStrategy::MaterializeToTemporary:
+ // FIXME: this case should never be handled this way.
+ return isDirectAccessorUse(strategy.getReadStrategy()) ||
+ isDirectAccessorUse(strategy.getWriteStrategy());
+
+ case AccessStrategy::DirectToAccessor:
+ return true;
+
+ case AccessStrategy::DispatchToAccessor:
+ return false;
+ }
+ llvm_unreachable("bad access strategy");
+}
+
+static AccessorKind getRepresentativeAccessor(AccessStrategy strategy) {
+ // HACK: this is only necessary because we don't do the generally-correct
+ // thing yet for MaterializeToTemporary.
+ if (strategy.getKind() == AccessStrategy::MaterializeToTemporary)
+ return AccessorKind::MaterializeForSet;
+
+ return strategy.getAccessor();
+}
+
void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
VarDecl *var,
SubstitutionMap subs,
@@ -2481,66 +2535,79 @@
CanType formalRValueType) {
CanType baseFormalType = getSubstFormalType();
- // Use the property accessors if the variable has accessors and this isn't a
- // direct access to underlying storage.
- if (strategy == AccessStrategy::DirectToAccessor ||
- strategy == AccessStrategy::DispatchToAccessor) {
+ switch (strategy.getKind()) {
+ case AccessStrategy::Storage: {
+ // For static variables, emit a reference to the global variable backing
+ // them.
+ // FIXME: This has to be dynamically looked up for classes, and
+ // dynamically instantiated for generics.
+ if (var->isStatic()) {
+ // FIXME: this implicitly drops the earlier components, but maybe
+ // we ought to evaluate them for side-effects even during the
+ // formal access?
+ *this = emitLValueForNonMemberVarDecl(SGF, loc, var,
+ formalRValueType, accessKind,
+ options, accessSemantics);
+ return;
+ }
+
+ // Otherwise, it's a physical member.
+ SILType varStorageType =
+ SGF.SGM.Types.getSubstitutedStorageType(var, formalRValueType);
+ auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
+
+ if (baseFormalType->mayHaveSuperclass()) {
+ add<RefElementComponent>(var, options, varStorageType, typeData);
+ } else {
+ assert(baseFormalType->getStructOrBoundGenericStruct());
+ add<StructElementComponent>(var, varStorageType, typeData);
+ }
+
+ // If the member has weak or unowned storage, convert it away.
+ if (varStorageType.is<ReferenceStorageType>()) {
+ add<OwnershipComponent>(typeData);
+ }
+ return;
+ }
+
+ case AccessStrategy::MaterializeToTemporary: // FIXME
+ case AccessStrategy::DirectToAccessor:
+ case AccessStrategy::DispatchToAccessor: {
+ auto accessor = getRepresentativeAccessor(strategy);
+
+ if (accessor == AccessorKind::Address ||
+ accessor == AccessorKind::MutableAddress) {
+ SILType varStorageType =
+ SGF.SGM.Types.getSubstitutedStorageType(var, formalRValueType);
+ auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
+
+ add<AddressorComponent>(var, isSuper, /*direct*/ true, subs,
+ baseFormalType, typeData, varStorageType);
+ return;
+ }
+
+ // Use the property accessors if the variable has accessors and this isn't a
+ // direct access to underlying storage.
+ bool isDirect = isDirectAccessorUse(strategy);
auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
- add<GetterSetterComponent>(var, isSuper,
- strategy == AccessStrategy::DirectToAccessor,
+ add<GetterSetterComponent>(var, isSuper, isDirect,
subs, baseFormalType, typeData);
return;
}
- assert(strategy == AccessStrategy::Addressor ||
- strategy == AccessStrategy::Storage ||
- strategy == AccessStrategy::BehaviorStorage);
-
- // Otherwise, the lvalue access is performed with a fragile element reference.
- // Find the substituted storage type.
- SILType varStorageType =
- SGF.SGM.Types.getSubstitutedStorageType(var, formalRValueType);
-
- // For static variables, emit a reference to the global variable backing
- // them.
- // FIXME: This has to be dynamically looked up for classes, and
- // dynamically instantiated for generics.
- if (strategy == AccessStrategy::Storage && var->isStatic()) {
- // FIXME: this implicitly drops the earlier components, but maybe
- // we ought to evaluate them for side-effects even during the
- // formal access?
- *this = emitLValueForNonMemberVarDecl(SGF, loc, var,
- formalRValueType, accessKind,
- options, accessSemantics);
- return;
- }
-
- auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
-
// For behavior initializations, we should have set up a marking proxy that
// replaces the access path.
- if (strategy == AccessStrategy::BehaviorStorage) {
+ case AccessStrategy::BehaviorStorage: {
auto addr = SGF.VarLocs.find(var);
assert(addr != SGF.VarLocs.end() && addr->second.value);
Path.clear();
+ auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
add<ValueComponent>(ManagedValue::forUnmanaged(addr->second.value),
None, typeData);
- // For member variables, this access is done w.r.t. a base computation that
- // was already emitted. This member is accessed off of it.
- } else if (strategy == AccessStrategy::Addressor) {
- add<AddressorComponent>(var, isSuper, /*direct*/ true, subs,
- baseFormalType, typeData, varStorageType);
- } else if (baseFormalType->mayHaveSuperclass()) {
- add<RefElementComponent>(var, options, varStorageType, typeData);
- } else {
- assert(baseFormalType->getStructOrBoundGenericStruct());
- add<StructElementComponent>(var, varStorageType, typeData);
+ return;
}
-
- // If the member has weak or unowned storage, convert it away.
- if (varStorageType.is<ReferenceStorageType>()) {
- add<OwnershipComponent>(typeData);
}
+ llvm_unreachable("bad access strategy");
}
LValue SILGenLValue::visitSubscriptExpr(SubscriptExpr *e,
@@ -2549,7 +2616,8 @@
auto decl = cast<SubscriptDecl>(e->getDecl().getDecl());
auto accessSemantics = e->getAccessSemantics();
- auto strategy = decl->getAccessStrategy(accessSemantics, accessKind);
+ auto strategy =
+ decl->getAccessStrategy(accessSemantics, accessKind, SGF.FunctionDC);
LValue lv = visitRec(e->getBase(),
getBaseAccessKind(decl, accessKind, strategy),
@@ -2627,22 +2695,36 @@
Expr *indexExprForDiagnostics) {
CanType baseFormalType = getSubstFormalType();
- if (strategy == AccessStrategy::DirectToAccessor ||
- strategy == AccessStrategy::DispatchToAccessor) {
- auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
- add<GetterSetterComponent>(decl, isSuper,
- strategy == AccessStrategy::DirectToAccessor,
- subs, baseFormalType, typeData,
- indexExprForDiagnostics, &indices);
- } else {
- assert(strategy == AccessStrategy::Addressor);
- auto typeData = getPhysicalStorageTypeData(SGF.SGM, decl, formalRValueType);
- auto storageType =
- SGF.SGM.Types.getSubstitutedStorageType(decl, formalRValueType);
- add<AddressorComponent>(decl, isSuper, /*direct*/ true,
- subs, baseFormalType, typeData, storageType,
- indexExprForDiagnostics, &indices);
+ switch (strategy.getKind()) {
+ case AccessStrategy::Storage:
+ llvm_unreachable("subscripts never have storage");
+
+ case AccessStrategy::BehaviorStorage:
+ llvm_unreachable("subscripts never have behaviors");
+
+ case AccessStrategy::MaterializeToTemporary:
+ case AccessStrategy::DirectToAccessor:
+ case AccessStrategy::DispatchToAccessor: {
+ auto accessor = getRepresentativeAccessor(strategy);
+ if (accessor == AccessorKind::Address ||
+ accessor == AccessorKind::MutableAddress) {
+ auto typeData = getPhysicalStorageTypeData(SGF.SGM, decl, formalRValueType);
+ auto storageType =
+ SGF.SGM.Types.getSubstitutedStorageType(decl, formalRValueType);
+ add<AddressorComponent>(decl, isSuper, /*direct*/ true,
+ subs, baseFormalType, typeData, storageType,
+ indexExprForDiagnostics, &indices);
+ } else {
+ bool isDirect = isDirectAccessorUse(strategy);
+ auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
+ add<GetterSetterComponent>(decl, isSuper, isDirect,
+ subs, baseFormalType, typeData,
+ indexExprForDiagnostics, &indices);
+ }
+ return;
}
+ }
+ llvm_unreachable("bad access strategy");
}
bool LValue::isObviouslyNonConflicting(const LValue &other,
@@ -2786,49 +2868,62 @@
->getCanonicalType();
AccessStrategy strategy =
- ivar->getAccessStrategy(semantics, accessKind);
+ ivar->getAccessStrategy(semantics, accessKind, FunctionDC);
// Use the property accessors if the variable has accessors and this
// isn't a direct access to underlying storage.
- if (strategy == AccessStrategy::DirectToAccessor ||
- strategy == AccessStrategy::DispatchToAccessor) {
- auto typeData = getLogicalStorageTypeData(SGM, substFormalType);
- lv.add<GetterSetterComponent>(ivar, /*super*/ false,
- strategy == AccessStrategy::DirectToAccessor,
- subMap, baseFormalType, typeData);
+ switch (strategy.getKind()) {
+ case AccessStrategy::Storage: {
+ // Find the substituted storage type.
+ SILType varStorageType =
+ SGM.Types.getSubstitutedStorageType(ivar, substFormalType);
+ auto typeData = getPhysicalStorageTypeData(SGM, ivar, substFormalType);
+
+ if (baseFormalType->hasReferenceSemantics()) {
+ lv.add<RefElementComponent>(ivar, options, varStorageType, typeData);
+ } else {
+ lv.add<StructElementComponent>(ivar, varStorageType, typeData);
+ }
+
+ if (varStorageType.is<ReferenceStorageType>()) {
+ auto formalRValueType =
+ ivar->getDeclContext()->mapTypeIntoContext(ivar->getInterfaceType())
+ ->getReferenceStorageReferent()
+ ->getCanonicalType();
+ auto typeData =
+ getPhysicalStorageTypeData(SGM, ivar, formalRValueType);
+ lv.add<OwnershipComponent>(typeData);
+ }
return lv;
}
- assert(strategy == AccessStrategy::Addressor ||
- strategy == AccessStrategy::Storage);
+ case AccessStrategy::DirectToAccessor:
+ case AccessStrategy::DispatchToAccessor:
+ case AccessStrategy::MaterializeToTemporary: {
+ auto accessor = getRepresentativeAccessor(strategy);
+ bool isDirect = isDirectAccessorUse(strategy);
+ if (accessor == AccessorKind::Address ||
+ accessor == AccessorKind::MutableAddress) {
+ SILType varStorageType =
+ SGM.Types.getSubstitutedStorageType(ivar, substFormalType);
+ auto typeData = getPhysicalStorageTypeData(SGM, ivar, substFormalType);
- // Find the substituted storage type.
- SILType varStorageType =
- SGM.Types.getSubstitutedStorageType(ivar, substFormalType);
-
- auto typeData = getPhysicalStorageTypeData(SGM, ivar, substFormalType);
-
- if (strategy == AccessStrategy::Addressor) {
- lv.add<AddressorComponent>(ivar, /*super*/ false, /*direct*/ true,
- subMap, baseFormalType, typeData, varStorageType);
- } else if (baseFormalType->hasReferenceSemantics()) {
- lv.add<RefElementComponent>(ivar, options, varStorageType, typeData);
- } else {
- lv.add<StructElementComponent>(ivar, varStorageType, typeData);
+ lv.add<AddressorComponent>(ivar, /*super*/ false, isDirect,
+ subMap, baseFormalType, typeData,
+ varStorageType);
+ } else {
+ auto typeData = getLogicalStorageTypeData(SGM, substFormalType);
+ lv.add<GetterSetterComponent>(ivar, /*super*/ false, isDirect,
+ subMap, baseFormalType, typeData);
+ }
+ return lv;
}
- if (varStorageType.is<ReferenceStorageType>()) {
- auto formalRValueType =
- ivar->getDeclContext()->mapTypeIntoContext(ivar->getInterfaceType())
- ->getReferenceStorageReferent()
- ->getCanonicalType();
- auto typeData =
- getPhysicalStorageTypeData(SGM, ivar, formalRValueType);
- lv.add<OwnershipComponent>(typeData);
+ case AccessStrategy::BehaviorStorage:
+ llvm_unreachable("behaviors not expected here?");
}
-
- return lv;
+ llvm_unreachable("bad kind");
}
// This is emitLoad that will handle re-abstraction and bridging for the client.
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 0f3f90b..2d4b300 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -345,18 +345,16 @@
emitter.RequirementStoragePattern = emitter.WitnessStoragePattern;
emitter.RequirementStorageType = emitter.WitnessStorageType;
- // When we're emitting a standard implementation, use direct semantics.
- // If we used TheAccessSemantics::Ordinary here, the only downside would
- // be unnecessary vtable dispatching for class materializeForSets.
- if (!emitter.WitnessStorage->hasObservers() &&
- (emitter.WitnessStorage->hasStorage() ||
- emitter.WitnessStorage->hasAddressors()))
- emitter.TheAccessSemantics = AccessSemantics::DirectToStorage;
- else if (emitter.WitnessStorage->hasClangNode() ||
- emitter.WitnessStorage->isDynamic())
+ if (emitter.WitnessStorage->hasClangNode() ||
+ emitter.WitnessStorage->isDynamic()) {
emitter.TheAccessSemantics = AccessSemantics::Ordinary;
- else
- emitter.TheAccessSemantics = AccessSemantics::DirectToAccessor;
+
+ // When we're emitting a standard implementation, use direct semantics.
+ // If we used AccessSemantics::Ordinary here, the only downside would
+ // be unnecessary vtable dispatching for class materializeForSets.
+ } else {
+ emitter.TheAccessSemantics = AccessSemantics::DirectToImplementation;
+ }
emitter.CallbackName = getMaterializeForSetCallbackName(
/*conformance=*/None, witness);
@@ -491,7 +489,8 @@
LValue lv = buildSelfLValue(SGF, loc, self);
auto strategy =
- WitnessStorage->getAccessStrategy(TheAccessSemantics, accessKind);
+ WitnessStorage->getAccessStrategy(TheAccessSemantics, accessKind,
+ SGF.FunctionDC);
// Drill down to the member storage.
lv.addMemberComponent(SGF, loc, WitnessStorage, WitnessSubs,
@@ -557,14 +556,22 @@
// If there's an abstraction difference, we always need to use the
// get/set pattern.
- AccessStrategy strategy;
- if (WitnessStorage->getInterfaceType()->is<ReferenceStorageType>() ||
- (RequirementStorageType != WitnessStorageType)) {
- strategy = AccessStrategy::DispatchToAccessor;
- } else {
- strategy = WitnessStorage->getAccessStrategy(TheAccessSemantics,
- AccessKind::ReadWrite);
- }
+ AccessStrategy strategy = [&] {
+ if (WitnessStorage->getInterfaceType()->is<ReferenceStorageType>() ||
+ (RequirementStorageType != WitnessStorageType)) {
+ return AccessStrategy::getMaterializeToTemporary(
+ WitnessStorage->getAccessStrategy(TheAccessSemantics,
+ AccessKind::Read,
+ SGF.FunctionDC),
+ WitnessStorage->getAccessStrategy(TheAccessSemantics,
+ AccessKind::Write,
+ SGF.FunctionDC));
+ } else {
+ return WitnessStorage->getAccessStrategy(TheAccessSemantics,
+ AccessKind::ReadWrite,
+ SGF.FunctionDC);
+ }
+ }();
// Handle the indices.
RValue indicesRV;
@@ -579,7 +586,7 @@
// Choose the right implementation.
SILValue address;
SILFunction *callbackFn = nullptr;
- switch (strategy) {
+ switch (strategy.getKind()) {
case AccessStrategy::BehaviorStorage:
llvm_unreachable("materializeForSet should never engage in behavior init");
@@ -588,13 +595,15 @@
callbackBuffer, callbackFn);
break;
- case AccessStrategy::Addressor:
- address = emitUsingAddressor(SGF, loc, self, std::move(indicesRV),
- callbackBuffer, callbackFn);
- break;
-
case AccessStrategy::DirectToAccessor:
case AccessStrategy::DispatchToAccessor:
+ if (strategy.getAccessor() == AccessorKind::MutableAddress) {
+ address = emitUsingAddressor(SGF, loc, self, std::move(indicesRV),
+ callbackBuffer, callbackFn);
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case AccessStrategy::MaterializeToTemporary:
address = emitUsingGetterSetter(SGF, loc, self, std::move(indicesRV),
resultBuffer, callbackBuffer, callbackFn);
break;
@@ -719,7 +728,8 @@
PrettyStackTraceSILFunction X("silgen materializeForSet callback", callback);
{
- SILGenFunction SGF(SGM, *callback);
+ SILGenFunction SGF(SGM, *callback,
+ WitnessStorage->getMaterializeForSetFunc());
auto makeParam = [&](unsigned index) -> SILArgument * {
SILType type = SGF.F.mapTypeIntoContext(
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 612a875..3d884bb 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2901,7 +2901,7 @@
// Build it if necessary.
if (thunk->empty()) {
thunk->setGenericEnvironment(genericEnv);
- SILGenFunction thunkSGF(SGF.SGM, *thunk);
+ SILGenFunction thunkSGF(SGF.SGM, *thunk, SGF.FunctionDC);
auto loc = RegularLocation::getAutoGeneratedLocation();
buildThunkBody(thunkSGF, loc,
inputOrigType,
@@ -3011,7 +3011,7 @@
if (thunk->empty()) {
thunk->setGenericEnvironment(genericEnv);
- SILGenFunction thunkSGF(SGM, *thunk);
+ SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
buildWithoutActuallyEscapingThunkBody(thunkSGF);
}
@@ -3623,7 +3623,7 @@
canonicalTy, F.isSerialized());
if (thunk->empty()) {
thunk->setGenericEnvironment(genericEnv);
- SILGenFunction thunkSGF(SGM, *thunk);
+ SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
auto loc = RegularLocation::getAutoGeneratedLocation();
buildCanonicalFunctionThunkBody(thunkSGF, loc, nonCanonicalTy, canonicalTy);
}
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index 88990d7..57cdc4f 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -58,7 +58,7 @@
// Currently a dynamic thunk looks just like a foreign-to-native thunk around
// an ObjC method. This would change if we introduced a native
// runtime-hookable mechanism.
- SILGenFunction SGF(*this, *F);
+ SILGenFunction SGF(*this, *F, SwiftModule);
SGF.emitForeignToNativeThunk(constant);
}
@@ -201,7 +201,7 @@
preEmitFunction(constant, fd, f, fd);
PrettyStackTraceSILFunction X("silgen emitCurryThunk", f);
- SILGenFunction(*this, *f).emitCurryThunk(constant);
+ SILGenFunction(*this, *f, SwiftModule).emitCurryThunk(constant);
postEmitFunction(constant, f);
}
@@ -214,7 +214,7 @@
f->setSerialized(IsSerializable);
preEmitFunction(thunk, thunk.getDecl(), f, thunk.getDecl());
PrettyStackTraceSILFunction X("silgen emitForeignToNativeThunk", f);
- SILGenFunction(*this, *f).emitForeignToNativeThunk(thunk);
+ SILGenFunction(*this, *f, SwiftModule).emitForeignToNativeThunk(thunk);
postEmitFunction(thunk, f);
}
@@ -231,7 +231,7 @@
PrettyStackTraceSILFunction X("silgen emitNativeToForeignThunk", f);
f->setBare(IsBare);
f->setThunk(IsThunk);
- SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+ SILGenFunction(*this, *f, SwiftModule).emitNativeToForeignThunk(thunk);
postEmitFunction(thunk, f);
}
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index aea67a9..21210c6 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -138,7 +138,7 @@
IsNotTransparent, IsNotSerialized);
thunk->setDebugScope(new (M) SILDebugScope(loc, thunk));
- SILGenFunction(*this, *thunk)
+ SILGenFunction(*this, *thunk, theClass)
.emitVTableThunk(derived, implFn, basePattern,
overrideInfo.LoweredType,
derivedInfo.LoweredType);
@@ -341,7 +341,7 @@
auto witnessStorage = cast<AbstractStorageDecl>(witness.getDecl());
auto witnessAccessor =
- witnessStorage->getAccessorFunction(reqAccessor->getAccessorKind());
+ witnessStorage->getAccessor(reqAccessor->getAccessorKind());
if (!witnessAccessor)
return asDerived().addMissingMethod(requirementRef);
@@ -676,7 +676,7 @@
PrettyStackTraceSILFunction trace("generating protocol witness thunk", f);
// Create the witness.
- SILGenFunction SGF(*this, *f);
+ SILGenFunction SGF(*this, *f, SwiftModule);
// Substitutions mapping the generic parameters of the witness to
// archetypes of the witness thunk generic environment.
@@ -864,7 +864,7 @@
void visitPatternBindingDecl(PatternBindingDecl *pd) {
// Emit initializers.
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i) {
- if (pd->getInit(i)) {
+ if (pd->getNonLazyInit(i)) {
if (pd->isStatic())
SGM.emitGlobalInitialization(pd, i);
else
@@ -955,7 +955,7 @@
void visitPatternBindingDecl(PatternBindingDecl *pd) {
// Emit initializers for static variables.
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i) {
- if (pd->getInit(i)) {
+ if (pd->getNonLazyInit(i)) {
assert(pd->isStatic() && "stored property in extension?!");
SGM.emitGlobalInitialization(pd, i);
}
diff --git a/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp b/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp
index 4948288..32695b3 100644
--- a/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp
@@ -174,7 +174,7 @@
for (auto &rawStorageInfo : otherStorageAccesses) {
const StorageAccessInfo &otherStorageInfo =
transformStorage(rawStorageInfo);
- // transformStorage() returns invalid storage object for local storage
+ // If transformStorage() returns invalid storage object for local storage,
// that should not be merged with the caller.
if (!otherStorageInfo)
continue;
@@ -272,7 +272,9 @@
SILValue argVal = getCallerArg(fullApply, storage.getParamIndex());
if (argVal) {
// Remap the argument source value and inherit the old storage info.
- return StorageAccessInfo(findAccessedStorageNonNested(argVal), storage);
+ auto calleeStorage = findAccessedStorageNonNested(argVal);
+ if (calleeStorage)
+ return StorageAccessInfo(calleeStorage, storage);
}
// If the argument can't be transformed, demote it to an unidentified
// access.
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 5156bdd..e2dfc57 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -678,6 +678,10 @@
auto *GetterRef = B.createFunctionRef(Call->getLoc(), GetterF);
auto *NewAI = B.createApply(Call->getLoc(), GetterRef, Args, false);
+ // FIXME: This is asserting that a specific SIL sequence follows an
+ // addressor! SIL passes should never do this without first specifying a
+ // structural SIL property independent of the SILOptimizer and enforced by
+ // the SILVerifier.
for (auto Use : Call->getUses()) {
auto *PTAI = dyn_cast<PointerToAddressInst>(Use->getUser());
assert(PTAI && "All uses should be pointer_to_address");
diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp
index d9556ed..285e456 100644
--- a/lib/SILOptimizer/LoopTransforms/LICM.cpp
+++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp
@@ -203,6 +203,17 @@
LoopNestSummary(LoopNestSummary &&) = delete;
};
+static unsigned getEdgeIndex(SILBasicBlock *BB, SILBasicBlock *ExitingBB) {
+ auto Succs = ExitingBB->getSuccessors();
+ for (unsigned EdgeIdx = 0; EdgeIdx < Succs.size(); ++EdgeIdx) {
+ SILBasicBlock *CurrBB = Succs[EdgeIdx];
+ if (CurrBB == BB) {
+ return EdgeIdx;
+ }
+ }
+ llvm_unreachable("BB is not a Successor");
+}
+
static bool sinkInstruction(DominanceInfo *DT,
std::unique_ptr<LoopNestSummary> &LoopSummary,
SILInstruction *Inst, SILLoopInfo *LI) {
@@ -216,14 +227,20 @@
bool Changed = false;
for (auto *ExitingBB : ExitingBBs) {
+ SmallVector<SILBasicBlock *, 8> BBSuccessors;
auto Succs = ExitingBB->getSuccessors();
for (unsigned EdgeIdx = 0; EdgeIdx < Succs.size(); ++EdgeIdx) {
SILBasicBlock *BB = Succs[EdgeIdx];
+ BBSuccessors.push_back(BB);
+ }
+ while (!BBSuccessors.empty()) {
+ SILBasicBlock *BB = BBSuccessors.pop_back_val();
if (std::find(NewExitBBs.begin(), NewExitBBs.end(), BB) !=
NewExitBBs.end()) {
// Already got a copy there
continue;
}
+ auto EdgeIdx = getEdgeIndex(BB, ExitingBB);
SILBasicBlock *OutsideBB = nullptr;
if (std::find(ExitBBs.begin(), ExitBBs.end(), BB) != ExitBBs.end()) {
auto *SplitBB =
@@ -472,8 +489,18 @@
return false;
}
+ // We can’t hoist everything that is hoist-able
+ // The canHoist method does not do all the required analysis
+ // Some of the work is done at COW Array Opt
+ // TODO: Refactor COW Array Opt + canHoist - radar 41601468
ArraySemanticsCall semCall(inst);
- return semCall.canHoist(Preheader->getTerminator(), DT);
+ switch (semCall.getKind()) {
+ case ArrayCallKind::kGetCount:
+ case ArrayCallKind::kGetCapacity:
+ return semCall.canHoist(Preheader->getTerminator(), DT);
+ default:
+ return false;
+ }
}
// Check If all the end accesses of the given begin do not prevent hoisting
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index c477e27..a2cb57a 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -30,10 +30,10 @@
using namespace swift;
// This temporary option allows markers during optimization passes. Enabling
-// this flag causes this pass to preserve only dynamic checks when dynamic
-// checking is enabled. Otherwise, this pass removes all checks.
+// this flag causes this pass to preserve all access markers. Otherwise, it only
+// preserved "dynamic" markers.
llvm::cl::opt<bool> EnableOptimizedAccessMarkers(
- "sil-optimized-access-markers", llvm::cl::init(true),
+ "sil-optimized-access-markers", llvm::cl::init(false),
llvm::cl::desc("Enable memory access markers during optimization passes."));
namespace {
@@ -70,8 +70,8 @@
bool AccessMarkerElimination::shouldPreserveAccess(
SILAccessEnforcement enforcement) {
- if (!EnableOptimizedAccessMarkers)
- return false;
+ if (EnableOptimizedAccessMarkers || Mod->getOptions().VerifyExclusivity)
+ return true;
switch (enforcement) {
case SILAccessEnforcement::Static:
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index 93a9c79..53517d5 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -734,6 +734,8 @@
SILValue Argument = Apply.getArgument(ArgumentIndex);
assert(Argument->getType().isAddress());
+ // A valid AccessedStorage should alway sbe found because Unsafe accesses
+ // are not tracked by AccessSummaryAnalysis.
const AccessedStorage &Storage = findValidAccessedStorage(Argument);
auto AccessIt = State.Accesses->find(Storage);
@@ -817,6 +819,9 @@
SILAccessKind Kind = BAI->getAccessKind();
const AccessedStorage &Storage =
findValidAccessedStorage(BAI->getSource());
+ // Storage may be associated with a nested access where the outer access is
+ // "unsafe". That's ok because the outer access can itself be treated like a
+ // valid source, as long as we don't ask for its source.
AccessInfo &Info = (*State.Accesses)[Storage];
const IndexTrieNode *SubPath = State.ASA->findSubPathAccessed(BAI);
if (auto Conflict = shouldReportAccess(Info, Kind, SubPath)) {
@@ -1071,7 +1076,16 @@
// initialization, not a formal memory access. The strength of
// verification rests on the completeness of the opcode list inside
// findAccessedStorage.
- if (!storage || !isPossibleFormalAccessBase(storage, memInst->getFunction()))
+ //
+ // For the purpose of verification, an unidentified access is
+ // unenforced. These occur in cases like global addressors and local buffers
+ // that make use of RawPointers.
+ if (!storage || storage.getKind() == AccessedStorage::Unidentified)
+ return;
+
+ // Some identifiable addresses can also be recognized as local initialization
+ // or other patterns that don't qualify as formal access.
+ if (!isPossibleFormalAccessBase(storage, memInst->getFunction()))
return;
// A box or stack variable may represent lvalues, but they can only conflict
diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp
index e837dc4..22529ce 100644
--- a/lib/SILOptimizer/PassManager/PassPipeline.cpp
+++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp
@@ -479,6 +479,7 @@
static void addLastChanceOptPassPipeline(SILPassPipelinePlan &P) {
// Optimize access markers for improved IRGen after all other optimizations.
P.addAccessEnforcementOpts();
+ P.addAccessEnforcementWMO();
// Only has an effect if the -assume-single-thread option is specified.
P.addAssumeSingleThreaded();
diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp
index 9b47513..dcef0b3 100644
--- a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp
+++ b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp
@@ -285,7 +285,7 @@
}
bool hasConflictFreeAccess() const {
NoNestedConflictIterator iterator(*this);
- return iterator.next() == nullptr;
+ return iterator.next() != nullptr;
}
bool hasInScopeAccess() const {
@@ -624,6 +624,9 @@
if (F->empty())
return;
+ DEBUG(llvm::dbgs() << "Running local AccessEnforcementOpts on "
+ << F->getName() << "\n");
+
PostOrderFunctionInfo *PO = getAnalysis<PostOrderAnalysis>()->get(F);
AccessedStorageAnalysis *ASA = getAnalysis<AccessedStorageAnalysis>();
auto result = AccessConflictAnalysis(F, PO, ASA).analyze();
diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
new file mode 100644
index 0000000..3440a83
--- /dev/null
+++ b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
@@ -0,0 +1,277 @@
+//===--- AccessEnforcementWMO.cpp - Whole-module access enforcement opt ---===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+///
+/// This module pass removes dynamic access enforcement based on whole module
+/// information.
+///
+/// This maps each access of identified storage onto a disjoint access
+/// location. Local accesses (Box and Stack) already have unique AccessedStorage
+/// and should be removed by an earlier function pass. This pass handles Class
+/// and Global access by partitioning their non-unique AccessedStorage objects
+/// into unique DisjointAccessLocations. These disjoint access locations may be
+/// accessed across multiple functions, so a module pass is required to identify
+/// and optimize them.
+///
+/// Class accesses are partitioned by their fully qualified property
+/// name. Global accesses are partitioned by the global variable name. Argument
+/// accesses are ignored because they are considered an access in the caller,
+/// while Class and Global access always occurs in the callee. Note that a SIL
+/// function argument value may be the source of a either a Class-kind
+/// AccessedStorage or an Argument-kind AccessedStorage. When the argument is
+/// used to access a class, it will always be identified as a Class-kind
+/// AccessedStorage even though its source is an argument.
+///
+/// For each function, discover the disjointly accessed locations. Each location
+/// is optimistically mapped to a `noNestedConflict` flag (if a location has not
+/// been mapped, then it is assumed not to have nested conflict). Each location
+/// without any nested conflict maps to a set of accesses that the optimization
+/// may be able to remove.
+///
+/// After analyzing all functions in the module, disable any class property and
+/// global variable access that still have not seen any nested conflicts by
+/// giving them static enforcement.
+///
+/// Warning: This is only sound when unidentified accesses can never alias with
+/// Class/Global access. To enforce this, the SILVerifier calls
+/// findAccessedStorage() for every access, which asserts that any Unidentified
+/// access belongs to a know pattern that cannot originate from Class or Global
+/// accesses.
+///
+/// Note: This optimization must be aware of all possible access to a Class or
+/// Global address. This includes unpaired access instructions and keypath
+/// instructions. Ignoring any access pattern would weaken enforcement.
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "access-enforcement-wmo"
+
+#include "swift/SIL/DebugUtils.h"
+#include "swift/SIL/MemAccessUtils.h"
+#include "swift/SIL/SILFunction.h"
+#include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+
+using namespace swift;
+
+using llvm::DenseMap;
+using llvm::SmallDenseSet;
+
+// Get the VarDecl that represents the DisjointAccessLocation for the given
+// AccessedStorage. Returns nullptr for any storage that can't be partitioned
+// into a disjoint location.
+//
+// findAccessedStorage may only return Unidentified storage for a global
+// variable access if the global is defined in a different module.
+VarDecl *getDisjointAccessLocation(const AccessedStorage &storage) {
+ switch (storage.getKind()) {
+ case AccessedStorage::Global:
+ // A global variable may return a null decl. These variables are
+ // implementation details that aren't formally accessed.
+ return storage.getGlobal()->getDecl();
+ case AccessedStorage::Class: {
+ const ObjectProjection &objProj = storage.getObjectProjection();
+ return objProj.getProjection().getVarDecl(objProj.getObject()->getType());
+ }
+ case AccessedStorage::Box:
+ case AccessedStorage::Stack:
+ case AccessedStorage::Argument:
+ case AccessedStorage::Unidentified:
+ return nullptr;
+ case AccessedStorage::Nested:
+ llvm_unreachable("Unexpected Nested access.");
+ }
+}
+
+namespace {
+// Implements an optimization to remove access markers on disjoint memory
+// locations that are never reentrantly accessed. For a given memory location,
+// if there are no potential nested conflicts, then enforcement must succeed for
+// any access to that location.
+//
+// The existence of unidentified access complicates this problem. For this
+// optimization to be valid, Global and Class property access must always be
+// identifiable. findAccessedStorage() in MemAccessUtils enforces a short list
+// of unidentified producers (non-address PHIArgument, PointerToAddress, Undef,
+// & local-init). We cannot allow the address of a global variable or class
+// property to be exposed via one of these instructions, unless the declaration
+// is considered "visible externally".
+//
+// Note: This assumes that PointerToAddress is never used to access a global or
+// class property unless it's done via an Unsafe API that doesn't need
+// enforcement.
+//
+// FIXME: Tail-allocated heap storage is currently categorized as
+// Unidentified. This is conservatively safe because it can't also be accessed
+// as a class property. However, it is inconsistent with the general rule that
+// only local storage is unidentified, and we can probably remove a lot of
+// accesses by being more precise here (OTOH, if this is known CoW storage, we
+// should eventually add an even stronger optimization to remove exclusivity
+// checks).
+class GlobalAccessRemoval {
+ SILModule &module;
+
+ using BeginAccessSet = SmallDenseSet<BeginAccessInst *, 8>;
+
+ /// Information for an access location that, if it is valid, must be disjoint
+ /// from all other access locations.
+ struct DisjointAccessLocationInfo {
+ AccessedStorage::Kind accessKind = AccessedStorage::Unidentified;
+ // False if any nested conflict has been seen at this location.
+ bool noNestedConflict = true;
+ BeginAccessSet beginAccessSet;
+ };
+
+ DenseMap<VarDecl *, DisjointAccessLocationInfo> disjointAccessMap;
+
+public:
+ GlobalAccessRemoval(SILModule &module) : module(module) {}
+
+ void perform();
+
+protected:
+ void visitInstruction(SILInstruction *I);
+ void recordAccess(SILInstruction *beginAccess, VarDecl *decl,
+ AccessedStorage::Kind storageKind,
+ bool hasNoNestedConflict);
+ void removeNonreentrantAccess();
+};
+} // namespace
+
+/// Process all begin_access instructions in the module, recording their
+/// DisjointAccessLocation. Ignore accesses at call sites because Arguments and
+/// Unidentified access can only local storage.
+void GlobalAccessRemoval::perform() {
+ for (auto &F : module) {
+ if (F.empty())
+ continue;
+
+ for (auto &BB : F) {
+ for (auto &I : BB)
+ visitInstruction(&I);
+ }
+ }
+ removeNonreentrantAccess();
+}
+
+void GlobalAccessRemoval::visitInstruction(SILInstruction *I) {
+ if (auto *BAI = dyn_cast<BeginAccessInst>(I)) {
+ AccessedStorage storage = findAccessedStorageNonNested(BAI->getSource());
+ VarDecl *decl = getDisjointAccessLocation(storage);
+ recordAccess(BAI, decl, storage.getKind(), BAI->hasNoNestedConflict());
+ return;
+ }
+ if (auto *BUAI = dyn_cast<BeginUnpairedAccessInst>(I)) {
+ AccessedStorage storage = findAccessedStorageNonNested(BUAI->getSource());
+ VarDecl *decl = getDisjointAccessLocation(storage);
+ recordAccess(BUAI, decl, storage.getKind(), BUAI->hasNoNestedConflict());
+ return;
+ }
+ if (auto *KPI = dyn_cast<KeyPathInst>(I)) {
+ for (const KeyPathPatternComponent &component :
+ KPI->getPattern()->getComponents()) {
+ switch (component.getKind()) {
+ case KeyPathPatternComponent::Kind::StoredProperty:
+ recordAccess(KPI, component.getStoredPropertyDecl(),
+ AccessedStorage::Class, /*hasNoNestedConflict=*/false);
+ break;
+ case KeyPathPatternComponent::Kind::GettableProperty:
+ case KeyPathPatternComponent::Kind::SettableProperty:
+ case KeyPathPatternComponent::Kind::External:
+ case KeyPathPatternComponent::Kind::OptionalChain:
+ case KeyPathPatternComponent::Kind::OptionalForce:
+ case KeyPathPatternComponent::Kind::OptionalWrap:
+ break;
+ }
+ }
+ return;
+ }
+}
+
+// Record an access in the disjointAccessMap.
+//
+// `beginAccess` is any instruction that represents a potential access,
+// including key_path. One of the following conditions must be true for every
+// begin_[unpaired_]access instructions:
+// - it is guaranteed to access local memory, not a class property or global.
+// - it has an identifiable source.
+// - is is generated from a Builtin, which is assumed to have an associated
+// key_path instruction somewhere else in the same module (or it must be dead
+// code, or only access public properties).
+//
+// `decl` may be nullptr if the declaration can't be determined from the
+// access. This is only legal when the access is known to be a local access, not
+// a class property or global.
+void GlobalAccessRemoval::recordAccess(SILInstruction *beginAccess,
+ VarDecl *decl,
+ AccessedStorage::Kind storageKind,
+ bool hasNoNestedConflict) {
+ if (!decl || module.isVisibleExternally(decl))
+ return;
+
+ DEBUG(if (!hasNoNestedConflict) llvm::dbgs()
+ << "Nested conflict on " << decl->getName() << " at" << *beginAccess
+ << "\n");
+
+ auto accessLocIter = disjointAccessMap.find(decl);
+ if (accessLocIter != disjointAccessMap.end()) {
+ // Add this begin_access to an existing DisjointAccessLocationInfo.
+ DisjointAccessLocationInfo &info = accessLocIter->second;
+ assert(info.accessKind == storageKind);
+ info.noNestedConflict &= hasNoNestedConflict;
+ // Don't currently optimize unpaired access.
+ if (auto *BAI = dyn_cast<BeginAccessInst>(beginAccess))
+ info.beginAccessSet.insert(BAI);
+ return;
+ }
+
+ // Create the first DisjointAccessLocationInfo for this begin_access.
+ DisjointAccessLocationInfo info;
+ info.accessKind = storageKind;
+ info.noNestedConflict = hasNoNestedConflict;
+ if (auto *BA = dyn_cast<BeginAccessInst>(beginAccess))
+ info.beginAccessSet.insert(BA);
+ disjointAccessMap.insert(std::make_pair(decl, info));
+}
+
+// For each unique storage within this function that is never reentrantly
+// accessed, promote all access checks for that storage to static enforcement.
+void GlobalAccessRemoval::removeNonreentrantAccess() {
+ for (auto &declAndInfo : disjointAccessMap) {
+ const DisjointAccessLocationInfo &info = declAndInfo.second;
+ if (!info.noNestedConflict)
+ continue;
+
+ VarDecl *decl = declAndInfo.first;
+ DEBUG(llvm::dbgs() << "Eliminating all formal access on " << decl->getName()
+ << "\n");
+ assert(!module.isVisibleExternally(decl));
+ (void)decl;
+
+ // Non-deterministic iteration, only used to set a flag.
+ for (BeginAccessInst *beginAccess : info.beginAccessSet) {
+ DEBUG(llvm::dbgs() << " Disabling access marker " << *beginAccess);
+ beginAccess->setEnforcement(SILAccessEnforcement::Static);
+ }
+ }
+}
+
+namespace {
+struct AccessEnforcementWMO : public SILModuleTransform {
+ void run() override {
+ GlobalAccessRemoval eliminationPass(*getModule());
+ eliminationPass.perform();
+ }
+};
+}
+
+SILTransform *swift::createAccessEnforcementWMO() {
+ return new AccessEnforcementWMO();
+}
diff --git a/lib/SILOptimizer/Transforms/CMakeLists.txt b/lib/SILOptimizer/Transforms/CMakeLists.txt
index e4d6c74..1e14f2c 100644
--- a/lib/SILOptimizer/Transforms/CMakeLists.txt
+++ b/lib/SILOptimizer/Transforms/CMakeLists.txt
@@ -1,6 +1,7 @@
silopt_register_sources(
ARCCodeMotion.cpp
AccessEnforcementOpts.cpp
+ AccessEnforcementWMO.cpp
AllocBoxToStack.cpp
ArrayCountPropagation.cpp
ArrayElementValuePropagation.cpp
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 3dbce08..17fe8f3 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -1409,6 +1409,10 @@
/// The sequence is traversed inside out, i.e.
/// starting with the innermost struct_element_addr
/// Move into utils.
+///
+/// FIXME: this utility does not make sense as an API. How can the caller
+/// guarantee that the only uses of `I` are struct_element_addr and
+/// tuple_element_addr?
void swift::replaceLoadSequence(SILInstruction *I,
SILValue Value,
SILBuilder &B) {
@@ -1434,6 +1438,18 @@
return;
}
+ if (auto *BA = dyn_cast<BeginAccessInst>(I)) {
+ for (auto Use : BA->getUses()) {
+ replaceLoadSequence(Use->getUser(), Value, B);
+ }
+ return;
+ }
+
+ // Incidental uses of an addres are meaningless with regard to the loaded
+ // value.
+ if (isIncidentalUse(I) || isa<BeginUnpairedAccessInst>(I))
+ return;
+
llvm_unreachable("Unknown instruction sequence for reading from a global");
}
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 8ee176a..2e9e1d5 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -48,7 +48,7 @@
TypeCheckProtocol.cpp
TypeCheckProtocolInference.cpp
TypeCheckREPL.cpp
- TypeCheckRequests.cpp
+ TypeCheckRequestFunctions.cpp
TypeCheckStmt.cpp
TypeCheckSwitchStmt.cpp
TypeCheckType.cpp
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 2b4fc2f..5712e1f 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -4000,6 +4000,12 @@
// Should already be type-checked.
return simplifyExprType(expr);
}
+
+ Expr *visitLazyInitializerExpr(LazyInitializerExpr *expr) {
+ simplifyExprType(expr);
+ assert(expr->getType()->isEqual(expr->getSubExpr()->getType()));
+ return expr;
+ }
Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
simplifyExprType(E);
@@ -7031,8 +7037,12 @@
// If we're calling an accessor, keep the base as an inout type, because the
// getter may be mutating.
- if (SD->hasAccessorFunctions() && baseTy->is<InOutType>() &&
- semantics != AccessSemantics::DirectToStorage)
+ auto strategy = SD->getAccessStrategy(semantics,
+ isSettableFromHere
+ ? AccessKind::ReadWrite
+ : AccessKind::Read,
+ UseDC);
+ if (baseTy->is<InOutType>() && strategy.getKind() != AccessStrategy::Storage)
return InOutType::get(baseObjectTy);
// Accesses to non-function members in value types are done through an @lvalue
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index d64ae88..172568d 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2810,6 +2810,10 @@
return CS.getASTContext().getBoolDecl()->getDeclaredType();
}
+ Type visitLazyInitializerExpr(LazyInitializerExpr *expr) {
+ return expr->getType();
+ }
+
Type visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
if (E->getTypeLoc().isNull()) {
auto locator = CS.getConstraintLocator(E);
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 7f017f6..30c30e6 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -34,6 +34,24 @@
const bool IsImplicit = true;
+/// Should a particular accessor for the given storage be synthesized
+/// on-demand, or is it always defined eagerly in the file that declared
+/// the storage?
+static bool isOnDemandAccessor(AbstractStorageDecl *storage,
+ AccessorKind kind) {
+ assert(kind == AccessorKind::Get || kind == AccessorKind::Set);
+
+ // Currently this only applies to imported declarations because we
+ // eagerly create accessors for all other member storage (except
+ // sometimes materializeForSet, but materializeForSet never needs a
+ // definition in the AST).
+ //
+ // Note that we can't just use hasClangNode() because the importer
+ // sometimes synthesizes things that lack clang nodes.
+ auto *mod = storage->getDeclContext()->getModuleScopeContext();
+ return (cast<FileUnit>(mod)->getKind() == FileUnitKind::ClangModule);
+}
+
/// Insert the specified decl into the DeclContext's member list. If the hint
/// decl is specified, the new decl is inserted next to the hint.
static void addMemberToContextIfNeeded(Decl *D, DeclContext *DC,
@@ -120,25 +138,37 @@
return ParameterList::create(context, elements);
}
-static AccessorDecl *createGetterPrototype(AbstractStorageDecl *storage,
- TypeChecker &TC) {
+static AccessorDecl *createGetterPrototype(TypeChecker &TC,
+ AbstractStorageDecl *storage) {
+ assert(!storage->getGetter());
+
SourceLoc loc = storage->getLoc();
// Create the parameter list for the getter.
SmallVector<ParameterList*, 2> getterParams;
+ GenericEnvironment *genericEnvironmentOfLazyAccessor = nullptr;
+
// The implicit 'self' argument if in a type context.
if (storage->getDeclContext()->isTypeContext()) {
ParamDecl *selfDecl;
// For lazy properties, steal the 'self' from the initializer context.
if (storage->getAttrs().hasAttribute<LazyAttr>()) {
+ // The getter is considered mutating if it's on a value type.
+ if (!storage->getDeclContext()->getAsClassOrClassExtensionContext() &&
+ !storage->isStatic()) {
+ storage->setIsGetterMutating(true);
+ }
+
auto *varDecl = cast<VarDecl>(storage);
auto *bindingDecl = varDecl->getParentPatternBinding();
auto *bindingInit = cast<PatternBindingInitializer>(
bindingDecl->getPatternEntryForVarDecl(varDecl).getInitContext());
selfDecl = bindingInit->getImplicitSelfDecl();
+ genericEnvironmentOfLazyAccessor =
+ bindingInit->getGenericEnvironmentOfContext();
} else {
selfDecl = ParamDecl::createSelf(loc,
storage->getDeclContext(),
@@ -169,6 +199,18 @@
storage->getDeclContext());
getter->setImplicit();
+ // We need to install the generic environment here because:
+ // 1) validating the getter will change the implicit self decl's DC to it,
+ // 2) it's likely that the initializer will be type-checked before the
+ // accessor (and therefore before the normal installation happens), and
+ // 3) type-checking a reference to the self decl will map its type into
+ // its context, which requires an environment to be installed on that
+ // context.
+ // We can safely use the enclosing environment because properties are never
+ // differently generic.
+ if (genericEnvironmentOfLazyAccessor)
+ getter->setGenericEnvironment(genericEnvironmentOfLazyAccessor);
+
if (storage->isGetterMutating())
getter->setSelfAccessKind(SelfAccessKind::Mutating);
@@ -179,12 +221,18 @@
if (auto *overriddenAccessor = overridden->getGetter())
getter->setOverriddenDecl(overriddenAccessor);
+ // Always add the getter to the context immediately after the storage.
+ addMemberToContextIfNeeded(getter, storage->getDeclContext(), storage);
+
return getter;
}
-static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
- ParamDecl *&valueDecl,
- TypeChecker &TC) {
+static AccessorDecl *createSetterPrototype(TypeChecker &TC,
+ AbstractStorageDecl *storage,
+ AccessorDecl *getter = nullptr) {
+ assert(!storage->getSetter());
+ assert(storage->supportsMutation());
+
SourceLoc loc = storage->getLoc();
// Create the parameter list for the setter.
@@ -204,9 +252,9 @@
// Add a "(value : T, indices...)" argument list.
auto storageType = getTypeOfStorage(storage, false);
auto storageInterfaceType = getTypeOfStorage(storage, true);
- valueDecl = buildArgument(storage->getLoc(), storage->getDeclContext(),
- "value", storageType, storageInterfaceType,
- VarDecl::Specifier::Default);
+ auto valueDecl = buildArgument(storage->getLoc(), storage->getDeclContext(),
+ "value", storageType, storageInterfaceType,
+ VarDecl::Specifier::Default);
params.push_back(buildIndexForwardingParamList(storage, valueDecl));
Type setterRetTy = TupleType::getEmpty(TC.Context);
@@ -233,6 +281,11 @@
}
}
+ // Always add the setter to the context immediately after the getter.
+ if (!getter) getter = storage->getGetter();
+ assert(getter && "always synthesize setter prototype after getter");
+ addMemberToContextIfNeeded(setter, storage->getDeclContext(), getter);
+
return setter;
}
@@ -254,10 +307,8 @@
/// If the storage is for a global stored property or a stored property of a
/// resilient type, we are synthesizing accessors to present a resilient
/// interface to the storage and they should not be transparent.
-static void maybeMarkTransparent(FuncDecl *accessor,
- AbstractStorageDecl *storage,
- TypeChecker &TC) {
- auto *DC = storage->getDeclContext();
+static void maybeMarkTransparent(TypeChecker &TC, AccessorDecl *accessor) {
+ auto *DC = accessor->getDeclContext();
auto *nominalDecl = DC->getAsNominalTypeOrNominalTypeExtensionContext();
// Global variable accessors are not @_transparent.
@@ -265,7 +316,13 @@
return;
// Accessors for resilient properties are not @_transparent.
- if (storage->isResilient())
+ if (accessor->getStorage()->isResilient())
+ return;
+
+ // Setters for lazy properties are not @_transparent (because the storage
+ // is not ABI-exposed).
+ if (accessor->getStorage()->getAttrs().hasAttribute<LazyAttr>() &&
+ accessor->getAccessorKind() == AccessorKind::Set)
return;
// Accessors for protocol storage requirements are never @_transparent
@@ -284,6 +341,19 @@
accessor->getAttrs().add(new (TC.Context) TransparentAttr(IsImplicit));
}
+template <class... Args>
+static void triggerSynthesis(TypeChecker &TC, FuncDecl *fn, Args... args) {
+ if (fn->hasBody()) return;
+
+ auto synthesisRecord = SynthesizedFunction(fn, args...);
+ TC.FunctionsToSynthesize.insert({ fn, synthesisRecord });
+}
+
+static void finishSynthesis(TypeChecker &TC, FuncDecl *fn) {
+ TC.Context.addSynthesizedDecl(fn);
+ TC.DeclsToFinalize.insert(fn);
+}
+
static AccessorDecl *
createMaterializeForSetPrototype(AbstractStorageDecl *storage,
FuncDecl *getter,
@@ -383,30 +453,17 @@
asAvailableAs.push_back(setter);
}
- maybeMarkTransparent(materializeForSet, storage, TC);
+ maybeMarkTransparent(TC, materializeForSet);
AvailabilityInference::applyInferredAvailableAttrs(materializeForSet,
asAvailableAs, ctx);
- TC.Context.addSynthesizedDecl(materializeForSet);
- TC.DeclsToFinalize.insert(materializeForSet);
-
+ addMemberToContextIfNeeded(materializeForSet, DC, setter);
+
+ finishSynthesis(TC, materializeForSet);
return materializeForSet;
}
-static void convertStoredVarInProtocolToComputed(VarDecl *VD, TypeChecker &TC) {
- auto *Get = createGetterPrototype(VD, TC);
-
- // Okay, we have the getter; make the VD computed.
- VD->setAccessors(AbstractStorageDecl::Computed,
- SourceLoc(), {Get}, SourceLoc());
-
- // We've added some members to our containing class, add them to the members
- // list.
- addMemberToContextIfNeeded(Get, VD->getDeclContext(), VD);
-}
-
-
/// Build an expression that evaluates the specified parameter list as a tuple
/// or paren expr, suitable for use in an applyexpr.
///
@@ -526,34 +583,64 @@
return buildSubscriptIndexReference(ctx, Accessor);
}
};
+
+ enum class TargetImpl {
+ /// We're referencing the physical storage created for the storage.
+ Storage,
+ /// We're referencing this specific implementation of the storage, not
+ /// an override of it.
+ Implementation,
+ /// We're referencing the superclass's implementation of the storage.
+ Super
+ };
} // end anonymous namespace
/// Build an l-value for the storage of a declaration.
static Expr *buildStorageReference(
const StorageReferenceContext &referenceContext,
AbstractStorageDecl *storage,
- AccessSemantics semantics,
- SelfAccessorKind selfAccessorKind,
+ TargetImpl target,
TypeChecker &TC) {
ASTContext &ctx = TC.Context;
+ AccessSemantics semantics;
+ SelfAccessorKind selfAccessKind;
+ switch (target) {
+ case TargetImpl::Storage:
+ semantics = AccessSemantics::DirectToStorage;
+ selfAccessKind = SelfAccessorKind::Peer;
+ break;
+
+ case TargetImpl::Implementation:
+ semantics = AccessSemantics::DirectToImplementation;
+ selfAccessKind = SelfAccessorKind::Peer;
+ break;
+
+ case TargetImpl::Super:
+ // If this really is an override, use a super-access.
+ if (auto override = storage->getOverriddenDecl()) {
+ semantics = AccessSemantics::Ordinary;
+ selfAccessKind = SelfAccessorKind::Super;
+ storage = override;
+
+ // Otherwise do a self-reference, which is dynamically bogus but
+ // should be statically valid. This should only happen in invalid cases.
+ } else {
+ assert(storage->isInvalid());
+ semantics = AccessSemantics::Ordinary;
+ selfAccessKind = SelfAccessorKind::Peer;
+ }
+ break;
+ }
+
VarDecl *selfDecl = referenceContext.getSelfDecl();
if (!selfDecl) {
+ assert(target != TargetImpl::Super);
return new (ctx) DeclRefExpr(storage, DeclNameLoc(), IsImplicit, semantics);
}
- // If we should use a super access if applicable, and we have an
- // overridden decl, then use ordinary access to it.
- if (selfAccessorKind == SelfAccessorKind::Super) {
- if (auto overridden = storage->getOverriddenDecl()) {
- storage = overridden;
- semantics = AccessSemantics::Ordinary;
- } else {
- selfAccessorKind = SelfAccessorKind::Peer;
- }
- }
-
- Expr *selfDRE = buildSelfReference(selfDecl, selfAccessorKind, TC);
+ Expr *selfDRE =
+ buildSelfReference(selfDecl, selfAccessKind, TC);
if (auto subscript = dyn_cast<SubscriptDecl>(storage)) {
Expr *indices = referenceContext.getIndexRefExpr(ctx, subscript);
@@ -570,21 +657,19 @@
static Expr *buildStorageReference(AccessorDecl *accessor,
AbstractStorageDecl *storage,
- AccessSemantics semantics,
- SelfAccessorKind selfAccessorKind,
+ TargetImpl target,
TypeChecker &TC) {
return buildStorageReference(AccessorStorageReferenceContext(accessor),
- storage, semantics, selfAccessorKind, TC);
+ storage, target, TC);
}
/// Load the value of VD. If VD is an @override of another value, we call the
/// superclass getter. Otherwise, we do a direct load of the value.
static Expr *createPropertyLoadOrCallSuperclassGetter(AccessorDecl *accessor,
AbstractStorageDecl *storage,
+ TargetImpl target,
TypeChecker &TC) {
- return buildStorageReference(accessor, storage,
- AccessSemantics::DirectToStorage,
- SelfAccessorKind::Super, TC);
+ return buildStorageReference(accessor, storage, target, TC);
}
/// Look up the NSCopying protocol from the Foundation module, if present.
@@ -609,7 +694,31 @@
return dyn_cast<ProtocolDecl>(results.front());
}
+static bool checkConformanceToNSCopying(TypeChecker &TC, VarDecl *var,
+ Type type) {
+ auto dc = var->getDeclContext();
+ auto proto = getNSCopyingProtocol(TC, dc);
+ if (!proto || !TC.conformsToProtocol(type, proto, dc, None)) {
+ TC.diagnose(var->getLoc(), diag::nscopying_doesnt_conform);
+ return true;
+ }
+ return false;
+}
+static std::pair<Type, bool> getUnderlyingTypeOfVariable(VarDecl *var) {
+ Type type = var->getType()->getReferenceStorageReferent();
+
+ if (Type objectType = type->getOptionalObjectType()) {
+ return {objectType, true};
+ } else {
+ return {type, false};
+ }
+}
+
+bool TypeChecker::checkConformanceToNSCopying(VarDecl *var) {
+ Type type = getUnderlyingTypeOfVariable(var).first;
+ return ::checkConformanceToNSCopying(*this, var, type);
+}
/// Synthesize the code to store 'Val' to 'VD', given that VD has an @NSCopying
/// attribute on it. We know that VD is a stored property in a class, so we
@@ -621,20 +730,13 @@
// We support @NSCopying on class types (which conform to NSCopying),
// protocols which conform, and option types thereof.
- Type UnderlyingType = VD->getType()->getReferenceStorageReferent();
-
- bool isOptional = false;
- if (Type optionalEltTy = UnderlyingType->getOptionalObjectType()) {
- UnderlyingType = optionalEltTy;
- isOptional = true;
- }
+ auto underlyingTypeAndIsOptional = getUnderlyingTypeOfVariable(VD);
+ auto underlyingType = underlyingTypeAndIsOptional.first;
+ auto isOptional = underlyingTypeAndIsOptional.second;
// The element type must conform to NSCopying. If not, emit an error and just
// recovery by synthesizing without the copy call.
- auto *CopyingProto = getNSCopyingProtocol(TC, VD->getDeclContext());
- if (!CopyingProto || !TC.conformsToProtocol(UnderlyingType, CopyingProto,
- VD->getDeclContext(), None)) {
- TC.diagnose(VD->getLoc(), diag::nscopying_doesnt_conform);
+ if (checkConformanceToNSCopying(TC, VD, underlyingType)) {
return Val;
}
@@ -664,7 +766,7 @@
// If we're working with non-optional types, we're forcing the cast.
if (!isOptional) {
Call = new (Ctx) ForcedCheckedCastExpr(Call, SourceLoc(), SourceLoc(),
- TypeLoc::withoutLoc(UnderlyingType));
+ TypeLoc::withoutLoc(underlyingType));
Call->setImplicit();
return Call;
}
@@ -672,7 +774,7 @@
// We're working with optional types, so perform a conditional checked
// downcast.
Call = new (Ctx) ConditionalCheckedCastExpr(Call, SourceLoc(), SourceLoc(),
- TypeLoc::withoutLoc(UnderlyingType));
+ TypeLoc::withoutLoc(underlyingType));
Call->setImplicit();
// Use OptionalEvaluationExpr to evaluate the "?".
@@ -686,6 +788,7 @@
static void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
Expr *value,
AbstractStorageDecl *storage,
+ TargetImpl target,
SmallVectorImpl<ASTNode> &body,
TypeChecker &TC) {
// If the storage is an @NSCopying property, then we store the
@@ -699,134 +802,139 @@
// (assign (decl_ref_expr(VD)), decl_ref_expr(value))
// or:
// (assign (member_ref_expr(decl_ref_expr(self), VD)), decl_ref_expr(value))
- Expr *dest = buildStorageReference(accessor, storage,
- AccessSemantics::DirectToStorage,
- SelfAccessorKind::Super, TC);
+ Expr *dest = buildStorageReference(accessor, storage, target, TC);
body.push_back(new (TC.Context) AssignExpr(dest, SourceLoc(), value,
IsImplicit));
}
+static bool isSynthesizedComputedProperty(AbstractStorageDecl *storage) {
+ return (storage->getAttrs().hasAttribute<LazyAttr>() ||
+ storage->getAttrs().hasAttribute<NSManagedAttr>());
+}
+
/// Synthesize the body of a trivial getter. For a non-member vardecl or one
/// which is not an override of a base class property, it performs a direct
/// storage load. For an override of a base member property, it chains up to
/// super.
-static void synthesizeTrivialGetter(AccessorDecl *getter,
- AbstractStorageDecl *storage,
- TypeChecker &TC) {
+static void synthesizeTrivialGetterBody(TypeChecker &TC, AccessorDecl *getter,
+ TargetImpl target) {
+ auto storage = getter->getStorage();
+ assert(!storage->getAttrs().hasAttribute<LazyAttr>() &&
+ !storage->getAttrs().hasAttribute<NSManagedAttr>());
+
auto &ctx = TC.Context;
-
- Expr *result = createPropertyLoadOrCallSuperclassGetter(getter, storage, TC);
+ SourceLoc loc = storage->getLoc();
+
+ Expr *result =
+ createPropertyLoadOrCallSuperclassGetter(getter, storage, target, TC);
ASTNode returnStmt = new (ctx) ReturnStmt(SourceLoc(), result, IsImplicit);
- SourceLoc loc = storage->getLoc();
getter->setBody(BraceStmt::create(ctx, loc, returnStmt, loc, true));
- TC.Context.addSynthesizedDecl(getter);
- TC.DeclsToFinalize.insert(getter);
+ finishSynthesis(TC, getter);
+
+ maybeMarkTransparent(TC, getter);
}
-/// Synthesize the body of a trivial setter.
-static void synthesizeTrivialSetter(AccessorDecl *setter,
- AbstractStorageDecl *storage,
- VarDecl *valueVar,
- TypeChecker &TC) {
- auto &ctx = TC.Context;
- SourceLoc loc = storage->getLoc();
+/// Synthesize the body of a getter which just directly accesses the
+/// underlying storage.
+static void synthesizeTrivialGetterBody(TypeChecker &TC, AccessorDecl *getter) {
+ assert(getter->getStorage()->hasStorage());
+ synthesizeTrivialGetterBody(TC, getter, TargetImpl::Storage);
+}
- auto *valueDRE = new (ctx) DeclRefExpr(valueVar, DeclNameLoc(), IsImplicit);
+/// Synthesize the body of a getter which just delegates to its superclass
+/// implementation.
+static void synthesizeInheritedGetterBody(TypeChecker &TC,
+ AccessorDecl *getter) {
+ // This should call the superclass getter.
+ synthesizeTrivialGetterBody(TC, getter, TargetImpl::Super);
+}
+
+/// Synthesize the body of a getter which just delegates to an addressor.
+static void synthesizeAddressedGetterBody(TypeChecker &TC,
+ AccessorDecl *getter) {
+ assert(getter->getStorage()->getAddressor());
+
+ // This should call the addressor.
+ synthesizeTrivialGetterBody(TC, getter, TargetImpl::Implementation);
+}
+
+/// Synthesize the body of a setter which just stores to the given storage
+/// declaration (which doesn't have to be the storage for the setter).
+static void synthesizeTrivialSetterBodyWithStorage(TypeChecker &TC,
+ AccessorDecl *setter,
+ TargetImpl target,
+ AbstractStorageDecl *storageToUse) {
+ auto &ctx = TC.Context;
+ SourceLoc loc = setter->getStorage()->getLoc();
+
+ VarDecl *valueParamDecl = getFirstParamDecl(setter);
+
+ auto *valueDRE =
+ new (ctx) DeclRefExpr(valueParamDecl, DeclNameLoc(), IsImplicit);
SmallVector<ASTNode, 1> setterBody;
- createPropertyStoreOrCallSuperclassSetter(setter, valueDRE, storage,
- setterBody, TC);
+ createPropertyStoreOrCallSuperclassSetter(setter, valueDRE, storageToUse,
+ target, setterBody, TC);
setter->setBody(BraceStmt::create(ctx, loc, setterBody, loc, true));
- TC.Context.addSynthesizedDecl(setter);
- TC.DeclsToFinalize.insert(setter);
+ finishSynthesis(TC, setter);
+
+ maybeMarkTransparent(TC, setter);
}
-/// Does a storage decl currently lacking accessor functions require a
-/// setter to be synthesized?
-static bool doesStorageNeedSetter(AbstractStorageDecl *storage) {
- assert(!storage->hasAccessorFunctions());
- switch (storage->getStorageKind()) {
- // Add a setter to a stored variable unless it's a let.
- case AbstractStorageDecl::Stored:
- return !cast<VarDecl>(storage)->isLet();
+static void synthesizeTrivialSetterBody(TypeChecker &TC, AccessorDecl *setter) {
+ auto storage = setter->getStorage();
+ assert(!isSynthesizedComputedProperty(storage));
+ synthesizeTrivialSetterBodyWithStorage(TC, setter, TargetImpl::Storage,
+ storage);
+}
- // Addressed storage gets a setter if it has a mutable addressor.
- case AbstractStorageDecl::Addressed:
- return storage->getMutableAddressor() != nullptr;
+static void addGetterToStorage(TypeChecker &TC, AbstractStorageDecl *storage) {
+ auto getter = createGetterPrototype(TC, storage);
- // These should already have accessor functions.
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- llvm_unreachable("already has accessor functions");
+ // Install the prototype.
+ storage->setSynthesizedGetter(getter);
+}
- case AbstractStorageDecl::Computed:
- llvm_unreachable("not stored");
- }
- llvm_unreachable("bad storage kind");
+static void addSetterToStorage(TypeChecker &TC, AbstractStorageDecl *storage) {
+ auto setter = createSetterPrototype(TC, storage);
+
+ // Install the prototype.
+ storage->setSynthesizedSetter(setter);
}
/// Add trivial accessors to a Stored or Addressed property.
static void addTrivialAccessorsToStorage(AbstractStorageDecl *storage,
TypeChecker &TC) {
- assert(!storage->hasAccessorFunctions() && "already has accessors?");
- assert(!storage->getAttrs().hasAttribute<LazyAttr>());
- assert(!storage->getAttrs().hasAttribute<NSManagedAttr>());
+ assert(!isSynthesizedComputedProperty(storage));
- auto *DC = storage->getDeclContext();
+ if (!storage->getGetter())
+ addGetterToStorage(TC, storage);
- // Create the getter.
- AccessorDecl *getter = createGetterPrototype(storage, TC);
+ if (storage->supportsMutation()) {
+ if (!storage->getSetter())
+ addSetterToStorage(TC, storage);
- // Create the setter.
- AccessorDecl *setter = nullptr;
- ParamDecl *setterValueParam = nullptr;
- if (doesStorageNeedSetter(storage))
- setter = createSetterPrototype(storage, setterValueParam, TC);
-
- // Okay, we have both the getter and setter. Set them in VD.
- storage->addTrivialAccessors(getter, setter, nullptr);
-
- // Synthesize the body of the getter.
- synthesizeTrivialGetter(getter, storage, TC);
- maybeMarkTransparent(getter, storage, TC);
-
- if (setter) {
- // Synthesize the body of the setter.
- synthesizeTrivialSetter(setter, storage, setterValueParam, TC);
- maybeMarkTransparent(setter, storage, TC);
+ if (!storage->getMaterializeForSetFunc())
+ maybeAddMaterializeForSet(storage, TC);
}
-
- // We've added some members to our containing context, add them to
- // the right list.
- addMemberToContextIfNeeded(getter, DC, storage);
- if (setter)
- addMemberToContextIfNeeded(setter, DC, getter);
-
- maybeAddMaterializeForSet(storage, TC);
}
-/// Add a trivial setter and materializeForSet to a
-/// ComputedWithMutableAddress storage decl.
-void swift::
-synthesizeSetterForMutableAddressedStorage(AbstractStorageDecl *storage,
- TypeChecker &TC) {
- auto setter = storage->getSetter();
- assert(setter);
- if (setter->getBody()) return;
- assert(storage->getStorageKind() ==
- AbstractStorageDecl::ComputedWithMutableAddress);
+static void convertStoredVarInProtocolToComputed(VarDecl *VD, TypeChecker &TC) {
+ if (!VD->getGetter()) {
+ addGetterToStorage(TC, VD);
+ }
- // Synthesize the body of the setter.
- VarDecl *valueParamDecl = getFirstParamDecl(setter);
- synthesizeTrivialSetter(setter, storage, valueParamDecl, TC);
- maybeMarkTransparent(setter, storage, TC);
+ // Okay, we have the getter; make the VD computed.
+ VD->overwriteImplInfo(StorageImplInfo::getImmutableComputed());
+}
+
+static void synthesizeMutableAddressSetterBody(TypeChecker &TC,
+ AccessorDecl *setter) {
+ synthesizeTrivialSetterBodyWithStorage(TC, setter, TargetImpl::Implementation,
+ setter->getStorage());
}
/// Add a materializeForSet accessor to the given declaration.
@@ -839,30 +947,37 @@
auto materializeForSet = createMaterializeForSetPrototype(
storage, storage->getGetter(), storage->getSetter(), TC);
- addMemberToContextIfNeeded(materializeForSet, storage->getDeclContext(),
- storage->getSetter());
- storage->setMaterializeForSetFunc(materializeForSet);
+
+ // Install the prototype.
+ storage->setSynthesizedMaterializeForSet(materializeForSet);
return materializeForSet;
}
static void convertNSManagedStoredVarToComputed(VarDecl *VD, TypeChecker &TC) {
- assert(VD->getStorageKind() == AbstractStorageDecl::Stored);
+ // If it's not still stored, just bail out.
+ if (!VD->getImplInfo().isSimpleStored())
+ return;
+
+ // We might already have synthesized the getter and setter declarations
+ // from e.g. type-checking a conformance, or just from an invalid earlier
+ // declaration.
+
+ // Creating these this way will not trigger synthesis of implementations
+ // because of the NSManaged attribute.
// Create the getter.
- auto *Get = createGetterPrototype(VD, TC);
+ if (!VD->getGetter()) {
+ addGetterToStorage(TC, VD);
+ }
// Create the setter.
- ParamDecl *SetValueDecl = nullptr;
- auto *Set = createSetterPrototype(VD, SetValueDecl, TC);
+ if (!VD->getSetter()) {
+ addSetterToStorage(TC, VD);
+ }
- // Okay, we have both the getter and setter. Set them in VD.
- VD->setAccessors(VarDecl::Computed, SourceLoc(), {Get, Set}, SourceLoc());
-
- // We've added some members to our containing class/extension, add them to
- // the members list.
- addMemberToContextIfNeeded(Get, VD->getDeclContext(), VD);
- addMemberToContextIfNeeded(Set, VD->getDeclContext(), Get);
+ // Okay, we have both a getter and setter; overwrite the impl info.
+ VD->overwriteImplInfo(StorageImplInfo::getMutableComputed());
maybeAddMaterializeForSet(VD, TC);
}
@@ -873,17 +988,31 @@
void TypeChecker::synthesizeWitnessAccessorsForStorage(
AbstractStorageDecl *requirement,
AbstractStorageDecl *storage) {
- // If the decl is stored, convert it to StoredWithTrivialAccessors
- // by synthesizing the full set of accessors.
- if (!storage->hasAccessorFunctions()) {
- // Don't do this if the declaration is lazy or NSManaged.
- // This must be a re-entrant attempt to synthesize accessors
- // before validateDecl has finished.
- if (storage->getAttrs().hasAttribute<LazyAttr>() ||
- storage->getAttrs().hasAttribute<NSManagedAttr>())
- return;
+ bool addedAccessor = false;
+ auto flagAddedAccessor = [&](AccessorDecl *accessor,
+ Optional<SynthesizedFunction::Kind> kind) {
+ addedAccessor = true;
- addTrivialAccessorsToStorage(storage, *this);
+ // Synthesize a trivial body when we create an on-demand accessor.
+ if (kind && isOnDemandAccessor(accessor->getStorage(),
+ accessor->getAccessorKind())) {
+ triggerSynthesis(*this, accessor, *kind);
+ }
+ };
+
+ // Synthesize a getter.
+ if (!storage->getGetter()) {
+ addGetterToStorage(*this, storage);
+ flagAddedAccessor(storage->getGetter(), SynthesizedFunction::Getter);
+ }
+
+ // Synthesize a setter if the storage is mutable and the requirement
+ // needs it.
+ if (!storage->getSetter() &&
+ storage->supportsMutation() &&
+ requirement->supportsMutation()) {
+ addSetterToStorage(*this, storage);
+ flagAddedAccessor(storage->getSetter(), SynthesizedFunction::Setter);
}
// @objc protocols don't need a materializeForSet since ObjC doesn't
@@ -892,34 +1021,32 @@
!requirement->isObjC() && requirement->getSetter();
// If we want wantMaterializeForSet, create it now.
- if (wantMaterializeForSet && !storage->getMaterializeForSetFunc())
+ if (wantMaterializeForSet && !storage->getMaterializeForSetFunc()) {
addMaterializeForSet(storage, *this);
+ flagAddedAccessor(storage->getMaterializeForSetFunc(), None);
+ }
+
+ // Cue (delayed) validation of any accessors we just added, just
+ // in case this is coming after the normal delayed validation finished.
+ if (addedAccessor) {
+ DeclsToFinalize.insert(storage);
+ }
}
/// Given a VarDecl with a willSet: and/or didSet: specifier, synthesize the
-/// (trivial) getter and the setter, which calls these.
-void swift::synthesizeObservingAccessors(VarDecl *VD, TypeChecker &TC) {
- assert(VD->hasObservers());
- assert(VD->getGetter() && VD->getSetter());
-
+/// setter which calls them.
+static void synthesizeObservedSetterBody(TypeChecker &TC, AccessorDecl *Set,
+ TargetImpl target) {
+ auto VD = cast<VarDecl>(Set->getStorage());
+
auto &Ctx = VD->getASTContext();
SourceLoc Loc = VD->getLoc();
// We have to be paranoid about the accessors already having bodies
// because there might be an (invalid) existing definition.
- // The getter is always trivial: just perform a (direct!) load of storage, or
- // a call of a superclass getter if this is an override.
- auto *Get = VD->getGetter();
- if (!Get->hasBody()) {
- synthesizeTrivialGetter(Get, VD, TC);
- maybeMarkTransparent(Get, VD, TC);
- }
-
// Okay, the getter is done, create the setter now. Start by finding the
// decls for 'self' and 'value'.
- auto *Set = VD->getSetter();
- if (Set->hasBody()) return;
auto *SelfDecl = Set->getImplicitSelfDecl();
VarDecl *ValueDecl = Set->getParameterLists().back()->get(0);
@@ -934,7 +1061,7 @@
VarDecl *OldValue = nullptr;
if (VD->getDidSetFunc()) {
Expr *OldValueExpr
- = createPropertyLoadOrCallSuperclassGetter(Set, VD, TC);
+ = createPropertyLoadOrCallSuperclassGetter(Set, VD, target, TC);
OldValue = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
/*IsCaptureList*/false, SourceLoc(),
@@ -967,16 +1094,12 @@
}
SetterBody.push_back(CallExpr::createImplicit(Ctx, Callee, { ValueDRE },
{ Identifier() }));
-
- // Make sure the didSet/willSet accessors are marked final if in a class.
- if (!willSet->isFinal() &&
- VD->getDeclContext()->getAsClassOrClassExtensionContext())
- makeFinal(Ctx, willSet);
}
// Create an assignment into the storage or call to superclass setter.
auto *ValueDRE = new (Ctx) DeclRefExpr(ValueDecl, DeclNameLoc(), true);
- createPropertyStoreOrCallSuperclassSetter(Set, ValueDRE, VD, SetterBody, TC);
+ createPropertyStoreOrCallSuperclassSetter(Set, ValueDRE, VD, target,
+ SetterBody, TC);
// Create:
// (call_expr (dot_syntax_call_expr (decl_ref_expr(didSet)),
@@ -995,14 +1118,21 @@
}
SetterBody.push_back(CallExpr::createImplicit(Ctx, Callee, { OldValueExpr },
{ Identifier() }));
-
- // Make sure the didSet/willSet accessors are marked final if in a class.
- if (!didSet->isFinal() &&
- VD->getDeclContext()->getAsClassOrClassExtensionContext())
- makeFinal(Ctx, didSet);
}
Set->setBody(BraceStmt::create(Ctx, Loc, SetterBody, Loc, true));
+
+ finishSynthesis(TC, Set);
+}
+
+static void synthesizeStoredWithObserversSetterBody(TypeChecker &TC,
+ AccessorDecl *setter) {
+ synthesizeObservedSetterBody(TC, setter, TargetImpl::Storage);
+}
+
+static void synthesizeInheritedWithObserversSetterBody(TypeChecker &TC,
+ AccessorDecl *setter) {
+ synthesizeObservedSetterBody(TC, setter, TargetImpl::Super);
}
namespace {
@@ -1039,9 +1169,12 @@
/// Synthesize the getter for a lazy property with the specified storage
/// vardecl.
-static FuncDecl *completeLazyPropertyGetter(VarDecl *VD, VarDecl *Storage,
- TypeChecker &TC) {
- auto &Ctx = VD->getASTContext();
+static void synthesizeLazyGetterBody(TypeChecker &TC, AccessorDecl *Get,
+ VarDecl *Storage) {
+ auto &Ctx = TC.Context;
+
+ // The lazy var itself.
+ auto VD = cast<VarDecl>(Get->getStorage());
// The getter checks the optional, storing the initial value in if nil. The
// specific pattern we generate is:
@@ -1054,8 +1187,6 @@
// storage = tmp2
// return tmp2
// }
- auto *Get = VD->getGetter();
-
SmallVector<ASTNode, 6> Body;
// Load the existing storage and store it into the 'tmp1' temporary.
@@ -1065,7 +1196,9 @@
Tmp1VD->setImplicit();
auto *Tmp1PBDPattern = new (Ctx) NamedPattern(Tmp1VD, /*implicit*/true);
- auto *Tmp1Init = createPropertyLoadOrCallSuperclassGetter(Get, Storage, TC);
+ auto *Tmp1Init =
+ createPropertyLoadOrCallSuperclassGetter(Get, Storage,
+ TargetImpl::Storage, TC);
auto *Tmp1PBD = PatternBindingDecl::create(Ctx, /*StaticLoc*/SourceLoc(),
StaticSpellingKind::None,
/*VarLoc*/SourceLoc(),
@@ -1110,13 +1243,22 @@
auto *InitValue = VD->getParentInitializer();
auto PBD = VD->getParentPatternBinding();
unsigned entryIndex = PBD->getPatternEntryIndexForVarDecl(VD);
- PBD->setInit(entryIndex, nullptr);
+ assert(PBD->isInitializerLazy(entryIndex));
+ bool wasInitializerChecked = PBD->isInitializerChecked(entryIndex);
PBD->setInitializerChecked(entryIndex);
// Recontextualize any closure declcontexts nested in the initializer to
// realize that they are in the getter function.
InitValue->walk(RecontextualizeClosures(Get));
+ // Wrap the initializer in a LazyInitializerExpr to avoid problems with
+ // re-typechecking it if it was already type-checked.
+ // FIXME: we should really have stronger invariants than this. Leaving it
+ // unwrapped may expose both expressions to naive walkers
+ if (wasInitializerChecked) {
+ InitValue = new (Ctx) LazyInitializerExpr(InitValue);
+ }
+
Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true);
Tmp2PBDPattern = new (Ctx) TypedPattern(Tmp2PBDPattern,
TypeLoc::withoutLoc(VD->getType()),
@@ -1132,7 +1274,8 @@
// Assign tmp2 into storage.
auto Tmp2DRE = new (Ctx) DeclRefExpr(Tmp2VD, DeclNameLoc(), /*Implicit*/true,
AccessSemantics::DirectToStorage);
- createPropertyStoreOrCallSuperclassSetter(Get, Tmp2DRE, Storage, Body, TC);
+ createPropertyStoreOrCallSuperclassSetter(Get, Tmp2DRE, Storage,
+ TargetImpl::Storage, Body, TC);
// Return tmp2.
Tmp2DRE = new (Ctx) DeclRefExpr(Tmp2VD, DeclNameLoc(), /*Implicit*/true,
@@ -1143,7 +1286,13 @@
Get->setBody(BraceStmt::create(Ctx, VD->getLoc(), Body, VD->getLoc(),
/*implicit*/true));
- return Get;
+ finishSynthesis(TC, Get);
+}
+
+static void synthesizeLazySetterBody(TypeChecker &TC, AccessorDecl *setter,
+ VarDecl *underlyingStorage) {
+ synthesizeTrivialSetterBodyWithStorage(TC, setter, TargetImpl::Storage,
+ underlyingStorage);
}
void TypeChecker::completePropertyBehaviorStorage(VarDecl *VD,
@@ -1553,8 +1702,8 @@
void TypeChecker::completeLazyVarImplementation(VarDecl *VD) {
assert(VD->getAttrs().hasAttribute<LazyAttr>());
- assert(VD->getStorageKind() == AbstractStorageDecl::Computed &&
- "variable not validated yet");
+ assert(VD->getReadImpl() == ReadImplKind::Get);
+ assert(VD->getWriteImpl() == WriteImplKind::Set);
assert(!VD->isStatic() && "Static vars are already lazy on their own");
// Create the storage property as an optional of VD's type.
@@ -1586,15 +1735,12 @@
PBD->setImplicit();
addMemberToContextIfNeeded(PBD, VD->getDeclContext(), VD);
- // Now that we've got the storage squared away, synthesize the getter.
- completeLazyPropertyGetter(VD, Storage, *this);
-
- // The setter just forwards on to storage without materializing the initial
- // value.
- auto *Set = VD->getSetter();
- VarDecl *SetValueDecl = getFirstParamDecl(Set);
- // FIXME: This is wrong for observed properties.
- synthesizeTrivialSetter(Set, Storage, SetValueDecl, *this);
+ // Now that we've got the storage squared away, enqueue the getter and
+ // setter to be synthesized.
+ triggerSynthesis(*this, VD->getGetter(),
+ SynthesizedFunction::LazyGetter, Storage);
+ triggerSynthesis(*this, VD->getSetter(),
+ SynthesizedFunction::LazySetter, Storage);
// Mark the vardecl to be final, implicit, and private. In a class, this
// prevents it from being dynamically dispatched. Note that we do this after
@@ -1611,7 +1757,7 @@
/// decl (which has accessors).
void swift::maybeAddMaterializeForSet(AbstractStorageDecl *storage,
TypeChecker &TC) {
- assert(storage->hasAccessorFunctions());
+ assert(storage->getGetter());
// Be idempotent. There are a bunch of places where we want to
// ensure that there's a materializeForSet accessor.
@@ -1639,209 +1785,247 @@
addMaterializeForSet(storage, TC);
}
-void swift::maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC) {
+void swift::triggerAccessorSynthesis(TypeChecker &TC,
+ AbstractStorageDecl *storage) {
+ auto VD = dyn_cast<VarDecl>(storage);
+
+ // Synthesize accessors for lazy, all checking already been performed.
+ if (VD && VD->getAttrs().hasAttribute<LazyAttr>() && !VD->isStatic() &&
+ !VD->getGetter()->hasBody())
+ TC.completeLazyVarImplementation(VD);
+
+ switch (storage->getReadImpl()) {
+ case ReadImplKind::Get:
+ break;
+
+ // Synthesize the getter override for an inherited observed property.
+ case ReadImplKind::Stored:
+ case ReadImplKind::Inherited:
+ case ReadImplKind::Address:
+ if (auto getter = storage->getGetter())
+ triggerSynthesis(TC, getter, SynthesizedFunction::Getter);
+ break;
+ }
+
+ switch (storage->getWriteImpl()) {
+ case WriteImplKind::Immutable:
+ case WriteImplKind::Set:
+ break;
+
+ // Synthesize the setter for an observed property.
+ case WriteImplKind::Stored:
+ case WriteImplKind::StoredWithObservers:
+ case WriteImplKind::InheritedWithObservers:
+ case WriteImplKind::MutableAddress:
+ if (auto setter = storage->getSetter())
+ triggerSynthesis(TC, setter, SynthesizedFunction::Setter);
+ break;
+ }
+}
+
+static void maybeAddAccessorsToBehaviorStorage(TypeChecker &TC, VarDecl *var) {
+ // If there's already a getter, we're done.
if (var->getGetter())
return;
auto *dc = var->getDeclContext();
- assert(!var->hasAccessorFunctions());
+ assert(!var->getBehavior()->Conformance.hasValue());
+
+ // The property should be considered computed by the time we're through.
+ SWIFT_DEFER {
+ assert(!var->hasStorage() && "behavior var was not made computed");
+ };
+
+ auto behavior = var->getMutableBehavior();
+ NormalProtocolConformance *conformance = nullptr;
+ VarDecl *valueProp = nullptr;
- // Introduce accessors for a property with behaviors.
- if (var->hasBehavior()) {
- assert(!var->getBehavior()->Conformance.hasValue());
-
- // The property should be considered computed by the time we're through.
- SWIFT_DEFER {
- assert(!var->hasStorage() && "behavior var was not made computed");
- };
-
- auto behavior = var->getMutableBehavior();
- NormalProtocolConformance *conformance = nullptr;
- VarDecl *valueProp = nullptr;
+ bool mightBeMutating = dc->isTypeContext()
+ && !var->isStatic()
+ && !dc->getDeclaredInterfaceType()->hasReferenceSemantics();
- bool mightBeMutating = dc->isTypeContext()
- && !var->isStatic()
- && !dc->getDeclaredInterfaceType()->hasReferenceSemantics();
+ auto makeBehaviorAccessors = [&]{
+ AccessorDecl *getter;
+ AccessorDecl *setter = nullptr;
+ if (valueProp && valueProp->getGetter()) {
+ getter = createGetterPrototype(TC, var);
+ // The getter is mutating if the behavior implementation is, unless
+ // we're in a class or non-instance context.
+ if (mightBeMutating && valueProp->isGetterMutating())
+ getter->setSelfAccessKind(SelfAccessKind::Mutating);
- auto makeBehaviorAccessors = [&]{
- AccessorDecl *getter;
- AccessorDecl *setter = nullptr;
- if (valueProp && valueProp->getGetter()) {
- getter = createGetterPrototype(var, TC);
- // The getter is mutating if the behavior implementation is, unless
- // we're in a class or non-instance context.
- if (mightBeMutating && valueProp->isGetterMutating())
- getter->setSelfAccessKind(SelfAccessKind::Mutating);
+ getter->setAccess(var->getFormalAccess());
- getter->setAccess(var->getFormalAccess());
-
- // Make a setter if the behavior property has one.
- if (valueProp->getSetter()) {
- ParamDecl *newValueParam = nullptr;
- setter = createSetterPrototype(var, newValueParam, TC);
- if (mightBeMutating && valueProp->isSetterMutating())
- setter->setSelfAccessKind(SelfAccessKind::Mutating);
- // TODO: max of property and implementation setter visibility?
- setter->setAccess(var->getFormalAccess());
- }
- } else {
- // Even if we couldn't find a value property, still make up a stub
- // getter and setter, so that subsequent diagnostics make sense for a
- // computed-ish property.
- getter = createGetterPrototype(var, TC);
- getter->setAccess(var->getFormalAccess());
- ParamDecl *newValueParam = nullptr;
- setter = createSetterPrototype(var, newValueParam, TC);
- setter->setSelfAccessKind(SelfAccessKind::NonMutating);
+ // Make a setter if the behavior property has one.
+ if (valueProp->getSetter()) {
+ setter = createSetterPrototype(TC, var, getter);
+ if (mightBeMutating && valueProp->isSetterMutating())
+ setter->setSelfAccessKind(SelfAccessKind::Mutating);
+ // TODO: max of property and implementation setter visibility?
setter->setAccess(var->getFormalAccess());
}
+ } else {
+ // Even if we couldn't find a value property, still make up a stub
+ // getter and setter, so that subsequent diagnostics make sense for a
+ // computed-ish property.
+ getter = createGetterPrototype(TC, var);
+ getter->setAccess(var->getFormalAccess());
+ setter = createSetterPrototype(TC, var, getter);
+ setter->setSelfAccessKind(SelfAccessKind::NonMutating);
+ setter->setAccess(var->getFormalAccess());
+ }
- SmallVector<AccessorDecl*, 2> accessors;
- accessors.push_back(getter);
- if (setter) accessors.push_back(setter);
- var->setAccessors(VarDecl::Computed, SourceLoc(), accessors, SourceLoc());
-
- // Save the conformance and 'value' decl for later type checking.
- behavior->Conformance = conformance;
- behavior->ValueDecl = valueProp;
+ SmallVector<AccessorDecl*, 2> accessors;
+ accessors.push_back(getter);
+ if (setter) accessors.push_back(setter);
+ var->setAccessors(StorageImplInfo::getComputed(setter != nullptr),
+ SourceLoc(), accessors, SourceLoc());
+
+ // Save the conformance and 'value' decl for later type checking.
+ behavior->Conformance = conformance;
+ behavior->ValueDecl = valueProp;
+ };
- addMemberToContextIfNeeded(getter, dc, var);
- if (setter)
- addMemberToContextIfNeeded(setter, dc, getter);
- };
+ // Try to resolve the behavior to a protocol.
+ auto behaviorType = TC.resolveType(behavior->ProtocolName, dc,
+ TypeResolutionOptions());
+ if (!behaviorType) {
+ return makeBehaviorAccessors();
+ }
+
+ {
+ // The type must refer to a protocol.
+ auto behaviorProtoTy = behaviorType->getAs<ProtocolType>();
+ if (!behaviorProtoTy) {
+ TC.diagnose(behavior->getLoc(),
+ diag::property_behavior_not_protocol);
+ behavior->Conformance = (NormalProtocolConformance*)nullptr;
+ return makeBehaviorAccessors();
+ }
+ auto behaviorProto = behaviorProtoTy->getDecl();
- // Try to resolve the behavior to a protocol.
- auto behaviorType = TC.resolveType(behavior->ProtocolName, dc,
- TypeResolutionOptions());
- if (!behaviorType) {
+ // Validate the behavior protocol and all its extensions so we can do
+ // name lookup.
+ TC.validateDecl(behaviorProto);
+ for (auto ext : behaviorProto->getExtensions()) {
+ TC.validateExtension(ext);
+ }
+
+ // Look up the behavior protocol's "value" property, or bail if it doesn't
+ // have one. The property's accessors will decide whether the getter
+ // is mutating, and whether there's a setter. We'll type-check to make
+ // sure the property type matches later after validation.
+ auto lookup = TC.lookupMember(dc, behaviorProtoTy, TC.Context.Id_value);
+ for (auto found : lookup) {
+ if (auto foundVar = dyn_cast<VarDecl>(found.getValueDecl())) {
+ if (valueProp) {
+ TC.diagnose(behavior->getLoc(),
+ diag::property_behavior_protocol_reqt_ambiguous,
+ TC.Context.Id_value);
+ TC.diagnose(valueProp->getLoc(), diag::identifier_declared_here,
+ TC.Context.Id_value);
+ TC.diagnose(foundVar->getLoc(), diag::identifier_declared_here,
+ TC.Context.Id_value);
+ break;
+ }
+
+ valueProp = foundVar;
+ }
+ }
+
+ if (!valueProp) {
+ TC.diagnose(behavior->getLoc(),
+ diag::property_behavior_protocol_no_value);
return makeBehaviorAccessors();
}
- {
- // The type must refer to a protocol.
- auto behaviorProtoTy = behaviorType->getAs<ProtocolType>();
- if (!behaviorProtoTy) {
- TC.diagnose(behavior->getLoc(),
- diag::property_behavior_not_protocol);
- behavior->Conformance = (NormalProtocolConformance*)nullptr;
- return makeBehaviorAccessors();
- }
- auto behaviorProto = behaviorProtoTy->getDecl();
-
- // Validate the behavior protocol and all its extensions so we can do
- // name lookup.
- TC.validateDecl(behaviorProto);
- for (auto ext : behaviorProto->getExtensions()) {
- TC.validateExtension(ext);
- }
-
- // Look up the behavior protocol's "value" property, or bail if it doesn't
- // have one. The property's accessors will decide whether the getter
- // is mutating, and whether there's a setter. We'll type-check to make
- // sure the property type matches later after validation.
- auto lookup = TC.lookupMember(dc, behaviorProtoTy, TC.Context.Id_value);
- for (auto found : lookup) {
- if (auto foundVar = dyn_cast<VarDecl>(found.getValueDecl())) {
- if (valueProp) {
- TC.diagnose(behavior->getLoc(),
- diag::property_behavior_protocol_reqt_ambiguous,
- TC.Context.Id_value);
- TC.diagnose(valueProp->getLoc(), diag::identifier_declared_here,
- TC.Context.Id_value);
- TC.diagnose(foundVar->getLoc(), diag::identifier_declared_here,
- TC.Context.Id_value);
- break;
- }
-
- valueProp = foundVar;
- }
- }
-
- if (!valueProp) {
- TC.diagnose(behavior->getLoc(),
- diag::property_behavior_protocol_no_value);
- return makeBehaviorAccessors();
- }
-
- TC.validateDecl(valueProp);
- var->setIsGetterMutating(mightBeMutating &&
- valueProp->isGetterMutating());
- var->setIsSetterMutating(mightBeMutating &&
- valueProp->isSetterMutating());
-
- // Set up a conformance to represent the behavior instantiation.
- // The conformance will be on the containing 'self' type, or '()' if the
- // property is in a non-type context.
- Type behaviorSelf;
- if (dc->isTypeContext()) {
- behaviorSelf = dc->getSelfInterfaceType();
- assert(behaviorSelf && "type context doesn't have self type?!");
- if (var->isStatic())
- behaviorSelf = MetatypeType::get(behaviorSelf);
- } else {
- behaviorSelf = TC.Context.TheEmptyTupleType;
- }
-
- conformance = TC.Context.getBehaviorConformance(behaviorSelf,
- behaviorProto,
- behavior->getLoc(), var,
- ProtocolConformanceState::Checking);
+ TC.validateDecl(valueProp);
+ var->setIsGetterMutating(mightBeMutating &&
+ valueProp->isGetterMutating());
+ var->setIsSetterMutating(mightBeMutating &&
+ valueProp->isSetterMutating());
+
+ // Set up a conformance to represent the behavior instantiation.
+ // The conformance will be on the containing 'self' type, or '()' if the
+ // property is in a non-type context.
+ Type behaviorSelf;
+ if (dc->isTypeContext()) {
+ behaviorSelf = dc->getSelfInterfaceType();
+ assert(behaviorSelf && "type context doesn't have self type?!");
+ if (var->isStatic())
+ behaviorSelf = MetatypeType::get(behaviorSelf);
+ } else {
+ behaviorSelf = TC.Context.TheEmptyTupleType;
}
- return makeBehaviorAccessors();
+
+ conformance = TC.Context.getBehaviorConformance(behaviorSelf,
+ behaviorProto,
+ behavior->getLoc(), var,
+ ProtocolConformanceState::Checking);
+ }
+ return makeBehaviorAccessors();
+}
+
+static void maybeAddAccessorsToLazyVariable(TypeChecker &TC, VarDecl *var) {
+ // If there are already accessors, something is invalid; bail out.
+ if (!var->getImplInfo().isSimpleStored())
+ return;
+
+ if (!var->getGetter()) {
+ addGetterToStorage(TC, var);
+ }
+
+ if (!var->getSetter()) {
+ addSetterToStorage(TC, var);
+ }
+
+ var->overwriteImplInfo(StorageImplInfo::getMutableComputed());
+
+ maybeAddMaterializeForSet(var, TC);
+}
+
+/// Try to add the appropriate accessors required a storage declaration.
+/// This needs to be idempotent.
+///
+/// Note that the parser synthesizes accessors in some cases:
+/// - it synthesizes a getter and setter for an observing property
+/// - it synthesizes a setter for get+mutableAddress
+void swift::maybeAddAccessorsToStorage(TypeChecker &TC,
+ AbstractStorageDecl *storage) {
+ // Introduce accessors for a property with behaviors.
+ if (storage->hasBehavior()) {
+ maybeAddAccessorsToBehaviorStorage(TC, cast<VarDecl>(storage));
+ return;
}
// Lazy properties require special handling.
- if (var->getAttrs().hasAttribute<LazyAttr>()) {
- auto *getter = createGetterPrototype(var, TC);
- // lazy getters are mutating on an enclosing value type.
- if (!dc->getAsClassOrClassExtensionContext()) {
- getter->setSelfAccessKind(SelfAccessKind::Mutating);
- var->setIsGetterMutating(true);
- }
- getter->setAccess(var->getFormalAccess());
-
- ParamDecl *newValueParam = nullptr;
- auto *setter = createSetterPrototype(var, newValueParam, TC);
-
- AccessorDecl *materializeForSet = nullptr;
- if (dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
- materializeForSet = createMaterializeForSetPrototype(var,
- getter, setter,
- TC);
- }
-
- SmallVector<AccessorDecl *, 3> accessors;
- accessors.push_back(getter);
- accessors.push_back(setter);
- if (materializeForSet) accessors.push_back(materializeForSet);
- var->setAccessors(VarDecl::Computed, SourceLoc(), accessors, SourceLoc());
-
- addMemberToContextIfNeeded(getter, dc, var);
- addMemberToContextIfNeeded(setter, dc, getter);
- if (materializeForSet)
- addMemberToContextIfNeeded(materializeForSet, dc, setter);
+ if (storage->getAttrs().hasAttribute<LazyAttr>()) {
+ maybeAddAccessorsToLazyVariable(TC, cast<VarDecl>(storage));
return;
}
+ auto *dc = storage->getDeclContext();
+
// Local variables don't otherwise get accessors.
if (dc->isLocalContext())
return;
// Implicit properties don't get accessors.
- if (var->isImplicit())
+ if (storage->isImplicit())
return;
if (!dc->isTypeContext()) {
// Fixed-layout global variables don't get accessors.
- if (!var->isResilient())
+ if (!storage->isResilient())
return;
// In a protocol context, variables written as just "var x : Int" or
// "let x : Int" are errors and recovered by building a computed property
// with just a getter. Diagnose this and create the getter decl now.
} else if (isa<ProtocolDecl>(dc)) {
- if (var->hasStorage()) {
+ if (storage->hasStorage()) {
+ auto var = cast<VarDecl>(storage);
if (var->isLet())
TC.diagnose(var->getLoc(),
diag::protocol_property_must_be_computed_var);
@@ -1850,11 +2034,14 @@
convertStoredVarInProtocolToComputed(var, TC);
}
+
+ maybeAddMaterializeForSet(storage, TC);
return;
// NSManaged properties on classes require special handling.
} else if (dc->getAsClassOrClassExtensionContext()) {
- if (var->getAttrs().hasAttribute<NSManagedAttr>()) {
+ auto var = dyn_cast<VarDecl>(storage);
+ if (var && var->getAttrs().hasAttribute<NSManagedAttr>()) {
convertNSManagedStoredVarToComputed(var, TC);
return;
}
@@ -1866,12 +2053,88 @@
}
// Stored properties in SIL mode don't get accessors.
+ // But they might get a materializeForSet.
if (auto sourceFile = dc->getParentSourceFile())
- if (sourceFile->Kind == SourceFileKind::SIL)
+ if (sourceFile->Kind == SourceFileKind::SIL) {
+ if (storage->getGetter() && storage->getSetter()) {
+ maybeAddMaterializeForSet(storage, TC);
+ }
return;
+ }
- // Everything else gets accessors.
- addTrivialAccessorsToStorage(var, TC);
+ // Everything else gets mandatory accessors.
+ addTrivialAccessorsToStorage(storage, TC);
+}
+
+static void synthesizeGetterBody(TypeChecker &TC, AccessorDecl *getter) {
+ switch (getter->getStorage()->getReadImpl()) {
+ case ReadImplKind::Stored:
+ synthesizeTrivialGetterBody(TC, getter);
+ return;
+
+ case ReadImplKind::Get:
+ llvm_unreachable("synthesizing getter that already exists?");
+
+ case ReadImplKind::Inherited:
+ synthesizeInheritedGetterBody(TC, getter);
+ return;
+
+ case ReadImplKind::Address:
+ synthesizeAddressedGetterBody(TC, getter);
+ return;
+ }
+ llvm_unreachable("bad ReadImplKind");
+}
+
+static void synthesizeSetterBody(TypeChecker &TC, AccessorDecl *setter) {
+ switch (setter->getStorage()->getWriteImpl()) {
+ case WriteImplKind::Immutable:
+ llvm_unreachable("synthesizing setter from immutable storage");
+
+ case WriteImplKind::Stored:
+ return synthesizeTrivialSetterBody(TC, setter);
+
+ case WriteImplKind::StoredWithObservers:
+ return synthesizeStoredWithObserversSetterBody(TC, setter);
+
+ case WriteImplKind::InheritedWithObservers:
+ return synthesizeInheritedWithObserversSetterBody(TC, setter);
+
+ case WriteImplKind::Set:
+ llvm_unreachable("synthesizing setter for unknown reason?");
+
+ case WriteImplKind::MutableAddress:
+ return synthesizeMutableAddressSetterBody(TC, setter);
+ }
+ llvm_unreachable("bad ReadImplKind");
+}
+
+void TypeChecker::synthesizeFunctionBody(SynthesizedFunction fn) {
+ switch (fn.getKind()) {
+ case SynthesizedFunction::Getter:
+ synthesizeGetterBody(*this, cast<AccessorDecl>(fn.getDecl()));
+ return;
+
+ case SynthesizedFunction::Setter:
+ synthesizeSetterBody(*this, cast<AccessorDecl>(fn.getDecl()));
+ return;
+
+ case SynthesizedFunction::MaterializeForSet:
+ llvm_unreachable("not used right now?");
+ //synthesizeMaterializeForSetBody(*this, cast<AccessorDecl>(fn.getDecl()));
+ return;
+
+ case SynthesizedFunction::LazyGetter:
+ synthesizeLazyGetterBody(*this, cast<AccessorDecl>(fn.getDecl()),
+ fn.getLazyTargetVariable());
+ return;
+
+ case SynthesizedFunction::LazySetter:
+ synthesizeLazySetterBody(*this, cast<AccessorDecl>(fn.getDecl()),
+ fn.getLazyTargetVariable());
+ return;
+ }
+ llvm_unreachable("bad synthesized function kind");
}
/// \brief Create an implicit struct or class constructor.
diff --git a/lib/Sema/CodeSynthesis.h b/lib/Sema/CodeSynthesis.h
index 1b7103e..c307cb4 100644
--- a/lib/Sema/CodeSynthesis.h
+++ b/lib/Sema/CodeSynthesis.h
@@ -19,6 +19,7 @@
#define SWIFT_TYPECHECKING_CODESYNTHESIS_H
#include "swift/AST/ForeignErrorConvention.h"
+#include "swift/Basic/ExternalUnion.h"
#include "swift/Basic/LLVM.h"
#include "llvm/ADT/Optional.h"
@@ -40,6 +41,57 @@
enum class ObjCReason;
+/// A function which needs to have its body synthesized.
+///
+/// This class exists in expectation that someone will need to add more
+/// information to it.
+class SynthesizedFunction {
+public:
+ enum Kind {
+ Getter,
+ Setter,
+ MaterializeForSet,
+ LazyGetter,
+ LazySetter,
+ };
+
+private:
+ FuncDecl *Fn;
+ Kind K;
+
+ using Members = ExternalUnionMembers<void, VarDecl*>;
+ static Members::Index getIndexForKind(Kind kind) {
+ switch (kind) {
+ case Kind::Getter:
+ case Kind::Setter:
+ case Kind::MaterializeForSet:
+ return Members::indexOf<void>();
+ case Kind::LazyGetter:
+ case Kind::LazySetter:
+ return Members::indexOf<VarDecl*>();
+ }
+ llvm_unreachable("bad kind");
+ };
+ ExternalUnion<Kind, Members, getIndexForKind> Extra;
+ static_assert(decltype(Extra)::union_is_trivially_copyable,
+ "expected all members to be trivial");
+
+public:
+ SynthesizedFunction(FuncDecl *fn, Kind kind) : Fn(fn), K(kind) {
+ assert(getIndexForKind(kind) == Members::indexOf<void>() &&
+ "this storage kind requires extra data");
+ }
+
+ SynthesizedFunction(FuncDecl *fn, Kind kind, VarDecl *var) : Fn(fn), K(kind) {
+ Extra.emplace<VarDecl*>(K, var);
+ }
+
+ FuncDecl *getDecl() const { return Fn; }
+ Kind getKind() const { return K; }
+
+ VarDecl *getLazyTargetVariable() const { return Extra.get<VarDecl*>(K); }
+};
+
// These are implemented in TypeCheckDecl.cpp.
void makeFinal(ASTContext &ctx, ValueDecl *D);
void makeDynamic(ASTContext &ctx, ValueDecl *D);
@@ -49,12 +101,11 @@
bool checkOverrides(TypeChecker &TC, ValueDecl *decl);
// These are implemented in CodeSynthesis.cpp.
-void synthesizeObservingAccessors(VarDecl *VD, TypeChecker &TC);
-void synthesizeSetterForMutableAddressedStorage(AbstractStorageDecl *storage,
- TypeChecker &TC);
void maybeAddMaterializeForSet(AbstractStorageDecl *storage,
TypeChecker &TC);
-void maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC);
+void maybeAddAccessorsToStorage(TypeChecker &TC, AbstractStorageDecl *storage);
+
+void triggerAccessorSynthesis(TypeChecker &TC, AbstractStorageDecl *storage);
/// \brief Describes the kind of implicit constructor that will be
/// generated.
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index b5fba35..eafa3d2 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -1087,8 +1087,8 @@
hashValueDecl->setImplicit();
hashValueDecl->setInterfaceType(intType);
hashValueDecl->setValidationStarted();
- hashValueDecl->setAccessors(VarDecl::Computed, SourceLoc(), {getterDecl},
- SourceLoc());
+ hashValueDecl->setAccessors(StorageImplInfo::getImmutableComputed(),
+ SourceLoc(), {getterDecl}, SourceLoc());
hashValueDecl->copyFormalAccessFrom(derived.Nominal,
/*sourceIsParentContext*/ true);
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index c646d4c..ce59bb4 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -272,7 +272,7 @@
auto getter =
declareDerivedPropertyGetter(tc, property, propertyContextType);
- property->setAccessors(VarDecl::Computed,
+ property->setAccessors(StorageImplInfo::getImmutableComputed(),
SourceLoc(), {getter}, SourceLoc());
return getter;
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index dab83ec..4ca4449 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -87,13 +87,16 @@
// message.
struct PartialApplication {
enum : unsigned {
- Function,
MutatingMethod,
SuperInit,
SelfInit,
};
- // 'kind' before 'level' is better for code gen.
- unsigned kind : 3;
+ enum : unsigned {
+ Error,
+ CompatibilityWarning,
+ };
+ unsigned compatibilityWarning: 1;
+ unsigned kind : 2;
unsigned level : 29;
};
@@ -105,49 +108,18 @@
~DiagnoseWalker() override {
for (auto &unapplied : InvalidPartialApplications) {
unsigned kind = unapplied.second.kind;
- TC.diagnose(unapplied.first->getLoc(),
- diag::partial_application_of_function_invalid,
- kind);
+ if (unapplied.second.compatibilityWarning) {
+ TC.diagnose(unapplied.first->getLoc(),
+ diag::partial_application_of_function_invalid_swift4,
+ kind);
+ } else {
+ TC.diagnose(unapplied.first->getLoc(),
+ diag::partial_application_of_function_invalid,
+ kind);
+ }
}
}
- /// If this is an application of a function that cannot be partially
- /// applied, arrange for us to check that it gets fully applied.
- void recordUnsupportedPartialApply(ApplyExpr *expr, Expr *fnExpr) {
-
- if (isa<OtherConstructorDeclRefExpr>(fnExpr)) {
- auto kind = expr->getArg()->isSuperExpr()
- ? PartialApplication::SuperInit
- : PartialApplication::SelfInit;
-
- // Partial applications of delegated initializers aren't allowed, and
- // don't really make sense to begin with.
- InvalidPartialApplications.insert({ expr, {kind, 1} });
- return;
- }
-
- auto fnDeclRef = dyn_cast<DeclRefExpr>(fnExpr);
- if (!fnDeclRef)
- return;
-
- auto fn = dyn_cast<FuncDecl>(fnDeclRef->getDecl());
- if (!fn)
- return;
-
- unsigned kind =
- fn->isInstanceMember() ? PartialApplication::MutatingMethod
- : PartialApplication::Function;
-
- // Functions with inout parameters cannot be partially applied.
- if (!expr->getArg()->getType()->isMaterializable()) {
- // We need to apply all argument clauses.
- InvalidPartialApplications.insert({
- fnExpr, {kind, fn->getNumParameterLists()}
- });
- }
- }
-
- /// This method is called in post-order over the AST to validate that
/// methods are fully applied when they can't support partial application.
void checkInvalidPartialApplication(Expr *E) {
if (auto AE = dyn_cast<ApplyExpr>(E)) {
@@ -158,8 +130,18 @@
fnExpr = dotSyntaxExpr->getRHS();
// Check to see if this is a potentially unsupported partial
- // application.
- recordUnsupportedPartialApply(AE, fnExpr);
+ // application of a constructor delegation.
+ if (isa<OtherConstructorDeclRefExpr>(fnExpr)) {
+ auto kind = AE->getArg()->isSuperExpr()
+ ? PartialApplication::SuperInit
+ : PartialApplication::SelfInit;
+
+ // Partial applications of delegated initializers aren't allowed, and
+ // don't really make sense to begin with.
+ InvalidPartialApplications.insert(
+ {E, {PartialApplication::Error, kind, 1}});
+ return;
+ }
// If this is adding a level to an active partial application, advance
// it to the next level.
@@ -173,11 +155,36 @@
InvalidPartialApplications.erase(foundApplication);
if (level > 1) {
// We have remaining argument clauses.
- InvalidPartialApplications.insert({ AE, {kind, level - 1} });
+ // Partial applications were always diagnosed in Swift 4 and before,
+ // so there's no need to preserve the compatibility warning bit.
+ InvalidPartialApplications.insert(
+ {AE, {PartialApplication::Error, kind, level - 1}});
}
return;
}
+
+ /// If this is a reference to a mutating method, it cannot be partially
+ /// applied or even referenced without full application, so arrange for
+ /// us to check that it gets fully applied.
+ auto fnDeclRef = dyn_cast<DeclRefExpr>(E);
+ if (!fnDeclRef)
+ return;
+ auto fn = dyn_cast<FuncDecl>(fnDeclRef->getDecl());
+ if (!fn || !fn->isInstanceMember() || !fn->isMutating())
+ return;
+
+ // Swift 4 and earlier failed to diagnose a reference to a mutating method
+ // without any applications at all, which would get miscompiled into a
+ // function with undefined behavior. Warn for source compatibility.
+ auto errorBehavior = TC.Context.LangOpts.isSwiftVersionAtLeast(5)
+ ? PartialApplication::Error
+ : PartialApplication::CompatibilityWarning;
+
+ InvalidPartialApplications.insert(
+ {fnDeclRef, {errorBehavior,
+ PartialApplication::MutatingMethod,
+ fn->getNumParameterLists()}});
}
// Not interested in going outside a basic expression.
@@ -1586,7 +1593,7 @@
if (auto *DRE = dyn_cast<DeclRefExpr>(subExpr)) {
if (DRE->getDecl() == Var) {
// Handle local and top-level computed variables.
- if (DRE->getAccessSemantics() != AccessSemantics::DirectToStorage) {
+ if (DRE->getAccessSemantics() == AccessSemantics::Ordinary) {
bool shouldDiagnose = false;
// Warn about any property access in the getter.
if (Accessor->isGetter())
@@ -1623,7 +1630,7 @@
isa<DeclRefExpr>(MRE->getBase()) &&
isImplicitSelfUse(MRE->getBase())) {
- if (MRE->getAccessSemantics() != AccessSemantics::DirectToStorage) {
+ if (MRE->getAccessSemantics() == AccessSemantics::Ordinary) {
bool shouldDiagnose = false;
// Warn about any property access in the getter.
if (Accessor->isGetter())
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 629b39d..1fad540 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -542,8 +542,8 @@
};
// @NSManaged properties must be written as stored.
- switch (VD->getStorageKind()) {
- case AbstractStorageDecl::Stored:
+ auto impl = VD->getImplInfo();
+ if (impl.isSimpleStored()) {
// @NSManaged properties end up being computed; complain if there is
// an initializer.
if (VD->getParentInitializer()) {
@@ -553,21 +553,14 @@
PBD->setInit(PBD->getPatternEntryIndexForVarDecl(VD), nullptr);
}
// Otherwise, ok.
- break;
-
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- llvm_unreachable("Already created accessors?");
-
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::Computed:
+ } else if (impl.getReadImpl() == ReadImplKind::Address ||
+ impl.getWriteImpl() == WriteImplKind::MutableAddress) {
+ return diagnoseNotStored(/*addressed*/ 2);
+ } else if (impl.getWriteImpl() == WriteImplKind::StoredWithObservers ||
+ impl.getWriteImpl() == WriteImplKind::InheritedWithObservers) {
+ return diagnoseNotStored(/*observing*/ 1);
+ } else {
return diagnoseNotStored(/*computed*/ 0);
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::InheritedWithObservers:
- return diagnoseNotStored(/*observing*/ 1);
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
- return diagnoseNotStored(/*addressed*/ 2);
}
// @NSManaged properties cannot be @NSCopying
@@ -630,24 +623,13 @@
// TODO: Lazy properties can't yet be observed.
- switch (VD->getStorageKind()) {
- case AbstractStorageDecl::Stored:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- break;
-
- case AbstractStorageDecl::StoredWithObservers:
+ auto impl = VD->getImplInfo();
+ if (impl.isSimpleStored()) {
+ // ok
+ } else if (VD->hasStorage()) {
diagnoseAndRemoveAttr(attr, diag::lazy_not_observable);
- break;
-
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::Computed:
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
- assert(!VD->hasStorage() && "Non-stored AbstractStorageDecl has storage?");
+ } else {
diagnoseAndRemoveAttr(attr, diag::lazy_not_on_computed);
- break;
}
}
@@ -1286,6 +1268,13 @@
return;
}
+ if (VD->hasInterfaceType()) {
+ if (TC.checkConformanceToNSCopying(VD)) {
+ attr->setInvalid();
+ return;
+ }
+ }
+
assert(VD->getOverriddenDecl() == nullptr &&
"Can't have value with storage that is an override");
diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp
index 9abe9d4..09e002f 100644
--- a/lib/Sema/TypeCheckAvailability.cpp
+++ b/lib/Sema/TypeCheckAvailability.cpp
@@ -179,7 +179,7 @@
// when we process the accessor, we can use this TRC as the
// parent.
if (auto *StorageDecl = dyn_cast<AbstractStorageDecl>(D)) {
- if (StorageDecl->hasAccessorFunctions()) {
+ if (StorageDecl->hasAnyAccessors()) {
StorageContexts[StorageDecl] = NewTRC;
}
}
@@ -228,7 +228,7 @@
// locations and have callers of that method provide appropriate source
// locations.
SourceLoc BracesEnd = storageDecl->getBracesRange().End;
- if (storageDecl->hasAccessorFunctions() && BracesEnd.isValid()) {
+ if (storageDecl->hasAnyAccessors() && BracesEnd.isValid()) {
return SourceRange(storageDecl->getStartLoc(),
BracesEnd);
}
@@ -2433,11 +2433,14 @@
if (!D)
return;
- if (!D->hasAccessorFunctions()) {
+ if (!D->hasAnyAccessors()) {
return;
}
- // Check availability of accessor functions
+ // Check availability of accessor functions.
+ // TODO: if we're talking about an inlineable storage declaration,
+ // this probably needs to be refined to not assume that the accesses are
+ // specifically using the getter/setter.
switch (AccessContext) {
case MemberAccessContext::Getter:
diagAccessorAvailability(D->getGetter(), ReferenceRange, ReferenceDC,
diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp
index 20df65a..3ee4622 100644
--- a/lib/Sema/TypeCheckCaptures.cpp
+++ b/lib/Sema/TypeCheckCaptures.cpp
@@ -19,6 +19,7 @@
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
+#include "swift/AST/Initializer.h"
#include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/ParameterList.h"
@@ -227,6 +228,13 @@
}
}
+ bool shouldWalkIntoLazyInitializers() override {
+ // We don't want to walk into lazy initializers because they're not
+ // really present at this level. We'll catch them when processing
+ // the getter.
+ return false;
+ }
+
std::pair<bool, Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
auto *D = DRE->getDecl();
@@ -262,6 +270,22 @@
if (TmpDC == DC)
break;
+ // The initializer of a lazy property will eventually get
+ // recontextualized into it, so treat it as if it's already there.
+ if (auto init = dyn_cast<PatternBindingInitializer>(TmpDC)) {
+ if (auto lazyVar = init->getInitializedLazyVar()) {
+ // Referring to the 'self' parameter is fine.
+ if (D == init->getImplicitSelfDecl())
+ return { false, DRE };
+
+ // Otherwise, act as if we're in the getter.
+ auto getter = lazyVar->getGetter();
+ assert(getter && "lazy variable without getter");
+ TmpDC = getter;
+ continue;
+ }
+ }
+
// We have an intervening nominal type context that is not the
// declaration context, and the declaration context is not global.
// This is not supported since nominal types cannot capture values.
@@ -382,8 +406,14 @@
// If this is a direct reference to underlying storage, then this is a
// capture of the storage address - not a capture of the getter/setter.
- if (DRE->getAccessSemantics() == AccessSemantics::DirectToStorage)
- Flags |= CapturedValue::IsDirect;
+ if (auto var = dyn_cast<VarDecl>(D)) {
+ if (var->getAccessStrategy(DRE->getAccessSemantics(),
+ var->supportsMutation()
+ ? AccessKind::ReadWrite : AccessKind::Read,
+ AFR.getAsDeclContext())
+ .getKind() == AccessStrategy::Storage)
+ Flags |= CapturedValue::IsDirect;
+ }
// If the closure is noescape, then we can capture the decl as noescape.
if (AFR.isKnownNoEscape())
@@ -619,6 +649,12 @@
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
return walkToDeclRefExpr(DRE);
+ // Look into lazy initializers.
+ if (auto *LIE = dyn_cast<LazyInitializerExpr>(E)) {
+ LIE->getSubExpr()->walk(*this);
+ return { true, E };
+ }
+
// When we see a reference to the 'super' expression, capture 'self' decl.
if (auto *superE = dyn_cast<SuperRefExpr>(E)) {
auto CurDC = AFR.getAsDeclContext();
@@ -721,9 +757,13 @@
if (!PBD) continue;
// Walk the initializers for all properties declared in the type with
// an initializer.
- for (auto &elt : PBD->getPatternList())
+ for (auto &elt : PBD->getPatternList()) {
+ if (elt.isInitializerLazy())
+ continue;
+
if (auto *init = elt.getInit())
init->walk(finder);
+ }
}
}
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 4250dd8..d47fc74 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -40,7 +40,7 @@
#include "swift/Parse/Parser.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Strings.h"
-#include "swift/Sema/TypeCheckRequests.h"
+#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Defer.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
@@ -233,21 +233,6 @@
/// Check that the declaration attributes are ok.
static void validateAttributes(TypeChecker &TC, Decl *D);
-Type TypeChecker::getSuperclass(const ClassDecl *classDecl) {
- return Context.evaluator(
- SuperclassTypeRequest(const_cast<ClassDecl *>(classDecl)));
-}
-
-Type TypeChecker::getRawType(EnumDecl *enumDecl) {
- return Context.evaluator(EnumRawTypeRequest(enumDecl));
-}
-
-Type TypeChecker::getInheritedType(
- llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
- unsigned index) {
- return Context.evaluator(InheritedTypeRequest(decl, index));
-}
-
void TypeChecker::resolveTrailingWhereClause(ProtocolDecl *proto) {
ProtocolRequirementTypeResolver resolver;
validateWhereClauses(proto, &resolver);
@@ -327,25 +312,15 @@
MutableArrayRef<TypeLoc> inheritedClause;
- // If we already checked the inheritance clause, don't do so again.
if (auto type = dyn_cast<TypeDecl>(decl)) {
- if (type->checkedInheritanceClause())
- return;
-
- // This breaks infinite recursion, which will be diagnosed separately.
- type->setCheckedInheritanceClause();
inheritedClause = type->getInherited();
} else {
auto ext = cast<ExtensionDecl>(decl);
validateExtension(ext);
-
- if (ext->isInvalid() ||
- ext->checkedInheritanceClause())
+ if (ext->isInvalid())
return;
- // This breaks infinite recursion, which will be diagnosed separately.
- ext->setCheckedInheritanceClause();
inheritedClause = ext->getInherited();
// Protocol extensions cannot have inheritance clauses.
@@ -624,7 +599,7 @@
for (unsigned i = 0, n = allProtocols.size(); i != n; /*in loop*/) {
if (allProtocols[i] == proto || allProtocols[i]->inheritsFrom(proto)) {
if (!diagnosedCircularity) {
- diagnose(proto, diag::circular_protocol_def, proto->getName().str());
+ diagnose(proto, diag::circular_protocol_def, proto->getName());
diagnosedCircularity = true;
}
@@ -643,17 +618,16 @@
getInheritedForCycleCheck(TypeChecker &tc,
ProtocolDecl *proto,
ProtocolDecl **scratch) {
- return tc.getDirectConformsTo(proto);
+ tc.resolveInheritedProtocols(proto);
+ return proto->getInheritedProtocols();
}
/// Retrieve the superclass of the given class.
static ArrayRef<ClassDecl *> getInheritedForCycleCheck(TypeChecker &tc,
ClassDecl *classDecl,
ClassDecl **scratch) {
- tc.checkInheritanceClause(classDecl);
-
if (classDecl->hasSuperclass()) {
- *scratch = classDecl->getSuperclass()->getClassOrBoundGenericClass();
+ *scratch = classDecl->getSuperclassDecl();
return *scratch;
}
return { };
@@ -663,8 +637,6 @@
static ArrayRef<EnumDecl *> getInheritedForCycleCheck(TypeChecker &tc,
EnumDecl *enumDecl,
EnumDecl **scratch) {
- tc.checkInheritanceClause(enumDecl);
-
if (enumDecl->hasRawType()) {
*scratch = enumDecl->getRawType()->getEnumOrBoundGenericEnum();
return *scratch ? ArrayRef<EnumDecl*>(*scratch) : ArrayRef<EnumDecl*>{};
@@ -692,7 +664,7 @@
/// Check for circular inheritance.
template<typename T>
static void checkCircularity(TypeChecker &tc, T *decl,
- Diag<StringRef> circularDiag,
+ Diag<Identifier> circularDiag,
DescriptiveDeclKind declKind,
SmallVectorImpl<T *> &path) {
switch (decl->getCircularityCheck()) {
@@ -716,7 +688,7 @@
if (path.end() - cycleStart == 1) {
tc.diagnose(path.back()->getLoc(),
circularDiag,
- path.back()->getName().str());
+ path.back()->getName());
decl->setInvalid();
decl->setInterfaceType(ErrorType::get(tc.Context));
@@ -724,17 +696,9 @@
break;
}
- // Form the textual path illustrating the cycle.
- llvm::SmallString<128> pathStr;
- for (auto i = cycleStart, iEnd = path.end(); i != iEnd; ++i) {
- if (!pathStr.empty())
- pathStr += " -> ";
- pathStr += ("'" + (*i)->getName().str() + "'").str();
- }
- pathStr += (" -> '" + decl->getName().str() + "'").str();
-
// Diagnose the cycle.
- tc.diagnose(decl->getLoc(), circularDiag, pathStr);
+ tc.diagnose(decl->getLoc(), circularDiag,
+ (*cycleStart)->getName());
for (auto i = cycleStart + 1, iEnd = path.end(); i != iEnd; ++i) {
tc.diagnose(*i, diag::kind_identifier_declared_here,
declKind, (*i)->getName());
@@ -1164,10 +1128,12 @@
// If the pattern didn't get a type or if it contains an unbound generic type,
// we'll need to check the initializer.
if (!pattern->hasType() || pattern->getType()->hasUnboundGenericType()) {
+ // We used to not apply the solution to lazy bindings here, but that's
+ // unnecessary: the code for building lazy getters already has to handle
+ // initializers which have had solutions applied, and not applying the
+ // solution blocks other diagnostics if we decide not to synthesize the
+ // getter.
bool skipApplyingSolution = false;
- if (auto var = binding->getSingleVar())
- skipApplyingSolution = var->getAttrs().hasAttribute<LazyAttr>();
-
if (tc.typeCheckPatternBinding(binding, entryNumber, skipApplyingSolution))
return;
}
@@ -1192,8 +1158,9 @@
// If we have any type-adjusting attributes, apply them here.
assert(binding->getPattern(entryNumber)->hasType() && "Type missing?");
- if (auto var = binding->getSingleVar())
+ if (auto var = binding->getSingleVar()) {
tc.checkTypeModifyingDeclAttributes(var);
+ }
}
/// Validate the entries in the given pattern binding declaration.
@@ -1565,8 +1532,21 @@
if (isa<DestructorDecl>(decl))
return;
+ assert(decl->isObjC() && "Must be known to be @objc");
auto attr = decl->getAttrs().getAttribute<ObjCAttr>();
- assert(attr && "should only be called on decls already marked @objc");
+
+ /// Set the @objc name.
+ auto setObjCName = [&](ObjCSelector selector) {
+ // If there already is an @objc attribute, update its name.
+ if (attr) {
+ const_cast<ObjCAttr *>(attr)->setName(selector, /*implicit=*/true);
+ return;
+ }
+
+ // Otherwise, create an @objc attribute with the implicit name.
+ attr = ObjCAttr::create(tc.Context, selector, /*implicitName=*/true);
+ decl->getAttrs().add(attr);
+ };
// If this declaration overrides an @objc declaration, use its name.
if (auto overridden = decl->getOverriddenDecl()) {
@@ -1577,8 +1557,8 @@
ObjCSelector overriddenSelector = overriddenFunc->getObjCSelector();
// Determine whether there is a name conflict.
- bool shouldFixName = !attr->hasName();
- if (attr->hasName() && *attr->getName() != overriddenSelector) {
+ bool shouldFixName = !attr || !attr->hasName();
+ if (attr && attr->hasName() && *attr->getName() != overriddenSelector) {
// If the user explicitly wrote the incorrect name, complain.
if (!attr->isNameImplicit()) {
{
@@ -1598,8 +1578,7 @@
// If we have to set the name, do so.
if (shouldFixName) {
// Override the name on the attribute.
- const_cast<ObjCAttr *>(attr)->setName(overriddenSelector,
- /*implicit=*/true);
+ setObjCName(overriddenSelector);
}
return;
}
@@ -1610,8 +1589,9 @@
ObjCSelector overriddenNameAsSel(tc.Context, 0, overriddenName);
// Determine whether there is a name conflict.
- bool shouldFixName = !attr->hasName();
- if (attr->hasName() && *attr->getName() != overriddenNameAsSel) {
+ bool shouldFixName = !attr || !attr->hasName();
+ if (attr && attr->hasName() &&
+ *attr->getName() != overriddenNameAsSel) {
// If the user explicitly wrote the wrong name, complain.
if (!attr->isNameImplicit()) {
tc.diagnose(attr->AtLoc,
@@ -1629,8 +1609,7 @@
// Fix the name, if needed.
if (shouldFixName) {
- const_cast<ObjCAttr *>(attr)->setName(overriddenNameAsSel,
- /*implicit=*/true);
+ setObjCName(overriddenNameAsSel);
}
return;
}
@@ -1639,7 +1618,7 @@
// If the decl already has a name, do nothing; the protocol conformance
// checker will handle any mismatches.
- if (attr->hasName()) return;
+ if (attr && attr->hasName()) return;
// When no override determined the Objective-C name, look for
// requirements for which this declaration is a witness.
@@ -1683,8 +1662,7 @@
// If we have a name, install it via an @objc attribute.
if (requirementObjCName) {
- const_cast<ObjCAttr *>(attr)->setName(*requirementObjCName,
- /*implicit=*/true);
+ setObjCName(*requirementObjCName);
}
}
@@ -1832,6 +1810,10 @@
// Mark the attribute as having used Swift 3 inference, or create an
// implicit @objc for that purpose.
auto attr = D->getAttrs().getAttribute<ObjCAttr>();
+ if (!attr) {
+ attr = ObjCAttr::createUnnamedImplicit(TC.Context);
+ D->getAttrs().add(attr);
+ }
attr->setSwift3Inferred();
}
}
@@ -2796,50 +2778,40 @@
static bool computeIsGetterMutating(TypeChecker &TC,
AbstractStorageDecl *storage) {
- switch (storage->getStorageKind()) {
- case AbstractStorageDecl::Stored:
+ switch (storage->getReadImpl()) {
+ case ReadImplKind::Stored:
return false;
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::Computed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
+ case ReadImplKind::Get:
+ case ReadImplKind::Inherited:
return validateAccessorIsMutating(TC, storage->getGetter());
- case AbstractStorageDecl::Addressed:
+ case ReadImplKind::Address:
return validateAccessorIsMutating(TC, storage->getAddressor());
}
- llvm_unreachable("bad storage kind");
+ llvm_unreachable("bad impl kind");
}
static bool computeIsSetterMutating(TypeChecker &TC,
AbstractStorageDecl *storage) {
- switch (storage->getStorageKind()) {
- case AbstractStorageDecl::Stored:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
+ switch (storage->getWriteImpl()) {
+ case WriteImplKind::Immutable:
+ case WriteImplKind::Stored:
// Instance member setters are mutating; static property setters and
// top-level setters are not.
+ // It's important that we use this logic for "immutable" storage
+ // in order to handle initialization of let-properties.
return storage->isInstanceMember() &&
doesContextHaveValueSemantics(storage->getDeclContext());
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::Computed:
- if (auto setter = storage->getSetter())
- return validateAccessorIsMutating(TC, setter);
- return false;
+ case WriteImplKind::StoredWithObservers:
+ case WriteImplKind::InheritedWithObservers:
+ case WriteImplKind::Set:
+ return validateAccessorIsMutating(TC, storage->getSetter());
- case AbstractStorageDecl::Addressed:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- if (auto addressor = storage->getMutableAddressor())
- return validateAccessorIsMutating(TC, addressor);
- return false;
+ case WriteImplKind::MutableAddress:
+ return validateAccessorIsMutating(TC, storage->getMutableAddressor());
}
llvm_unreachable("bad storage kind");
}
@@ -2851,6 +2823,9 @@
storage->setIsGetterMutating(computeIsGetterMutating(TC, storage));
storage->setIsSetterMutating(computeIsSetterMutating(TC, storage));
+ // Add any mandatory accessors now.
+ maybeAddAccessorsToStorage(TC, storage);
+
// We can't delay validation of getters and setters on @objc properties,
// because if they never get validated at all then conformance checkers
// will complain about selector mismatches.
@@ -2861,31 +2836,16 @@
TC.validateDecl(setter);
}
- // Create a materializeForSet function if necessary. This needs to
- // happen immediately so that subclass materializeForSet functions
- // will be properly marked as overriding it.
- if (storage->hasAccessorFunctions())
- maybeAddMaterializeForSet(storage, TC);
- if (storage->isFinal())
- makeFinal(TC.Context, storage->getMaterializeForSetFunc());
-
// Everything else about the accessors can wait until finalization.
+ // This will validate all the accessors.
TC.DeclsToFinalize.insert(storage);
}
static void finalizeAbstractStorageDecl(TypeChecker &TC,
AbstractStorageDecl *storage) {
- if (auto getter = storage->getGetter())
- TC.validateDecl(getter);
- if (auto setter = storage->getSetter())
- TC.validateDecl(setter);
- if (auto materializeForSet = storage->getMaterializeForSetFunc())
- TC.validateDecl(materializeForSet);
- if (storage->hasAddressors()) {
- if (auto addressor = storage->getAddressor())
- TC.validateDecl(addressor);
- if (auto addressor = storage->getMutableAddressor())
- TC.validateDecl(addressor);
+ for (auto accessor : storage->getAllAccessors()) {
+ // Are there accessors we can safely ignore here, like maybe observers?
+ TC.validateDecl(accessor);
}
}
@@ -3082,7 +3042,7 @@
// allowed.
if (VD->hasStorage()) {
// Stored properties in protocols are diagnosed in
- // maybeAddAccessorsToVariable(), to ensure they run when a
+ // maybeAddAccessorsToStorage(), to ensure they run when a
// protocol requirement is validated but not type checked.
// Enums and extensions cannot have stored instance properties.
@@ -3138,37 +3098,9 @@
}
}
- // Synthesize accessors for lazy, all checking already been performed.
- if (VD->getAttrs().hasAttribute<LazyAttr>() && !VD->isStatic() &&
- !VD->getGetter()->hasBody())
- TC.completeLazyVarImplementation(VD);
-
- // If this is a willSet/didSet property, synthesize the getter and setter
- // decl.
- if (VD->hasObservers() &&
- (!VD->getGetter()->getBody() || !VD->getSetter()->getBody()))
- synthesizeObservingAccessors(VD, TC);
-
- // If this is a get+mutableAddress property, synthesize the setter body.
- if (VD->getStorageKind() == VarDecl::ComputedWithMutableAddress &&
- !VD->getSetter()->getBody()) {
- synthesizeSetterForMutableAddressedStorage(VD, TC);
- }
-
- // Typecheck any accessors that were previously synthesized
- // (that were previously only validated at point of synthesis)
- if (auto getter = VD->getGetter()) {
- if (getter->hasBody()) {
- TC.typeCheckDecl(getter);
- }
- }
- if (auto setter = VD->getSetter()) {
- if (setter->hasBody()) {
- TC.typeCheckDecl(setter);
- }
- }
-
TC.checkDeclAttributes(VD);
+
+ triggerAccessorSynthesis(TC, VD);
}
@@ -3251,7 +3183,7 @@
auto *varDC = var->getDeclContext();
// Non-member observing properties need an initializer.
- if (var->getStorageKind() == VarDecl::StoredWithObservers &&
+ if (var->getWriteImpl() == WriteImplKind::StoredWithObservers &&
!isTypeContext && !var->isInvalid() && !PBD->isInvalid()) {
TC.diagnose(var->getLoc(), diag::observingprop_requires_initializer);
PBD->setInvalid();
@@ -3310,6 +3242,8 @@
AccessControlChecker::checkAccessControl(TC, SD);
UsableFromInlineChecker::checkUsableFromInline(TC, SD);
+
+ triggerAccessorSynthesis(TC, SD);
}
void visitTypeAliasDecl(TypeAliasDecl *TAD) {
@@ -3325,6 +3259,8 @@
void visitAssociatedTypeDecl(AssociatedTypeDecl *AT) {
TC.validateDecl(AT);
+ TC.checkInheritanceClause(AT);
+
auto *proto = AT->getProtocol();
if (proto->isObjC()) {
TC.diagnose(AT->getLoc(),
@@ -3403,6 +3339,8 @@
TC.checkDeclAttributes(ED);
+ TC.checkInheritanceClause(ED);
+
AccessControlChecker::checkAccessControl(TC, ED);
UsableFromInlineChecker::checkUsableFromInline(TC, ED);
@@ -3434,6 +3372,8 @@
TC.checkDeclAttributes(SD);
+ TC.checkInheritanceClause(SD);
+
AccessControlChecker::checkAccessControl(TC, SD);
UsableFromInlineChecker::checkUsableFromInline(TC, SD);
@@ -3667,6 +3607,8 @@
TC.checkDeclAttributes(CD);
+ TC.checkInheritanceClause(CD);
+
AccessControlChecker::checkAccessControl(TC, CD);
UsableFromInlineChecker::checkUsableFromInline(TC, CD);
@@ -4858,8 +4800,8 @@
// Returns true if we will already diagnose a bad override
// on the property's accessor of the given kind.
auto accessorOverrideAlreadyDiagnosed = [&](AccessorKind kind) {
- FuncDecl *overrideAccessor = overrideASD->getAccessorFunction(kind);
- FuncDecl *baseAccessor = baseASD->getAccessorFunction(kind);
+ FuncDecl *overrideAccessor = overrideASD->getAccessor(kind);
+ FuncDecl *baseAccessor = baseASD->getAccessor(kind);
if (overrideAccessor && baseAccessor &&
!TC.isAvailabilitySafeForOverride(overrideAccessor, baseAccessor)) {
return true;
@@ -4920,7 +4862,8 @@
auto *overrideASD = cast<AbstractStorageDecl>(override);
// Make sure that the overriding property doesn't have storage.
- if (overrideASD->hasStorage() && !overrideASD->hasObservers()) {
+ if (overrideASD->hasStorage() &&
+ !(overrideASD->getWillSetFunc() || overrideASD->getDidSetFunc())) {
bool downgradeToWarning = false;
if (!TC.Context.isSwiftVersionAtLeast(5) &&
overrideASD->getAttrs().hasAttribute<LazyAttr>()) {
@@ -4947,7 +4890,8 @@
baseIsSettable =
baseASD->isSetterAccessibleFrom(overrideASD->getDeclContext());
}
- if (overrideASD->hasObservers() && !baseIsSettable) {
+ if (overrideASD->getWriteImpl() == WriteImplKind::InheritedWithObservers
+ && !baseIsSettable) {
TC.diagnose(overrideASD, diag::observing_readonly_property,
overrideASD->getBaseName().getIdentifier());
TC.diagnose(baseASD, diag::property_override_here);
@@ -5075,13 +5019,13 @@
overridingASD->setOverriddenDecl(baseASD);
// Make sure we get consistent overrides for the accessors as well.
- assert(baseASD->hasAccessorFunctions());
+ assert(baseASD->getGetter());
auto recordAccessorOverride = [&](AccessorKind kind) {
// We need the same accessor on both.
- auto baseAccessor = baseASD->getAccessorFunction(kind);
+ auto baseAccessor = baseASD->getAccessor(kind);
if (!baseAccessor) return;
- auto overridingAccessor = overridingASD->getAccessorFunction(kind);
+ auto overridingAccessor = overridingASD->getAccessor(kind);
if (!overridingAccessor) return;
// For setter accessors, we need the base's setter to be
@@ -5797,7 +5741,6 @@
SWIFT_DEFER { assocType->setIsBeingValidated(false); };
checkDeclAttributesEarly(assocType);
- checkInheritanceClause(assocType);
// Check the default definition, if there is one.
TypeLoc &defaultDefinition = assocType->getDefaultDefinitionLoc();
@@ -5851,8 +5794,6 @@
validateGenericTypeSignature(nominal);
nominal->setIsBeingValidated(false);
- checkInheritanceClause(D);
-
validateAttributes(*this, D);
if (auto CD = dyn_cast<ClassDecl>(nominal)) {
@@ -5933,6 +5874,7 @@
// Record inherited protocols.
resolveInheritedProtocols(proto);
+ resolveTrailingWhereClause(proto);
validateAttributes(*this, D);
@@ -6098,9 +6040,6 @@
// Perform accessor-related validation.
validateAbstractStorageDecl(*this, VD);
- // Synthesize accessors as necessary.
- maybeAddAccessorsToVariable(VD, *this);
-
break;
}
@@ -6203,6 +6142,13 @@
// to the value type.
case AccessorKind::DidSet:
case AccessorKind::WillSet:
+ // Make sure that observing accessors are marked final if in a class.
+ if (!accessor->isFinal() &&
+ accessor->getDeclContext()->getAsClassOrClassExtensionContext()) {
+ makeFinal(Context, accessor);
+ }
+ LLVM_FALLTHROUGH;
+
case AccessorKind::Set: {
auto newValueParam = valueParams->get(0);
newValueParam->setType(valueTy);
@@ -6357,12 +6303,13 @@
if (!isObjC) {
// Make this accessor @objc because its property is @objc.
isObjC = ObjCReason::Accessor;
- } else {
+ } else if (auto storageObjCAttr =
+ storage->getAttrs().getAttribute<ObjCAttr>()) {
// If @objc on the storage declaration was inferred using a
// deprecated rule, but this accessor is @objc in its own right,
// complain.
- auto storageObjCAttr = storage->getAttrs().getAttribute<ObjCAttr>();
- if (storageObjCAttr->isSwift3Inferred() &&
+ ;
+ if (storageObjCAttr && storageObjCAttr->isSwift3Inferred() &&
shouldDiagnoseObjCReason(*isObjC, Context)) {
diagnose(storage, diag::accessor_swift3_objc_inference,
storage->getDescriptiveKind(), storage->getFullName(),
@@ -6636,7 +6583,10 @@
// Destructors are always @objc, because their Objective-C entry point is
// -dealloc.
- markAsObjC(*this, DD, ObjCReason::ImplicitlyObjC);
+ if (Context.LangOpts.EnableObjCInterop)
+ markAsObjC(*this, DD, ObjCReason::ImplicitlyObjC);
+ else
+ DD->setIsObjC(false);
break;
}
@@ -6735,12 +6685,6 @@
// Perform accessor-related validation.
validateAbstractStorageDecl(*this, SD);
- // If this is a get+mutableAddress property, synthesize the setter body.
- if (SD->getStorageKind() == SubscriptDecl::ComputedWithMutableAddress &&
- !SD->getSetter()->getBody()) {
- synthesizeSetterForMutableAddressedStorage(SD, *this);
- }
-
break;
}
@@ -6840,6 +6784,7 @@
// Record inherited protocols.
resolveInheritedProtocols(proto);
+ resolveTrailingWhereClause(proto);
for (auto ATD : proto->getAssociatedTypeMembers()) {
validateDeclForNameLookup(ATD);
@@ -7363,12 +7308,6 @@
assert(!nominal->isGenericContext());
}
-llvm::TinyPtrVector<ProtocolDecl *>
-TypeChecker::getDirectConformsTo(ProtocolDecl *proto) {
- resolveInheritedProtocols(proto);
- return proto->getInheritedProtocols();
-}
-
/// Build a default initializer string for the given pattern.
///
/// This string is suitable for display in diagnostics.
@@ -8049,7 +7988,7 @@
// default-initializable.
if (isa<ClassDecl>(decl)) {
// We need to look for a default constructor.
- if (auto superTy = getSuperClassOf(decl->getDeclaredInterfaceType())) {
+ if (auto superTy = decl->getDeclaredInterfaceType()->getSuperclass()) {
// If there are no default ctors for our supertype, we can't do anything.
auto ctors = lookupConstructors(decl, superTy);
if (!ctors)
diff --git a/lib/Sema/TypeCheckError.cpp b/lib/Sema/TypeCheckError.cpp
index 6cf8938..deab8f6 100644
--- a/lib/Sema/TypeCheckError.cpp
+++ b/lib/Sema/TypeCheckError.cpp
@@ -134,6 +134,9 @@
fn = conversion->getSubExpr()->getValueProvidingExpr();
} else if (auto conversion = dyn_cast<BindOptionalExpr>(fn)) {
fn = conversion->getSubExpr()->getValueProvidingExpr();
+ // Look through optional injections
+ } else if (auto injection = dyn_cast<InjectIntoOptionalExpr>(fn)) {
+ fn = injection->getSubExpr()->getValueProvidingExpr();
// Look through function conversions.
} else if (auto conversion = dyn_cast<FunctionConversionExpr>(fn)) {
fn = conversion->getSubExpr()->getValueProvidingExpr();
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index d3f9486..7cc8154 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -461,7 +461,6 @@
void TypeChecker::revertGenericParamList(GenericParamList *genericParams) {
// Revert the inherited clause of the generic parameter list.
for (auto param : *genericParams) {
- param->setCheckedInheritanceClause(false);
for (auto &inherited : param->getInherited())
revertDependentTypeLoc(inherited);
}
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index f3c8185..d3a8308 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -206,38 +206,6 @@
return std::make_tuple(reqtType, witnessType, optAdjustment);
}
-// Given that we're looking at a stored property, should we use the
-// mutating rules for the setter or the getter when trying to match
-// the given requirement?
-static bool shouldUseSetterRequirements(AccessorKind reqtKind) {
- // We have cases for addressors here because we might reasonably
- // allow them as protocol requirements someday.
-
- switch (reqtKind) {
- case AccessorKind::Get:
- case AccessorKind::Address:
- return false;
-
- case AccessorKind::Set:
- case AccessorKind::MutableAddress:
- case AccessorKind::MaterializeForSet:
- return true;
-
- case AccessorKind::WillSet:
- case AccessorKind::DidSet:
- llvm_unreachable("willSet/didSet protocol requirement?");
- }
- llvm_unreachable("bad accessor kind");
-}
-
-static AccessorDecl *getAddressorForRequirement(AbstractStorageDecl *witness,
- AccessorKind reqtKind) {
- assert(witness->hasAddressors());
- if (shouldUseSetterRequirements(reqtKind))
- return witness->getMutableAddressor();
- return witness->getAddressor();
-}
-
// Verify that the mutating bit is correct between a protocol requirement and a
// witness. This returns true on invalid.
static bool checkMutating(FuncDecl *requirement, FuncDecl *witness,
@@ -257,31 +225,70 @@
else {
auto reqtAsAccessor = cast<AccessorDecl>(requirement);
auto storage = cast<AbstractStorageDecl>(witnessDecl);
- switch (storage->getStorageKind()) {
- // A stored property on a value type will have a mutating setter
- // and a non-mutating getter.
- case AbstractStorageDecl::Stored:
- witnessMutating = reqtAsAccessor->isInstanceMember() &&
- shouldUseSetterRequirements(reqtAsAccessor->getAccessorKind());
+ auto isReadMutating = [&] {
+ switch (storage->getReadImpl()) {
+ case ReadImplKind::Stored:
+ return false;
+ case ReadImplKind::Address:
+ return storage->getAddressor()->isMutating();
+ case ReadImplKind::Inherited:
+ case ReadImplKind::Get:
+ llvm_unreachable("should have a getter");
+ }
+ };
+
+ auto isStoredSetterMutating = [&] {
+ // A stored property on a value type will have a mutating setter
+ // and a non-mutating getter.
+ return reqtAsAccessor->isInstanceMember();
+ };
+
+ auto isWriteMutating = [&] {
+ switch (storage->getWriteImpl()) {
+ case WriteImplKind::Stored:
+ return isStoredSetterMutating();
+ case WriteImplKind::MutableAddress:
+ return storage->getMutableAddressor()->isMutating();
+ case WriteImplKind::Immutable:
+ llvm_unreachable("asking for setter for immutable storage");
+ case WriteImplKind::Set:
+ case WriteImplKind::StoredWithObservers:
+ case WriteImplKind::InheritedWithObservers:
+ llvm_unreachable("should have a setter");
+ }
+ };
+
+ auto isReadWriteMutating = [&] {
+ switch (storage->getReadWriteImpl()) {
+ case ReadWriteImplKind::Stored:
+ return isStoredSetterMutating();
+ case ReadWriteImplKind::MutableAddress:
+ return storage->getMutableAddressor()->isMutating();
+ case ReadWriteImplKind::MaterializeToTemporary:
+ return isReadMutating() || isWriteMutating();
+ case ReadWriteImplKind::Immutable:
+ llvm_unreachable("asking for setter for immutable storage");
+ case ReadWriteImplKind::MaterializeForSet:
+ llvm_unreachable("should have a materializeForSet");
+ }
+ };
+
+ switch (reqtAsAccessor->getAccessorKind()) {
+ case AccessorKind::Get:
+ witnessMutating = isReadMutating();
break;
- // For an addressed property, consider the appropriate addressor.
- case AbstractStorageDecl::Addressed: {
- AccessorDecl *addressor =
- getAddressorForRequirement(storage, reqtAsAccessor->getAccessorKind());
- witnessMutating = addressor->isMutating();
+ case AccessorKind::Set:
+ witnessMutating = isWriteMutating();
break;
- }
- case AbstractStorageDecl::StoredWithObservers:
- case AbstractStorageDecl::StoredWithTrivialAccessors:
- case AbstractStorageDecl::InheritedWithObservers:
- case AbstractStorageDecl::AddressedWithTrivialAccessors:
- case AbstractStorageDecl::AddressedWithObservers:
- case AbstractStorageDecl::ComputedWithMutableAddress:
- case AbstractStorageDecl::Computed:
- llvm_unreachable("missing witness reference for kind with accessors");
+ case AccessorKind::MaterializeForSet:
+ witnessMutating = isReadWriteMutating();
+ break;
+
+ default:
+ llvm_unreachable("unexpected accessor requirement");
}
}
@@ -343,6 +350,48 @@
return subscript->getIndices();
}
+// Find a standin declaration to place the diagnostic at for the
+// given accessor kind.
+static ValueDecl *getStandinForAccessor(AbstractStorageDecl *witnessStorage,
+ AccessorKind requirementKind) {
+ auto getExplicitAccessor = [&](AccessorKind kind) -> AccessorDecl* {
+ if (auto accessor = witnessStorage->getAccessor(kind)) {
+ if (!accessor->isImplicit())
+ return accessor;
+ }
+ return nullptr;
+ };
+
+ // If the storage actually explicitly provides that accessor, great.
+ if (auto accessor = getExplicitAccessor(requirementKind))
+ return accessor;
+
+ // If it didn't, check to see if it provides something else that corresponds
+ // to the requirement.
+ switch (requirementKind) {
+ case AccessorKind::Get:
+ if (auto addressor = getExplicitAccessor(AccessorKind::Address))
+ return addressor;
+ break;
+
+ case AccessorKind::MaterializeForSet:
+ if (auto setter = getExplicitAccessor(AccessorKind::Set))
+ return setter;
+ LLVM_FALLTHROUGH;
+
+ case AccessorKind::Set:
+ if (auto addressor = getExplicitAccessor(AccessorKind::MutableAddress))
+ return addressor;
+ break;
+
+ default:
+ break;
+ }
+
+ // Otherwise, just diagnose starting at the storage declaration itself.
+ return witnessStorage;
+}
+
RequirementMatch
swift::matchWitness(
TypeChecker &tc,
@@ -420,34 +469,15 @@
!witness->isSettable(witness->getDeclContext()))
return RequirementMatch(witness, MatchKind::SettableConflict);
- // Find a standin declaration to place the diagnostic at for the
- // given accessor kind.
- auto getStandinForAccessor = [&](AccessorKind kind) -> ValueDecl* {
- // If the witness actually explicitly provided that accessor,
- // then great.
- if (auto accessor = witnessASD->getAccessorFunction(kind))
- if (!accessor->isImplicit())
- return accessor;
-
- // If it didn't, check to see if it provides something else.
- if (witnessASD->hasAddressors()) {
- return getAddressorForRequirement(witnessASD, kind);
- }
-
- // Otherwise, just diagnose starting at the storage declaration
- // itself.
- return witnessASD;
- };
-
// Validate that the 'mutating' bit lines up for getters and setters.
if (checkMutating(reqASD->getGetter(), witnessASD->getGetter(),
witnessASD))
- return RequirementMatch(getStandinForAccessor(AccessorKind::Get),
+ return RequirementMatch(getStandinForAccessor(witnessASD, AccessorKind::Get),
MatchKind::MutatingConflict);
if (req->isSettable(req->getDeclContext()) &&
checkMutating(reqASD->getSetter(), witnessASD->getSetter(), witnessASD))
- return RequirementMatch(getStandinForAccessor(AccessorKind::Set),
+ return RequirementMatch(getStandinForAccessor(witnessASD, AccessorKind::Set),
MatchKind::MutatingConflict);
// Decompose the parameters for subscript declarations.
@@ -3115,7 +3145,7 @@
for (auto candidate : candidates) {
// Skip nested generic types.
if (auto *genericDecl = dyn_cast<GenericTypeDecl>(candidate.Member))
- if (genericDecl->getGenericParams())
+ if (genericDecl->isGeneric())
continue;
// Skip typealiases with an unbound generic type as their underlying type.
@@ -4924,7 +4954,7 @@
auto *storageReq = dyn_cast<AbstractStorageDecl>(req);
if (!storageReq)
continue;
- req = storageReq->getAccessorFunction(*accessorKind);
+ req = storageReq->getAccessor(*accessorKind);
if (!req)
continue;
}
@@ -4942,10 +4972,10 @@
auto *storageFound = dyn_cast_or_null<AbstractStorageDecl>(found);
if (!storageReq || !storageFound)
continue;
- req = storageReq->getAccessorFunction(*accessorKind);
+ req = storageReq->getAccessor(*accessorKind);
if (!req)
continue;
- found = storageFound->getAccessorFunction(*accessorKind);
+ found = storageFound->getAccessor(*accessorKind);
}
// Determine whether the witness for this conformance is in fact
diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp
new file mode 100644
index 0000000..699a560
--- /dev/null
+++ b/lib/Sema/TypeCheckRequestFunctions.cpp
@@ -0,0 +1,153 @@
+//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+#include "GenericTypeResolver.h"
+#include "TypeChecker.h"
+#include "swift/AST/TypeCheckRequests.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/ExistentialLayout.h"
+#include "swift/AST/TypeLoc.h"
+#include "swift/AST/Types.h"
+#include "swift/Subsystems.h"
+
+using namespace swift;
+
+Type InheritedTypeRequest::evaluate(
+ Evaluator &evaluator,
+ llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
+ unsigned index) const {
+ // Figure out how to resolve types.
+ TypeResolutionOptions options;
+ DeclContext *dc;
+ if (auto typeDecl = decl.dyn_cast<TypeDecl *>()) {
+ if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
+ dc = nominal;
+ options |= TypeResolutionFlags::GenericSignature;
+ options |= TypeResolutionFlags::InheritanceClause;
+ options |= TypeResolutionFlags::AllowUnavailableProtocol;
+ } else {
+ dc = typeDecl->getDeclContext();
+
+ if (isa<GenericTypeParamDecl>(typeDecl)) {
+ // For generic parameters, we want name lookup to look at just the
+ // signature of the enclosing entity.
+ if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
+ dc = nominal;
+ options |= TypeResolutionFlags::GenericSignature;
+ } else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
+ dc = ext;
+ options |= TypeResolutionFlags::GenericSignature;
+ } else if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) {
+ dc = func;
+ options |= TypeResolutionFlags::GenericSignature;
+ } else if (!dc->isModuleScopeContext()) {
+ // Skip the generic parameter's context entirely.
+ dc = dc->getParent();
+ }
+ }
+ }
+ } else {
+ auto ext = decl.get<ExtensionDecl *>();
+ dc = ext;
+ options |= TypeResolutionFlags::GenericSignature;
+ options |= TypeResolutionFlags::InheritanceClause;
+ options |= TypeResolutionFlags::AllowUnavailableProtocol;
+ }
+
+ ProtocolRequirementTypeResolver protoResolver;
+ GenericTypeToArchetypeResolver archetypeResolver(dc);
+ GenericTypeResolver *resolver;
+ if (isa<ProtocolDecl>(dc)) {
+ resolver = &protoResolver;
+ } else {
+ resolver = &archetypeResolver;
+ }
+
+ // FIXME: Hack for calls through here when we have no type checker.
+ auto lazyResolver = dc->getASTContext().getLazyResolver();
+ if (!lazyResolver) return ErrorType::get(dc->getASTContext());
+
+ TypeChecker &tc = *static_cast<TypeChecker *>(lazyResolver);
+ TypeLoc &typeLoc = getTypeLoc(decl, index);
+
+ Type inheritedType =
+ tc.resolveType(typeLoc.getTypeRepr(), dc, options, resolver);
+ if (inheritedType && !isa<ProtocolDecl>(dc))
+ inheritedType = inheritedType->mapTypeOutOfContext();
+ return inheritedType ? inheritedType : ErrorType::get(tc.Context);
+}
+
+Type SuperclassTypeRequest::evaluate(Evaluator &evaluator,
+ NominalTypeDecl *nominalDecl) const {
+ assert(isa<ClassDecl>(nominalDecl) || isa<ProtocolDecl>(nominalDecl));
+
+ for (unsigned int idx : indices(nominalDecl->getInherited())) {
+ Type inheritedType = evaluator(InheritedTypeRequest{nominalDecl, idx});
+ if (!inheritedType) continue;
+
+ // If we found a class, return it.
+ if (inheritedType->getClassOrBoundGenericClass()) {
+ if (inheritedType->hasArchetype())
+ return inheritedType->mapTypeOutOfContext();
+
+ return inheritedType;
+ }
+
+ // If we found an existential with a superclass bound, return it.
+ if (inheritedType->isExistentialType()) {
+ if (auto superclassType =
+ inheritedType->getExistentialLayout().superclass) {
+ if (superclassType->getClassOrBoundGenericClass()) {
+ if (superclassType->hasArchetype())
+ return superclassType->mapTypeOutOfContext();
+
+ return superclassType;
+ }
+ }
+ }
+ }
+
+ // No superclass.
+ return Type();
+}
+
+Type EnumRawTypeRequest::evaluate(Evaluator &evaluator,
+ EnumDecl *enumDecl) const {
+ for (unsigned int idx : indices(enumDecl->getInherited())) {
+ Type inheritedType = evaluator(InheritedTypeRequest{enumDecl, idx});
+ if (!inheritedType) continue;
+
+ // Skip existential types.
+ if (inheritedType->isExistentialType()) continue;
+
+ // We found a raw type; return it.
+ if (inheritedType->hasArchetype())
+ return inheritedType->mapTypeOutOfContext();
+
+ return inheritedType;
+ }
+
+ // No raw type.
+ return Type();
+}
+
+// Define request evaluation functions for each of the type checker requests.
+static AbstractRequestFunction *typeCheckerRequestFunctions[] = {
+#define SWIFT_TYPEID(Name) \
+ reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
+#include "swift/AST/TypeCheckerTypeIDZone.def"
+#undef SWIFT_TYPEID
+};
+
+void swift::registerTypeCheckerRequestFunctions(Evaluator &evaluator) {
+ evaluator.registerRequestFunctions(SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE,
+ typeCheckerRequestFunctions);
+}
diff --git a/lib/Sema/TypeCheckRequests.cpp b/lib/Sema/TypeCheckRequests.cpp
deleted file mode 100644
index 079537c..0000000
--- a/lib/Sema/TypeCheckRequests.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-#include "GenericTypeResolver.h"
-#include "TypeChecker.h"
-#include "swift/Sema/TypeCheckRequests.h"
-#include "swift/AST/Decl.h"
-#include "swift/AST/ExistentialLayout.h"
-#include "swift/AST/TypeLoc.h"
-#include "swift/AST/Types.h"
-using namespace swift;
-
-namespace swift {
-// Implement the type checker type zone (zone 10).
-#define SWIFT_TYPEID_ZONE 10
-#define SWIFT_TYPEID_HEADER "swift/Sema/TypeCheckerTypeIDZone.def"
-#include "swift/Basic/ImplementTypeIDZone.h"
-
-}
-
-void swift::simple_display(
- llvm::raw_ostream &out,
- const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value) {
- if (auto type = value.dyn_cast<TypeDecl *>()) {
- type->dumpRef(out);
- return;
- }
-
- auto ext = value.get<ExtensionDecl *>();
- out << "extension of ";
- ext->getAsNominalTypeOrNominalTypeExtensionContext()->dumpRef(out);
-}
-
-//----------------------------------------------------------------------------//
-// Inherited type computation.
-//----------------------------------------------------------------------------//
-
-TypeLoc &InheritedTypeRequest::getTypeLoc(
- llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
- unsigned index) const {
- if (auto typeDecl = decl.dyn_cast<TypeDecl *>())
- return typeDecl->getInherited()[index];
-
- return decl.get<ExtensionDecl *>()->getInherited()[index];
-}
-
-Type InheritedTypeRequest::operator()(
- Evaluator &evaluator,
- llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
- unsigned index) const {
- // Figure out how to resolve types.
- TypeResolutionOptions options;
- DeclContext *dc;
- if (auto typeDecl = decl.dyn_cast<TypeDecl *>()) {
- if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
- dc = nominal;
- options |= TypeResolutionFlags::GenericSignature;
- options |= TypeResolutionFlags::InheritanceClause;
- options |= TypeResolutionFlags::AllowUnavailableProtocol;
- } else {
- dc = typeDecl->getDeclContext();
-
- if (isa<GenericTypeParamDecl>(typeDecl)) {
- // For generic parameters, we want name lookup to look at just the
- // signature of the enclosing entity.
- if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
- dc = nominal;
- options |= TypeResolutionFlags::GenericSignature;
- } else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
- dc = ext;
- options |= TypeResolutionFlags::GenericSignature;
- } else if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) {
- dc = func;
- options |= TypeResolutionFlags::GenericSignature;
- } else if (!dc->isModuleScopeContext()) {
- // Skip the generic parameter's context entirely.
- dc = dc->getParent();
- }
- }
- }
- } else {
- auto ext = decl.get<ExtensionDecl *>();
- dc = ext;
- options |= TypeResolutionFlags::GenericSignature;
- options |= TypeResolutionFlags::InheritanceClause;
- options |= TypeResolutionFlags::AllowUnavailableProtocol;
- }
-
- ProtocolRequirementTypeResolver protoResolver;
- GenericTypeToArchetypeResolver archetypeResolver(dc);
- GenericTypeResolver *resolver;
- if (isa<ProtocolDecl>(dc)) {
- resolver = &protoResolver;
- } else {
- resolver = &archetypeResolver;
- }
-
- // FIXME: Hack for calls through here when we have no type checker.
- auto lazyResolver = dc->getASTContext().getLazyResolver();
- if (!lazyResolver) return ErrorType::get(dc->getASTContext());
-
- TypeChecker &tc = *static_cast<TypeChecker *>(lazyResolver);
- TypeLoc &typeLoc = getTypeLoc(decl, index);
-
- Type inheritedType =
- tc.resolveType(typeLoc.getTypeRepr(), dc, options, resolver);
- if (inheritedType && !isa<ProtocolDecl>(dc))
- inheritedType = inheritedType->mapTypeOutOfContext();
- return inheritedType ? inheritedType : ErrorType::get(tc.Context);
-}
-
-void InheritedTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
- const auto &storage = getStorage();
- auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
- diags.diagnose(typeLoc.getLoc(), diag::circular_reference);
-}
-
-void InheritedTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
- const auto &storage = getStorage();
- auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
- diags.diagnose(typeLoc.getLoc(), diag::circular_reference_through);
-}
-
-Optional<Type> InheritedTypeRequest::getCachedResult() const {
- const auto &storage = getStorage();
- auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
- if (typeLoc.wasValidated())
- return typeLoc.getType();
-
- return None;
-}
-
-void InheritedTypeRequest::cacheResult(Type value) const {
- const auto &storage = getStorage();
- auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
- typeLoc.setType(value);
-}
-
-//----------------------------------------------------------------------------//
-// Superclass computation.
-//----------------------------------------------------------------------------//
-Type SuperclassTypeRequest::operator()(Evaluator &evaluator,
- ClassDecl *classDecl) const {
- for (unsigned int idx : indices(classDecl->getInherited())) {
- Type inheritedType = evaluator(InheritedTypeRequest{classDecl, idx});
- if (!inheritedType) continue;
-
- // If we found a class, return it.
- if (inheritedType->getClassOrBoundGenericClass()) {
- if (inheritedType->hasArchetype())
- return inheritedType->mapTypeOutOfContext();
-
- return inheritedType;
- }
-
- // If we found an existential with a superclass bound, return it.
- if (inheritedType->isExistentialType()) {
- if (auto superclassType =
- inheritedType->getExistentialLayout().superclass) {
- if (superclassType->getClassOrBoundGenericClass()) {
- if (superclassType->hasArchetype())
- return superclassType->mapTypeOutOfContext();
-
- return superclassType;
- }
- }
- }
- }
-
- // No superclass.
- return Type();
-}
-
-void SuperclassTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
- // FIXME: Improve this diagnostic.
- auto classDecl = std::get<0>(getStorage());
- std::string className = "'" + std::string(classDecl->getNameStr()) + "'";
- diags.diagnose(classDecl, diag::circular_class_inheritance, className);
-}
-
-void SuperclassTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
- auto classDecl = std::get<0>(getStorage());
- // FIXME: Customize this further.
- diags.diagnose(classDecl, diag::circular_reference_through);
-}
-
-Optional<Type> SuperclassTypeRequest::getCachedResult() const {
- auto classDecl = std::get<0>(getStorage());
- if (classDecl->LazySemanticInfo.Superclass.getInt())
- return classDecl->LazySemanticInfo.Superclass.getPointer();
-
- return None;
-}
-
-void SuperclassTypeRequest::cacheResult(Type value) const {
- auto classDecl = std::get<0>(getStorage());
- classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
-}
-
-//----------------------------------------------------------------------------//
-// Enum raw type computation.
-//----------------------------------------------------------------------------//
-Type EnumRawTypeRequest::operator()(Evaluator &evaluator,
- EnumDecl *enumDecl) const {
- for (unsigned int idx : indices(enumDecl->getInherited())) {
- Type inheritedType = evaluator(InheritedTypeRequest{enumDecl, idx});
- if (!inheritedType) continue;
-
- // Skip existential types.
- if (inheritedType->isExistentialType()) continue;
-
- // We found a raw type; return it.
- if (inheritedType->hasArchetype())
- return inheritedType->mapTypeOutOfContext();
-
- return inheritedType;
- }
-
- // No raw type.
- return Type();
-}
-
-void EnumRawTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
- // FIXME: Improve this diagnostic.
- auto enumDecl = std::get<0>(getStorage());
- std::string className = "'" + std::string(enumDecl->getNameStr()) + "'";
- diags.diagnose(enumDecl, diag::circular_enum_inheritance, className);
-}
-
-void EnumRawTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
- auto enumDecl = std::get<0>(getStorage());
- // FIXME: Customize this further.
- diags.diagnose(enumDecl, diag::circular_reference_through);
-}
-
-Optional<Type> EnumRawTypeRequest::getCachedResult() const {
- auto enumDecl = std::get<0>(getStorage());
- if (enumDecl->LazySemanticInfo.RawType.getInt())
- return enumDecl->LazySemanticInfo.RawType.getPointer();
-
- return None;
-}
-
-void EnumRawTypeRequest::cacheResult(Type value) const {
- auto enumDecl = std::get<0>(getStorage());
- enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
-}
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 4045d5a..cbfa4eb 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -954,7 +954,7 @@
auto decl = parentType->getAnyNominal();
if (decl) {
tc.diagnose(decl->getLoc(), diag::circular_class_inheritance,
- decl->getNameStr());
+ decl->getName());
return ErrorType::get(tc.Context);
}
}
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 0bd9268..3ad3629 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -17,6 +17,7 @@
#include "swift/Subsystems.h"
#include "TypeChecker.h"
+#include "CodeSynthesis.h"
#include "MiscDiagnostics.h"
#include "GenericTypeResolver.h"
#include "swift/AST/ASTWalker.h"
@@ -484,6 +485,17 @@
TC.validateDecl(decl);
}
+ // Synthesize any necessary function bodies.
+ // FIXME: If we're not planning to run SILGen, this is wasted effort.
+ while (!TC.FunctionsToSynthesize.empty()) {
+ auto function = TC.FunctionsToSynthesize.back().second;
+ TC.FunctionsToSynthesize.pop_back();
+ if (function.getDecl()->isInvalid() || TC.Context.hadError())
+ continue;
+
+ TC.synthesizeFunctionBody(function);
+ }
+
// Validate any referenced declarations for SIL's purposes.
// Note: if we ever start putting extension members in vtables, we'll need
// to validate those members too.
@@ -523,6 +535,7 @@
} while (currentFunctionIdx < TC.definedFunctions.size() ||
currentExternalDef < TC.Context.ExternalDefinitions.size() ||
currentSynthesizedDecl < SF.SynthesizedDecls.size() ||
+ !TC.FunctionsToSynthesize.empty() ||
!TC.DeclsToFinalize.empty() ||
!TC.ConformanceContexts.empty() ||
!TC.DelayedRequirementSignatures.empty() ||
@@ -789,7 +802,7 @@
return TypeChecker(Ctx).handleSILGenericParams(genericParams, DC);
}
-bool swift::typeCheckCompletionDecl(Decl *D) {
+void swift::typeCheckCompletionDecl(Decl *D) {
auto &Ctx = D->getASTContext();
// Set up a diagnostics engine that swallows diagnostics.
@@ -799,8 +812,7 @@
if (auto ext = dyn_cast<ExtensionDecl>(D))
TC.validateExtension(ext);
else
- TC.typeCheckDecl(D);
- return true;
+ TC.validateDecl(cast<ValueDecl>(D));
}
static Optional<Type> getTypeOfCompletionContextExpr(
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 2da25c8..c30e3a9 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -43,6 +43,7 @@
class TypeChecker;
class TypoCorrectionResults;
class ExprPattern;
+class SynthesizedFunction;
namespace constraints {
enum class ConstraintKind : char;
@@ -744,6 +745,9 @@
/// we can hand them off to SILGen etc.
llvm::SetVector<ValueDecl *> DeclsToFinalize;
+ /// The list of functions that need to have their bodies synthesized.
+ llvm::MapVector<FuncDecl*, SynthesizedFunction> FunctionsToSynthesize;
+
/// The list of protocols that need their requirement signatures computed,
/// because they were first validated by validateDeclForNameLookup(),
/// which skips this step.
@@ -1371,7 +1375,6 @@
virtual void resolveExtension(ExtensionDecl *ext) override {
validateExtension(ext);
- checkInheritanceClause(ext);
}
virtual void resolveExtensionForConformanceConstruction(
ExtensionDecl *ext,
@@ -1544,12 +1547,6 @@
GenericRequirementsCheckListener *listener = nullptr,
SubstOptions options = None);
- /// Get the superclass of the given class.
- Type getSuperclass(const ClassDecl *classDecl) override;
-
- /// Get the raw type of the given enum.
- Type getRawType(EnumDecl *enumDecl) override;
-
/// Resolve the inherited protocols of a given protocol.
void resolveInheritedProtocols(ProtocolDecl *protocol);
@@ -1558,19 +1555,12 @@
void validateWhereClauses(ProtocolDecl *protocol,
GenericTypeResolver *resolver);
- /// Get a specific inherited type from the given declaration.
- Type getInheritedType(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
- unsigned index) override;
-
void resolveTrailingWhereClause(ProtocolDecl *proto) override;
/// Check the inheritance clause of the given declaration.
void checkInheritanceClause(Decl *decl,
GenericTypeResolver *resolver = nullptr);
- /// Retrieve the set of inherited protocols for this protocol type.
- llvm::TinyPtrVector<ProtocolDecl *> getDirectConformsTo(ProtocolDecl *proto);
-
/// Diagnose if the class has no designated initializers.
void maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl);
@@ -1590,6 +1580,8 @@
void synthesizeWitnessAccessorsForStorage(AbstractStorageDecl *requirement,
AbstractStorageDecl *storage);
+ void synthesizeFunctionBody(SynthesizedFunction fn);
+
/// Provide storage and accessor implementations for the given property,
/// which must be lazy.
void completeLazyVarImplementation(VarDecl *lazyVar);
@@ -2079,6 +2071,11 @@
void checkConformancesInContext(DeclContext *dc,
IterableDeclContext *idc);
+ /// Check that the type of the given property conforms to NSCopying.
+ ///
+ /// Return true if there was an error.
+ bool checkConformanceToNSCopying(VarDecl *var);
+
/// Find the @objc requirement that are witnessed by the given
/// declaration.
///
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index cd0f9ee..3e018e6 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2119,31 +2119,67 @@
return None;
}
-static Optional<AbstractStorageDecl::StorageKindTy>
-getActualStorageKind(unsigned raw) {
- switch (serialization::StorageKind(raw)) {
-#define CASE(KIND) \
- case serialization::StorageKind::KIND: \
- return AbstractStorageDecl::KIND;
+static Optional<swift::ReadImplKind>
+getActualReadImplKind(unsigned rawKind) {
+ switch (serialization::ReadImplKind(rawKind)) {
+#define CASE(KIND) \
+ case serialization::ReadImplKind::KIND: \
+ return swift::ReadImplKind::KIND;
CASE(Stored)
- CASE(StoredWithTrivialAccessors)
+ CASE(Get)
+ CASE(Inherited)
+ CASE(Address)
+#undef CASE
+ }
+ return None;
+}
+
+static Optional<swift::WriteImplKind>
+getActualWriteImplKind(unsigned rawKind) {
+ switch (serialization::WriteImplKind(rawKind)) {
+#define CASE(KIND) \
+ case serialization::WriteImplKind::KIND: \
+ return swift::WriteImplKind::KIND;
+ CASE(Immutable)
+ CASE(Stored)
+ CASE(Set)
CASE(StoredWithObservers)
CASE(InheritedWithObservers)
- CASE(Computed)
- CASE(ComputedWithMutableAddress)
- CASE(Addressed)
- CASE(AddressedWithTrivialAccessors)
- CASE(AddressedWithObservers)
+ CASE(MutableAddress)
+#undef CASE
+ }
+ return None;
+}
+
+static Optional<swift::ReadWriteImplKind>
+getActualReadWriteImplKind(unsigned rawKind) {
+ switch (serialization::ReadWriteImplKind(rawKind)) {
+#define CASE(KIND) \
+ case serialization::ReadWriteImplKind::KIND: \
+ return swift::ReadWriteImplKind::KIND;
+ CASE(Immutable)
+ CASE(Stored)
+ CASE(MaterializeForSet)
+ CASE(MutableAddress)
+ CASE(MaterializeToTemporary)
#undef CASE
}
return None;
}
void ModuleFile::configureStorage(AbstractStorageDecl *decl,
- unsigned rawStorageKind,
+ uint8_t rawReadImplKind,
+ uint8_t rawWriteImplKind,
+ uint8_t rawReadWriteImplKind,
AccessorRecord &rawIDs) {
- auto storageKind = getActualStorageKind(rawStorageKind);
- if (!storageKind) return;
+ auto readImpl = getActualReadImplKind(rawReadImplKind);
+ if (!readImpl) return;
+
+ auto writeImpl = getActualWriteImplKind(rawWriteImplKind);
+ if (!writeImpl) return;
+
+ auto readWriteImpl = getActualReadWriteImplKind(rawReadWriteImplKind);
+ if (!readWriteImpl) return;
SmallVector<AccessorDecl*, 8> accessors;
for (DeclID id : rawIDs.IDs) {
@@ -2152,13 +2188,14 @@
accessors.push_back(accessor);
}
- if (*storageKind == AbstractStorageDecl::Stored && accessors.empty())
+ auto implInfo = StorageImplInfo(*readImpl, *writeImpl, *readWriteImpl);
+ if (implInfo.isSimpleStored() && accessors.empty())
return;
// We currently don't serialize these locations.
SourceLoc beginLoc, endLoc;
- decl->setAccessors(*storageKind, beginLoc, accessors, endLoc);
+ decl->setAccessors(implInfo, beginLoc, accessors, endLoc);
}
template <typename T, typename ...Args>
@@ -2301,7 +2338,6 @@
tl = TypeLoc::withoutLoc(getType(rawID));
});
nominal->setInherited(inheritedTypes);
- nominal->setCheckedInheritanceClause();
};
while (true) {
@@ -2590,7 +2626,6 @@
if (isImplicit)
alias->setImplicit();
- alias->setCheckedInheritanceClause();
break;
}
@@ -2662,8 +2697,6 @@
if (isImplicit)
assocType->setImplicit();
- assocType->setCheckedInheritanceClause();
-
// Overridden associated types.
SmallVector<AssociatedTypeDecl *, 2> overriddenAssocTypes;
for (auto overriddenID : rawOverriddenIDs) {
@@ -2681,13 +2714,14 @@
IdentifierID nameID;
DeclContextID contextID;
bool isImplicit;
+ bool isObjC;
GenericEnvironmentID genericEnvID;
uint8_t rawAccessLevel;
unsigned numConformances;
ArrayRef<uint64_t> rawInheritedIDs;
decls_block::StructLayout::readRecord(scratch, nameID, contextID,
- isImplicit, genericEnvID,
+ isImplicit, isObjC, genericEnvID,
rawAccessLevel,
numConformances,
rawInheritedIDs);
@@ -2717,6 +2751,7 @@
if (isImplicit)
theStruct->setImplicit();
+ theStruct->setIsObjC(isObjC);
theStruct->computeType();
@@ -2856,6 +2891,7 @@
if (isImplicit)
ctor->setImplicit();
+ ctor->setIsObjC(isObjC);
if (hasStubImplementation)
ctor->setStubImplementation(true);
if (initKind.hasValue())
@@ -2882,7 +2918,8 @@
bool isImplicit, isObjC, isStatic, hasNonPatternBindingInit;
bool isGetterMutating, isSetterMutating;
unsigned rawSpecifier, numAccessors;
- uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
+ uint8_t readImpl, writeImpl, readWriteImpl;
+ uint8_t rawAccessLevel, rawSetterAccessLevel;
TypeID interfaceTypeID;
AccessorRecord accessors;
DeclID overriddenID;
@@ -2892,7 +2929,8 @@
isImplicit, isObjC, isStatic, rawSpecifier,
hasNonPatternBindingInit,
isGetterMutating, isSetterMutating,
- storageKind, numAccessors,
+ readImpl, writeImpl, readWriteImpl,
+ numAccessors,
interfaceTypeID,
overriddenID,
rawAccessLevel, rawSetterAccessLevel,
@@ -2920,20 +2958,9 @@
DeclDeserializationError::Flags flags;
if (!isStatic) {
- switch ((StorageKind)storageKind) {
- case StorageKind::Stored:
- case StorageKind::StoredWithObservers:
- case StorageKind::StoredWithTrivialAccessors:
+ auto actualReadImpl = getActualReadImplKind(readImpl);
+ if (actualReadImpl && *actualReadImpl == ReadImplKind::Stored) {
flags |= DeclDeserializationError::Flag::NeedsFieldOffsetVectorEntry;
- break;
-
- case StorageKind::Addressed:
- case StorageKind::AddressedWithObservers:
- case StorageKind::AddressedWithTrivialAccessors:
- case StorageKind::Computed:
- case StorageKind::ComputedWithMutableAddress:
- case StorageKind::InheritedWithObservers:
- break;
}
}
@@ -2968,7 +2995,7 @@
AddAttribute(
new (ctx) ReferenceOwnershipAttr(referenceStorage->getOwnership()));
- configureStorage(var, storageKind, accessors);
+ configureStorage(var, readImpl, writeImpl, readWriteImpl, accessors);
if (auto accessLevel = getActualAccessLevel(rawAccessLevel)) {
var->setAccess(*accessLevel);
@@ -2988,6 +3015,7 @@
if (isImplicit)
var->setImplicit();
+ var->setIsObjC(isObjC);
if (auto overriddenVar = cast_or_null<VarDecl>(overridden.get())) {
var->setOverriddenDecl(overriddenVar);
@@ -3123,7 +3151,7 @@
// into this code. When we come out, don't create the accessor twice.
// TODO: find some better way of breaking this cycle, like lazily
// deserializing the accessors.
- if (auto accessor = storage->getAccessorFunction(accessorKind))
+ if (auto accessor = storage->getAccessor(accessorKind))
return accessor;
}
@@ -3258,6 +3286,7 @@
fn->setStatic(isStatic);
if (isImplicit)
fn->setImplicit();
+ fn->setIsObjC(isObjC);
fn->setDynamicSelf(hasDynamicSelf);
fn->setForcedStaticDispatch(hasForcedStaticDispatch);
fn->setNeedsNewVTableEntry(needsNewVTableEntry);
@@ -3336,14 +3365,15 @@
DeclContextID contextID;
bool isImplicit, isClassBounded, isObjC, existentialTypeSupported;
GenericEnvironmentID genericEnvID;
+ TypeID superclassID;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> rawInheritedIDs;
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
isImplicit, isClassBounded, isObjC,
existentialTypeSupported,
- genericEnvID, rawAccessLevel,
- rawInheritedIDs);
+ genericEnvID, superclassID,
+ rawAccessLevel, rawInheritedIDs);
auto DC = getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -3354,6 +3384,7 @@
/*TrailingWhere=*/nullptr);
declOrOffset = proto;
+ proto->setSuperclass(getType(superclassID));
proto->setRequiresClass(isClassBounded);
proto->setExistentialTypeSupported(existentialTypeSupported);
@@ -3374,6 +3405,8 @@
if (isImplicit)
proto->setImplicit();
+ proto->setIsObjC(isObjC);
+
proto->computeType();
proto->setCircularityCheck(CircularityCheck::Checked);
@@ -3555,6 +3588,7 @@
theClass->setAddedImplicitInitializers();
if (isImplicit)
theClass->setImplicit();
+ theClass->setIsObjC(isObjC);
theClass->setSuperclass(getType(superclassID));
if (requiresStoredPropertyInits)
theClass->setRequiresStoredPropertyInits(true);
@@ -3581,6 +3615,7 @@
IdentifierID nameID;
DeclContextID contextID;
bool isImplicit;
+ bool isObjC;
GenericEnvironmentID genericEnvID;
TypeID rawTypeID;
uint8_t rawAccessLevel;
@@ -3588,8 +3623,8 @@
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
- isImplicit, genericEnvID, rawTypeID,
- rawAccessLevel,
+ isImplicit, isObjC, genericEnvID,
+ rawTypeID, rawAccessLevel,
numConformances, numInheritedTypes,
rawInheritedAndDependencyIDs);
@@ -3627,6 +3662,8 @@
if (isImplicit)
theEnum->setImplicit();
+ theEnum->setIsObjC(isObjC);
+
theEnum->setRawType(getType(rawTypeID));
theEnum->computeType();
@@ -3737,14 +3774,15 @@
AccessorRecord accessors;
DeclID overriddenID;
uint8_t rawAccessLevel, rawSetterAccessLevel;
- uint8_t rawStorageKind;
+ uint8_t readImpl, writeImpl, readWriteImpl;
unsigned numArgNames, numAccessors;
ArrayRef<uint64_t> argNameAndDependencyIDs;
decls_block::SubscriptLayout::readRecord(scratch, contextID,
isImplicit, isObjC,
isGetterMutating, isSetterMutating,
- rawStorageKind, numAccessors,
+ readImpl, writeImpl, readWriteImpl,
+ numAccessors,
genericEnvID,
interfaceTypeID,
overriddenID, rawAccessLevel,
@@ -3796,7 +3834,7 @@
subscript->setIndices(readParameterList());
- configureStorage(subscript, rawStorageKind, accessors);
+ configureStorage(subscript, readImpl, writeImpl, readWriteImpl, accessors);
if (auto accessLevel = getActualAccessLevel(rawAccessLevel)) {
subscript->setAccess(*accessLevel);
@@ -3819,6 +3857,7 @@
if (isImplicit)
subscript->setImplicit();
+ subscript->setIsObjC(isObjC);
if (auto overriddenSub = cast_or_null<SubscriptDecl>(overridden.get())) {
subscript->setOverriddenDecl(overriddenSub);
AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
@@ -3880,7 +3919,6 @@
tl = TypeLoc::withoutLoc(getType(rawID));
});
extension->setInherited(inheritedTypes);
- extension->setCheckedInheritanceClause();
extension->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
skipRecord(DeclTypeCursor, decls_block::MEMBERS);
@@ -3940,6 +3978,7 @@
if (isImplicit)
dtor->setImplicit();
+ dtor->setIsObjC(isObjC);
break;
}
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 5d608cb..5f788f4 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -481,32 +481,63 @@
namespace {
struct Accessors {
- StorageKind Kind;
+ uint8_t ReadImpl, WriteImpl, ReadWriteImpl;
SmallVector<AccessorDecl *, 8> Decls;
};
} // end anonymous namespace
-static StorageKind getRawStorageKind(AbstractStorageDecl::StorageKindTy kind) {
+static uint8_t getRawReadImplKind(swift::ReadImplKind kind) {
switch (kind) {
-#define CASE(KIND) case AbstractStorageDecl::KIND: return StorageKind::KIND
- CASE(Stored);
- CASE(StoredWithTrivialAccessors);
- CASE(StoredWithObservers);
- CASE(InheritedWithObservers);
- CASE(Computed);
- CASE(ComputedWithMutableAddress);
- CASE(Addressed);
- CASE(AddressedWithTrivialAccessors);
- CASE(AddressedWithObservers);
+#define CASE(KIND) \
+ case swift::ReadImplKind::KIND: \
+ return uint8_t(serialization::ReadImplKind::KIND);
+ CASE(Stored)
+ CASE(Get)
+ CASE(Inherited)
+ CASE(Address)
#undef CASE
}
- llvm_unreachable("bad storage kind");
+ llvm_unreachable("bad kind");
+}
+
+static unsigned getRawWriteImplKind(swift::WriteImplKind kind) {
+ switch (kind) {
+#define CASE(KIND) \
+ case swift::WriteImplKind::KIND: \
+ return uint8_t(serialization::WriteImplKind::KIND);
+ CASE(Immutable)
+ CASE(Stored)
+ CASE(Set)
+ CASE(StoredWithObservers)
+ CASE(InheritedWithObservers)
+ CASE(MutableAddress)
+#undef CASE
+ }
+ llvm_unreachable("bad kind");
+}
+
+static unsigned getRawReadWriteImplKind(swift::ReadWriteImplKind kind) {
+ switch (kind) {
+#define CASE(KIND) \
+ case swift::ReadWriteImplKind::KIND: \
+ return uint8_t(serialization::ReadWriteImplKind::KIND);
+ CASE(Immutable)
+ CASE(Stored)
+ CASE(MaterializeForSet)
+ CASE(MutableAddress)
+ CASE(MaterializeToTemporary)
+#undef CASE
+ }
+ llvm_unreachable("bad kind");
}
static Accessors getAccessors(const AbstractStorageDecl *storage) {
Accessors accessors;
- accessors.Kind = getRawStorageKind(storage->getStorageKind());
- auto decls = storage->getAllAccessorFunctions();
+ auto impl = storage->getImplInfo();
+ accessors.ReadImpl = getRawReadImplKind(impl.getReadImpl());
+ accessors.WriteImpl = getRawWriteImplKind(impl.getWriteImpl());
+ accessors.ReadWriteImpl = getRawReadWriteImplKind(impl.getReadWriteImpl());
+ auto decls = storage->getAllAccessors();
accessors.Decls.append(decls.begin(), decls.end());
return accessors;
}
@@ -2952,6 +2983,7 @@
addDeclBaseNameRef(theStruct->getName()),
contextID,
theStruct->isImplicit(),
+ theStruct->isObjC(),
addGenericEnvironmentRef(
theStruct->getGenericEnvironment()),
rawAccessLevel,
@@ -3002,6 +3034,7 @@
addDeclBaseNameRef(theEnum->getName()),
contextID,
theEnum->isImplicit(),
+ theEnum->isObjC(),
addGenericEnvironmentRef(
theEnum->getGenericEnvironment()),
addTypeRef(theEnum->getRawType()),
@@ -3084,6 +3117,7 @@
/*resolver=*/nullptr),
addGenericEnvironmentRef(
proto->getGenericEnvironment()),
+ addTypeRef(proto->getSuperclass()),
rawAccessLevel,
inherited);
@@ -3126,7 +3160,9 @@
var->hasNonPatternBindingInit(),
var->isGetterMutating(),
var->isSetterMutating(),
- (unsigned) accessors.Kind,
+ accessors.ReadImpl,
+ accessors.WriteImpl,
+ accessors.ReadWriteImpl,
accessors.Decls.size(),
addTypeRef(ty),
addDeclRef(var->getOverriddenDecl()),
@@ -3351,7 +3387,9 @@
subscript->isObjC(),
subscript->isGetterMutating(),
subscript->isSetterMutating(),
- (unsigned) accessors.Kind,
+ accessors.ReadImpl,
+ accessors.WriteImpl,
+ accessors.ReadWriteImpl,
accessors.Decls.size(),
addGenericEnvironmentRef(
subscript->getGenericEnvironment()),
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 9955594..f8dddb9 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -71,16 +71,16 @@
SourcePresence Presence, bool ManualMemory) {
assert(Kind != SyntaxKind::Token &&
"'token' syntax node must be constructed with dedicated constructor");
- Bits.Kind = unsigned(Kind);
- Bits.Presence = unsigned(Presence);
- Bits.ManualMemory = unsigned(ManualMemory);
- Bits.NumChildren = Layout.size();
+ Bits.Common.Kind = unsigned(Kind);
+ Bits.Common.Presence = unsigned(Presence);
+ Bits.Common.ManualMemory = unsigned(ManualMemory);
+ Bits.Layout.NumChildren = Layout.size();
// Compute the text length
- Bits.TextLength = 0;
+ Bits.Layout.TextLength = 0;
for (const auto ChildNode : Layout) {
if (ChildNode && !ChildNode->isMissing()) {
- Bits.TextLength += ChildNode->getTextLength();
+ Bits.Layout.TextLength += ChildNode->getTextLength();
}
}
@@ -93,12 +93,12 @@
ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia,
SourcePresence Presence, bool ManualMemory) {
- Bits.Kind = unsigned(SyntaxKind::Token);
- Bits.Presence = unsigned(Presence);
- Bits.ManualMemory = unsigned(ManualMemory);
- Bits.TokenKind = unsigned(TokKind);
- Bits.NumLeadingTrivia = LeadingTrivia.size();
- Bits.NumTrailingTrivia = TrailingTrivia.size();
+ Bits.Common.Kind = unsigned(SyntaxKind::Token);
+ Bits.Common.Presence = unsigned(Presence);
+ Bits.Common.ManualMemory = unsigned(ManualMemory);
+ Bits.Token.TokenKind = unsigned(TokKind);
+ Bits.Token.NumLeadingTrivia = LeadingTrivia.size();
+ Bits.Token.NumTrailingTrivia = TrailingTrivia.size();
// Initialize token text.
::new (static_cast<void *>(getTrailingObjects<OwnedString>()))
@@ -109,7 +109,7 @@
// Initialize trailing trivia.
std::uninitialized_copy(TrailingTrivia.begin(), TrailingTrivia.end(),
getTrailingObjects<TriviaPiece>() +
- Bits.NumLeadingTrivia);
+ Bits.Token.NumLeadingTrivia);
}
RawSyntax::~RawSyntax() {
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index 917ca68..3177c37 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -46,7 +46,7 @@
auto *var = entry.getAnchoringVarDecl();
// Non-global variables might have an explicit initializer symbol.
- if (entry.getInit() && !isGlobalOrStaticVar(var)) {
+ if (entry.getNonLazyInit() && !isGlobalOrStaticVar(var)) {
auto declRef =
SILDeclRef(var, SILDeclRef::Kind::StoredPropertyInitializer);
// Stored property initializers for public properties are currently
@@ -164,7 +164,7 @@
void TBDGenVisitor::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
// Explicitly look at each accessor here: see visitAccessorDecl.
- for (auto accessor : ASD->getAllAccessorFunctions()) {
+ for (auto accessor : ASD->getAllAccessors()) {
visitAbstractFunctionDecl(accessor);
}
}
diff --git a/stdlib/private/StdlibUnittest/MinimalTypes.swift b/stdlib/private/StdlibUnittest/MinimalTypes.swift
index ad03648..e538e19 100644
--- a/stdlib/private/StdlibUnittest/MinimalTypes.swift
+++ b/stdlib/private/StdlibUnittest/MinimalTypes.swift
@@ -220,7 +220,7 @@
fatalError("GenericMinimalHashableValue_equalImpl is not set yet")
})
public var GenericMinimalHashableValue_hashIntoImpl =
- ResettableValue<(Any, inout Hasher) -> Void>({ _ in
+ ResettableValue<(Any, inout Hasher) -> Void>({ (_,_) in
fatalError("GenericMinimalHashableValue_hashIntoImpl is not set yet")
})
@@ -276,7 +276,7 @@
fatalError("GenericMinimalHashableClass_equalImpl is not set yet")
})
public var GenericMinimalHashableClass_hashIntoImpl =
- ResettableValue<(Any, inout Hasher) -> Void>({ _ in
+ ResettableValue<(Any, inout Hasher) -> Void>({ (_,_) in
fatalError("GenericMinimalHashableClass_hashIntoImpl is not set yet")
})
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
index 99798f3..f27cebf 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
@@ -1775,15 +1775,15 @@
}
func _getOSVersion() -> OSVersion {
-#if os(iOS) && (arch(i386) || arch(x86_64))
+#if os(iOS) && targetEnvironment(simulator)
// On simulator, the plist file that we try to read turns out to be host's
// plist file, which indicates OS X.
//
// FIXME: how to get the simulator version *without* UIKit?
return .iOSSimulator
-#elseif os(tvOS) && (arch(i386) || arch(x86_64))
+#elseif os(tvOS) && targetEnvironment(simulator)
return .tvOSSimulator
-#elseif os(watchOS) && (arch(i386) || arch(x86_64))
+#elseif os(watchOS) && targetEnvironment(simulator)
return .watchOSSimulator
#elseif os(Linux)
return .linux
@@ -2410,6 +2410,33 @@
return hasher.finalize()
}
+/// Test that the elements of `groups` consist of instances that satisfy the
+/// semantic requirements of `Hashable`, with each group defining a distinct
+/// equivalence class under `==`.
+public func checkHashableGroups<Groups: Collection>(
+ _ groups: Groups,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where Groups.Element: Collection, Groups.Element.Element: Hashable {
+ let instances = groups.flatMap { $0 }
+ // groupIndices[i] is the index of the element in groups that contains
+ // instances[i].
+ let groupIndices =
+ zip(0..., groups).flatMap { i, group in group.map { _ in i } }
+ func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
+ return groupIndices[lhs] == groupIndices[rhs]
+ }
+ checkHashable(
+ instances,
+ equalityOracle: equalityOracle,
+ hashEqualityOracle: equalityOracle,
+ allowBrokenTransitivity: false,
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ showFrame: false)
+}
+
/// Test that the elements of `instances` satisfy the semantic requirements of
/// `Hashable`, using `equalityOracle` to generate equality and hashing
/// expectations from pairs of positions in `instances`.
diff --git a/stdlib/public/SDK/AppKit/AppKit.swift b/stdlib/public/SDK/AppKit/AppKit.swift
index ffb9f7d..a716201 100644
--- a/stdlib/public/SDK/AppKit/AppKit.swift
+++ b/stdlib/public/SDK/AppKit/AppKit.swift
@@ -13,7 +13,7 @@
import Foundation
@_exported import AppKit
-extension NSCursor : _DefaultCustomPlaygroundQuickLookable {
+extension NSCursor : __DefaultCustomPlaygroundQuickLookable {
@available(*, deprecated, message: "NSCursor._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
return .image(image)
@@ -24,7 +24,7 @@
static var views = Set<NSView>()
}
-extension NSView : _DefaultCustomPlaygroundQuickLookable {
+extension NSView : __DefaultCustomPlaygroundQuickLookable {
@available(*, deprecated, message: "NSView._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
// if you set NSView.needsDisplay, you can get yourself in a recursive scenario where the same view
diff --git a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
index 1ce4f6b..69623cd 100644
--- a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
+++ b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
@@ -228,11 +228,13 @@
}
}
-extension CGPoint : CustomReflectable, CustomPlaygroundQuickLookable {
+extension CGPoint : CustomReflectable {
public var customMirror: Mirror {
return Mirror(self, children: ["x": x, "y": y], displayStyle: .`struct`)
}
+}
+extension CGPoint : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "CGPoint.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .point(Double(x), Double(y))
@@ -293,14 +295,16 @@
}
}
-extension CGSize : CustomReflectable, CustomPlaygroundQuickLookable {
+extension CGSize : CustomReflectable {
public var customMirror: Mirror {
return Mirror(
self,
children: ["width": width, "height": height],
displayStyle: .`struct`)
}
+}
+extension CGSize : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "CGSize.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .size(Double(width), Double(height))
@@ -431,14 +435,16 @@
public var y: CGFloat { return minY }
}
-extension CGRect : CustomReflectable, CustomPlaygroundQuickLookable {
+extension CGRect : CustomReflectable {
public var customMirror: Mirror {
return Mirror(
self,
children: ["origin": origin, "size": size],
displayStyle: .`struct`)
}
+}
+extension CGRect : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "CGRect.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .rectangle(
diff --git a/stdlib/public/SDK/Foundation/Date.swift b/stdlib/public/SDK/Foundation/Date.swift
index 967b158..7231a6d 100644
--- a/stdlib/public/SDK/Foundation/Date.swift
+++ b/stdlib/public/SDK/Foundation/Date.swift
@@ -272,7 +272,7 @@
}
}
-extension Date : CustomPlaygroundQuickLookable {
+extension Date : _CustomPlaygroundQuickLookable {
var summary: String {
let df = DateFormatter()
df.dateStyle = .medium
diff --git a/stdlib/public/SDK/Foundation/NSCoder.swift b/stdlib/public/SDK/Foundation/NSCoder.swift
index 0086f9f..8c57d1a 100644
--- a/stdlib/public/SDK/Foundation/NSCoder.swift
+++ b/stdlib/public/SDK/Foundation/NSCoder.swift
@@ -172,7 +172,7 @@
@available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *)
public static func unarchivedObject<DecodedObjectType>(ofClass cls: DecodedObjectType.Type, from data: Data) throws -> DecodedObjectType? where DecodedObjectType : NSCoding, DecodedObjectType : NSObject {
var error: NSError?
- let result = __NSKeyedUnarchiverSecureUnarchiveObjectOfClass(cls as! AnyClass, data, &error)
+ let result = __NSKeyedUnarchiverSecureUnarchiveObjectOfClass(cls as AnyClass, data, &error)
try resolveError(error)
return result as? DecodedObjectType
}
diff --git a/stdlib/public/SDK/Foundation/NSDate.swift b/stdlib/public/SDK/Foundation/NSDate.swift
index 4896e9d..2c4a0be 100644
--- a/stdlib/public/SDK/Foundation/NSDate.swift
+++ b/stdlib/public/SDK/Foundation/NSDate.swift
@@ -12,7 +12,7 @@
@_exported import Foundation // Clang module
-extension NSDate : CustomPlaygroundQuickLookable {
+extension NSDate : _CustomPlaygroundQuickLookable {
@nonobjc
var summary: String {
let df = DateFormatter()
diff --git a/stdlib/public/SDK/Foundation/NSRange.swift b/stdlib/public/SDK/Foundation/NSRange.swift
index 85228fc..f4943c0 100644
--- a/stdlib/public/SDK/Foundation/NSRange.swift
+++ b/stdlib/public/SDK/Foundation/NSRange.swift
@@ -197,7 +197,7 @@
}
}
-extension NSRange : CustomPlaygroundQuickLookable {
+extension NSRange : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "NSRange.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .range(Int64(location), Int64(length))
diff --git a/stdlib/public/SDK/Foundation/NSString.swift b/stdlib/public/SDK/Foundation/NSString.swift
index d04e178..9bff141 100644
--- a/stdlib/public/SDK/Foundation/NSString.swift
+++ b/stdlib/public/SDK/Foundation/NSString.swift
@@ -107,7 +107,7 @@
}
}
-extension NSString : CustomPlaygroundQuickLookable {
+extension NSString : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "NSString.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .text(self as String)
diff --git a/stdlib/public/SDK/Foundation/NSURL.swift b/stdlib/public/SDK/Foundation/NSURL.swift
index 6cf6522..6dacb8b 100644
--- a/stdlib/public/SDK/Foundation/NSURL.swift
+++ b/stdlib/public/SDK/Foundation/NSURL.swift
@@ -12,7 +12,7 @@
@_exported import Foundation // Clang module
-extension NSURL : CustomPlaygroundQuickLookable {
+extension NSURL : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "NSURL.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
guard let str = absoluteString else { return .text("Unknown URL") }
diff --git a/stdlib/public/SDK/Foundation/URL.swift b/stdlib/public/SDK/Foundation/URL.swift
index f176a9f..b4bf0f1 100644
--- a/stdlib/public/SDK/Foundation/URL.swift
+++ b/stdlib/public/SDK/Foundation/URL.swift
@@ -412,6 +412,26 @@
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public var volumeSupportsCompression : Bool? { return _get(.volumeSupportsCompressionKey) }
+ /// true if the volume supports clonefile(2).
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ public var volumeSupportsFileCloning : Bool? { return _get(.volumeSupportsFileCloningKey) }
+
+ /// true if the volume supports renamex_np(2)'s RENAME_SWAP option.
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ public var volumeSupportsSwapRenaming : Bool? { return _get(.volumeSupportsSwapRenamingKey) }
+
+ /// true if the volume supports renamex_np(2)'s RENAME_EXCL option.
+ @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+ public var volumeSupportsExclusiveRenaming : Bool? { return _get(.volumeSupportsExclusiveRenamingKey) }
+
+ /// true if the volume supports making files immutable with isUserImmutable or isSystemImmutable.
+ @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+ public var volumeSupportsImmutableFiles : Bool? { return _get(.volumeSupportsImmutableFilesKey) }
+
+ /// true if the volume supports setting POSIX access permissions with fileSecurity.
+ @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+ public var volumeSupportsAccessPermissions : Bool? { return _get(.volumeSupportsAccessPermissionsKey) }
+
/// true if this item is synced to the cloud, false if it is only a local file.
public var isUbiquitousItem : Bool? { return _get(.isUbiquitousItemKey) }
@@ -1210,7 +1230,7 @@
}
}
-extension URL : CustomPlaygroundQuickLookable {
+extension URL : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "URL.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .url(absoluteString)
diff --git a/stdlib/public/SDK/Foundation/URLComponents.swift b/stdlib/public/SDK/Foundation/URLComponents.swift
index 95f9cb7..28f71dc 100644
--- a/stdlib/public/SDK/Foundation/URLComponents.swift
+++ b/stdlib/public/SDK/Foundation/URLComponents.swift
@@ -291,6 +291,15 @@
set { _applyMutation { $0.queryItems = newValue } }
}
+ /// Returns an array of query items for this `URLComponents`, in the order in which they appear in the original query string. Any percent-encoding in a query item name or value is retained
+ ///
+ /// The setter combines an array containing any number of `URLQueryItem`s, each of which represents a single key-value pair, into a query string and sets the `URLComponents` query property. This property assumes the query item names and values are already correctly percent-encoded, and that the query item names do not contain the query item delimiter characters '&' and '='. Attempting to set an incorrectly percent-encoded query item or a query item name with the query item delimiter characters '&' and '=' will cause a `fatalError`.
+ @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+ public var percentEncodedQueryItems: [URLQueryItem]? {
+ get { return _handle.map { $0.percentEncodedQueryItems } }
+ set { _applyMutation { $0.percentEncodedQueryItems = newValue } }
+ }
+
public var hashValue: Int {
return _handle.map { $0.hash }
}
diff --git a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
index 5a0893b..69a7aeb 100644
--- a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
+++ b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
@@ -14,7 +14,7 @@
% for Self in ['SKShapeNode', 'SKSpriteNode', 'SKTextureAtlas', 'SKTexture']:
-extension ${Self} : CustomPlaygroundQuickLookable {
+extension ${Self} : _CustomPlaygroundQuickLookable {
@available(*, deprecated, message: "${Self}.customPlaygroundQuickLook will be removed in a future Swift version")
public var customPlaygroundQuickLook: PlaygroundQuickLook {
let data = (self as AnyObject)._copyImageData?() as Data?
diff --git a/stdlib/public/core/Algorithm.swift b/stdlib/public/core/Algorithm.swift
index df836fe..72bf086 100644
--- a/stdlib/public/core/Algorithm.swift
+++ b/stdlib/public/core/Algorithm.swift
@@ -158,6 +158,3 @@
return Iterator(_base: _base.makeIterator())
}
}
-
-@available(*, deprecated: 4.2, renamed: "EnumeratedSequence.Iterator")
-public typealias EnumeratedIterator<T: Sequence> = EnumeratedSequence<T>.Iterator
diff --git a/stdlib/public/core/AnyHashable.swift b/stdlib/public/core/AnyHashable.swift
index 45c4700..a0b6d4c 100644
--- a/stdlib/public/core/AnyHashable.swift
+++ b/stdlib/public/core/AnyHashable.swift
@@ -39,20 +39,29 @@
@usableFromInline // FIXME(sil-serialize-all)
internal protocol _AnyHashableBox {
- func _unbox<T : Hashable>() -> T?
+ var _canonicalBox: _AnyHashableBox { get }
/// Determine whether values in the boxes are equivalent.
///
+ /// - Precondition: `self` and `box` are in canonical form.
/// - Returns: `nil` to indicate that the boxes store different types, so
/// no comparison is possible. Otherwise, contains the result of `==`.
- func _isEqual(to: _AnyHashableBox) -> Bool?
+ func _isEqual(to box: _AnyHashableBox) -> Bool?
var _hashValue: Int { get }
func _hash(into hasher: inout Hasher)
+ func _rawHashValue(_seed: (UInt64, UInt64)) -> Int
var _base: Any { get }
+ func _unbox<T: Hashable>() -> T?
func _downCastConditional<T>(into result: UnsafeMutablePointer<T>) -> Bool
}
+extension _AnyHashableBox {
+ var _canonicalBox: _AnyHashableBox {
+ return self
+ }
+}
+
@_fixed_layout // FIXME(sil-serialize-all)
@usableFromInline // FIXME(sil-serialize-all)
internal struct _ConcreteHashableBox<Base : Hashable> : _AnyHashableBox {
@@ -88,6 +97,11 @@
}
@inlinable // FIXME(sil-serialize-all)
+ func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ return _baseHashable._rawHashValue(seed: _seed)
+ }
+
+ @inlinable // FIXME(sil-serialize-all)
internal var _base: Any {
return _baseHashable
}
@@ -101,19 +115,6 @@
}
}
-#if _runtime(_ObjC)
-// Retrieve the custom AnyHashable representation of the value after it
-// has been bridged to Objective-C. This mapping to Objective-C and back
-// turns a non-custom representation into a custom one, which is used as
-// the lowest-common-denominator for comparisons.
-@inlinable // FIXME(sil-serialize-all)
-internal func _getBridgedCustomAnyHashable<T>(_ value: T) -> AnyHashable? {
- let bridgedValue = _bridgeAnythingToObjectiveC(value)
- return (bridgedValue as?
- _HasCustomAnyHashableRepresentation)?._toCustomAnyHashable()
-}
-#endif
-
/// A type-erased hashable value.
///
/// The `AnyHashable` type forwards equality comparisons and hashing operations
@@ -137,8 +138,11 @@
public struct AnyHashable {
@usableFromInline // FIXME(sil-serialize-all)
internal var _box: _AnyHashableBox
- @usableFromInline // FIXME(sil-serialize-all)
- internal var _usedCustomRepresentation: Bool
+
+ @inlinable // FIXME(sil-serialize-all)
+ internal init(_box box: _AnyHashableBox) {
+ self._box = box
+ }
/// Creates a type-erased hashable value that wraps the given instance.
///
@@ -160,15 +164,13 @@
/// - Parameter base: A hashable value to wrap.
@inlinable // FIXME(sil-serialize-all)
public init<H : Hashable>(_ base: H) {
- if let customRepresentation =
+ if let custom =
(base as? _HasCustomAnyHashableRepresentation)?._toCustomAnyHashable() {
- self = customRepresentation
- self._usedCustomRepresentation = true
+ self = custom
return
}
- self._box = _ConcreteHashableBox(0 as Int)
- self._usedCustomRepresentation = false
+ self.init(_box: _ConcreteHashableBox(false)) // Dummy value
_makeAnyHashableUpcastingToHashableBaseType(
base,
storingResultInto: &self)
@@ -177,7 +179,6 @@
@inlinable // FIXME(sil-serialize-all)
internal init<H : Hashable>(_usingDefaultRepresentationOf base: H) {
self._box = _ConcreteHashableBox(base)
- self._usedCustomRepresentation = false
}
/// The value wrapped by this instance.
@@ -206,13 +207,11 @@
if _box._downCastConditional(into: result) { return true }
#if _runtime(_ObjC)
- // If we used a custom representation, bridge to Objective-C and then
- // attempt the cast from there.
- if _usedCustomRepresentation {
- if let value = _bridgeAnythingToObjectiveC(_box._base) as? T {
- result.initialize(to: value)
- return true
- }
+ // Bridge to Objective-C and then attempt the cast from there.
+ // FIXME: This should also work without the Objective-C runtime.
+ if let value = _bridgeAnythingToObjectiveC(_box._base) as? T {
+ result.initialize(to: value)
+ return true
}
#endif
@@ -248,34 +247,7 @@
/// - rhs: Another type-erased hashable value.
@inlinable // FIXME(sil-serialize-all)
public static func == (lhs: AnyHashable, rhs: AnyHashable) -> Bool {
- // If they're equal, we're done.
- if let result = lhs._box._isEqual(to: rhs._box) { return result }
-
- #if _runtime(_ObjC)
- // If one used a custom representation but the other did not, bridge
- // the one that did *not* use the custom representation to Objective-C:
- // if the bridged result has a custom representation, compare those custom
- // custom representations.
- if lhs._usedCustomRepresentation != rhs._usedCustomRepresentation {
- // If the lhs used a custom representation, try comparing against the
- // custom representation of the bridged rhs (if there is one).
- if lhs._usedCustomRepresentation {
- if let customRHS = _getBridgedCustomAnyHashable(rhs._box._base) {
- return lhs._box._isEqual(to: customRHS._box) ?? false
- }
- return false
- }
-
- // Otherwise, try comparing the rhs against the custom representation of
- // the bridged lhs (if there is one).
- if let customLHS = _getBridgedCustomAnyHashable(lhs._box._base) {
- return customLHS._box._isEqual(to: rhs._box) ?? false
- }
- return false
- }
- #endif
-
- return false
+ return lhs._box._canonicalBox._isEqual(to: rhs._box._canonicalBox) ?? false
}
}
@@ -283,7 +255,7 @@
/// The hash value.
@inlinable
public var hashValue: Int {
- return _box._hashValue
+ return _box._canonicalBox._hashValue
}
/// Hashes the essential components of this value by feeding them into the
@@ -293,7 +265,12 @@
/// of this instance.
@inlinable
public func hash(into hasher: inout Hasher) {
- _box._hash(into: &hasher)
+ _box._canonicalBox._hash(into: &hasher)
+ }
+
+ @inlinable // FIXME(sil-serialize-all)
+ public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
+ return _box._canonicalBox._rawHashValue(_seed: seed)
}
}
diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift
index 2fd1057..a23c6d1 100644
--- a/stdlib/public/core/Array.swift
+++ b/stdlib/public/core/Array.swift
@@ -1758,3 +1758,76 @@
}
}
#endif
+
+extension Array: _HasCustomAnyHashableRepresentation
+ where Element: Hashable {
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return AnyHashable(_box: _ArrayAnyHashableBox(self))
+ }
+}
+
+internal protocol _ArrayAnyHashableProtocol: _AnyHashableBox {
+ var count: Int { get }
+ subscript(index: Int) -> AnyHashable { get }
+}
+
+internal struct _ArrayAnyHashableBox<Element: Hashable>
+ : _ArrayAnyHashableProtocol {
+ internal let _value: [Element]
+
+ internal init(_ value: [Element]) {
+ self._value = value
+ }
+
+ internal var _base: Any {
+ return _value
+ }
+
+ internal var count: Int {
+ return _value.count
+ }
+
+ internal subscript(index: Int) -> AnyHashable {
+ return _value[index] as AnyHashable
+ }
+
+ func _isEqual(to other: _AnyHashableBox) -> Bool? {
+ guard let other = other as? _ArrayAnyHashableProtocol else { return nil }
+ guard _value.count == other.count else { return false }
+ for i in 0 ..< _value.count {
+ if self[i] != other[i] { return false }
+ }
+ return true
+ }
+
+ var _hashValue: Int {
+ var hasher = Hasher()
+ _hash(into: &hasher)
+ return hasher.finalize()
+ }
+
+ func _hash(into hasher: inout Hasher) {
+ hasher.combine(_value.count) // discriminator
+ for i in 0 ..< _value.count {
+ hasher.combine(self[i])
+ }
+ }
+
+ func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ var hasher = Hasher(_seed: _seed)
+ self._hash(into: &hasher)
+ return hasher._finalize()
+ }
+
+ internal func _unbox<T : Hashable>() -> T? {
+ return _value as? T
+ }
+
+ internal func _downCastConditional<T>(
+ into result: UnsafeMutablePointer<T>
+ ) -> Bool {
+ guard let value = _value as? T else { return false }
+ result.initialize(to: value)
+ return true
+ }
+}
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index 3665c56..b2c83bc 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -10,15 +10,6 @@
//
//===----------------------------------------------------------------------===//
-/// A type that provides subscript access to its elements, with bidirectional
-/// index traversal.
-///
-/// In most cases, it's best to ignore this protocol and use the
-/// `BidirectionalCollection` protocol instead, because it has a more complete
-/// interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'BidirectionalCollection' instead")
-public typealias BidirectionalIndexable = BidirectionalCollection
-
/// A collection that supports backward as well as forward traversal.
///
/// Bidirectional collections offer traversal backward from any valid index,
diff --git a/stdlib/public/core/BridgeObjectiveC.swift b/stdlib/public/core/BridgeObjectiveC.swift
index 38c8b31..5c66c58 100644
--- a/stdlib/public/core/BridgeObjectiveC.swift
+++ b/stdlib/public/core/BridgeObjectiveC.swift
@@ -788,7 +788,7 @@
var done = false
var result: AnyObject!
- var source: Any = x
+ let source: Any = x
if let dynamicSource = _extractDynamicValue(x) {
result = dynamicSource as AnyObject
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 41545b5..e17f92a 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -73,7 +73,6 @@
Hashing.swift
HeapBuffer.swift
ICU.swift
- ImplicitlyUnwrappedOptional.swift
Indices.swift
InputStream.swift
IntegerParsing.swift
@@ -123,7 +122,6 @@
Sort.swift.gyb
StaticString.swift
Stride.swift.gyb
- StringCharacterView.swift # ORDER DEPENDENCY: Must precede String.swift
StringHashable.swift # ORDER DEPENDENCY: Must precede String.swift
String.swift
StringBridge.swift
@@ -168,6 +166,7 @@
StringGraphemeBreaking.swift # ORDER DEPENDENCY: Must follow UTF16.swift
ValidUTF8Buffer.swift
WriteBackMutableSlice.swift
+ MigrationSupport.swift
)
# The complete list of sources in the core standard library. Includes
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 7b4cf52..f7a80c0 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -459,16 +459,7 @@
}
}
-extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {
- /// Now that Range is conditionally a collection when Bound: Strideable,
- /// CountableRange is no longer needed. This is a deprecated initializer
- /// for any remaining uses of Range(countableRange).
- @available(*,deprecated: 4.2,
- message: "CountableRange is now Range. No need to convert any more.")
- public init(_ other: ClosedRange<Bound>) {
- self = other
- }
-
+extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {
/// Creates an instance equivalent to the given `Range`.
///
/// - Parameter other: A `Range` to convert to a `ClosedRange` instance.
@@ -495,8 +486,7 @@
}
}
-@available(*, deprecated, renamed: "ClosedRange.Index")
-public typealias ClosedRangeIndex<T> = ClosedRange<T>.Index where T: Strideable, T.Stride: SignedInteger
-
+// Note: this is not for compatibility only, it is considered a useful
+// shorthand. TODO: Add documentation
public typealias CountableClosedRange<Bound: Strideable> = ClosedRange<Bound>
where Bound.Stride : SignedInteger
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index 879625c..acb38c8 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -10,22 +10,6 @@
//
//===----------------------------------------------------------------------===//
-/// A type that provides subscript access to its elements, with forward
-/// index traversal.
-///
-/// In most cases, it's best to ignore this protocol and use the `Collection`
-/// protocol instead, because it has a more complete interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'Collection' instead")
-public typealias IndexableBase = Collection
-
-/// A type that provides subscript access to its elements, with forward index
-/// traversal.
-///
-/// In most cases, it's best to ignore this protocol and use the `Collection`
-/// protocol instead, because it has a more complete interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'Collection' instead")
-public typealias Indexable = Collection
-
/// A type that iterates over a collection using its indices.
///
/// The `IndexingIterator` type is the default iterator for any collection that
@@ -349,6 +333,11 @@
/// the number of contained elements, accessing its `count` property is an
/// O(*n*) operation.
public protocol Collection: Sequence where SubSequence: Collection {
+ // FIXME: ideally this would be in MigrationSupport.swift, but it needs
+ // to be on the protocol instead of as an extension
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+ typealias IndexDistance = Int
+
// FIXME(ABI): Associated type inference requires this.
associatedtype Element
@@ -807,28 +796,6 @@
/// - Parameter i: A valid index of the collection. `i` must be less than
/// `endIndex`.
func formIndex(after i: inout Index)
-
- /// Returns a random element of the collection, using the given generator as
- /// a source for randomness.
- ///
- /// You use this method to select a random element from a collection when you
- /// are using a custom random number generator. For example, call
- /// `randomElement(using:)` to select a random element from an array of names.
- ///
- /// let names = ["Zoey", "Chloe", "Amani", "Amaia"]
- /// let randomName = names.randomElement(using: &myGenerator)!
- /// // randomName == "Amani"
- ///
- /// - Parameter generator: The random number generator to use when choosing
- /// a random element.
- /// - Returns: A random element from the collection. If the collection is
- /// empty, the method returns `nil`.
- __consuming func randomElement<T: RandomNumberGenerator>(
- using generator: inout T
- ) -> Element?
-
- @available(*, deprecated, message: "all index distances are now of type Int")
- typealias IndexDistance = Int
}
/// Default implementation for forward collections.
@@ -1803,35 +1770,3 @@
return try preprocess()
}
}
-
-extension Collection {
- // FIXME: <rdar://problem/34142121>
- // This typealias should be removed as it predates the source compatibility
- // guarantees of Swift 3, but it cannot due to a bug.
- @available(*, unavailable, renamed: "Iterator")
- public typealias Generator = Iterator
-
- @available(swift, deprecated: 3.2, renamed: "Element")
- public typealias _Element = Element
-
- @available(*, deprecated, message: "all index distances are now of type Int")
- public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T) -> Index {
- return index(i, offsetBy: Int(n))
- }
- @available(*, deprecated, message: "all index distances are now of type Int")
- public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T) {
- return formIndex(&i, offsetBy: Int(n))
- }
- @available(*, deprecated, message: "all index distances are now of type Int")
- public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T, limitedBy limit: Index) -> Index? {
- return index(i, offsetBy: Int(n), limitedBy: limit)
- }
- @available(*, deprecated, message: "all index distances are now of type Int")
- public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T, limitedBy limit: Index) -> Bool {
- return formIndex(&i, offsetBy: Int(n), limitedBy: limit)
- }
- @available(*, deprecated, message: "all index distances are now of type Int")
- public func distance<T: BinaryInteger>(from start: Index, to end: Index) -> T {
- return numericCast(distance(from: start, to: end) as Int)
- }
-}
diff --git a/stdlib/public/core/CollectionOfOne.swift b/stdlib/public/core/CollectionOfOne.swift
index 2fd1ca4..575ff5f 100644
--- a/stdlib/public/core/CollectionOfOne.swift
+++ b/stdlib/public/core/CollectionOfOne.swift
@@ -170,6 +170,3 @@
return Mirror(self, children: ["element": _element])
}
}
-
-@available(*,deprecated: 4.2,renamed: "CollectionOfOne.Iterator")
-public typealias IteratorOverOne<T> = CollectionOfOne<T>.Iterator
\ No newline at end of file
diff --git a/stdlib/public/core/CompilerProtocols.swift b/stdlib/public/core/CompilerProtocols.swift
index d49be2c..3bd0b9f 100644
--- a/stdlib/public/core/CompilerProtocols.swift
+++ b/stdlib/public/core/CompilerProtocols.swift
@@ -723,7 +723,7 @@
///
/// The `ExpressibleByStringInterpolation` protocol is deprecated. Do not add
/// new conformances to the protocol.
-@available(*, deprecated, message: "it will be replaced or redesigned in Swift 4.0. Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'")
+@available(*, deprecated, message: "it will be replaced or redesigned in Swift 5.0. Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'")
public typealias ExpressibleByStringInterpolation = _ExpressibleByStringInterpolation
public protocol _ExpressibleByStringInterpolation {
/// Creates an instance by concatenating the given values.
@@ -773,18 +773,6 @@
init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float)
}
-extension _ExpressibleByColorLiteral {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 4.0,
- message: "This initializer is only meant to be used by color literals")
- public init(
- colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float
- ) {
- self.init(
- _colorLiteralRed: red, green: green, blue: blue, alpha: alpha)
- }
-}
-
/// A type that can be initialized using an image literal (e.g.
/// `#imageLiteral(resourceName: "hi.png")`).
public protocol _ExpressibleByImageLiteral {
@@ -819,67 +807,3 @@
/// then Array would no longer be a _DestructorSafeContainer.
public protocol _DestructorSafeContainer {
}
-
-// Deprecated by SE-0115.
-
-@available(*, deprecated, renamed: "ExpressibleByNilLiteral")
-public typealias NilLiteralConvertible
- = ExpressibleByNilLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinIntegerLiteral")
-public typealias _BuiltinIntegerLiteralConvertible
- = _ExpressibleByBuiltinIntegerLiteral
-@available(*, deprecated, renamed: "ExpressibleByIntegerLiteral")
-public typealias IntegerLiteralConvertible
- = ExpressibleByIntegerLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinFloatLiteral")
-public typealias _BuiltinFloatLiteralConvertible
- = _ExpressibleByBuiltinFloatLiteral
-@available(*, deprecated, renamed: "ExpressibleByFloatLiteral")
-public typealias FloatLiteralConvertible
- = ExpressibleByFloatLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinBooleanLiteral")
-public typealias _BuiltinBooleanLiteralConvertible
- = _ExpressibleByBuiltinBooleanLiteral
-@available(*, deprecated, renamed: "ExpressibleByBooleanLiteral")
-public typealias BooleanLiteralConvertible
- = ExpressibleByBooleanLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinUnicodeScalarLiteral")
-public typealias _BuiltinUnicodeScalarLiteralConvertible
- = _ExpressibleByBuiltinUnicodeScalarLiteral
-@available(*, deprecated, renamed: "ExpressibleByUnicodeScalarLiteral")
-public typealias UnicodeScalarLiteralConvertible
- = ExpressibleByUnicodeScalarLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinExtendedGraphemeClusterLiteral")
-public typealias _BuiltinExtendedGraphemeClusterLiteralConvertible
- = _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
-@available(*, deprecated, renamed: "ExpressibleByExtendedGraphemeClusterLiteral")
-public typealias ExtendedGraphemeClusterLiteralConvertible
- = ExpressibleByExtendedGraphemeClusterLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinStringLiteral")
-public typealias _BuiltinStringLiteralConvertible
- = _ExpressibleByBuiltinStringLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinUTF16StringLiteral")
-public typealias _BuiltinUTF16StringLiteralConvertible
- = _ExpressibleByBuiltinUTF16StringLiteral
-@available(*, deprecated, renamed: "ExpressibleByStringLiteral")
-public typealias StringLiteralConvertible
- = ExpressibleByStringLiteral
-@available(*, deprecated, renamed: "ExpressibleByArrayLiteral")
-public typealias ArrayLiteralConvertible
- = ExpressibleByArrayLiteral
-@available(*, deprecated, renamed: "ExpressibleByDictionaryLiteral")
-public typealias DictionaryLiteralConvertible
- = ExpressibleByDictionaryLiteral
-@available(*, deprecated, message: "it will be replaced or redesigned in Swift 4.0. Instead of conforming to 'StringInterpolationConvertible', consider adding an 'init(_:String)'")
-public typealias StringInterpolationConvertible
- = ExpressibleByStringInterpolation
-@available(*, deprecated, renamed: "_ExpressibleByColorLiteral")
-public typealias _ColorLiteralConvertible
- = _ExpressibleByColorLiteral
-@available(*, deprecated, renamed: "_ExpressibleByImageLiteral")
-public typealias _ImageLiteralConvertible
- = _ExpressibleByImageLiteral
-@available(*, deprecated, renamed: "_ExpressibleByFileReferenceLiteral")
-public typealias _FileReferenceLiteralConvertible
- = _ExpressibleByFileReferenceLiteral
-
diff --git a/stdlib/public/core/Dictionary.swift b/stdlib/public/core/Dictionary.swift
index 2a4bdb3..d3589b7 100644
--- a/stdlib/public/core/Dictionary.swift
+++ b/stdlib/public/core/Dictionary.swift
@@ -1153,53 +1153,6 @@
}
}
-// Maintain old `keys` and `values` types in Swift 3 mode.
-
-extension Dictionary {
- /// A collection containing just the keys of the dictionary.
- ///
- /// When iterated over, keys appear in this collection in the same order as
- /// they occur in the dictionary's key-value pairs. Each key in the keys
- /// collection has a unique value.
- ///
- /// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
- /// print(countryCodes)
- /// // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
- ///
- /// for k in countryCodes.keys {
- /// print(k)
- /// }
- /// // Prints "BR"
- /// // Prints "JP"
- /// // Prints "GH"
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4.0)
- public var keys: LazyMapCollection<[Key: Value], Key> {
- return self.lazy.map { $0.key }
- }
-
- /// A collection containing just the values of the dictionary.
- ///
- /// When iterated over, values appear in this collection in the same order as
- /// they occur in the dictionary's key-value pairs.
- ///
- /// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
- /// print(countryCodes)
- /// // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
- ///
- /// for v in countryCodes.values {
- /// print(v)
- /// }
- /// // Prints "Brazil"
- /// // Prints "Japan"
- /// // Prints "Ghana"
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4.0)
- public var values: LazyMapCollection<[Key: Value], Value> {
- return self.lazy.map { $0.value }
- }
-}
-
extension Dictionary {
/// A collection containing just the keys of the dictionary.
///
@@ -1518,6 +1471,65 @@
}
}
+extension Dictionary: _HasCustomAnyHashableRepresentation
+where Value: Hashable {
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return AnyHashable(_box: _DictionaryAnyHashableBox(self))
+ }
+}
+
+internal struct _DictionaryAnyHashableBox<Key: Hashable, Value: Hashable>
+ : _AnyHashableBox {
+ internal let _value: Dictionary<Key, Value>
+ internal let _canonical: Dictionary<AnyHashable, AnyHashable>
+
+ internal init(_ value: Dictionary<Key, Value>) {
+ self._value = value
+ self._canonical = value as Dictionary<AnyHashable, AnyHashable>
+ }
+
+ internal var _base: Any {
+ return _value
+ }
+
+ internal var _canonicalBox: _AnyHashableBox {
+ return _DictionaryAnyHashableBox<AnyHashable, AnyHashable>(_canonical)
+ }
+
+ internal func _isEqual(to other: _AnyHashableBox) -> Bool? {
+ guard
+ let other = other as? _DictionaryAnyHashableBox<AnyHashable, AnyHashable>
+ else {
+ return nil
+ }
+ return _canonical == other._value
+ }
+
+ internal var _hashValue: Int {
+ return _canonical.hashValue
+ }
+
+ internal func _hash(into hasher: inout Hasher) {
+ _canonical.hash(into: &hasher)
+ }
+
+ internal func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ return _canonical._rawHashValue(seed: _seed)
+ }
+
+ internal func _unbox<T: Hashable>() -> T? {
+ return _value as? T
+ }
+
+ internal func _downCastConditional<T>(
+ into result: UnsafeMutablePointer<T>
+ ) -> Bool {
+ guard let value = _value as? T else { return false }
+ result.initialize(to: value)
+ return true
+ }
+}
+
extension Dictionary: CustomStringConvertible, CustomDebugStringConvertible {
@inlinable // FIXME(sil-serialize-all)
internal func _makeDescription() -> String {
@@ -4736,20 +4748,6 @@
return remove(at: startIndex)
}
- @inlinable
- @available(swift, obsoleted: 4.0)
- public func filter(
- _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
- ) rethrows -> [Element] {
- var result: [Element] = []
- for x in self {
- if try isIncluded(x) {
- result.append(x)
- }
- }
- return result
- }
-
/// The total number of key-value pairs that the dictionary can contain without
/// allocating new storage.
@inlinable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/DropWhile.swift b/stdlib/public/core/DropWhile.swift
index bc7538e..8c78847 100644
--- a/stdlib/public/core/DropWhile.swift
+++ b/stdlib/public/core/DropWhile.swift
@@ -256,10 +256,3 @@
}
}
-@available(*, deprecated, renamed: "LazyDropWhileSequence.Iterator")
-public typealias LazyDropWhileIterator<T> = LazyDropWhileSequence<T>.Iterator where T: Sequence
-@available(*, deprecated, renamed: "LazyDropWhileCollection.Index")
-public typealias LazyDropWhileIndex<T> = LazyDropWhileCollection<T>.Index where T: Collection
-@available(*, deprecated, renamed: "LazyDropWhileCollection")
-public typealias LazyDropWhileBidirectionalCollection<T> = LazyDropWhileCollection<T> where T: BidirectionalCollection
-
diff --git a/stdlib/public/core/EmptyCollection.swift b/stdlib/public/core/EmptyCollection.swift
index 5bd6312..d4605fe 100644
--- a/stdlib/public/core/EmptyCollection.swift
+++ b/stdlib/public/core/EmptyCollection.swift
@@ -172,6 +172,3 @@
return true
}
}
-
-@available(*, deprecated: 4.2, renamed: "EmptyCollection.Iterator")
-public typealias EmptyIterator<T> = EmptyCollection<T>.Iterator
diff --git a/stdlib/public/core/Filter.swift b/stdlib/public/core/Filter.swift
index 8ccee84..edff25e 100644
--- a/stdlib/public/core/Filter.swift
+++ b/stdlib/public/core/Filter.swift
@@ -408,11 +408,3 @@
}
}
}
-
-// @available(*, deprecated, renamed: "LazyFilterSequence.Iterator")
-public typealias LazyFilterIterator<T: Sequence> = LazyFilterSequence<T>.Iterator
-// @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use Base.Index")
-public typealias LazyFilterIndex<Base: Collection> = Base.Index
-@available(*, deprecated, renamed: "LazyFilterCollection")
-public typealias LazyFilterBidirectionalCollection<T> = LazyFilterCollection<T> where T : BidirectionalCollection
-
diff --git a/stdlib/public/core/FlatMap.swift b/stdlib/public/core/FlatMap.swift
index 1c40708..3ece0b8 100644
--- a/stdlib/public/core/FlatMap.swift
+++ b/stdlib/public/core/FlatMap.swift
@@ -48,29 +48,6 @@
> {
return self.map(transform).filter { $0 != nil }.map { $0! }
}
-
- /// Returns the non-`nil` results of mapping the given transformation over
- /// this sequence.
- ///
- /// Use this method to receive a sequence of nonoptional values when your
- /// transformation produces an optional value.
- ///
- /// - Parameter transform: A closure that accepts an element of this sequence
- /// as its argument and returns an optional value.
- ///
- /// - Complexity: O(1)
- @inline(__always)
- @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
- message: "Please use compactMap(_:) for the case where closure returns an optional value")
- public func flatMap<ElementOfResult>(
- _ transform: @escaping (Elements.Element) -> ElementOfResult?
- ) -> LazyMapSequence<
- LazyFilterSequence<
- LazyMapSequence<Elements, ElementOfResult?>>,
- ElementOfResult
- > {
- return self.compactMap(transform)
- }
}
extension LazyCollectionProtocol {
@@ -113,27 +90,4 @@
> {
return self.map(transform).filter { $0 != nil }.map { $0! }
}
-
- /// Returns the non-`nil` results of mapping the given transformation over
- /// this collection.
- ///
- /// Use this method to receive a collection of nonoptional values when your
- /// transformation produces an optional value.
- ///
- /// - Parameter transform: A closure that accepts an element of this
- /// collection as its argument and returns an optional value.
- ///
- /// - Complexity: O(1)
- @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
- message: "Please use compactMap(_:) for the case where closure returns an optional value")
- @inlinable // FIXME(sil-serialize-all)
- public func flatMap<ElementOfResult>(
- _ transform: @escaping (Elements.Element) -> ElementOfResult?
- ) -> LazyMapCollection<
- LazyFilterCollection<
- LazyMapCollection<Elements, ElementOfResult?>>,
- ElementOfResult
- > {
- return self.map(transform).filter { $0 != nil }.map { $0! }
- }
}
diff --git a/stdlib/public/core/Flatten.swift b/stdlib/public/core/Flatten.swift
index 4ec2081..09b217d 100644
--- a/stdlib/public/core/Flatten.swift
+++ b/stdlib/public/core/Flatten.swift
@@ -525,10 +525,3 @@
return FlattenCollection(elements).lazy
}
}
-
-// @available(*, deprecated, renamed: "FlattenCollection.Index")
-public typealias FlattenCollectionIndex<T> = FlattenCollection<T>.Index where T : Collection, T.Element : Collection
-@available(*, deprecated, renamed: "FlattenCollection.Index")
-public typealias FlattenBidirectionalCollectionIndex<T> = FlattenCollection<T>.Index where T : BidirectionalCollection, T.Element : BidirectionalCollection
-@available(*, deprecated, renamed: "FlattenCollection")
-public typealias FlattenBidirectionalCollection<T> = FlattenCollection<T> where T : BidirectionalCollection, T.Element : BidirectionalCollection
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index b4419c8..2fb08da 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -2501,93 +2501,6 @@
% end
-extension FloatingPoint {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public func negated() -> Self {
- return -self
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public func adding(_ other: Self) -> Self {
- return self + other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public mutating func add(_ other: Self) {
- self += other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public func subtracting(_ other: Self) -> Self {
- return self - other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public mutating func subtract(_ other: Self) {
- self -= other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public func multiplied(by other: Self) -> Self {
- return self * other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public mutating func multiply(by other: Self) {
- self *= other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public func divided(by other: Self) -> Self {
- return self / other
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use operators instead.")
- public mutating func divide(by other: Self) {
- self /= other
- }
-}
-
-extension FloatingPoint {
- @available(*, unavailable, message: "Use bitPattern property instead")
- public func _toBitPattern() -> UInt {
- fatalError("unavailable")
- }
-
- @available(*, unavailable, message: "Use init(bitPattern:) instead")
- public static func _fromBitPattern(_ bits: UInt) -> Self {
- fatalError("unavailable")
- }
-}
-
-extension BinaryFloatingPoint {
- @available(*, unavailable, renamed: "isSignalingNaN")
- public var isSignaling: Bool {
- fatalError("unavailable")
- }
-
- @available(*, unavailable, renamed: "nan")
- public var NaN: Bool {
- fatalError("unavailable")
- }
- @available(*, unavailable, renamed: "nan")
- public var quietNaN: Bool {
- fatalError("unavailable")
- }
-}
-
-@available(*, unavailable, renamed: "FloatingPoint")
-public typealias FloatingPointType = FloatingPoint
-
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index d780d6c..a2a76e7 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1559,6 +1559,13 @@
}
}
+extension ${Self}: _HasCustomAnyHashableRepresentation {
+ // Not @inlinable
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return AnyHashable(_box: _${Self}AnyHashableBox(self))
+ }
+}
+
extension ${Self} {
/// The magnitude of this value.
///
@@ -1810,43 +1817,90 @@
}
//===----------------------------------------------------------------------===//
-// Deprecated operators
+// AnyHashable
//===----------------------------------------------------------------------===//
-@_transparent
-@available(*, unavailable, message: "use += 1")
-@discardableResult
-public prefix func ++ (rhs: inout ${Self}) -> ${Self} {
- fatalError("++ is not available")
-}
-@_transparent
-@available(*, unavailable, message: "use -= 1")
-@discardableResult
-public prefix func -- (rhs: inout ${Self}) -> ${Self} {
- fatalError("-- is not available")
-}
-@_transparent
-@available(*, unavailable, message: "use += 1")
-@discardableResult
-public postfix func ++ (lhs: inout ${Self}) -> ${Self} {
- fatalError("++ is not available")
-}
-@_transparent
-@available(*, unavailable, message: "use -= 1")
-@discardableResult
-public postfix func -- (lhs: inout ${Self}) -> ${Self} {
- fatalError("-- is not available")
-}
+internal struct _${Self}AnyHashableBox: _AnyHashableBox {
+ internal typealias Base = ${Self}
+ internal let _value: Base
-extension ${Self} {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Please use the `abs(_:)` free function")
- @_transparent
- public static func abs(_ x: ${Self}) -> ${Self} {
- return x.magnitude
+ internal init(_ value: Base) {
+ self._value = value
+ }
+
+ internal var _canonicalBox: _AnyHashableBox {
+ // Float and Double are bridged with NSNumber, so we have to follow
+ // NSNumber's rules for equality. I.e., we need to make sure equal
+ // numerical values end up in identical boxes after canonicalization, so
+ // that _isEqual will consider them equal and they're hashed the same way.
+ //
+ // Note that these AnyHashable boxes don't currently feed discriminator bits
+ // to the hasher, so we allow repeatable collisions. E.g., -1 will always
+ // collide with UInt64.max.
+ if _value < 0 {
+ if let i = Int64(exactly: _value) {
+ return _IntegerAnyHashableBox(i)
+ }
+ } else {
+ if let i = UInt64(exactly: _value) {
+ return _IntegerAnyHashableBox(i)
+ }
+ }
+ if let d = Double(exactly: _value) {
+ return _DoubleAnyHashableBox(d)
+ }
+ // If a value can't be represented by a Double, keep it in its original
+ // representation so that it won't compare equal to approximations. (So that
+ // we don't round off Float80 values.)
+ return self
+ }
+
+ internal func _isEqual(to box: _AnyHashableBox) -> Bool? {
+ _sanityCheck(Int64(exactly: _value) == nil, "self isn't canonical")
+ _sanityCheck(UInt64(exactly: _value) == nil, "self isn't canonical")
+ if let box = box as? _${Self}AnyHashableBox {
+ return _value == box._value
+ }
+ return nil
+ }
+
+ internal var _hashValue: Int {
+ return _rawHashValue(_seed: Hasher._seed)
+ }
+
+ internal func _hash(into hasher: inout Hasher) {
+ _sanityCheck(Int64(exactly: _value) == nil, "self isn't canonical")
+ _sanityCheck(UInt64(exactly: _value) == nil, "self isn't canonical")
+ hasher.combine(_value)
+ }
+
+ internal func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ var hasher = Hasher(_seed: _seed)
+ _hash(into: &hasher)
+ return hasher.finalize()
+ }
+
+ internal var _base: Any {
+ return _value
+ }
+
+ internal func _unbox<T: Hashable>() -> T? {
+ return _value as? T
+ }
+
+ internal func _downCastConditional<T>(
+ into result: UnsafeMutablePointer<T>
+ ) -> Bool {
+ guard let value = _value as? T else { return false }
+ result.initialize(to: value)
+ return true
}
}
+//===----------------------------------------------------------------------===//
+// Deprecated operators
+//===----------------------------------------------------------------------===//
+
% if bits == 80:
#else
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index 09dfc6b..73acf81 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -14,7 +14,6 @@
"StaticString.swift",
"String.swift",
"StringBridge.swift",
- "StringCharacterView.swift",
"StringComparable.swift",
"StringComparison.swift",
"StringObject.swift",
@@ -145,7 +144,6 @@
"FloatingPointTypes.swift"]}
],
"Optional": [
- "ImplicitlyUnwrappedOptional.swift",
"Optional.swift"
],
"Pointer": [
@@ -193,6 +191,7 @@
"Equatable.swift",
"Comparable.swift",
"Hashable.swift",
- "Codable.swift"
+ "Codable.swift",
+ "MigrationSupport.swift"
]
}
diff --git a/stdlib/public/core/Hasher.swift b/stdlib/public/core/Hasher.swift
index 0aaf1a1..5e48f11 100644
--- a/stdlib/public/core/Hasher.swift
+++ b/stdlib/public/core/Hasher.swift
@@ -437,6 +437,7 @@
seed: (UInt64, UInt64),
bytes value: UInt64,
count: Int) -> Int {
+ _sanityCheck(count >= 0 && count < 8)
var core = RawCore(seed: seed)
let tbc = _HasherTailBuffer(tail: value, byteCount: count)
return Int(truncatingIfNeeded: core.finalize(tailAndByteCount: tbc.value))
diff --git a/stdlib/public/core/ImplicitlyUnwrappedOptional.swift b/stdlib/public/core/ImplicitlyUnwrappedOptional.swift
deleted file mode 100644
index 289a0d1..0000000
--- a/stdlib/public/core/ImplicitlyUnwrappedOptional.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-/// An optional type that allows implicit member access.
-///
-/// The `ImplicitlyUnwrappedOptional` type is deprecated. To create an optional
-/// value that is implicitly unwrapped, place an exclamation mark (`!`) after
-/// the type that you want to denote as optional.
-///
-/// // An implicitly unwrapped optional integer
-/// let guaranteedNumber: Int! = 6
-///
-/// // An optional integer
-/// let possibleNumber: Int? = 5
-@available(*, unavailable, renamed: "Optional")
-public typealias ImplicitlyUnwrappedOptional<Wrapped> = Optional<Wrapped>
diff --git a/stdlib/public/core/Indices.swift b/stdlib/public/core/Indices.swift
index 018c19e..0a45f88 100644
--- a/stdlib/public/core/Indices.swift
+++ b/stdlib/public/core/Indices.swift
@@ -127,8 +127,3 @@
endIndex: self.endIndex)
}
}
-
-@available(*, deprecated, renamed: "DefaultIndices")
-public typealias DefaultBidirectionalIndices<T> = DefaultIndices<T> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "DefaultIndices")
-public typealias DefaultRandomAccessIndices<T> = DefaultIndices<T> where T : RandomAccessCollection
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 9562cd7..99ad000 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -2270,7 +2270,7 @@
/// methods, the standard library provides default implementations for all
/// other arithmetic methods and operators.
public protocol FixedWidthInteger :
- BinaryInteger, LosslessStringConvertible, _BitwiseOperations
+ BinaryInteger, LosslessStringConvertible
where Magnitude : FixedWidthInteger
{
/// The number of bits used for the underlying binary representation of
@@ -2424,11 +2424,6 @@
}
extension FixedWidthInteger {
- /// The empty bitset.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
- public static var allZeros: Self { return 0 }
-
/// The number of bits in the binary representation of this value.
@inlinable
public var bitWidth: Int { return Self.bitWidth }
@@ -2536,93 +2531,6 @@
% for Range in ['Range', 'ClosedRange']:
% exampleRange = '1..<100' if Range == 'Range' else '1...100'
-extension ${Range}
- where Bound: FixedWidthInteger, Bound.Stride : SignedInteger,
- Bound.Magnitude: UnsignedInteger
-{
-
- /// Returns a random element of the range, using the given generator as
- /// a source for randomness.
- ///
- /// You can use this method to select a random element of a range when you
- /// are using a custom random number generator. If you're generating a random
- /// number, in most cases, you should prefer using the `random(in:using:)`
- /// static method of the desired numeric type. That static method is available
- /// for both integer and floating point types, and returns a non-optional
- /// value.
- ///
- /// - Parameter generator: The random number generator to use when choosing
- /// a random element.
- /// - Returns: A random element of the range.
-% if 'Closed' not in Range:
- /// If the range is empty, the method returns `nil`.
-% else:
- /// This method never returns `nil`.
-% end
- @inlinable
- public func randomElement<T: RandomNumberGenerator>(
- using generator: inout T
- ) -> Element? {
- guard !isEmpty else {
- return nil
- }
- // Compute delta, the distance between the lower and upper bounds. This
- // value may not representable by the type Bound if Bound is signed, but
- // is always representable as Bound.Magnitude.
-% if 'Closed' in Range:
- var delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
-% else:
- let delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
-% end
-% if 'Closed' in Range:
- // Subtle edge case: if the range is the whole set of representable values,
- // then adding one to delta to account for a closed range will overflow.
- // If we used &+ instead, the result would be zero, which isn't helpful,
- // so we actually need to handle this case separately.
- if delta == Bound.Magnitude.max {
- return Bound(truncatingIfNeeded: generator.next() as Bound.Magnitude)
- }
- // Need to widen delta to account for the right-endpoint of a closed range.
- delta += 1
-% end
- // The mathematical result we want is lowerBound plus a random value in
- // 0 ..< delta. We need to be slightly careful about how we do this
- // arithmetic; the Bound type cannot generally represent the random value,
- // so we use a wrapping addition on Bound.Magnitude. This will often
- // overflow, but produces the correct bit pattern for the result when
- // converted back to Bound.
- return Bound(truncatingIfNeeded:
- Bound.Magnitude(truncatingIfNeeded: lowerBound) &+
- generator.next(upperBound: delta)
- )
- }
-
- /// Returns a random element of the range, using the given generator as
- /// a source for randomness.
- ///
- /// You can use this method to select a random element of a range when you
- /// are using a custom random number generator. If you're generating a random
- /// number, in most cases, you should prefer using the `random(in:)`
- /// static method of the desired numeric type. That static method is available
- /// for both integer and floating point types, and returns a non-optional
- /// value.
- ///
- /// This method uses the default random generator, `Random.default`. Calling
- /// `(${exampleRange}).randomElement()` is equivalent to calling
- /// `(${exampleRange}).randomElement(using: &Random.default)`.
- ///
- /// - Returns: A random element of the range.
-% if 'Closed' not in Range:
- /// If the range is empty, the method returns `nil`.
-% else:
- /// This method never returns `nil`.
-% end
- @inlinable
- public func randomElement() -> Element? {
- return randomElement(using: &Random.default)
- }
-}
-
extension FixedWidthInteger
where Self.Stride : SignedInteger,
Self.Magnitude : UnsignedInteger {
@@ -2658,7 +2566,36 @@
!range.isEmpty,
"Can't get random value with an empty range"
)
- return range.randomElement(using: &generator)!
+
+ // Compute delta, the distance between the lower and upper bounds. This
+ // value may not representable by the type Bound if Bound is signed, but
+ // is always representable as Bound.Magnitude.
+% if 'Closed' in Range:
+ var delta = Magnitude(truncatingIfNeeded: range.upperBound &- range.lowerBound)
+% else:
+ let delta = Magnitude(truncatingIfNeeded: range.upperBound &- range.lowerBound)
+% end
+% if 'Closed' in Range:
+ // Subtle edge case: if the range is the whole set of representable values,
+ // then adding one to delta to account for a closed range will overflow.
+ // If we used &+ instead, the result would be zero, which isn't helpful,
+ // so we actually need to handle this case separately.
+ if delta == Magnitude.max {
+ return Self(truncatingIfNeeded: generator.next() as Magnitude)
+ }
+ // Need to widen delta to account for the right-endpoint of a closed range.
+ delta += 1
+% end
+ // The mathematical result we want is lowerBound plus a random value in
+ // 0 ..< delta. We need to be slightly careful about how we do this
+ // arithmetic; the Bound type cannot generally represent the random value,
+ // so we use a wrapping addition on Bound.Magnitude. This will often
+ // overflow, but produces the correct bit pattern for the result when
+ // converted back to Bound.
+ return Self(truncatingIfNeeded:
+ Magnitude(truncatingIfNeeded: range.lowerBound) &+
+ generator.next(upperBound: delta)
+ )
}
/// Returns a random value within the specified range.
@@ -3882,41 +3819,31 @@
/// of this instance.
@inlinable
public func hash(into hasher: inout Hasher) {
- // FIXME(hasher): To correctly bridge `Set`s/`Dictionary`s containing
- // `AnyHashable`-boxed integers, all integer values are currently required
- // to hash exactly the same way as the corresponding (U)Int64 value. To fix
- // this, we should introduce a custom AnyHashable box for integer values
- // that sign-extends values to 64 bits.
- % if bits <= word_bits:
- hasher._combine(_lowWord)
- % elif bits == 2 * word_bits:
- if let word = ${"" if signed else "U"}Int(exactly: self) {
- hasher._combine(word._lowWord)
- } else {
- hasher._combine(UInt64(_value))
- }
- % else:
- fatalError("Unsupported integer width")
- % end
+ hasher._combine(${U}${Self}(_value))
}
@inlinable
public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
- // FIXME(hasher): Note that the AnyHashable concern applies here too,
- // because hashValue uses top-level hashing.
- % if bits <= word_bits:
- return Hasher._hash(seed: seed, _lowWord)
- % elif bits == 2 * word_bits:
- if let word = ${"" if signed else "U"}Int(exactly: self) {
- return Hasher._hash(seed: seed, word._lowWord)
- }
+ % if bits == 64:
return Hasher._hash(seed: seed, UInt64(_value))
+ % elif bits == word_bits:
+ return Hasher._hash(seed: seed, UInt(_value))
% else:
- fatalError("Unsupported integer width")
+ return Hasher._hash(
+ seed: seed,
+ bytes: UInt64(truncatingIfNeeded: ${U}${Self}(_value)),
+ count: ${bits / 8})
% end
}
}
+extension ${Self} : _HasCustomAnyHashableRepresentation {
+ // Not @inlinable
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return AnyHashable(_box: _IntegerAnyHashableBox(self))
+ }
+}
+
// Create an ambiguity when indexing or slicing
// Range[OfStrideable]<${Self}> outside a generic context. See
@@ -4095,48 +4022,6 @@
#endif
}
-// Swift 3 compatibility APIs
-
-@available(swift, obsoleted: 4, renamed: "BinaryInteger")
-public typealias Integer = BinaryInteger
-
-@available(swift, obsoleted: 4, renamed: "BinaryInteger")
-public typealias IntegerArithmetic = BinaryInteger
-
-@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
-public typealias SignedNumber = SignedNumeric & Comparable
-
-@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
-public typealias AbsoluteValuable = SignedNumeric & Comparable
-
-@available(swift, obsoleted: 4, renamed: "SignedInteger")
-public typealias _SignedInteger = SignedInteger
-
-extension SignedNumeric where Self : Comparable {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "Please use the 'abs(_:)' free function.")
- @_transparent
- public static func abs(_ x: Self) -> Self {
- return Swift.abs(x)
- }
-}
-
-extension BinaryInteger {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public func toIntMax() -> Int64 {
- return Int64(self)
- }
-}
-
-extension UnsignedInteger {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public func toUIntMax() -> UInt64 {
- return UInt64(self)
- }
-}
-
// FIXME(integers): These overloads allow expressions like the following in
// Swift 3 compatibility mode:
// let x = 1 << i32
@@ -4256,6 +4141,73 @@
% end
}
+internal struct _IntegerAnyHashableBox<
+ Base: FixedWidthInteger
+>: _AnyHashableBox {
+ internal let _value: Base
+
+ internal init(_ value: Base) {
+ self._value = value
+ }
+
+ internal var _canonicalBox: _AnyHashableBox {
+ // We need to follow NSNumber semantics here; the AnyHashable forms of
+ // integer types holding the same mathematical value should compare equal.
+ // Sign-extend value to a 64-bit integer. This will generate hash conflicts
+ // between, say -1 and UInt.max, but that's fine.
+ if _value < 0 {
+ return _IntegerAnyHashableBox<Int64>(Int64(truncatingIfNeeded: _value))
+ }
+ return _IntegerAnyHashableBox<UInt64>(UInt64(truncatingIfNeeded: _value))
+ }
+
+ internal func _isEqual(to box: _AnyHashableBox) -> Bool? {
+ if Base.self == UInt64.self {
+ guard let box = box as? _IntegerAnyHashableBox<UInt64> else { return nil }
+ return _value == box._value
+ }
+ if Base.self == Int64.self {
+ guard let box = box as? _IntegerAnyHashableBox<Int64> else { return nil }
+ return _value == box._value
+ }
+ _preconditionFailure("self isn't canonical")
+ }
+
+ internal var _hashValue: Int {
+ _sanityCheck(Base.self == UInt64.self || Base.self == Int64.self,
+ "self isn't canonical")
+ return _value.hashValue
+ }
+
+ internal func _hash(into hasher: inout Hasher) {
+ _sanityCheck(Base.self == UInt64.self || Base.self == Int64.self,
+ "self isn't canonical")
+ _value.hash(into: &hasher)
+ }
+
+ internal func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ _sanityCheck(Base.self == UInt64.self || Base.self == Int64.self,
+ "self isn't canonical")
+ return _value._rawHashValue(seed: _seed)
+ }
+
+ internal var _base: Any {
+ return _value
+ }
+
+ internal func _unbox<T: Hashable>() -> T? {
+ return _value as? T
+ }
+
+ internal func _downCastConditional<T>(
+ into result: UnsafeMutablePointer<T>
+ ) -> Bool {
+ guard let value = _value as? T else { return false }
+ result.initialize(to: value)
+ return true
+ }
+}
+
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
diff --git a/stdlib/public/core/Join.swift b/stdlib/public/core/Join.swift
index 4dbc3b5..b17908a 100644
--- a/stdlib/public/core/Join.swift
+++ b/stdlib/public/core/Join.swift
@@ -191,6 +191,3 @@
return JoinedSequence(base: self, separator: separator)
}
}
-
-// @available(*, deprecated, renamed: "JoinedSequence.Iterator")
-public typealias JoinedIterator<T: Sequence> = JoinedSequence<T>.Iterator where T.Element: Sequence
diff --git a/stdlib/public/core/LazyCollection.swift b/stdlib/public/core/LazyCollection.swift
index d5dd497..b9ce84e 100644
--- a/stdlib/public/core/LazyCollection.swift
+++ b/stdlib/public/core/LazyCollection.swift
@@ -263,8 +263,3 @@
extension Slice: LazyCollectionProtocol where Base: LazyCollectionProtocol { }
extension ReversedCollection: LazySequenceProtocol where Base: LazySequenceProtocol { }
extension ReversedCollection: LazyCollectionProtocol where Base: LazyCollectionProtocol { }
-
-@available(*, deprecated, renamed: "LazyCollection")
-public typealias LazyBidirectionalCollection<T> = LazyCollection<T> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "LazyCollection")
-public typealias LazyRandomAccessCollection<T> = LazyCollection<T> where T : RandomAccessCollection
diff --git a/stdlib/public/core/Map.swift b/stdlib/public/core/Map.swift
index 9f2ef4c..9ca87ec 100644
--- a/stdlib/public/core/Map.swift
+++ b/stdlib/public/core/Map.swift
@@ -257,22 +257,6 @@
}
}
-extension LazyMapCollection {
- // This overload is needed to re-enable Swift 3 source compatibility related
- // to a bugfix in ranking behavior of the constraint solver.
- @available(swift, obsoleted: 4.0)
- public static func + <
- Other : LazyCollectionProtocol
- >(lhs: LazyMapCollection, rhs: Other) -> [Element]
- where Other.Element == Element {
- var result: [Element] = []
- result.reserveCapacity(numericCast(lhs.count + rhs.count))
- result.append(contentsOf: lhs)
- result.append(contentsOf: rhs)
- return result
- }
-}
-
extension LazyMapSequence {
@inlinable
@available(swift, introduced: 5)
@@ -296,10 +280,3 @@
transform: {transform(self._transform($0))})
}
}
-
-// @available(*, deprecated, renamed: "LazyMapSequence.Iterator")
-public typealias LazyMapIterator<T, E> = LazyMapSequence<T, E>.Iterator where T: Sequence
-@available(*, deprecated, renamed: "LazyMapCollection")
-public typealias LazyMapBidirectionalCollection<T, E> = LazyMapCollection<T, E> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "LazyMapCollection")
-public typealias LazyMapRandomAccessCollection<T, E> = LazyMapCollection<T, E> where T : RandomAccessCollection
diff --git a/stdlib/public/core/MigrationSupport.swift b/stdlib/public/core/MigrationSupport.swift
new file mode 100644
index 0000000..9f9e8ad
--- /dev/null
+++ b/stdlib/public/core/MigrationSupport.swift
@@ -0,0 +1,1288 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+// This file contains only support for types deprecated from previous versions
+// of Swift
+
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "BidirectionalCollection", message: "it will be removed in Swift 5.0. Please use 'BidirectionalCollection' instead")
+public typealias BidirectionalIndexable = BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Collection", message: "it will be removed in Swift 5.0. Please use 'Collection' instead")
+public typealias IndexableBase = Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Collection", message: "it will be removed in Swift 5.0. Please use 'Collection' instead")
+public typealias Indexable = Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "MutableCollection", message: "it will be removed in Swift 5.0. Please use 'MutableCollection' instead")
+public typealias MutableIndexable = MutableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "RandomAccessCollection", message: "it will be removed in Swift 5.0. Please use 'RandomAccessCollection' instead")
+public typealias RandomAccessIndexable = RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "RangeReplaceableIndexable", message: "it will be removed in Swift 5.0. Please use 'RangeReplaceableCollection' instead")
+public typealias RangeReplaceableIndexable = RangeReplaceableCollection
+@available(*, deprecated: 4.2, renamed: "EnumeratedSequence.Iterator")
+public typealias EnumeratedIterator<T: Sequence> = EnumeratedSequence<T>.Iterator
+@available(*,deprecated: 4.2/*, obsoleted: 5.0*/, renamed: "CollectionOfOne.Iterator")
+public typealias IteratorOverOne<T> = CollectionOfOne<T>.Iterator
+@available(*, deprecated: 4.2/*, obsoleted: 5.0*/, renamed: "EmptyCollection.Iterator")
+public typealias EmptyIterator<T> = EmptyCollection<T>.Iterator
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyFilterSequence.Iterator")
+public typealias LazyFilterIterator<T: Sequence> = LazyFilterSequence<T>.Iterator
+@available(swift, deprecated: 3.1/*, obsoleted: 5.0*/, message: "Use Base.Index")
+public typealias LazyFilterIndex<Base: Collection> = Base.Index
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileSequence.Iterator")
+public typealias LazyDropWhileIterator<T> = LazyDropWhileSequence<T>.Iterator where T: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileCollection.Index")
+public typealias LazyDropWhileIndex<T> = LazyDropWhileCollection<T>.Index where T: Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileCollection")
+public typealias LazyDropWhileBidirectionalCollection<T> = LazyDropWhileCollection<T> where T: BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyFilterCollection")
+public typealias LazyFilterBidirectionalCollection<T> = LazyFilterCollection<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyMapSequence.Iterator")
+public typealias LazyMapIterator<T, E> = LazyMapSequence<T, E>.Iterator where T: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyMapCollection")
+public typealias LazyMapBidirectionalCollection<T, E> = LazyMapCollection<T, E> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyMapCollection")
+public typealias LazyMapRandomAccessCollection<T, E> = LazyMapCollection<T, E> where T : RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyCollection")
+public typealias LazyBidirectionalCollection<T> = LazyCollection<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyCollection")
+public typealias LazyRandomAccessCollection<T> = LazyCollection<T> where T : RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "FlattenCollection.Index")
+public typealias FlattenCollectionIndex<T> = FlattenCollection<T>.Index where T : Collection, T.Element : Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "FlattenCollection.Index")
+public typealias FlattenBidirectionalCollectionIndex<T> = FlattenCollection<T>.Index where T : BidirectionalCollection, T.Element : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "FlattenCollection")
+public typealias FlattenBidirectionalCollection<T> = FlattenCollection<T> where T : BidirectionalCollection, T.Element : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "JoinedSequence.Iterator")
+public typealias JoinedIterator<T: Sequence> = JoinedSequence<T>.Iterator where T.Element: Sequence
+@available(*, deprecated: 4.2/*, obsoleted: 5.0*/, renamed: "Zip2Sequence.Iterator")
+public typealias Zip2Iterator<T, U> = Zip2Sequence<T, U>.Iterator where T: Sequence, U: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileSequence.Iterator")
+public typealias LazyPrefixWhileIterator<T> = LazyPrefixWhileSequence<T>.Iterator where T: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileCollection.Index")
+public typealias LazyPrefixWhileIndex<T> = LazyPrefixWhileCollection<T>.Index where T: Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyPrefixWhileCollection")
+public typealias LazyPrefixWhileBidirectionalCollection<T> = LazyPrefixWhileCollection<T> where T: BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ReversedCollection")
+public typealias ReversedRandomAccessCollection<T: RandomAccessCollection> = ReversedCollection<T>
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ReversedCollection.Index")
+public typealias ReversedIndex<T: BidirectionalCollection> = ReversedCollection<T>
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias BidirectionalSlice<T> = Slice<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RandomAccessSlice<T> = Slice<T> where T : RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RangeReplaceableSlice<T> = Slice<T> where T : RangeReplaceableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RangeReplaceableBidirectionalSlice<T> = Slice<T> where T : RangeReplaceableCollection & BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RangeReplaceableRandomAccessSlice<T> = Slice<T> where T : RangeReplaceableCollection & RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableSlice<T> = Slice<T> where T : MutableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRangeReplaceableSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRangeReplaceableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRangeReplaceableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "DefaultIndices")
+public typealias DefaultBidirectionalIndices<T> = DefaultIndices<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "DefaultIndices")
+public typealias DefaultRandomAccessIndices<T> = DefaultIndices<T> where T : RandomAccessCollection
+
+// Deprecated by SE-0115.
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByNilLiteral")
+public typealias NilLiteralConvertible = ExpressibleByNilLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinIntegerLiteral")
+public typealias _BuiltinIntegerLiteralConvertible = _ExpressibleByBuiltinIntegerLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByIntegerLiteral")
+public typealias IntegerLiteralConvertible = ExpressibleByIntegerLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinFloatLiteral")
+public typealias _BuiltinFloatLiteralConvertible = _ExpressibleByBuiltinFloatLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByFloatLiteral")
+public typealias FloatLiteralConvertible = ExpressibleByFloatLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinBooleanLiteral")
+public typealias _BuiltinBooleanLiteralConvertible = _ExpressibleByBuiltinBooleanLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByBooleanLiteral")
+public typealias BooleanLiteralConvertible = ExpressibleByBooleanLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinUnicodeScalarLiteral")
+public typealias _BuiltinUnicodeScalarLiteralConvertible = _ExpressibleByBuiltinUnicodeScalarLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByUnicodeScalarLiteral")
+public typealias UnicodeScalarLiteralConvertible = ExpressibleByUnicodeScalarLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinExtendedGraphemeClusterLiteral")
+public typealias _BuiltinExtendedGraphemeClusterLiteralConvertible = _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByExtendedGraphemeClusterLiteral")
+public typealias ExtendedGraphemeClusterLiteralConvertible = ExpressibleByExtendedGraphemeClusterLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinStringLiteral")
+public typealias _BuiltinStringLiteralConvertible = _ExpressibleByBuiltinStringLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinUTF16StringLiteral")
+public typealias _BuiltinUTF16StringLiteralConvertible = _ExpressibleByBuiltinUTF16StringLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByStringLiteral")
+public typealias StringLiteralConvertible = ExpressibleByStringLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByArrayLiteral")
+public typealias ArrayLiteralConvertible = ExpressibleByArrayLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByDictionaryLiteral")
+public typealias DictionaryLiteralConvertible = ExpressibleByDictionaryLiteral
+@available(*, deprecated, message: "it will be replaced or redesigned in Swift 4.0. Instead of conforming to 'StringInterpolationConvertible', consider adding an 'init(_:String)'")
+public typealias StringInterpolationConvertible = ExpressibleByStringInterpolation
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByColorLiteral")
+public typealias _ColorLiteralConvertible = _ExpressibleByColorLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByImageLiteral")
+public typealias _ImageLiteralConvertible = _ExpressibleByImageLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByFileReferenceLiteral")
+public typealias _FileReferenceLiteralConvertible = _ExpressibleByFileReferenceLiteral
+
+@available(*, deprecated, obsoleted: 5.0, renamed: "ClosedRange.Index")
+public typealias ClosedRangeIndex<T> = ClosedRange<T>.Index where T: Strideable, T.Stride: SignedInteger
+
+/// An optional type that allows implicit member access.
+///
+/// The `ImplicitlyUnwrappedOptional` type is deprecated. To create an optional
+/// value that is implicitly unwrapped, place an exclamation mark (`!`) after
+/// the type that you want to denote as optional.
+///
+/// // An implicitly unwrapped optional integer
+/// let guaranteedNumber: Int! = 6
+///
+/// // An optional integer
+/// let possibleNumber: Int? = 5
+@available(*, unavailable, renamed: "Optional")
+public typealias ImplicitlyUnwrappedOptional<Wrapped> = Optional<Wrapped>
+
+@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use FixedWidthInteger protocol instead")
+public typealias BitwiseOperations = _BitwiseOperations
+
+public protocol _BitwiseOperations {
+ static func & (lhs: Self, rhs: Self) -> Self
+ static func | (lhs: Self, rhs: Self) -> Self
+ static func ^ (lhs: Self, rhs: Self) -> Self
+ static prefix func ~ (x: Self) -> Self
+ static var allZeros: Self { get }
+}
+
+extension _BitwiseOperations {
+ @available(swift, obsoleted: 4.1)
+ public static func |= (lhs: inout Self, rhs: Self) {
+ lhs = lhs | rhs
+ }
+
+ @available(swift, obsoleted: 4.1)
+ public static func &= (lhs: inout Self, rhs: Self) {
+ lhs = lhs & rhs
+ }
+
+ @available(swift, obsoleted: 4.1)
+ public static func ^= (lhs: inout Self, rhs: Self) {
+ lhs = lhs ^ rhs
+ }
+}
+
+extension FloatingPoint {
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public func negated() -> Self {
+ return -self
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public func adding(_ other: Self) -> Self {
+ return self + other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public mutating func add(_ other: Self) {
+ self += other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public func subtracting(_ other: Self) -> Self {
+ return self - other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public mutating func subtract(_ other: Self) {
+ self -= other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public func multiplied(by other: Self) -> Self {
+ return self * other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public mutating func multiply(by other: Self) {
+ self *= other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public func divided(by other: Self) -> Self {
+ return self / other
+ }
+
+ @available(swift, obsoleted: 4, message: "Please use operators instead.")
+ public mutating func divide(by other: Self) {
+ self /= other
+ }
+}
+
+extension FloatingPoint {
+ @available(*, unavailable, message: "Use bitPattern property instead")
+ public func _toBitPattern() -> UInt {
+ fatalError("unavailable")
+ }
+
+ @available(*, unavailable, message: "Use init(bitPattern:) instead")
+ public static func _fromBitPattern(_ bits: UInt) -> Self {
+ fatalError("unavailable")
+ }
+}
+
+extension BinaryFloatingPoint {
+ @available(*, unavailable, renamed: "isSignalingNaN")
+ public var isSignaling: Bool {
+ fatalError("unavailable")
+ }
+
+ @available(*, unavailable, renamed: "nan")
+ public var NaN: Bool {
+ fatalError("unavailable")
+ }
+ @available(*, unavailable, renamed: "nan")
+ public var quietNaN: Bool {
+ fatalError("unavailable")
+ }
+}
+
+@available(*, unavailable, renamed: "FloatingPoint")
+public typealias FloatingPointType = FloatingPoint
+
+// Swift 3 compatibility APIs
+@available(swift, obsoleted: 4, renamed: "BinaryInteger")
+public typealias Integer = BinaryInteger
+
+@available(swift, obsoleted: 4, renamed: "BinaryInteger")
+public typealias IntegerArithmetic = BinaryInteger
+
+@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
+public typealias SignedNumber = SignedNumeric & Comparable
+
+@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
+public typealias AbsoluteValuable = SignedNumeric & Comparable
+
+@available(swift, obsoleted: 4, renamed: "SignedInteger")
+public typealias _SignedInteger = SignedInteger
+
+extension SignedNumeric where Self : Comparable {
+ @available(swift, obsoleted: 4, message: "Please use the 'abs(_:)' free function.")
+ @_transparent
+ public static func abs(_ x: Self) -> Self {
+ return Swift.abs(x)
+ }
+}
+
+extension BinaryInteger {
+ @available(swift, obsoleted: 4)
+ public func toIntMax() -> Int64 {
+ return Int64(self)
+ }
+}
+
+extension UnsignedInteger {
+ @available(swift, obsoleted: 4)
+ public func toUIntMax() -> UInt64 {
+ return UInt64(self)
+ }
+}
+
+extension Range where Bound: Strideable, Bound.Stride : SignedInteger {
+ /// Now that Range is conditionally a collection when Bound: Strideable,
+ /// CountableRange is no longer needed. This is a deprecated initializer
+ /// for any remaining uses of Range(countableRange).
+ @available(*, deprecated: 4.2/*, obsoleted: 5.0*/, message: "CountableRange is now a Range. No need to convert any more.")
+ public init(_ other: Range<Bound>) {
+ self = other
+ }
+}
+
+extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {
+ /// Now that Range is conditionally a collection when Bound: Strideable,
+ /// CountableRange is no longer needed. This is a deprecated initializer
+ /// for any remaining uses of Range(countableRange).
+ @available(*, deprecated: 4.2/*, obsoleted: 5.0*/, message: "CountableClosedRange is now a ClosedRange. No need to convert any more.")
+ public init(_ other: ClosedRange<Bound>) {
+ self = other
+ }
+}
+
+extension _ExpressibleByColorLiteral {
+ @available(swift, deprecated: 3.2, obsoleted: 4.0, message: "This initializer is only meant to be used by color literals")
+ public init(colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) {
+ self.init(_colorLiteralRed: red, green: green, blue: blue, alpha: alpha)
+ }
+}
+
+extension LazySequenceProtocol {
+ /// Returns the non-`nil` results of mapping the given transformation over
+ /// this sequence.
+ ///
+ /// Use this method to receive a sequence of nonoptional values when your
+ /// transformation produces an optional value.
+ ///
+ /// - Parameter transform: A closure that accepts an element of this sequence
+ /// as its argument and returns an optional value.
+ ///
+ /// - Complexity: O(1)
+ @available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
+ public func flatMap<ElementOfResult>(
+ _ transform: @escaping (Elements.Element) -> ElementOfResult?
+ ) -> LazyMapSequence<
+ LazyFilterSequence<
+ LazyMapSequence<Elements, ElementOfResult?>>,
+ ElementOfResult
+ > {
+ return self.compactMap(transform)
+ }
+}
+
+extension LazyMapCollection {
+ // This overload is needed to re-enable Swift 3 source compatibility related
+ // to a bugfix in ranking behavior of the constraint solver.
+ @available(swift, obsoleted: 4.0)
+ public static func + <
+ Other : LazyCollectionProtocol
+ >(lhs: LazyMapCollection, rhs: Other) -> [Element]
+ where Other.Element == Element {
+ var result: [Element] = []
+ result.reserveCapacity(numericCast(lhs.count + rhs.count))
+ result.append(contentsOf: lhs)
+ result.append(contentsOf: rhs)
+ return result
+ }
+}
+
+@available(*, unavailable, message: "use += 1")
+@discardableResult
+public prefix func ++ <F: FloatingPoint>(rhs: inout F) -> F {
+ fatalError("++ is not available")
+}
+@available(*, unavailable, message: "use -= 1")
+@discardableResult
+public prefix func -- <F: FloatingPoint>(rhs: inout F) -> F {
+ fatalError("-- is not available")
+}
+@available(*, unavailable, message: "use += 1")
+@discardableResult
+public postfix func ++ <F: FloatingPoint>(lhs: inout F) -> F {
+ fatalError("++ is not available")
+}
+@available(*, unavailable, message: "use -= 1")
+@discardableResult
+public postfix func -- <F: FloatingPoint>(lhs: inout F) -> F {
+ fatalError("-- is not available")
+}
+
+extension FloatingPoint {
+ @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Please use the `abs(_:)` free function")
+ public static func abs(_ x: Self) -> Self {
+ return x.magnitude
+ }
+}
+
+extension FixedWidthInteger {
+ /// The empty bitset.
+ @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
+ public static var allZeros: Self { return 0 }
+}
+
+extension LazyCollectionProtocol {
+ /// Returns the non-`nil` results of mapping the given transformation over
+ /// this collection.
+ ///
+ /// Use this method to receive a collection of nonoptional values when your
+ /// transformation produces an optional value.
+ ///
+ /// - Parameter transform: A closure that accepts an element of this
+ /// collection as its argument and returns an optional value.
+ ///
+ /// - Complexity: O(1)
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "compactMap(_:)",
+ message: "Please use compactMap(_:) for the case where closure returns an optional value")
+ public func flatMap<ElementOfResult>(
+ _ transform: @escaping (Elements.Element) -> ElementOfResult?
+ ) -> LazyMapCollection<
+ LazyFilterCollection<
+ LazyMapCollection<Elements, ElementOfResult?>>,
+ ElementOfResult
+ > {
+ return self.map(transform).filter { $0 != nil }.map { $0! }
+ }
+}
+
+extension String {
+ /// A view of a string's contents as a collection of characters.
+ ///
+ /// Previous versions of Swift provided this view since String
+ /// itself was not a collection. String is now a collection of
+ /// characters, so this type is now just an alias for String.
+ @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use String directly")
+ public typealias CharacterView = String
+
+ /// A view of the string's contents as a collection of characters.
+ ///
+ /// Previous versions of Swift provided this view since String
+ /// itself was not a collection. String is now a collection of
+ /// characters, so this type is now just an alias for String.
+ @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use String directly")
+ public var characters: String {
+ get {
+ return self
+ }
+ set {
+ self = newValue
+ }
+ }
+
+ /// Applies the given closure to a mutable view of the string's characters.
+ ///
+ /// Previous versions of Swift provided this view since String
+ /// itself was not a collection. String is now a collection of
+ /// characters, so this type is now just an alias for String.
+ @available(swift, deprecated: 3.2/*, obsoleted: 5.0*/, message: "Please mutate the String directly")
+ public mutating func withMutableCharacters<R>(
+ _ body: (inout String) -> R
+ ) -> R {
+ return body(&self)
+ }
+
+ @available(swift, deprecated: 3.2, obsoleted: 4.0)
+ public init?(_ utf16: UTF16View) {
+ // Attempt to recover the whole string, the better to implement the actual
+ // Swift 3.1 semantics, which are not as documented above! Full Swift 3.1
+ // semantics may be impossible to preserve in the case of string literals,
+ // since we no longer have access to the length of the original string when
+ // there is no owner and elements are dropped from the end.
+ let wholeString = String(utf16._guts)
+ guard
+ let start = UTF16Index(encodedOffset: utf16._offset)
+ .samePosition(in: wholeString),
+ let end = UTF16Index(encodedOffset: utf16._offset + utf16._length)
+ .samePosition(in: wholeString)
+ else
+ {
+ return nil
+ }
+ self = String(wholeString[start..<end])
+ }
+
+ @available(swift, deprecated: 3.2, message: "Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)")
+ @available(swift, obsoleted: 4.0, message: "Please use non-failable String.init(_:UTF8View) instead")
+ public init?(_ utf8: UTF8View) {
+ if utf8.startIndex.transcodedOffset != 0
+ || utf8.endIndex.transcodedOffset != 0
+ || utf8._legacyPartialCharacters.start
+ || utf8._legacyPartialCharacters.end {
+ return nil
+ }
+ self = String(utf8._guts)
+ }
+}
+
+extension String { // RangeReplaceableCollection
+ // The defaulted argument prevents this initializer from satisfies the
+ // LosslessStringConvertible conformance. You can satisfy a protocol
+ // requirement with something that's not yet available, but not with
+ // something that has become unavailable. Without this, the code won't
+ // compile as Swift 4.
+ @available(swift, obsoleted: 4, message: "String.init(_:String) is no longer failable")
+ public init?(_ other: String, obsoletedInSwift4: () = ()) {
+ self.init(other._guts)
+ }
+}
+
+extension String.UnicodeScalarView : _CustomPlaygroundQuickLookable {
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnicodeScalarView.customPlaygroundQuickLook will be removed in Swift 5.0")
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+ return .text(description)
+ }
+}
+
+// backward compatibility for index interchange.
+extension String.UnicodeScalarView {
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public func index(after i: Index?) -> Index {
+ return index(after: i!)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public func index(_ i: Index?, offsetBy n: Int) -> Index {
+ return index(i!, offsetBy: n)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+ public func distance(from i: Index?, to j: Index?) -> Int {
+ return distance(from: i!, to: j!)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public subscript(i: Index?) -> Unicode.Scalar {
+ return self[i!]
+ }
+}
+
+// backward compatibility for index interchange.
+extension String.UTF16View {
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public func index(after i: Index?) -> Index {
+ return index(after: i!)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public func index(_ i: Index?, offsetBy n: Int) -> Index {
+ return index(i!, offsetBy: n)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+ public func distance(from i: Index?, to j: Index?) -> Int {
+ return distance(from: i!, to: j!)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public subscript(i: Index?) -> Unicode.UTF16.CodeUnit {
+ return self[i!]
+ }
+}
+
+// backward compatibility for index interchange.
+extension String.UTF8View {
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public func index(after i: Index?) -> Index {
+ return index(after: i!)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public func index(_ i: Index?, offsetBy n: Int) -> Index {
+ return index(i!, offsetBy: n)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+ public func distance(from i: Index?, to j: Index?) -> Int {
+ return distance(from: i!, to: j!)
+ }
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+ public subscript(i: Index?) -> Unicode.UTF8.CodeUnit {
+ return self[i!]
+ }
+}
+
+//===--- String/Substring Slicing Support ---------------------------------===//
+/// In Swift 3.2, in the absence of type context,
+///
+/// someString[someString.startIndex..<someString.endIndex]
+///
+/// was deduced to be of type `String`. Therefore have a more-specific
+/// Swift-3-only `subscript` overload on `String` (and `Substring`) that
+/// continues to produce `String`.
+extension String {
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: Range<Index>) -> String {
+ _boundsCheck(bounds)
+ return String(Substring(_slice: Slice(base: self, bounds: bounds)))
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: ClosedRange<Index>) -> String {
+ let r = bounds.relative(to: self)
+ _boundsCheck(r)
+ return String(Substring(_slice: Slice(
+ base: self,
+ bounds: r)))
+ }
+}
+
+
+//===--- Slicing Support --------------------------------------------------===//
+// In Swift 3.2, in the absence of type context,
+//
+// someString.unicodeScalars[
+// someString.unicodeScalars.startIndex
+// ..< someString.unicodeScalars.endIndex]
+//
+// was deduced to be of type `String.UnicodeScalarView`. Provide a
+// more-specific Swift-3-only `subscript` overload that continues to produce
+// `String.UnicodeScalarView`.
+extension String.UnicodeScalarView {
+ private subscript(_bounds bounds: Range<Index>) -> String.UnicodeScalarView {
+ let rawSubRange: Range<Int> =
+ _toCoreIndex(bounds.lowerBound)..<_toCoreIndex(bounds.upperBound)
+ return String.UnicodeScalarView(
+ _guts._extractSlice(rawSubRange),
+ coreOffset: bounds.lowerBound.encodedOffset)
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: Range<Index>) -> String.UnicodeScalarView {
+ return self[_bounds: bounds]
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: ClosedRange<Index>) -> String.UnicodeScalarView {
+ return self[_bounds: bounds.relative(to: self)]
+ }
+}
+
+//===--- Slicing Support --------------------------------------------------===//
+// In Swift 3.2, in the absence of type context,
+//
+// someString.utf16[someString.utf16.startIndex..<someString.utf16.endIndex]
+//
+// was deduced to be of type `String.UTF16View`. Provide a more-specific
+// Swift-3-only `subscript` overload that continues to produce
+// `String.UTF16View`.
+extension String.UTF16View {
+ private subscript(_bounds bounds: Range<Index>) -> String.UTF16View {
+ return String.UTF16View(
+ _guts,
+ offset: _internalIndex(at: bounds.lowerBound.encodedOffset),
+ length: bounds.upperBound.encodedOffset - bounds.lowerBound.encodedOffset)
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: Range<Index>) -> String.UTF16View {
+ return self[_bounds: bounds]
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: ClosedRange<Index>) -> String.UTF16View {
+ return self[_bounds: bounds.relative(to: self)]
+ }
+}
+
+//===--- Slicing Support --------------------------------------------------===//
+/// In Swift 3.2, in the absence of type context,
+///
+/// someString.utf8[someString.utf8.startIndex..<someString.utf8.endIndex]
+///
+/// was deduced to be of type `String.UTF8View`. Provide a more-specific
+/// Swift-3-only `subscript` overload that continues to produce
+/// `String.UTF8View`.
+extension String.UTF8View {
+ private subscript(_bounds bounds: Range<Index>) -> String.UTF8View {
+ let wholeString = String(_guts)
+ let legacyPartialCharacters = (
+ (self._legacyPartialCharacters.start &&
+ bounds.lowerBound.encodedOffset == 0) ||
+ bounds.lowerBound.samePosition(in: wholeString) == nil,
+ (self._legacyPartialCharacters.end &&
+ bounds.upperBound.encodedOffset == _guts.count) ||
+ bounds.upperBound.samePosition(in: wholeString) == nil)
+
+ if bounds.upperBound.transcodedOffset == 0 {
+ return String.UTF8View(
+ _guts._extractSlice(
+ bounds.lowerBound.encodedOffset..<bounds.upperBound.encodedOffset),
+ legacyOffsets: (bounds.lowerBound.transcodedOffset, 0),
+ legacyPartialCharacters: legacyPartialCharacters)
+ }
+
+ let b0 = bounds.upperBound.utf8Buffer!.first!
+ let scalarLength8 = (~b0).leadingZeroBitCount
+ let scalarLength16 = scalarLength8 == 4 ? 2 : 1
+ let coreEnd = bounds.upperBound.encodedOffset + scalarLength16
+ return String.UTF8View(
+ _guts._extractSlice(bounds.lowerBound.encodedOffset..<coreEnd),
+ legacyOffsets: (
+ bounds.lowerBound.transcodedOffset,
+ bounds.upperBound.transcodedOffset - scalarLength8),
+ legacyPartialCharacters: legacyPartialCharacters)
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: Range<Index>) -> String.UTF8View {
+ return self[_bounds: bounds]
+ }
+
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: ClosedRange<Index>) -> String.UTF8View {
+ return self[_bounds: bounds.relative(to: self)]
+ }
+}
+
+@available(swift,deprecated: 5.0, renamed: "Unicode.UTF8")
+public typealias UTF8 = Unicode.UTF8
+@available(swift, deprecated: 5.0, renamed: "Unicode.UTF16")
+public typealias UTF16 = Unicode.UTF16
+@available(swift, deprecated: 5.0, renamed: "Unicode.UTF32")
+public typealias UTF32 = Unicode.UTF32
+@available(swift, obsoleted: 5.0, renamed: "Unicode.Scalar")
+public typealias UnicodeScalar = Unicode.Scalar
+
+
+// popFirst() is only present when a collection is its own subsequence. This was
+// dropped in Swift 4.
+extension String {
+ @available(swift, deprecated: 3.2, obsoleted: 4, message: "Please use 'first', 'dropFirst()', or 'Substring.popFirst()'.")
+ public mutating func popFirst() -> String.Element? {
+ guard !isEmpty else { return nil }
+ let element = first!
+ let nextIdx = self.index(after: self.startIndex)
+ self = String(self[nextIdx...])
+ return element
+ }
+}
+
+extension String.UnicodeScalarView {
+ @available(swift, deprecated: 3.2, obsoleted: 4, message: "Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'.")
+ public mutating func popFirst() -> String.UnicodeScalarView.Element? {
+ guard !isEmpty else { return nil }
+ let element = first!
+ let nextIdx = self.index(after: self.startIndex)
+ self = String(self[nextIdx...]).unicodeScalars
+ return element
+ }
+}
+
+extension String.UTF16View : _CustomPlaygroundQuickLookable {
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UTF16View.customPlaygroundQuickLook will be removed in Swift 5.0")
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+ return .text(description)
+ }
+}
+
+extension String.UTF8View : _CustomPlaygroundQuickLookable {
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UTF8View.customPlaygroundQuickLook will be removed in Swift 5.0")
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+ return .text(description)
+ }
+}
+
+extension StringProtocol {
+ @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF8View.Index")
+ public typealias UTF8Index = UTF8View.Index
+ @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF16View.Index")
+ public typealias UTF16Index = UTF16View.Index
+ @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UnicodeScalarView.Index")
+ public typealias UnicodeScalarIndex = UnicodeScalarView.Index
+}
+
+extension Substring {
+ /// A view of a string's contents as a collection of characters.
+ ///
+ /// Previous versions of Swift provided this view since String
+ /// itself was not a collection. String is now a collection of
+ /// characters, so this type is now just an alias for String.
+ @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use Substring directly")
+ public typealias CharacterView = Substring
+
+ /// A view of the string's contents as a collection of characters.
+ @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use Substring directly")
+ public var characters: Substring {
+ get {
+ return self
+ }
+ set {
+ self = newValue
+ }
+ }
+
+ /// Applies the given closure to a mutable view of the string's characters.
+ ///
+ /// Previous versions of Swift provided this view since String
+ /// itself was not a collection. String is now a collection of
+ /// characters, so this type is now just an alias for String.
+ @available(swift, deprecated: 3.2/*, obsoleted: 5.0*/, message: "Please mutate the Substring directly")
+ public mutating func withMutableCharacters<R>(
+ _ body: (inout Substring) -> R
+ ) -> R {
+ return body(&self)
+ }
+
+ private func _boundsCheck(_ range: Range<Index>) {
+ _precondition(range.lowerBound >= startIndex,
+ "String index range is out of bounds")
+ _precondition(range.upperBound <= endIndex,
+ "String index range is out of bounds")
+ }
+
+ @available(swift, obsoleted: 4)
+ public subscript(bounds: ClosedRange<Index>) -> String {
+ return String(self[bounds.relative(to: self)])
+ }
+}
+
+extension Substring : _CustomPlaygroundQuickLookable {
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "Substring.customPlaygroundQuickLook will be removed in Swift 5.0")
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+ return String(self).customPlaygroundQuickLook
+ }
+}
+
+extension Collection {
+ // FIXME: <rdar://problem/34142121>
+ // This typealias should be removed as it predates the source compatibility
+ // guarantees of Swift 3, but it cannot due to a bug.
+ @available(*, unavailable, renamed: "Iterator")
+ public typealias Generator = Iterator
+
+ @available(swift, deprecated: 3.2, obsoleted: 5.0, renamed: "Element")
+ public typealias _Element = Element
+
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+ public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T) -> Index {
+ return index(i, offsetBy: Int(n))
+ }
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+ public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T) {
+ return formIndex(&i, offsetBy: Int(n))
+ }
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+ public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T, limitedBy limit: Index) -> Index? {
+ return index(i, offsetBy: Int(n), limitedBy: limit)
+ }
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+ public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T, limitedBy limit: Index) -> Bool {
+ return formIndex(&i, offsetBy: Int(n), limitedBy: limit)
+ }
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+ public func distance<T: BinaryInteger>(from start: Index, to end: Index) -> T {
+ return numericCast(distance(from: start, to: end) as Int)
+ }
+}
+
+
+extension UnsafeMutablePointer {
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "initialize(repeating:count:)")
+ public func initialize(to newValue: Pointee, count: Int = 1) {
+ initialize(repeating: newValue, count: count)
+ }
+
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, message: "the default argument to deinitialize(count:) has been removed, please specify the count explicitly")
+ @discardableResult
+ public func deinitialize() -> UnsafeMutableRawPointer {
+ return deinitialize(count: 1)
+ }
+
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
+ public func deallocate(capacity _: Int) {
+ self.deallocate()
+ }
+
+ /// Initializes memory starting at this pointer's address with the elements
+ /// of the given collection.
+ ///
+ /// The region of memory starting at this pointer and covering `source.count`
+ /// instances of the pointer's `Pointee` type must be uninitialized or
+ /// `Pointee` must be a trivial type. After calling `initialize(from:)`, the
+ /// region is initialized.
+ ///
+ /// - Parameter source: A collection of elements of the pointer's `Pointee`
+ /// type.
+ // This is fundamentally unsafe since collections can underreport their count.
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "it will be removed in Swift 5.0. Please use 'UnsafeMutableBufferPointer.initialize(from:)' instead")
+ public func initialize<C : Collection>(from source: C)
+ where C.Element == Pointee {
+ let buf = UnsafeMutableBufferPointer(start: self, count: numericCast(source.count))
+ var (remainders,writtenUpTo) = source._copyContents(initializing: buf)
+ // ensure that exactly rhs.count elements were written
+ _precondition(remainders.next() == nil, "rhs underreported its count")
+ _precondition(writtenUpTo == buf.endIndex, "rhs overreported its count")
+ }
+}
+
+extension UnsafeRawPointer : _CustomPlaygroundQuickLookable {
+ internal var summary: String {
+ let ptrValue = UInt64(
+ bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+ return ptrValue == 0
+ ? "UnsafeRawPointer(nil)"
+ : "UnsafeRawPointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+ }
+
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafeRawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+ return .text(summary)
+ }
+}
+
+extension UnsafeMutableRawPointer : _CustomPlaygroundQuickLookable {
+ private var summary: String {
+ let ptrValue = UInt64(
+ bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+ return ptrValue == 0
+ ? "UnsafeMutableRawPointer(nil)"
+ : "UnsafeMutableRawPointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+ }
+
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafeMutableRawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+ return .text(summary)
+ }
+}
+
+extension UnsafePointer: _CustomPlaygroundQuickLookable {
+ private var summary: String {
+ let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+ return ptrValue == 0
+ ? "UnsafePointer(nil)"
+ : "UnsafePointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+ }
+
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafePointer.customPlaygroundQuickLook will be removed in a future Swift version")
+ public var customPlaygroundQuickLook: PlaygroundQuickLook {
+ return .text(summary)
+ }
+}
+
+extension UnsafeMutablePointer: _CustomPlaygroundQuickLookable {
+ private var summary: String {
+ let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+ return ptrValue == 0
+ ? "UnsafeMutablePointer(nil)"
+ : "UnsafeMutablePointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+ }
+
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafeMutablePointer.customPlaygroundQuickLook will be removed in a future Swift version")
+ public var customPlaygroundQuickLook: PlaygroundQuickLook {
+ return .text(summary)
+ }
+}
+
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "UnsafeBufferPointer.Iterator")
+public typealias UnsafeBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "UnsafeRawBufferPointer.Iterator")
+public typealias UnsafeRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "UnsafeRawBufferPointer.Iterator")
+public typealias UnsafeMutableRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
+
+extension UnsafeMutableRawPointer {
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "allocate(byteCount:alignment:)")
+ public static func allocate(
+ bytes size: Int, alignedTo alignment: Int
+ ) -> UnsafeMutableRawPointer {
+ return UnsafeMutableRawPointer.allocate(byteCount: size, alignment: alignment)
+ }
+
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "deallocate()", message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
+ public func deallocate(bytes _: Int, alignedTo _: Int) {
+ self.deallocate()
+ }
+
+ @available(swift, deprecated: 4.1, obsoleted: 5.0, renamed: "copyMemory(from:byteCount:)")
+ public func copyBytes(from source: UnsafeRawPointer, count: Int) {
+ copyMemory(from: source, byteCount: count)
+ }
+
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "initializeMemory(as:repeating:count:)")
+ @discardableResult
+ public func initializeMemory<T>(
+ as type: T.Type, at offset: Int = 0, count: Int = 1, to repeatedValue: T
+ ) -> UnsafeMutablePointer<T> {
+ return (self + offset * MemoryLayout<T>.stride).initializeMemory(
+ as: type, repeating: repeatedValue, count: count)
+ }
+
+ @available(*, deprecated/*, obsoleted: 5.0*/, message: "it will be removed in Swift 5.0. Please use 'UnsafeMutableRawBufferPointer.initialize(from:)' instead")
+ @discardableResult
+ public func initializeMemory<C : Collection>(
+ as type: C.Element.Type, from source: C
+ ) -> UnsafeMutablePointer<C.Element> {
+ // TODO: Optimize where `C` is a `ContiguousArrayBuffer`.
+ // Initialize and bind each element of the container.
+ var ptr = self
+ for element in source {
+ ptr.initializeMemory(as: C.Element.self, repeating: element, count: 1)
+ ptr += MemoryLayout<C.Element>.stride
+ }
+ return UnsafeMutablePointer(_rawValue)
+ }
+}
+
+extension UnsafeMutableRawBufferPointer {
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "allocate(byteCount:alignment:)")
+ public static func allocate(count: Int) -> UnsafeMutableRawBufferPointer {
+ return UnsafeMutableRawBufferPointer.allocate(
+ byteCount: count, alignment: MemoryLayout<UInt>.alignment)
+ }
+
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "copyMemory(from:)")
+ public func copyBytes(from source: UnsafeRawBufferPointer) {
+ copyMemory(from: source)
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// The following overloads of flatMap are carefully crafted to allow the code
+// like the following:
+// ["hello"].flatMap { $0 }
+// return an array of strings without any type context in Swift 3 mode, at the
+// same time allowing the following code snippet to compile:
+// [0, 1].flatMap { x in
+// if String(x) == "foo" { return "bar" } else { return nil }
+// }
+// Note that the second overload is declared on a more specific protocol.
+// See: test/stdlib/StringFlatMap.swift for tests.
+extension Sequence {
+ @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "compactMap(_:)",
+ message: "Please use compactMap(_:) for the case where closure returns an optional value")
+ public func flatMap<ElementOfResult>(
+ _ transform: (Element) throws -> ElementOfResult?
+ ) rethrows -> [ElementOfResult] {
+ return try _compactMap(transform)
+ }
+
+ @available(swift, obsoleted: 4)
+ public func flatMap(
+ _ transform: (Element) throws -> String
+ ) rethrows -> [String] {
+ return try map(transform)
+ }
+}
+
+extension Collection {
+ @available(swift, deprecated: 4.1, obsoleted: 5.0, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
+ public func flatMap(
+ _ transform: (Element) throws -> String?
+ ) rethrows -> [String] {
+ return try _compactMap(transform)
+ }
+}
+
+extension String.Index {
+ @available(swift, deprecated: 3.2, obsoleted: 4.0)
+ public init(_position: Int) {
+ self.init(encodedOffset: _position)
+ }
+
+ @available(swift, deprecated: 3.2, obsoleted: 4.0)
+ public init(_codeUnitOffset: Int) {
+ self.init(encodedOffset: _codeUnitOffset)
+ }
+
+ @available(swift, deprecated: 3.2, obsoleted: 4.0)
+ public var _utf16Index: Int {
+ return self.encodedOffset
+ }
+
+ @available(swift, deprecated: 3.2, obsoleted: 4.0)
+ public var _offset: Int {
+ return self.encodedOffset
+ }
+}
+
+// backward compatibility for index interchange.
+extension Optional where Wrapped == String.Index {
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+ public static func ..<(
+ lhs: String.Index?, rhs: String.Index?
+ ) -> Range<String.Index> {
+ return lhs! ..< rhs!
+ }
+
+ @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+ public static func ...(
+ lhs: String.Index?, rhs: String.Index?
+ ) -> ClosedRange<String.Index> {
+ return lhs! ... rhs!
+ }
+}
+
+extension Zip2Sequence {
+ @available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Sequence1.Iterator")
+ public typealias Stream1 = Sequence1.Iterator
+ @available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Sequence2.Iterator")
+ public typealias Stream2 = Sequence2.Iterator
+}
+
+
+//===--- QuickLooks -------------------------------------------------------===//
+
+/// The sum of types that can be used as a Quick Look representation.
+///
+/// The `PlaygroundQuickLook` protocol is deprecated, and will be removed from
+/// the standard library in a future Swift release. To customize the logging of
+/// your type in a playground, conform to the
+/// `CustomPlaygroundDisplayConvertible` protocol, which does not use the
+/// `PlaygroundQuickLook` enum.
+///
+/// If you need to provide a customized playground representation in Swift 4.0
+/// or Swift 3.2 or earlier, use a conditional compilation block:
+///
+/// #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
+/// // With Swift 4.1 and later (including Swift 3.3 and later), use
+/// // the CustomPlaygroundDisplayConvertible protocol.
+/// #else
+/// // With Swift 4.0 and Swift 3.2 and earlier, use PlaygroundQuickLook
+/// // and the CustomPlaygroundQuickLookable protocol.
+/// #endif
+@available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
+public typealias PlaygroundQuickLook = _PlaygroundQuickLook
+
+@_frozen // rdar://problem/38719739 - needed by LLDB
+public enum _PlaygroundQuickLook {
+ case text(String)
+ case int(Int64)
+ case uInt(UInt64)
+ case float(Float32)
+ case double(Float64)
+ case image(Any)
+ case sound(Any)
+ case color(Any)
+ case bezierPath(Any)
+ case attributedString(Any)
+ case rectangle(Float64, Float64, Float64, Float64)
+ case point(Float64, Float64)
+ case size(Float64, Float64)
+ case bool(Bool)
+ case range(Int64, Int64)
+ case view(Any)
+ case sprite(Any)
+ case url(String)
+ case _raw([UInt8], String)
+}
+
+// Maintain old `keys` and `values` types in Swift 3 mode.
+extension Dictionary {
+ /// A collection containing just the keys of the dictionary.
+ ///
+ /// When iterated over, keys appear in this collection in the same order as
+ /// they occur in the dictionary's key-value pairs. Each key in the keys
+ /// collection has a unique value.
+ ///
+ /// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
+ /// print(countryCodes)
+ /// // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
+ ///
+ /// for k in countryCodes.keys {
+ /// print(k)
+ /// }
+ /// // Prints "BR"
+ /// // Prints "JP"
+ /// // Prints "GH"
+ @available(swift, obsoleted: 4.0)
+ public var keys: LazyMapCollection<[Key: Value], Key> {
+ return self.lazy.map { $0.key }
+ }
+
+ /// A collection containing just the values of the dictionary.
+ ///
+ /// When iterated over, values appear in this collection in the same order as
+ /// they occur in the dictionary's key-value pairs.
+ ///
+ /// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
+ /// print(countryCodes)
+ /// // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
+ ///
+ /// for v in countryCodes.values {
+ /// print(v)
+ /// }
+ /// // Prints "Brazil"
+ /// // Prints "Japan"
+ /// // Prints "Ghana"
+ @available(swift, obsoleted: 4.0)
+ public var values: LazyMapCollection<[Key: Value], Value> {
+ return self.lazy.map { $0.value }
+ }
+
+ @available(swift, obsoleted: 4.0)
+ public func filter(
+ _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
+ ) rethrows -> [Element] {
+ var result: [Element] = []
+ for x in self {
+ if try isIncluded(x) {
+ result.append(x)
+ }
+ }
+ return result
+ }
+}
+
+extension Set {
+ @available(swift, obsoleted: 4.0)
+ public func filter(
+ _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
+ ) rethrows -> [Element] {
+ var result: [Element] = []
+ for x in self {
+ if try isIncluded(x) {
+ result.append(x)
+ }
+ }
+ return result
+ }
+}
+
+extension _PlaygroundQuickLook {
+ /// Creates a new Quick Look for the given instance.
+ ///
+ /// If the dynamic type of `subject` conforms to
+ /// `CustomPlaygroundQuickLookable`, the result is found by calling its
+ /// `customPlaygroundQuickLook` property. Otherwise, the result is
+ /// synthesized by the language. In some cases, the synthesized result may
+ /// be `.text(String(reflecting: subject))`.
+ ///
+ /// - Note: If the dynamic type of `subject` has value semantics, subsequent
+ /// mutations of `subject` will not observable in the Quick Look. In
+ /// general, though, the observability of such mutations is unspecified.
+ ///
+ /// - Parameter subject: The instance to represent with the resulting Quick
+ /// Look.
+ @available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version.")
+ public init(reflecting subject: Any) {
+ if let customized = subject as? CustomPlaygroundQuickLookable {
+ self = customized.customPlaygroundQuickLook
+ }
+ else if let customized = subject as? _DefaultCustomPlaygroundQuickLookable {
+ self = customized._defaultCustomPlaygroundQuickLook
+ }
+ else {
+ if let q = Mirror.quickLookObject(subject) {
+ self = q
+ }
+ else {
+ self = .text(String(reflecting: subject))
+ }
+ }
+ }
+}
+
+/// A type that explicitly supplies its own playground Quick Look.
+///
+/// The `CustomPlaygroundQuickLookable` protocol is deprecated, and will be
+/// removed from the standard library in a future Swift release. To customize
+/// the logging of your type in a playground, conform to the
+/// `CustomPlaygroundDisplayConvertible` protocol.
+///
+/// If you need to provide a customized playground representation in Swift 4.0
+/// or Swift 3.2 or earlier, use a conditional compilation block:
+///
+/// #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
+/// // With Swift 4.1 and later (including Swift 3.3 and later),
+/// // conform to CustomPlaygroundDisplayConvertible.
+/// extension MyType: CustomPlaygroundDisplayConvertible { /*...*/ }
+/// #else
+/// // Otherwise, on Swift 4.0 and Swift 3.2 and earlier,
+/// // conform to CustomPlaygroundQuickLookable.
+/// extension MyType: CustomPlaygroundQuickLookable { /*...*/ }
+/// #endif
+@available(*, deprecated/*, obsoleted: 5.0*/, message: "CustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
+public typealias CustomPlaygroundQuickLookable = _CustomPlaygroundQuickLookable
+
+public protocol _CustomPlaygroundQuickLookable {
+ /// A custom playground Quick Look for this instance.
+ ///
+ /// If this type has value semantics, the `PlaygroundQuickLook` instance
+ /// should be unaffected by subsequent mutations.
+ var customPlaygroundQuickLook: _PlaygroundQuickLook { get }
+}
+
+// Double-underscored real version allows us to keep using this in AppKit while
+// warning for non-SDK use. This is probably overkill but it doesn't cost
+// anything.
+@available(*, deprecated/*, obsoleted: 5.0*/, message: "_DefaultCustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
+public typealias _DefaultCustomPlaygroundQuickLookable = __DefaultCustomPlaygroundQuickLookable
+
+public protocol __DefaultCustomPlaygroundQuickLookable {
+ var _defaultCustomPlaygroundQuickLook: _PlaygroundQuickLook { get }
+}
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index 2d500fd..68397a4 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -459,168 +459,6 @@
}
}
-//===--- QuickLooks -------------------------------------------------------===//
-
-/// The sum of types that can be used as a Quick Look representation.
-///
-/// The `PlaygroundQuickLook` protocol is deprecated, and will be removed from
-/// the standard library in a future Swift release. To customize the logging of
-/// your type in a playground, conform to the
-/// `CustomPlaygroundDisplayConvertible` protocol, which does not use the
-/// `PlaygroundQuickLook` enum.
-///
-/// If you need to provide a customized playground representation in Swift 4.0
-/// or Swift 3.2 or earlier, use a conditional compilation block:
-///
-/// #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
-/// // With Swift 4.1 and later (including Swift 3.3 and later), use
-/// // the CustomPlaygroundDisplayConvertible protocol.
-/// #else
-/// // With Swift 4.0 and Swift 3.2 and earlier, use PlaygroundQuickLook
-/// // and the CustomPlaygroundQuickLookable protocol.
-/// #endif
-@_frozen // rdar://problem/38719739 - needed by LLDB
-@available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
-public enum PlaygroundQuickLook {
- /// Plain text.
- case text(String)
-
- /// An integer numeric value.
- case int(Int64)
-
- /// An unsigned integer numeric value.
- case uInt(UInt64)
-
- /// A single precision floating-point numeric value.
- case float(Float32)
-
- /// A double precision floating-point numeric value.
- case double(Float64)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// An image.
- case image(Any)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// A sound.
- case sound(Any)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// A color.
- case color(Any)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// A bezier path.
- case bezierPath(Any)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// An attributed string.
- case attributedString(Any)
-
- // FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
- /// A rectangle.
- case rectangle(Float64, Float64, Float64, Float64)
-
- // FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
- /// A point.
- case point(Float64, Float64)
-
- // FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
- /// A size.
- case size(Float64, Float64)
-
- /// A boolean value.
- case bool(Bool)
-
- // FIXME: Uses explicit values to avoid coupling a particular Cocoa type.
- /// A range.
- case range(Int64, Int64)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// A GUI view.
- case view(Any)
-
- // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
- /// A graphical sprite.
- case sprite(Any)
-
- /// A Uniform Resource Locator.
- case url(String)
-
- /// Raw data that has already been encoded in a format the IDE understands.
- case _raw([UInt8], String)
-}
-
-extension PlaygroundQuickLook {
- /// Creates a new Quick Look for the given instance.
- ///
- /// If the dynamic type of `subject` conforms to
- /// `CustomPlaygroundQuickLookable`, the result is found by calling its
- /// `customPlaygroundQuickLook` property. Otherwise, the result is
- /// synthesized by the language. In some cases, the synthesized result may
- /// be `.text(String(reflecting: subject))`.
- ///
- /// - Note: If the dynamic type of `subject` has value semantics, subsequent
- /// mutations of `subject` will not observable in the Quick Look. In
- /// general, though, the observability of such mutations is unspecified.
- ///
- /// - Parameter subject: The instance to represent with the resulting Quick
- /// Look.
- @available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version.")
- public init(reflecting subject: Any) {
- if let customized = subject as? CustomPlaygroundQuickLookable {
- self = customized.customPlaygroundQuickLook
- }
- else if let customized = subject as? _DefaultCustomPlaygroundQuickLookable {
- self = customized._defaultCustomPlaygroundQuickLook
- }
- else {
- if let q = Mirror.quickLookObject(subject) {
- self = q
- }
- else {
- self = .text(String(reflecting: subject))
- }
- }
- }
-}
-
-/// A type that explicitly supplies its own playground Quick Look.
-///
-/// The `CustomPlaygroundQuickLookable` protocol is deprecated, and will be
-/// removed from the standard library in a future Swift release. To customize
-/// the logging of your type in a playground, conform to the
-/// `CustomPlaygroundDisplayConvertible` protocol.
-///
-/// If you need to provide a customized playground representation in Swift 4.0
-/// or Swift 3.2 or earlier, use a conditional compilation block:
-///
-/// #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
-/// // With Swift 4.1 and later (including Swift 3.3 and later),
-/// // conform to CustomPlaygroundDisplayConvertible.
-/// extension MyType: CustomPlaygroundDisplayConvertible { /*...*/ }
-/// #else
-/// // Otherwise, on Swift 4.0 and Swift 3.2 and earlier,
-/// // conform to CustomPlaygroundQuickLookable.
-/// extension MyType: CustomPlaygroundQuickLookable { /*...*/ }
-/// #endif
-@available(*, deprecated, message: "CustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
-public protocol CustomPlaygroundQuickLookable {
- /// A custom playground Quick Look for this instance.
- ///
- /// If this type has value semantics, the `PlaygroundQuickLook` instance
- /// should be unaffected by subsequent mutations.
- var customPlaygroundQuickLook: PlaygroundQuickLook { get }
-}
-
-
-// A workaround for <rdar://problem/26182650>
-// FIXME(ABI)#50 (Dynamic Dispatch for Class Extensions) though not if it moves out of stdlib.
-@available(*, deprecated, message: "_DefaultCustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
-public protocol _DefaultCustomPlaygroundQuickLookable {
- var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook { get }
-}
-
//===--- General Utilities ------------------------------------------------===//
// This component could stand alone, but is used in Mirror's public interface.
diff --git a/stdlib/public/core/Mirrors.swift.gyb b/stdlib/public/core/Mirrors.swift.gyb
index 3c23082..26414ae 100644
--- a/stdlib/public/core/Mirrors.swift.gyb
+++ b/stdlib/public/core/Mirrors.swift.gyb
@@ -44,11 +44,11 @@
}
}
-extension ${Type[0]} : CustomPlaygroundQuickLookable {
+extension ${Type[0]} : _CustomPlaygroundQuickLookable {
/// A custom playground Quick Look for the `${Type[0]}` instance.
@inlinable // FIXME(sil-serialize-all)
@available(*, deprecated, message: "${Type[0]}.customPlaygroundQuickLook will be removed in a future Swift version")
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
+ public var customPlaygroundQuickLook: _PlaygroundQuickLook {
return ${Type[1]}(${Type[2]})
}
}
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index dc1f10b..5eceea4 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -10,14 +10,6 @@
//
//===----------------------------------------------------------------------===//
-/// A type that provides subscript access to its elements.
-///
-/// In most cases, it's best to ignore this protocol and use the
-/// `MutableCollection` protocol instead, because it has a more complete
-/// interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'MutableCollection' instead")
-public typealias MutableIndexable = MutableCollection
-
/// A collection that supports subscript assignment.
///
/// Collections that conform to `MutableCollection` gain the ability to
diff --git a/stdlib/public/core/NewtypeWrapper.swift b/stdlib/public/core/NewtypeWrapper.swift
index 5024c9d..c9493a5 100644
--- a/stdlib/public/core/NewtypeWrapper.swift
+++ b/stdlib/public/core/NewtypeWrapper.swift
@@ -13,9 +13,10 @@
/// An implementation detail used to implement support importing
/// (Objective-)C entities marked with the swift_newtype Clang
/// attribute.
-public protocol _SwiftNewtypeWrapper : RawRepresentable { }
+public protocol _SwiftNewtypeWrapper
+: RawRepresentable, _HasCustomAnyHashableRepresentation { }
-extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue : Hashable {
+extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue: Hashable {
/// The hash value.
@inlinable
public var hashValue: Int {
@@ -31,6 +32,70 @@
public func hash(into hasher: inout Hasher) {
hasher.combine(rawValue)
}
+
+ @inlinable // FIXME(sil-serialize-all)
+ public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
+ return rawValue._rawHashValue(seed: seed)
+ }
+}
+
+extension _SwiftNewtypeWrapper {
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return nil
+ }
+}
+
+extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue: Hashable {
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return AnyHashable(_box: _NewtypeWrapperAnyHashableBox(self))
+ }
+}
+
+internal struct _NewtypeWrapperAnyHashableBox<Base>: _AnyHashableBox
+where Base: _SwiftNewtypeWrapper & Hashable, Base.RawValue: Hashable {
+ var _value: Base
+
+ init(_ value: Base) {
+ self._value = value
+ }
+
+ var _canonicalBox: _AnyHashableBox {
+ return (_value.rawValue as AnyHashable)._box._canonicalBox
+ }
+
+ func _isEqual(to other: _AnyHashableBox) -> Bool? {
+ _preconditionFailure("_isEqual called on non-canonical AnyHashable box")
+ }
+
+ var _hashValue: Int {
+ _preconditionFailure("_hashValue called on non-canonical AnyHashable box")
+ }
+
+ func _hash(into hasher: inout Hasher) {
+ _preconditionFailure("_hash(into:) called on non-canonical AnyHashable box")
+ }
+
+ func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ _preconditionFailure("_rawHashValue(_seed:) called on non-canonical AnyHashable box")
+ }
+
+ var _base: Any { return _value }
+
+ func _unbox<T: Hashable>() -> T? {
+ return _value as? T ?? _value.rawValue as? T
+ }
+
+ func _downCastConditional<T>(into result: UnsafeMutablePointer<T>) -> Bool {
+ if let value = _value as? T {
+ result.initialize(to: value)
+ return true
+ }
+ if let value = _value.rawValue as? T {
+ result.initialize(to: value)
+ return true
+ }
+ return false
+ }
}
#if _runtime(_ObjC)
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index 327cdde..4c7787a 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -283,221 +283,6 @@
/// // Prints "nil"
public typealias AnyClass = AnyObject.Type
-/// A type that supports standard bitwise arithmetic operators.
-///
-/// Types that conform to the `BitwiseOperations` protocol implement operators
-/// for bitwise arithmetic. The integer types in the standard library all
-/// conform to `BitwiseOperations` by default. When you use bitwise operators
-/// with an integer, you perform operations on the raw data bits that store
-/// the integer's value.
-///
-/// In the following examples, the binary representation of any values are
-/// shown in a comment to the right, like this:
-///
-/// let x: UInt8 = 5 // 0b00000101
-///
-/// Here are the required operators for the `BitwiseOperations` protocol:
-///
-/// - The bitwise OR operator (`|`) returns a value that has each bit set to
-/// `1` where *one or both* of its arguments had that bit set to `1`. This
-/// is equivalent to the union of two sets. For example:
-///
-/// let x: UInt8 = 5 // 0b00000101
-/// let y: UInt8 = 14 // 0b00001110
-/// let z = x | y // 0b00001111
-///
-/// Performing a bitwise OR operation with a value and `allZeros` always
-/// returns the same value.
-///
-/// print(x | .allZeros) // 0b00000101
-/// // Prints "5"
-///
-/// - The bitwise AND operator (`&`) returns a value that has each bit set to
-/// `1` where *both* of its arguments had that bit set to `1`. This is
-/// equivalent to the intersection of two sets. For example:
-///
-/// let x: UInt8 = 5 // 0b00000101
-/// let y: UInt8 = 14 // 0b00001110
-/// let z = x & y // 0b00000100
-///
-/// Performing a bitwise AND operation with a value and `allZeros` always
-/// returns `allZeros`.
-///
-/// print(x & .allZeros) // 0b00000000
-/// // Prints "0"
-///
-/// - The bitwise XOR operator (`^`), or exclusive OR operator, returns a value
-/// that has each bit set to `1` where *one or the other but not both* of
-/// its operators has that bit set to `1`. This is equivalent to the
-/// symmetric difference of two sets. For example:
-///
-/// let x: UInt8 = 5 // 0b00000101
-/// let y: UInt8 = 14 // 0b00001110
-/// let z = x ^ y // 0b00001011
-///
-/// Performing a bitwise XOR operation with a value and `allZeros` always
-/// returns the same value.
-///
-/// print(x ^ .allZeros) // 0b00000101
-/// // Prints "5"
-///
-/// - The bitwise NOT operator (`~`) is a prefix operator that returns a value
-/// where all the bits of its argument are flipped: Bits that are `1` in the
-/// argument are `0` in the result, and bits that are `0` in the argument
-/// are `1` in the result. This is equivalent to the inverse of a set. For
-/// example:
-///
-/// let x: UInt8 = 5 // 0b00000101
-/// let notX = ~x // 0b11111010
-///
-/// Performing a bitwise NOT operation on `allZeros` returns a value with
-/// every bit set to `1`.
-///
-/// let allOnes = ~UInt8.allZeros // 0b11111111
-///
-/// The `OptionSet` protocol uses a raw value that conforms to
-/// `BitwiseOperations` to provide mathematical set operations like
-/// `union(_:)`, `intersection(_:)` and `contains(_:)` with O(1) performance.
-///
-/// Conforming to the BitwiseOperations Protocol
-/// ============================================
-///
-/// To make your custom type conform to `BitwiseOperations`, add a static
-/// `allZeros` property and declare the four required operator functions. Any
-/// type that conforms to `BitwiseOperations`, where `x` is an instance of the
-/// conforming type, must satisfy the following conditions:
-///
-/// - `x | Self.allZeros == x`
-/// - `x ^ Self.allZeros == x`
-/// - `x & Self.allZeros == .allZeros`
-/// - `x & ~Self.allZeros == x`
-/// - `~x == x ^ ~Self.allZeros`
-@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use FixedWidthInteger protocol instead")
-public typealias BitwiseOperations = _BitwiseOperations
-
-public protocol _BitwiseOperations {
- /// Returns the intersection of bits set in the two arguments.
- ///
- /// The bitwise AND operator (`&`) returns a value that has each bit set to
- /// `1` where *both* of its arguments had that bit set to `1`. This is
- /// equivalent to the intersection of two sets. For example:
- ///
- /// let x: UInt8 = 5 // 0b00000101
- /// let y: UInt8 = 14 // 0b00001110
- /// let z = x & y // 0b00000100
- ///
- /// Performing a bitwise AND operation with a value and `allZeros` always
- /// returns `allZeros`.
- ///
- /// print(x & .allZeros) // 0b00000000
- /// // Prints "0"
- ///
- /// - Complexity: O(1).
- static func & (lhs: Self, rhs: Self) -> Self
-
- /// Returns the union of bits set in the two arguments.
- ///
- /// The bitwise OR operator (`|`) returns a value that has each bit set to
- /// `1` where *one or both* of its arguments had that bit set to `1`. For
- /// example:
- ///
- /// let x: UInt8 = 5 // 0b00000101
- /// let y: UInt8 = 14 // 0b00001110
- /// let z = x | y // 0b00001111
- ///
- /// Performing a bitwise OR operation with a value and `allZeros` always
- /// returns the same value.
- ///
- /// print(x | .allZeros) // 0b00000101
- /// // Prints "5"
- ///
- /// - Complexity: O(1).
- static func | (lhs: Self, rhs: Self) -> Self
-
- /// Returns the bits that are set in exactly one of the two arguments.
- ///
- /// The bitwise XOR operator (`^`), or exclusive OR operator, returns a value
- /// that has each bit set to `1` where *one or the other but not both* of
- /// its operators has that bit set to `1`. This is equivalent to the
- /// symmetric difference of two sets. For example:
- ///
- /// let x: UInt8 = 5 // 0b00000101
- /// let y: UInt8 = 14 // 0b00001110
- /// let z = x ^ y // 0b00001011
- ///
- /// Performing a bitwise XOR with a value and `allZeros` always returns the
- /// same value:
- ///
- /// print(x ^ .allZeros) // 0b00000101
- /// // Prints "5"
- ///
- /// - Complexity: O(1).
- static func ^ (lhs: Self, rhs: Self) -> Self
-
- /// Returns the inverse of the bits set in the argument.
- ///
- /// The bitwise NOT operator (`~`) is a prefix operator that returns a value
- /// in which all the bits of its argument are flipped: Bits that are `1` in the
- /// argument are `0` in the result, and bits that are `0` in the argument
- /// are `1` in the result. This is equivalent to the inverse of a set. For
- /// example:
- ///
- /// let x: UInt8 = 5 // 0b00000101
- /// let notX = ~x // 0b11111010
- ///
- /// Performing a bitwise NOT operation on `allZeros` returns a value with
- /// every bit set to `1`.
- ///
- /// let allOnes = ~UInt8.allZeros // 0b11111111
- ///
- /// - Complexity: O(1).
- static prefix func ~ (x: Self) -> Self
-
- /// The empty bitset.
- @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0 or init() of a type conforming to FixedWidthInteger")
- static var allZeros: Self { get }
-}
-
-extension _BitwiseOperations {
- /// Calculates the union of bits sets in the two arguments and stores the result
- /// in the first argument.
- ///
- /// - Parameters:
- /// - lhs: A value to update with the union of bits set in the two arguments.
- /// - rhs: Another value.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4.1)
- public static func |= (lhs: inout Self, rhs: Self) {
- lhs = lhs | rhs
- }
-
- /// Calculates the intersections of bits sets in the two arguments and stores
- /// the result in the first argument.
- ///
- /// - Parameters:
- /// - lhs: A value to update with the intersections of bits set in the two
- /// arguments.
- /// - rhs: Another value.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4.1)
- public static func &= (lhs: inout Self, rhs: Self) {
- lhs = lhs & rhs
- }
-
- /// Calculates the bits that are set in exactly one of the two arguments and
- /// stores the result in the first argument.
- ///
- /// - Parameters:
- /// - lhs: A value to update with the bits that are set in exactly one of the
- /// two arguments.
- /// - rhs: Another value.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4.1)
- public static func ^= (lhs: inout Self, rhs: Self) {
- lhs = lhs ^ rhs
- }
-}
-
//===----------------------------------------------------------------------===//
// Standard pattern matching forms
//===----------------------------------------------------------------------===//
diff --git a/stdlib/public/core/PrefixWhile.swift b/stdlib/public/core/PrefixWhile.swift
index a05419f..4c80aac 100644
--- a/stdlib/public/core/PrefixWhile.swift
+++ b/stdlib/public/core/PrefixWhile.swift
@@ -311,10 +311,3 @@
_base: self.elements, predicate: predicate)
}
}
-
-@available(*, deprecated, renamed: "LazyDropWhileSequence.Iterator")
-public typealias LazyPrefixWhileIterator<T> = LazyPrefixWhileSequence<T>.Iterator where T: Sequence
-@available(*, deprecated, renamed: "LazyDropWhileCollection.Index")
-public typealias LazyPrefixWhileIndex<T> = LazyPrefixWhileCollection<T>.Index where T: Collection
-@available(*, deprecated, renamed: "LazyPrefixWhileCollection")
-public typealias LazyPrefixWhileBidirectionalCollection<T> = LazyPrefixWhileCollection<T> where T: BidirectionalCollection
diff --git a/stdlib/public/core/Random.swift b/stdlib/public/core/Random.swift
index 1dea1b4..97398e0 100644
--- a/stdlib/public/core/Random.swift
+++ b/stdlib/public/core/Random.swift
@@ -90,13 +90,14 @@
/// Returns a random value that is less than the given upper bound.
///
/// - Parameter upperBound: The upper bound for the randomly generated value.
+ /// Must be non-zero.
/// - Returns: A random value of `T` in the range `0..<upperBound`. Every
/// value in the range `0..<upperBound` is equally likely to be returned.
@inlinable
public mutating func next<T: FixedWidthInteger & UnsignedInteger>(
upperBound: T
) -> T {
- guard upperBound != 0 else { return 0 }
+ _precondition(upperBound != 0, "upperBound cannot be zero.")
let tmp = (T.max % upperBound) + 1
let range = tmp == upperBound ? 0 : tmp
var random: T = 0
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index 8e9f34e..8a28a20 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -12,14 +12,6 @@
/// A collection that supports efficient random-access index traversal.
///
-/// In most cases, it's best to ignore this protocol and use the
-/// `RandomAccessCollection` protocol instead, because it has a more complete
-/// interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'RandomAccessCollection' instead")
-public typealias RandomAccessIndexable = RandomAccessCollection
-
-/// A collection that supports efficient random-access index traversal.
-///
/// Random-access collections can move indices any distance and
/// measure the distance between indices in O(1) time. Therefore, the
/// fundamental difference between random-access and bidirectional collections
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index 7993857..1741c5a 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -278,16 +278,7 @@
}
}
-extension Range where Bound: Strideable, Bound.Stride : SignedInteger {
- /// Now that Range is conditionally a collection when Bound: Strideable,
- /// CountableRange is no longer needed. This is a deprecated initializer
- /// for any remaining uses of Range(countableRange).
- @available(*,deprecated: 4.2,
- message: "CountableRange is now Range. No need to convert any more.")
- public init(_ other: Range<Bound>) {
- self = other
- }
-
+extension Range where Bound: Strideable, Bound.Stride : SignedInteger {
/// Creates an instance equivalent to the given `ClosedRange`.
///
/// - Parameter other: A closed range to convert to a `Range` instance.
@@ -849,6 +840,7 @@
return self[startIndex...]
}
}
+
extension MutableCollection {
@inlinable
public subscript<R: RangeExpression>(r: R) -> SubSequence
@@ -907,8 +899,12 @@
}
}
+// Note: this is not for compatibility only, it is considered a useful
+// shorthand. TODO: Add documentation
public typealias CountableRange<Bound: Strideable> = Range<Bound>
where Bound.Stride : SignedInteger
+// Note: this is not for compatibility only, it is considered a useful
+// shorthand. TODO: Add documentation
public typealias CountablePartialRangeFrom<Bound: Strideable> = PartialRangeFrom<Bound>
where Bound.Stride : SignedInteger
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift
index 367647c..5b6b259 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -14,15 +14,6 @@
//
//===----------------------------------------------------------------------===//
-/// A type that supports replacement of an arbitrary subrange of elements with
-/// the elements of another collection.
-///
-/// In most cases, it's best to ignore this protocol and use the
-/// `RangeReplaceableCollection` protocol instead, because it has a more
-/// complete interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'RandomAccessCollection' instead")
-public typealias RangeReplaceableIndexable = RangeReplaceableCollection
-
/// A collection that supports replacement of an arbitrary subrange of elements
/// with the elements of another collection.
///
diff --git a/stdlib/public/core/ReflectionMirror.swift b/stdlib/public/core/ReflectionMirror.swift
index 4806ae6..6e516f4 100644
--- a/stdlib/public/core/ReflectionMirror.swift
+++ b/stdlib/public/core/ReflectionMirror.swift
@@ -55,7 +55,7 @@
internal func _getClassPlaygroundQuickLook(
_ object: AnyObject
-) -> PlaygroundQuickLook? {
+) -> _PlaygroundQuickLook? {
if _is(object, kindOf: "NSNumber") {
let number: _NSNumber = unsafeBitCast(object, to: _NSNumber.self)
switch UInt8(number.objCType[0]) {
@@ -149,7 +149,7 @@
self._defaultDescendantRepresentation = .generated
}
- internal static func quickLookObject(_ subject: Any) -> PlaygroundQuickLook? {
+ internal static func quickLookObject(_ subject: Any) -> _PlaygroundQuickLook? {
#if _runtime(_ObjC)
let object = _getQuickLookObject(subject)
return object.flatMap(_getClassPlaygroundQuickLook)
diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift
index b40bcae..4ba2e82 100644
--- a/stdlib/public/core/Reverse.swift
+++ b/stdlib/public/core/Reverse.swift
@@ -307,9 +307,3 @@
return ReversedCollection(_base: elements).lazy
}
}
-
-// @available(*, deprecated, renamed: "ReversedCollection")
-public typealias ReversedRandomAccessCollection<T: RandomAccessCollection> = ReversedCollection<T>
-
-// @available(*, deprecated, renamed: "ReversedCollection.Index")
-public typealias ReversedIndex<T: BidirectionalCollection> = ReversedCollection<T>
diff --git a/stdlib/public/core/SequenceAlgorithms.swift b/stdlib/public/core/SequenceAlgorithms.swift
index 9850b26..583f071 100644
--- a/stdlib/public/core/SequenceAlgorithms.swift
+++ b/stdlib/public/core/SequenceAlgorithms.swift
@@ -749,39 +749,6 @@
return try _compactMap(transform)
}
- /// Returns an array containing the non-`nil` results of calling the given
- /// transformation with each element of this sequence.
- ///
- /// Use this method to receive an array of nonoptional values when your
- /// transformation produces an optional value.
- ///
- /// In this example, note the difference in the result of using `map` and
- /// `flatMap` with a transformation that returns an optional `Int` value.
- ///
- /// let possibleNumbers = ["1", "2", "three", "///4///", "5"]
- ///
- /// let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
- /// // [1, 2, nil, nil, 5]
- ///
- /// let flatMapped: [Int] = possibleNumbers.flatMap { str in Int(str) }
- /// // [1, 2, 5]
- ///
- /// - Parameter transform: A closure that accepts an element of this
- /// sequence as its argument and returns an optional value.
- /// - Returns: An array of the non-`nil` results of calling `transform`
- /// with each element of the sequence.
- ///
- /// - Complexity: O(*m* + *n*), where *m* is the length of this sequence
- /// and *n* is the length of the result.
- @inline(__always)
- @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
- message: "Please use compactMap(_:) for the case where closure returns an optional value")
- public func flatMap<ElementOfResult>(
- _ transform: (Element) throws -> ElementOfResult?
- ) rethrows -> [ElementOfResult] {
- return try _compactMap(transform)
- }
-
// The implementation of flatMap accepting a closure with an optional result.
// Factored out into a separate functions in order to be used in multiple
// overloads.
diff --git a/stdlib/public/core/Set.swift b/stdlib/public/core/Set.swift
index 7551284..40b4258 100644
--- a/stdlib/public/core/Set.swift
+++ b/stdlib/public/core/Set.swift
@@ -503,6 +503,61 @@
}
}
+extension Set: _HasCustomAnyHashableRepresentation {
+ public func _toCustomAnyHashable() -> AnyHashable? {
+ return AnyHashable(_box: _SetAnyHashableBox(self))
+ }
+}
+
+internal struct _SetAnyHashableBox<Element: Hashable>: _AnyHashableBox {
+ internal let _value: Set<Element>
+ internal let _canonical: Set<AnyHashable>
+
+ internal init(_ value: Set<Element>) {
+ self._value = value
+ self._canonical = value as Set<AnyHashable>
+ }
+
+ internal var _base: Any {
+ return _value
+ }
+
+ internal var _canonicalBox: _AnyHashableBox {
+ return _SetAnyHashableBox<AnyHashable>(_canonical)
+ }
+
+ internal func _isEqual(to other: _AnyHashableBox) -> Bool? {
+ guard let other = other as? _SetAnyHashableBox<AnyHashable> else {
+ return nil
+ }
+ return _canonical == other._value
+ }
+
+ internal var _hashValue: Int {
+ return _canonical.hashValue
+ }
+
+ internal func _hash(into hasher: inout Hasher) {
+ _canonical.hash(into: &hasher)
+ }
+
+ func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+ return _canonical._rawHashValue(seed: _seed)
+ }
+
+ internal func _unbox<T: Hashable>() -> T? {
+ return _value as? T
+ }
+
+ internal func _downCastConditional<T>(
+ into result: UnsafeMutablePointer<T>
+ ) -> Bool {
+ guard let value = _value as? T else { return false }
+ result.initialize(to: value)
+ return true
+ }
+}
+
extension Set: SetAlgebra {
/// Inserts the given element in the set if it is not already present.
@@ -4003,20 +4058,6 @@
return remove(at: startIndex)
}
- @inlinable
- @available(swift, obsoleted: 4.0)
- public func filter(
- _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
- ) rethrows -> [Element] {
- var result: [Element] = []
- for x in self {
- if try isIncluded(x) {
- result.append(x)
- }
- }
- return result
- }
-
/// The total number of elements that the set can contain without
/// allocating new storage.
@inlinable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/Slice.swift b/stdlib/public/core/Slice.swift
index 57c8f54..139a52b 100644
--- a/stdlib/public/core/Slice.swift
+++ b/stdlib/public/core/Slice.swift
@@ -467,27 +467,3 @@
}
}
}
-
-@available(*, deprecated, renamed: "Slice")
-public typealias BidirectionalSlice<T> = Slice<T> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RandomAccessSlice<T> = Slice<T> where T : RandomAccessCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RangeReplaceableSlice<T> = Slice<T> where T : RangeReplaceableCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RangeReplaceableBidirectionalSlice<T> = Slice<T> where T : RangeReplaceableCollection & BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RangeReplaceableRandomAccessSlice<T> = Slice<T> where T : RangeReplaceableCollection & RandomAccessCollection
-
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableSlice<T> = Slice<T> where T : MutableCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RandomAccessCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRangeReplaceableSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRangeReplaceableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRangeReplaceableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & RandomAccessCollection
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
deleted file mode 100644
index d2baf42..0000000
--- a/stdlib/public/core/StringCharacterView.swift
+++ /dev/null
@@ -1,97 +0,0 @@
-//===--- StringCharacterView.swift - String's Collection of Characters ----===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-//
-// String is-not-a Sequence or Collection, but it exposes a
-// collection of characters.
-//
-//===----------------------------------------------------------------------===//
-
-// FIXME(ABI)#70 : The character string view should have a custom iterator type
-// to allow performance optimizations of linear traversals.
-
-import SwiftShims
-
-extension String {
- /// A view of a string's contents as a collection of characters.
- ///
- /// Previous versions of Swift provided this view since String
- /// itself was not a collection. String is now a collection of
- /// characters, so this type is now just an alias for String.
- @available(swift, deprecated: 3.2, obsoleted: 5.0,
- message: "Please use String directly")
- public typealias CharacterView = String
-
- /// A view of the string's contents as a collection of characters.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 5.0,
- message: "Please use String directly")
- public var characters: String {
- get {
- return self
- }
- set {
- self = newValue
- }
- }
-
- /// Applies the given closure to a mutable view of the string's characters.
- ///
- /// Previous versions of Swift provided this view since String
- /// itself was not a collection. String is now a collection of
- /// characters, so this type is now just an alias for String.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 5.0,
- message: "Please mutate the String directly")
- public mutating func withMutableCharacters<R>(
- _ body: (inout String) -> R
- ) -> R {
- return body(&self)
- }
-}
-
-extension Substring {
- /// A view of a string's contents as a collection of characters.
- ///
- /// Previous versions of Swift provided this view since String
- /// itself was not a collection. String is now a collection of
- /// characters, so this type is now just an alias for String.
- @available(swift, deprecated: 3.2, obsoleted: 5.0,
- message: "Please use Substring directly")
- public typealias CharacterView = Substring
-
- /// A view of the string's contents as a collection of characters.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 5.0,
- message: "Please use Substring directly")
- public var characters: Substring {
- get {
- return self
- }
- set {
- self = newValue
- }
- }
-
- /// Applies the given closure to a mutable view of the string's characters.
- ///
- /// Previous versions of Swift provided this view since String
- /// itself was not a collection. String is now a collection of
- /// characters, so this type is now just an alias for String.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 5.0,
- message: "Please mutate the Substring directly")
- public mutating func withMutableCharacters<R>(
- _ body: (inout Substring) -> R
- ) -> R {
- return body(&self)
- }
-}
diff --git a/stdlib/public/core/StringGraphemeBreaking.swift b/stdlib/public/core/StringGraphemeBreaking.swift
index 9a021ad..2f4c67b 100644
--- a/stdlib/public/core/StringGraphemeBreaking.swift
+++ b/stdlib/public/core/StringGraphemeBreaking.swift
@@ -255,7 +255,7 @@
// Nuclear option: copy out the rest of the string into a contiguous buffer.
let longStart = UnsafeMutablePointer<UInt16>.allocate(capacity: count)
- defer { longStart.deallocate(capacity: count) }
+ defer { longStart.deallocate() }
self._copy(into: UnsafeMutableBufferPointer(start: longStart, count: count))
return UTF16._measureFirstExtendedGraphemeCluster(
in: UnsafeBufferPointer(start: longStart, count: count))
@@ -282,7 +282,7 @@
// Nuclear option: copy out the rest of the string into a contiguous buffer.
let longStart = UnsafeMutablePointer<UInt16>.allocate(capacity: count)
- defer { longStart.deallocate(capacity: count) }
+ defer { longStart.deallocate() }
self._copy(into: UnsafeMutableBufferPointer(start: longStart, count: count))
return UTF16._measureLastExtendedGraphemeCluster(
in: UnsafeBufferPointer(start: longStart, count: count))
diff --git a/stdlib/public/core/StringIndex.swift b/stdlib/public/core/StringIndex.swift
index 39c6f62..6a45ed9 100644
--- a/stdlib/public/core/StringIndex.swift
+++ b/stdlib/public/core/StringIndex.swift
@@ -139,64 +139,3 @@
return Int(truncatingIfNeeded: _compoundOffset & 0x3)
}
}
-
-// SPI for Foundation
-extension String.Index {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2)
- @available(swift, obsoleted: 4.0)
- public // SPI(Foundation)
- init(_position: Int) {
- self.init(encodedOffset: _position)
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2)
- @available(swift, obsoleted: 4.0)
- public // SPI(Foundation)
- init(_codeUnitOffset: Int) {
- self.init(encodedOffset: _codeUnitOffset)
- }
-
- /// The integer offset of this index in UTF-16 code units.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2)
- @available(swift, obsoleted: 4.0)
- public // SPI(Foundation)
- var _utf16Index: Int {
- return self.encodedOffset
- }
-
- /// The integer offset of this index in UTF-16 code units.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2)
- @available(swift, obsoleted: 4.0)
- public // SPI(Foundation)
- var _offset: Int {
- return self.encodedOffset
- }
-}
-
-
-// backward compatibility for index interchange.
-extension Optional where Wrapped == String.Index {
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
- public static func ..<(
- lhs: String.Index?, rhs: String.Index?
- ) -> Range<String.Index> {
- return lhs! ..< rhs!
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
- public static func ...(
- lhs: String.Index?, rhs: String.Index?
- ) -> ClosedRange<String.Index> {
- return lhs! ... rhs!
- }
-}
diff --git a/stdlib/public/core/StringProtocol.swift b/stdlib/public/core/StringProtocol.swift
index 0dacf5a..8842115 100644
--- a/stdlib/public/core/StringProtocol.swift
+++ b/stdlib/public/core/StringProtocol.swift
@@ -126,18 +126,6 @@
}
}
-extension StringProtocol {
- //@available(swift, deprecated: 3.2, obsoleted: 4.0, message: "Please use the StringProtocol itself")
- //public var characters: Self { return self }
-
- @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF8View.Index")
- public typealias UTF8Index = UTF8View.Index
- @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF16View.Index")
- public typealias UTF16Index = UTF16View.Index
- @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UnicodeScalarView.Index")
- public typealias UnicodeScalarIndex = UnicodeScalarView.Index
-}
-
/// A protocol that provides fast access to a known representation of String.
///
/// Can be used to specialize generic functions that would otherwise end up
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift b/stdlib/public/core/StringRangeReplaceableCollection.swift
index 000ac08..f943a22 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift
@@ -65,17 +65,6 @@
self = other.description
}
- // The defaulted argument prevents this initializer from satisfies the
- // LosslessStringConvertible conformance. You can satisfy a protocol
- // requirement with something that's not yet available, but not with
- // something that has become unavailable. Without this, the code won't
- // compile as Swift 4.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4, message: "String.init(_:String) is no longer failable")
- public init?(_ other: String, obsoletedInSwift4: () = ()) {
- self.init(other._guts)
- }
-
/// The position of the first character in a nonempty string.
///
/// In an empty string, `startIndex` is equal to `endIndex`.
@@ -522,37 +511,6 @@
}
//===----------------------------------------------------------------------===//
-// The following overloads of flatMap are carefully crafted to allow the code
-// like the following:
-// ["hello"].flatMap { $0 }
-// return an array of strings without any type context in Swift 3 mode, at the
-// same time allowing the following code snippet to compile:
-// [0, 1].flatMap { x in
-// if String(x) == "foo" { return "bar" } else { return nil }
-// }
-// Note that the second overload is declared on a more specific protocol.
-// See: test/stdlib/StringFlatMap.swift for tests.
-extension Sequence {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public func flatMap(
- _ transform: (Element) throws -> String
- ) rethrows -> [String] {
- return try map(transform)
- }
-}
-
-extension Collection {
- @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
- message: "Please use compactMap(_:) for the case where closure returns an optional value")
- @inline(__always)
- public func flatMap(
- _ transform: (Element) throws -> String?
- ) rethrows -> [String] {
- return try _compactMap(transform)
- }
-}
-//===----------------------------------------------------------------------===//
extension Sequence where Element == String {
@available(*, unavailable, message: "Operator '+' cannot be used to append a String to a sequence of strings")
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index e8d31e9..8c8c1f1 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -294,45 +294,6 @@
}
/// Creates a string corresponding to the given sequence of UTF-16 code units.
- ///
- /// If `utf16` contains unpaired UTF-16 surrogates, the result is `nil`.
- ///
- /// You can use this initializer to create a new string from a slice of
- /// another string's `utf16` view.
- ///
- /// let picnicGuest = "Deserving porcupine"
- /// if let i = picnicGuest.utf16.firstIndex(of: 32) {
- /// let adjective = String(picnicGuest.utf16[..<i])
- /// print(adjective)
- /// }
- /// // Prints "Optional(Deserving)"
- ///
- /// The `adjective` constant is created by calling this initializer with a
- /// slice of the `picnicGuest.utf16` view.
- ///
- /// - Parameter utf16: A UTF-16 code sequence.
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 4.0)
- public init?(_ utf16: UTF16View) {
- // Attempt to recover the whole string, the better to implement the actual
- // Swift 3.1 semantics, which are not as documented above! Full Swift 3.1
- // semantics may be impossible to preserve in the case of string literals,
- // since we no longer have access to the length of the original string when
- // there is no owner and elements are dropped from the end.
- let wholeString = String(utf16._guts)
- guard
- let start = UTF16Index(encodedOffset: utf16._offset)
- .samePosition(in: wholeString),
- let end = UTF16Index(encodedOffset: utf16._offset + utf16._length)
- .samePosition(in: wholeString)
- else
- {
- return nil
- }
- self = wholeString[start..<end]
- }
-
- /// Creates a string corresponding to the given sequence of UTF-16 code units.
@inlinable // FIXME(sil-serialize-all)
@available(swift, introduced: 4.0)
public init(_ utf16: UTF16View) {
@@ -434,14 +395,6 @@
}
}
-extension String.UTF16View : CustomPlaygroundQuickLookable {
- @inlinable // FIXME(sil-serialize-all)
- @available(*, deprecated, message: "UTF16View.customPlaygroundQuickLook will be removed in a future Swift version")
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
- return .text(description)
- }
-}
-
extension String.UTF16View.Indices : BidirectionalCollection {
public typealias Index = String.UTF16View.Index
public typealias Indices = String.UTF16View.Indices
@@ -534,39 +487,6 @@
}
}
-// backward compatibility for index interchange.
-extension String.UTF16View {
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public func index(after i: Index?) -> Index {
- return index(after: i!)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public func index(
- _ i: Index?, offsetBy n: Int) -> Index {
- return index(i!, offsetBy: n)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
- public func distance(from i: Index?, to j: Index?) -> Int {
- return distance(from: i!, to: j!)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public subscript(i: Index?) -> Unicode.UTF16.CodeUnit {
- return self[i!]
- }
-}
-
//===--- Slicing Support --------------------------------------------------===//
/// In Swift 3.2, in the absence of type context,
///
@@ -580,22 +500,7 @@
@inlinable // FIXME(sil-serialize-all)
@available(swift, introduced: 4)
- public subscript(r: Range<Index>) -> String.UTF16View.SubSequence {
- return String.UTF16View.SubSequence(self, _bounds: r)
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: Range<Index>) -> String.UTF16View {
- return String.UTF16View(
- _guts,
- offset: _internalIndex(at: bounds.lowerBound.encodedOffset),
- length: bounds.upperBound.encodedOffset - bounds.lowerBound.encodedOffset)
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: ClosedRange<Index>) -> String.UTF16View {
- return self[bounds.relative(to: self)]
+ public subscript(bounds: Range<Index>) -> String.UTF16View.SubSequence {
+ return String.UTF16View.SubSequence(self, _bounds: bounds)
}
}
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index ab76cd2..65b155b 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -178,7 +178,7 @@
_guts, range: (n..<count, performBoundsCheck: true),
ascii: { _ in
Builtin.unreachable()
- return Index._UTF8Buffer() },
+ /* return Index._UTF8Buffer() */ },
utf16: { utf16 in
var i = utf16.makeIterator()
return UTF8View._fillBuffer(from: &i) },
@@ -451,38 +451,6 @@
}
/// Creates a string corresponding to the given sequence of UTF-8 code units.
- ///
- /// If `utf8` is an ill-formed UTF-8 code sequence, the result is `nil`.
- ///
- /// You can use this initializer to create a new string from a slice of
- /// another string's `utf8` view.
- ///
- /// let picnicGuest = "Deserving porcupine"
- /// if let i = picnicGuest.utf8.firstIndex(of: 32) {
- /// let adjective = String(picnicGuest.utf8[..<i])
- /// print(adjective)
- /// }
- /// // Prints "Optional(Deserving)"
- ///
- /// The `adjective` constant is created by calling this initializer with a
- /// slice of the `picnicGuest.utf8` view.
- ///
- /// - Parameter utf8: A UTF-8 code sequence.
- @available(swift, deprecated: 3.2,
- message: "Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)")
- @available(swift, obsoleted: 4.0,
- message: "Please use non-failable String.init(_:UTF8View) instead")
- public init?(_ utf8: UTF8View) {
- if utf8.startIndex.transcodedOffset != 0
- || utf8.endIndex.transcodedOffset != 0
- || utf8._legacyPartialCharacters.start
- || utf8._legacyPartialCharacters.end {
- return nil
- }
- self = String(utf8._guts)
- }
-
- /// Creates a string corresponding to the given sequence of UTF-8 code units.
@inlinable // FIXME(sil-serialize-all)
@available(swift, introduced: 4.0, message:
"Please use failable String.init?(_:UTF8View) when in Swift 3.2 mode")
@@ -722,47 +690,6 @@
}
}
-extension String.UTF8View : CustomPlaygroundQuickLookable {
- @inlinable // FIXME(sil-serialize-all)
- @available(*, deprecated, message: "UTF8View.customPlaygroundQuickLook will be removed in a future Swift version")
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
- return .text(description)
- }
-}
-
-// backward compatibility for index interchange.
-extension String.UTF8View {
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public func index(after i: Index?) -> Index {
- return index(after: i!)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public func index(_ i: Index?, offsetBy n: Int) -> Index {
- return index(i!, offsetBy: n)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
- public func distance(
- from i: Index?, to j: Index?) -> Int {
- return distance(from: i!, to: j!)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public subscript(i: Index?) -> Unicode.UTF8.CodeUnit {
- return self[i!]
- }
-}
-
//===--- Slicing Support --------------------------------------------------===//
/// In Swift 3.2, in the absence of type context,
///
@@ -779,42 +706,6 @@
public subscript(r: Range<Index>) -> String.UTF8View.SubSequence {
return String.UTF8View.SubSequence(self, _bounds: r)
}
-
- @available(swift, obsoleted: 4)
- public subscript(r: Range<Index>) -> String.UTF8View {
- let wholeString = String(_guts)
- let legacyPartialCharacters = (
- (self._legacyPartialCharacters.start &&
- r.lowerBound.encodedOffset == 0) ||
- r.lowerBound.samePosition(in: wholeString) == nil,
- (self._legacyPartialCharacters.end &&
- r.upperBound.encodedOffset == _guts.count) ||
- r.upperBound.samePosition(in: wholeString) == nil)
-
- if r.upperBound.transcodedOffset == 0 {
- return String.UTF8View(
- _guts._extractSlice(
- r.lowerBound.encodedOffset..<r.upperBound.encodedOffset),
- legacyOffsets: (r.lowerBound.transcodedOffset, 0),
- legacyPartialCharacters: legacyPartialCharacters)
- }
-
- let b0 = r.upperBound.utf8Buffer!.first!
- let scalarLength8 = (~b0).leadingZeroBitCount
- let scalarLength16 = scalarLength8 == 4 ? 2 : 1
- let coreEnd = r.upperBound.encodedOffset + scalarLength16
- return String.UTF8View(
- _guts._extractSlice(r.lowerBound.encodedOffset..<coreEnd),
- legacyOffsets: (
- r.lowerBound.transcodedOffset,
- r.upperBound.transcodedOffset - scalarLength8),
- legacyPartialCharacters: legacyPartialCharacters)
- }
-
- @available(swift, obsoleted: 4)
- public subscript(bounds: ClosedRange<Index>) -> String.UTF8View {
- return self[bounds.relative(to: self)]
- }
}
extension String.UTF8View {
diff --git a/stdlib/public/core/StringUnicodeScalarView.swift b/stdlib/public/core/StringUnicodeScalarView.swift
index 586a9da..b0c047d 100644
--- a/stdlib/public/core/StringUnicodeScalarView.swift
+++ b/stdlib/public/core/StringUnicodeScalarView.swift
@@ -124,7 +124,7 @@
public func index(after i: Index) -> Index {
let offset = _toCoreIndex(i)
let length: Int = _visitGuts(_guts, args: offset,
- ascii: { _ -> Int in return 1 },
+ ascii: { (_,_) -> Int in return 1 },
utf16: { utf16, offset in
return utf16.unicodeScalarWidth(startingAt: offset) },
opaque: { opaque, offset in
@@ -140,7 +140,7 @@
public func index(before i: Index) -> Index {
let offset = _toCoreIndex(i)
let length: Int = _visitGuts(_guts, args: offset,
- ascii: { _ -> Int in return 1 },
+ ascii: { (_,_) -> Int in return 1 },
utf16: { utf16, offset in
return utf16.unicodeScalarWidth(endingAt: offset) },
opaque: { opaque, offset in
@@ -554,46 +554,6 @@
}
}
-extension String.UnicodeScalarView : CustomPlaygroundQuickLookable {
- @inlinable // FIXME(sil-serialize-all)
- @available(*, deprecated, message: "UnicodeScalarView.customPlaygroundQuickLook will be removed in a future Swift version")
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
- return .text(description)
- }
-}
-
-// backward compatibility for index interchange.
-extension String.UnicodeScalarView {
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public func index(after i: Index?) -> Index {
- return index(after: i!)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public func index(_ i: Index?, offsetBy n: Int) -> Index {
- return index(i!, offsetBy: n)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
- public func distance(from i: Index?, to j: Index?) -> Int {
- return distance(from: i!, to: j!)
- }
- @inlinable // FIXME(sil-serialize-all)
- @available(
- swift, obsoleted: 4.0,
- message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
- public subscript(i: Index?) -> Unicode.Scalar {
- return self[i!]
- }
-}
-
//===--- Slicing Support --------------------------------------------------===//
/// In Swift 3.2, in the absence of type context,
///
@@ -609,35 +569,7 @@
@inlinable // FIXME(sil-serialize-all)
@available(swift, introduced: 4)
- public subscript(r: Range<Index>) -> String.UnicodeScalarView.SubSequence {
- return String.UnicodeScalarView.SubSequence(self, _bounds: r)
- }
-
- /// Accesses the Unicode scalar values in the given range.
- ///
- /// The example below uses this subscript to access the scalar values up
- /// to, but not including, the first comma (`","`) in the string.
- ///
- /// let str = "All this happened, more or less."
- /// let i = str.unicodeScalars.firstIndex(of: ",")!
- /// let substring = str.unicodeScalars[str.unicodeScalars.startIndex ..< i]
- /// print(String(substring))
- /// // Prints "All this happened"
- ///
- /// - Complexity: O(*n*) if the underlying string is bridged from
- /// Objective-C, where *n* is the length of the string; otherwise, O(1).
- @available(swift, obsoleted: 4)
- public subscript(r: Range<Index>) -> String.UnicodeScalarView {
- let rawSubRange: Range<Int> =
- _toCoreIndex(r.lowerBound)..<_toCoreIndex(r.upperBound)
- return String.UnicodeScalarView(
- _guts._extractSlice(rawSubRange),
- coreOffset: r.lowerBound.encodedOffset)
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: ClosedRange<Index>) -> String.UnicodeScalarView {
- return self[bounds.relative(to: self)]
+ public subscript(bounds: Range<Index>) -> String.UnicodeScalarView.SubSequence {
+ return String.UnicodeScalarView.SubSequence(self, _bounds: bounds)
}
}
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index f9038b0..2bd5684 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -330,14 +330,6 @@
}
}
-extension Substring : CustomPlaygroundQuickLookable {
- @inlinable // FIXME(sil-serialize-all)
- @available(*, deprecated, message: "Substring.customPlaygroundQuickLook will be removed in a future Swift version")
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
- return String(self).customPlaygroundQuickLook
- }
-}
-
extension Substring : CustomStringConvertible {
@inlinable // FIXME(sil-serialize-all)
public var description: String {
@@ -622,22 +614,6 @@
return Substring(
_slice: Slice(base: self, bounds: r))
}
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: Range<Index>) -> String {
- _boundsCheck(bounds)
- return String(Substring(_slice: Slice(base: self, bounds: bounds)))
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: ClosedRange<Index>) -> String {
- _boundsCheck(bounds)
- return String(Substring(_slice: Slice(
- base: self,
- bounds: bounds.relative(to: self))))
- }
}
extension Substring {
@@ -646,46 +622,6 @@
public subscript(r: Range<Index>) -> Substring {
return Substring(_slice: _slice[r])
}
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: Range<Index>) -> String {
- return String(Substring(_slice: _slice[bounds]))
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, obsoleted: 4)
- public subscript(bounds: ClosedRange<Index>) -> String {
- return self[bounds.relative(to: self)]
- }
-}
-//===----------------------------------------------------------------------===//
-
-// popFirst() is only present when a collection is its own subsequence. This was
-// dropped in Swift 4.
-extension String {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 4, message:
- "Please use 'first', 'dropFirst()', or 'Substring.popFirst()'.")
- public mutating func popFirst() -> String.Element? {
- guard !isEmpty else { return nil }
- let element = first!
- let nextIdx = self.index(after: self.startIndex)
- self = String(self[nextIdx...])
- return element
- }
-}
-extension String.UnicodeScalarView {
- @inlinable // FIXME(sil-serialize-all)
- @available(swift, deprecated: 3.2, obsoleted: 4, message:
- "Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'.")
- public mutating func popFirst() -> String.UnicodeScalarView.Element? {
- guard !isEmpty else { return nil }
- let element = first!
- let nextIdx = self.index(after: self.startIndex)
- self = String(self[nextIdx...]).unicodeScalars
- return element
- }
}
// ${'Local Variables'}:
diff --git a/stdlib/public/core/Unicode.swift b/stdlib/public/core/Unicode.swift
index 64ca5d1..768ec85 100644
--- a/stdlib/public/core/Unicode.swift
+++ b/stdlib/public/core/Unicode.swift
@@ -314,9 +314,6 @@
}
}
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.UTF8")
-public typealias UTF8 = Unicode.UTF8
-
/// A codec for translating between Unicode scalar values and UTF-16 code
/// units.
extension Unicode.UTF16 : UnicodeCodec {
@@ -428,8 +425,6 @@
processCodeUnit(UInt16(truncatingIfNeeded: s))
}
}
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.UTF16")
-public typealias UTF16 = Unicode.UTF16
/// A codec for translating between Unicode scalar values and UTF-32 code
/// units.
@@ -523,8 +518,6 @@
processCodeUnit(UInt32(input))
}
}
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.UTF32")
-public typealias UTF32 = Unicode.UTF32
/// Translates the given input from one Unicode encoding to another by calling
/// the given closure.
diff --git a/stdlib/public/core/UnicodeScalar.swift b/stdlib/public/core/UnicodeScalar.swift
index 7d095f6..9691523 100644
--- a/stdlib/public/core/UnicodeScalar.swift
+++ b/stdlib/public/core/UnicodeScalar.swift
@@ -466,6 +466,3 @@
Builtin.unreachable()
}
}
-
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.Scalar")
-public typealias UnicodeScalar = Unicode.Scalar
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index f6c7cf7..13c8031 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -667,9 +667,6 @@
}
}
-@available(*, deprecated, renamed: "UnsafeBufferPointer.Iterator")
-public typealias UnsafeBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
-
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
diff --git a/stdlib/public/core/UnsafePointer.swift.gyb b/stdlib/public/core/UnsafePointer.swift.gyb
index 51d619d..bd9584f 100644
--- a/stdlib/public/core/UnsafePointer.swift.gyb
+++ b/stdlib/public/core/UnsafePointer.swift.gyb
@@ -436,12 +436,6 @@
Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self)
return UnsafeMutablePointer(rawPtr)
}
-
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
- public func deallocate(capacity _: Int) {
- self.deallocate()
- }
-
% end
/// Deallocates the memory block previously allocated at this pointer.
@@ -485,11 +479,6 @@
}
% if mutable:
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "initialize(repeating:count:)")
- public func initialize(to newValue: Pointee, count: Int = 1) {
- initialize(repeating: newValue, count: count)
- }
-
/// Initializes this pointer's memory with the specified number of
/// consecutive copies of the given value.
///
@@ -683,28 +672,6 @@
// }
}
- /// Initializes memory starting at this pointer's address with the elements
- /// of the given collection.
- ///
- /// The region of memory starting at this pointer and covering `source.count`
- /// instances of the pointer's `Pointee` type must be uninitialized or
- /// `Pointee` must be a trivial type. After calling `initialize(from:)`, the
- /// region is initialized.
- ///
- /// - Parameter source: A collection of elements of the pointer's `Pointee`
- /// type.
- // This is fundamentally unsafe since collections can underreport their count.
- @inlinable
- @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'UnsafeMutableBufferPointer.initialize(from:)' instead")
- public func initialize<C : Collection>(from source: C)
- where C.Element == Pointee {
- let buf = UnsafeMutableBufferPointer(start: self, count: numericCast(source.count))
- var (remainders,writtenUpTo) = source._copyContents(initializing: buf)
- // ensure that exactly rhs.count elements were written
- _precondition(remainders.next() == nil, "rhs underreported its count")
- _precondition(writtenUpTo == buf.endIndex, "rhs overreported its count")
- }
-
/// Replaces the memory referenced by this pointer with the values
/// starting at the given pointer, leaving the source memory uninitialized.
///
@@ -735,13 +702,6 @@
// }
}
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, message: "the default argument to deinitialize(count:) has been removed, please specify the count explicitly")
- @inlinable
- @discardableResult
- public func deinitialize() -> UnsafeMutableRawPointer {
- return deinitialize(count: 1)
- }
-
/// Deinitializes the specified number of values starting at this pointer.
///
/// The region of memory starting at this pointer and covering `count`
@@ -999,21 +959,6 @@
}
}
-extension ${Self} : CustomPlaygroundQuickLookable {
- @inlinable // FIXME(sil-serialize-all)
- internal var summary: String {
- let selfType = "${Self}"
- let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
- return ptrValue == 0 ? "\(selfType)(nil)" : "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
- }
-
- @inlinable // FIXME(sil-serialize-all)
- @available(*, deprecated, message: "${Self}.customPlaygroundQuickLook will be removed in a future Swift version")
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
- return .text(summary)
- }
-}
-
extension Int {
/// Creates a new value with the bit pattern of the given pointer.
///
diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
index 7abe817..cb3b501 100644
--- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
@@ -263,12 +263,6 @@
extension Unsafe${Mutable}RawBufferPointer {
% if mutable:
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "allocate(byteCount:alignment:)")
- public static func allocate(count: Int) -> UnsafeMutableRawBufferPointer {
- return UnsafeMutableRawBufferPointer.allocate(
- byteCount: count, alignment: MemoryLayout<UInt>.alignment)
- }
-
/// Returns a newly allocated buffer with the given size, in bytes.
///
/// The memory referenced by the new buffer is allocated, but not
@@ -374,10 +368,6 @@
baseAddress!.storeBytes(of: value, toByteOffset: offset, as: T.self)
}
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "copyMemory(from:)")
- public func copyBytes(from source: UnsafeRawBufferPointer) {
- copyMemory(from: source)
- }
/// Copies the bytes from the given buffer to this buffer's memory.
///
/// If the `source.count` bytes of memory referenced by this buffer are bound
@@ -814,12 +804,6 @@
return try body(buffer)
}
-// @available(*, deprecated, renamed: "UnsafeRawBufferPointer.Iterator")
-public typealias UnsafeRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
-
-// @available(*, deprecated, renamed: "UnsafeRawBufferPointer.Iterator")
-public typealias UnsafeMutableRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
-
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
diff --git a/stdlib/public/core/UnsafeRawPointer.swift.gyb b/stdlib/public/core/UnsafeRawPointer.swift.gyb
index 5fc78d8..e52a332 100644
--- a/stdlib/public/core/UnsafeRawPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawPointer.swift.gyb
@@ -426,15 +426,6 @@
% end # !mutable
% if mutable:
-
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "allocate(byteCount:alignment:)")
- @inlinable
- public static func allocate(
- bytes size: Int, alignedTo alignment: Int
- ) -> UnsafeMutableRawPointer {
- return UnsafeMutableRawPointer.allocate(byteCount: size, alignment: alignment)
- }
-
/// Allocates uninitialized memory with the specified size and alignment.
///
/// You are in charge of managing the allocated memory. Be sure to deallocate
@@ -460,11 +451,6 @@
}
% end # mutable
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
- public func deallocate(bytes _: Int, alignedTo _: Int) {
- self.deallocate()
- }
-
/// Deallocates the previously allocated memory block referenced by this pointer.
///
/// The memory to be deallocated must be uninitialized or initialized to a
@@ -537,17 +523,7 @@
return Unsafe${Mutable}Pointer<T>(_rawValue)
}
-% if mutable:
-
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "initializeMemory(as:repeating:count:)")
- @discardableResult
- public func initializeMemory<T>(
- as type: T.Type, at offset: Int = 0, count: Int = 1, to repeatedValue: T
- ) -> UnsafeMutablePointer<T> {
- return (self + offset * MemoryLayout<T>.stride).initializeMemory(
- as: type, repeating: repeatedValue, count: count)
- }
-
+% if mutable:
/// Initializes the memory referenced by this pointer with the given value,
/// binds the memory to the value's type, and returns a typed pointer to the
/// initialized memory.
@@ -665,62 +641,6 @@
return UnsafeMutablePointer(_rawValue)
}
- /// Initializes the memory referenced by this pointer with the values of the
- /// given collection, binds the memory to the values' type, and returns a
- /// typed pointer to the initialized memory.
- ///
- /// The memory referenced by this pointer must be uninitialized or
- /// initialized to a trivial type, and must be properly aligned for
- /// accessing `T`.
- ///
- /// The following example allocates enough raw memory to hold four instances
- /// of `Int8`, and then uses the `initializeMemory(as:from:)` method to
- /// initialize the allocated memory.
- ///
- /// let count = 4
- /// let bytesPointer = UnsafeMutableRawPointer.allocate(
- /// bytes: count * MemoryLayout<Int8>.stride,
- /// alignedTo: MemoryLayout<Int8>.alignment)
- /// let values: [Int8] = [1, 2, 3, 4]
- /// let int8Pointer = bytesPointer.initializeMemory(
- /// as: Int8.self,
- /// from: values)
- /// // int8Pointer.pointee == 1
- /// // (int8Pointer + 3).pointee == 4
- ///
- /// // After using 'int8Pointer':
- /// int8Pointer.deallocate(count)
- ///
- /// After calling this method on a raw pointer `p`, the region starting at
- /// `p` and continuing up to `p + count * MemoryLayout<T>.stride` is bound
- /// to type `T` and initialized. If `T` is a nontrivial type, you must
- /// eventually deinitialize or move from the values in this region to avoid
- /// leaks.
- ///
- /// - Parameters:
- /// - type: The type to bind this memory to.
- /// - source: A pointer to the values to copy. If `source` is an
- /// `UnsafeBufferPointer` or `UnsafeMutableBufferPointer` instance, the
- /// memory region referenced by `source` must not overlap the
- /// destination region.
- /// - Returns: A typed pointer to the memory referenced by this raw pointer.
- // This is fundamentally unsafe since collections can underreport their count.
- @inlinable
- @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'UnsafeMutableRawBufferPointer.initialize(from:)' instead")
- @discardableResult
- public func initializeMemory<C : Collection>(
- as type: C.Element.Type, from source: C
- ) -> UnsafeMutablePointer<C.Element> {
- // TODO: Optimize where `C` is a `ContiguousArrayBuffer`.
- // Initialize and bind each element of the container.
- var ptr = self
- for element in source {
- ptr.initializeMemory(as: C.Element.self, repeating: element, count: 1)
- ptr += MemoryLayout<C.Element>.stride
- }
- return UnsafeMutablePointer(_rawValue)
- }
-
/// Initializes the memory referenced by this pointer with the values
/// starting at the given pointer, binds the memory to the values' type,
/// deinitializes the source memory, and returns a typed pointer to the
@@ -864,11 +784,6 @@
/*volatile:*/ false._value)
}
}
-
- @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "copyMemory(from:byteCount:)")
- public func copyBytes(from source: UnsafeRawPointer, count: Int) {
- copyMemory(from: source, byteCount: count)
- }
/// Copies the specified number of bytes from the given raw pointer's memory
/// into this pointer's memory.
@@ -991,24 +906,6 @@
}
}
-extension Unsafe${Mutable}RawPointer : CustomPlaygroundQuickLookable {
- @inlinable // FIXME(sil-serialize-all)
- @available(*, deprecated, message: "Unsafe${Mutable}RawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
- internal var summary: String {
- let selfType = "${Self}"
- let ptrValue = UInt64(
- bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
- return ptrValue == 0
- ? "\(selfType)(nil)"
- : "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
- }
-
- @inlinable // FIXME(sil-serialize-all)
- public var customPlaygroundQuickLook: PlaygroundQuickLook {
- return .text(summary)
- }
-}
-
extension OpaquePointer {
@inlinable
public init(_ from: Unsafe${Mutable}RawPointer) {
diff --git a/stdlib/public/core/Zip.swift b/stdlib/public/core/Zip.swift
index eb6a6c8..5bb3dc5 100644
--- a/stdlib/public/core/Zip.swift
+++ b/stdlib/public/core/Zip.swift
@@ -74,11 +74,6 @@
@usableFromInline // FIXME(sil-serialize-all)
internal let _sequence2: Sequence2
- @available(*, deprecated, renamed: "Sequence1.Iterator")
- public typealias Stream1 = Sequence1.Iterator
- @available(*, deprecated, renamed: "Sequence2.Iterator")
- public typealias Stream2 = Sequence2.Iterator
-
/// Creates an instance that makes pairs of elements from `sequence1` and
/// `sequence2`.
@inlinable // FIXME(sil-serialize-all)
@@ -151,6 +146,3 @@
_sequence2.makeIterator())
}
}
-
-@available(*, deprecated: 4.2, renamed: "Zip2Sequence.Iterator")
-public typealias Zip2Iterator<T, U> = Zip2Sequence<T, U>.Iterator where T: Sequence, U: Sequence
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 626e18f..32c7440 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -2941,6 +2941,12 @@
return true;
}
}
+ // Try to bridge NSError to Error.
+ if (tryDynamicCastNSErrorObjectToValue(sourceValue, destValue, nativeType,
+ DynamicCastFlags::Default)) {
+ return true;
+ }
+
return false;
}
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 07fb3fe..55aeb92 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -160,8 +160,14 @@
auto typeNode = Dem.createNode(nodeKind);
typeNode->addChild(node, Dem);
- auto identifier = Dem.createNode(Node::Kind::Identifier, name);
- typeNode->addChild(identifier, Dem);
+ auto nameNode = Dem.createNode(Node::Kind::Identifier, name);
+ if (type->isSynthesizedRelatedEntity()) {
+ auto relatedName = Dem.createNode(Node::Kind::RelatedEntityDeclName,
+ type->getSynthesizedDeclRelatedEntityTag());
+ relatedName->addChild(nameNode, Dem);
+ nameNode = relatedName;
+ }
+ typeNode->addChild(nameNode, Dem);
node = typeNode;
// Apply generic arguments if the context is generic.
diff --git a/stdlib/public/runtime/ErrorObject.h b/stdlib/public/runtime/ErrorObject.h
index 43358f0..8d4cdfe 100644
--- a/stdlib/public/runtime/ErrorObject.h
+++ b/stdlib/public/runtime/ErrorObject.h
@@ -223,8 +223,17 @@
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_SPI
id _swift_stdlib_bridgeErrorToNSError(SwiftError *errorObject);
+/// Attempt to dynamically cast an NSError object to a Swift ErrorType
+/// implementation using the _ObjectiveCBridgeableErrorType protocol or by
+/// putting it directly into an Error existential.
+bool tryDynamicCastNSErrorObjectToValue(HeapObject *object,
+ OpaqueValue *dest,
+ const Metadata *destType,
+ DynamicCastFlags flags);
+
/// Attempt to dynamically cast an NSError instance to a Swift ErrorType
-/// implementation using the _ObjectiveCBridgeableErrorType protocol.
+/// implementation using the _ObjectiveCBridgeableErrorType protocol or by
+/// putting it directly into an Error existential.
///
/// srcType must be some kind of class metadata.
bool tryDynamicCastNSErrorToValue(OpaqueValue *dest,
diff --git a/stdlib/public/runtime/ErrorObject.mm b/stdlib/public/runtime/ErrorObject.mm
index d67b4cd..e5b3a39 100644
--- a/stdlib/public/runtime/ErrorObject.mm
+++ b/stdlib/public/runtime/ErrorObject.mm
@@ -462,47 +462,27 @@
extern "C" const ProtocolDescriptor PROTOCOL_DESCR_SYM(s5Error);
bool
-swift::tryDynamicCastNSErrorToValue(OpaqueValue *dest,
- OpaqueValue *src,
- const Metadata *srcType,
- const Metadata *destType,
- DynamicCastFlags flags) {
+swift::tryDynamicCastNSErrorObjectToValue(HeapObject *object,
+ OpaqueValue *dest,
+ const Metadata *destType,
+ DynamicCastFlags flags) {
Class NSErrorClass = getNSErrorClass();
- auto CFErrorTypeID = SWIFT_LAZY_CONSTANT(CFErrorGetTypeID());
- NSError *srcInstance;
-
- // Is the input type an NSError?
- switch (srcType->getKind()) {
- case MetadataKind::Class:
- case MetadataKind::ObjCClassWrapper:
- // Native class or ObjC class should be an NSError subclass.
- if (![srcType->getObjCClassObject() isSubclassOfClass: NSErrorClass])
- return false;
-
- srcInstance = *reinterpret_cast<NSError * const*>(src);
-
- // A _SwiftNativeNSError box can always be unwrapped to cast the value back
- // out as an Error existential.
- if (!reinterpret_cast<SwiftError*>(srcInstance)->isPureNSError()) {
- auto theErrorProtocol = &PROTOCOL_DESCR_SYM(s5Error);
- auto theErrorTy =
- swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
- nullptr, 1, &theErrorProtocol);
- return swift_dynamicCast(dest, src, theErrorTy, destType, flags);
- }
-
- break;
- case MetadataKind::ForeignClass: {
- // Foreign class should be CFError.
- CFTypeRef srcInstance = *reinterpret_cast<CFTypeRef *>(src);
- if (CFGetTypeID(srcInstance) != CFErrorTypeID)
- return false;
- break;
- }
- // Not a class.
- default:
+ // The object must be an NSError subclass.
+ if (![reinterpret_cast<id>(object) isKindOfClass: NSErrorClass])
return false;
+
+ NSError *srcInstance = reinterpret_cast<NSError *>(object);
+
+ // A _SwiftNativeNSError box can always be unwrapped to cast the value back
+ // out as an Error existential.
+ if (!reinterpret_cast<SwiftError*>(srcInstance)->isPureNSError()) {
+ auto theErrorProtocol = &PROTOCOL_DESCR_SYM(s5Error);
+ auto theErrorTy =
+ swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
+ nullptr, 1, &theErrorProtocol);
+ return swift_dynamicCast(dest, reinterpret_cast<OpaqueValue *>(&object),
+ theErrorTy, destType, flags);
}
// public func Foundation._bridgeNSErrorToError<
@@ -521,19 +501,47 @@
auto witness = swift_conformsToProtocol(destType,
TheObjectiveCBridgeableError);
- if (!witness)
- return false;
+ if (witness) {
+ // If so, attempt the bridge.
+ if (bridgeNSErrorToError(srcInstance, dest, destType, witness)) {
+ if (flags & DynamicCastFlags::TakeOnSuccess)
+ objc_release(srcInstance);
+ return true;
+ }
+ }
- // If so, attempt the bridge.
- SWIFT_CC_PLUSONE_GUARD(objc_retain(srcInstance));
- if (bridgeNSErrorToError(srcInstance, dest, destType, witness)) {
- if (flags & DynamicCastFlags::TakeOnSuccess)
- objc_release(srcInstance);
+ // If the destination is just an Error then we can bridge directly.
+ auto *destTypeExistential = dyn_cast<ExistentialTypeMetadata>(destType);
+ if (destTypeExistential &&
+ destTypeExistential->getRepresentation() == ExistentialTypeRepresentation::Error) {
+ auto destBoxAddr = reinterpret_cast<NSError**>(dest);
+ *destBoxAddr = objc_retain(srcInstance);
return true;
}
+
return false;
}
+bool
+swift::tryDynamicCastNSErrorToValue(OpaqueValue *dest,
+ OpaqueValue *src,
+ const Metadata *srcType,
+ const Metadata *destType,
+ DynamicCastFlags flags) {
+ // NSError instances must be class instances, anything else automatically fails.
+ switch (srcType->getKind()) {
+ case MetadataKind::Class:
+ case MetadataKind::ObjCClassWrapper:
+ case MetadataKind::ForeignClass:
+ return tryDynamicCastNSErrorObjectToValue(*reinterpret_cast<HeapObject **>(src),
+ dest, destType, flags);
+
+ // Not a class.
+ default:
+ return false;
+ }
+}
+
SwiftError *
swift::swift_errorRetain(SwiftError *error) {
// For now, SwiftError is always objc-refcounted.
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 903511d..70b3580 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1473,7 +1473,20 @@
&& kind <= ContextDescriptorKind::Type_Last) {
auto typeA = cast<TypeContextDescriptor>(a);
auto typeB = cast<TypeContextDescriptor>(b);
- return strcmp(typeA->Name.get(), typeB->Name.get()) == 0;
+ if (strcmp(typeA->Name.get(), typeB->Name.get()) != 0)
+ return false;
+
+ // A synthesized entity has to match the related entity tag too.
+ if (typeA->isSynthesizedRelatedEntity()) {
+ if (!typeB->isSynthesizedRelatedEntity())
+ return false;
+
+ if (typeA->getSynthesizedDeclRelatedEntityTag()
+ != typeB->getSynthesizedDeclRelatedEntityTag())
+ return false;
+ }
+
+ return true;
}
// Otherwise, this runtime doesn't know anything about this context kind.
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index a239b0b..be28b62 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -264,14 +264,31 @@
}
auto nameNode = node->getChild(1);
- if (nameNode->getKind() == Demangle::Node::Kind::PrivateDeclName)
- return false;
-
- if (nameNode->getText() != type->Name.get())
- return false;
- node = node->getChild(0);
- break;
+ // Declarations synthesized by the Clang importer get a small tag
+ // string in addition to their name.
+ if (nameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName){
+ if (nameNode->getText() != type->getSynthesizedDeclRelatedEntityTag())
+ return false;
+
+ nameNode = nameNode->getChild(0);
+ } else if (type->isSynthesizedRelatedEntity()) {
+ return false;
+ }
+
+ // We should only match public or internal declarations with stable
+ // names. The runtime metadata for private declarations would be
+ // anonymized.
+ if (nameNode->getKind() == Demangle::Node::Kind::Identifier) {
+ if (nameNode->getText() != type->Name.get())
+ return false;
+
+ node = node->getChild(0);
+ break;
+ }
+
+ return false;
+
}
// We don't know about this kind of context, or it doesn't have a stable
@@ -1166,7 +1183,7 @@
if (typeInfo == nullptr) {
typeInfo = TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {});
warning(0, "SWIFT RUNTIME BUG: unable to demangle type of field '%*s'. "
- "mangled type name is '%*s'",
+ "mangled type name is '%*s'\n",
(int)name.size(), name.data(),
(int)typeName.size(), typeName.data());
}
@@ -1214,6 +1231,17 @@
return;
}
}
+
+ // If we failed to find the field descriptor metadata for the type, fall
+ // back to returning an empty tuple as a standin.
+ auto typeName = swift_getTypeName(base, /*qualified*/ true);
+ warning(0, "SWIFT RUNTIME BUG: unable to find field metadata for type '%*s'\n",
+ (int)typeName.length, typeName.data);
+ callback("unknown",
+ FieldType()
+ .withType(TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {}))
+ .withIndirect(false)
+ .withWeak(false));
}
#define OVERRIDE_METADATALOOKUP COMPATIBILITY_OVERRIDE
diff --git a/test/Compatibility/lazy_properties.swift b/test/Compatibility/lazy_properties.swift
index c621521..313011b 100644
--- a/test/Compatibility/lazy_properties.swift
+++ b/test/Compatibility/lazy_properties.swift
@@ -4,7 +4,7 @@
lazy var refs = (i, f())
// expected-error@-1 {{cannot use instance member 'i' within property initializer; property initializers run before 'self' is available}}
lazy var trefs: (Int, Int) = (i, f())
- // expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
+ // expected-error@-1 {{cannot use instance member 'i' within property initializer; property initializers run before 'self' is available}}
lazy var qrefs = (self.i, self.f())
lazy var qtrefs: (Int, Int) = (self.i, self.f())
@@ -53,5 +53,5 @@
static var i = 42
static func f() -> Int { return 0 }
- // expected-note@-1 {{did you mean 'f'?}}
+ // expected-note@-1 2 {{did you mean 'f'?}}
}
diff --git a/test/Compatibility/members.swift b/test/Compatibility/members.swift
index 1805106..6af2274 100644
--- a/test/Compatibility/members.swift
+++ b/test/Compatibility/members.swift
@@ -7,5 +7,4 @@
func g0(_: (inout X) -> (Float) -> ()) {}
-// This becomes an error in Swift 4 mode -- probably a bug
-g0(X.f1)
+g0(X.f1) // expected-warning{{partial application of 'mutating' method}}
diff --git a/test/Constraints/generic_super_constraint.swift b/test/Constraints/generic_super_constraint.swift
index c227519..4f46e93 100644
--- a/test/Constraints/generic_super_constraint.swift
+++ b/test/Constraints/generic_super_constraint.swift
@@ -17,3 +17,11 @@
// expected-error@+1{{cannot convert return expression}}
return (x, y)
}
+
+// SR-7551 captures a crash on this code.
+class IntegerClass : ExpressibleByIntegerLiteral, Equatable {
+ required init(integerLiteral value: Int) { }
+ static func ==(lhs: IntegerClass, rhs: IntegerClass) -> Bool { return true }
+}
+
+func foo<T: IntegerClass>(_ num: T) { let _ = num != 0 }
diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift
index 752e33a..4192a11 100644
--- a/test/Constraints/members.swift
+++ b/test/Constraints/members.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift -swift-version 4
+// RUN: %target-typecheck-verify-swift -swift-version 5
////
// Members of structs
@@ -28,7 +28,7 @@
_ = x.f0(i)
x.f0(i).f1(i)
-g0(X.f1)
+g0(X.f1) // expected-error{{partial application of 'mutating' method}}
_ = x.f0(x.f2(1))
_ = x.f0(1).f2(i)
diff --git a/test/Constraints/mutating_members.swift b/test/Constraints/mutating_members.swift
new file mode 100644
index 0000000..dea386b
--- /dev/null
+++ b/test/Constraints/mutating_members.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend -typecheck -verify -swift-version 5 %s
+
+struct Foo {
+ mutating func boom() {}
+}
+
+let x = Foo.boom // expected-error{{partial application of 'mutating' method}}
+var y = Foo()
+let z0 = y.boom // expected-error{{partial application of 'mutating' method}}
+let z1 = Foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
+
+func fromLocalContext() -> (inout Foo) -> () -> () {
+ return Foo.boom // expected-error{{partial application of 'mutating' method}}
+}
+func fromLocalContext2(x: inout Foo, y: Bool) -> () -> () {
+ if y {
+ return x.boom // expected-error{{partial application of 'mutating' method}}
+ } else {
+ return Foo.boom(&x) // expected-error{{partial application of 'mutating' method}}
+ }
+}
+
diff --git a/test/Constraints/mutating_members_compat.swift b/test/Constraints/mutating_members_compat.swift
new file mode 100644
index 0000000..e29fd34
--- /dev/null
+++ b/test/Constraints/mutating_members_compat.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend -typecheck -verify -swift-version 4 %s
+
+struct Foo {
+ mutating func boom() {}
+}
+
+let x = Foo.boom // expected-warning{{partial application of 'mutating' method}}
+var y = Foo()
+let z0 = y.boom // expected-error{{partial application of 'mutating' method}}
+let z1 = Foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
+
+func fromLocalContext() -> (inout Foo) -> () -> () {
+ return Foo.boom // expected-warning{{partial application of 'mutating' method}}
+}
+func fromLocalContext2(x: inout Foo, y: Bool) -> () -> () {
+ if y {
+ return x.boom // expected-error{{partial application of 'mutating' method}}
+ } else {
+ return Foo.boom(&x) // expected-error{{partial application of 'mutating' method}}
+ }
+}
+
diff --git a/test/IDE/print_ast_tc_decls.swift b/test/IDE/print_ast_tc_decls.swift
index 8d031d2..3c9c4e5 100644
--- a/test/IDE/print_ast_tc_decls.swift
+++ b/test/IDE/print_ast_tc_decls.swift
@@ -529,7 +529,7 @@
// PASS_COMMON-LABEL: {{^}}@objc class d0180_TestIBAttrs {{{$}}
@IBAction func anAction(_: AnyObject) {}
-// PASS_COMMON-NEXT: {{^}} @IBAction @objc func anAction(_: AnyObject){{$}}
+// PASS_COMMON-NEXT: {{^}} @objc @IBAction func anAction(_: AnyObject){{$}}
@IBDesignable
class ADesignableClass {}
@@ -541,13 +541,13 @@
// PASS_EXPLODE_PATTERN-LABEL: {{^}}@objc class d0181_TestIBAttrs {{{$}}
@IBOutlet weak var anOutlet: d0181_TestIBAttrs!
-// PASS_EXPLODE_PATTERN-NEXT: {{^}} @IBOutlet @_implicitly_unwrapped_optional @objc weak var anOutlet: @sil_weak d0181_TestIBAttrs!{{$}}
+// PASS_EXPLODE_PATTERN-NEXT: {{^}} @objc @IBOutlet @_implicitly_unwrapped_optional weak var anOutlet: @sil_weak d0181_TestIBAttrs!{{$}}
@IBInspectable var inspectableProp: Int = 0
-// PASS_EXPLODE_PATTERN-NEXT: {{^}} @IBInspectable @objc var inspectableProp: Int{{$}}
+// PASS_EXPLODE_PATTERN-NEXT: {{^}} @objc @IBInspectable var inspectableProp: Int{{$}}
@GKInspectable var inspectableProp2: Int = 0
-// PASS_EXPLODE_PATTERN-NEXT: {{^}} @GKInspectable @objc var inspectableProp2: Int{{$}}
+// PASS_EXPLODE_PATTERN-NEXT: {{^}} @objc @GKInspectable var inspectableProp2: Int{{$}}
}
struct d0190_LetVarDecls {
diff --git a/test/Migrator/Inputs/MyAppKit.swift b/test/Migrator/Inputs/MyAppKit.swift
index ed93508..818f136 100644
--- a/test/Migrator/Inputs/MyAppKit.swift
+++ b/test/Migrator/Inputs/MyAppKit.swift
@@ -2,3 +2,4 @@
public class NSOpenGLOption {}
public func NSOpenGLGetOption(_ c : NSOpenGLOption, _ p :UnsafePointer<Int>) {}
public func NSOpenGLSetOption(_ c : NSOpenGLOption, _ p : Int) {}
+public func UIApplicationMain(_ a: Int32, _ b: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>, _ c: String?, _ d: String?) -> Int32 { return 0 }
\ No newline at end of file
diff --git a/test/Migrator/Inputs/SpecialCaseAPI.json b/test/Migrator/Inputs/SpecialCaseAPI.json
index 26c4a98..1518592 100644
--- a/test/Migrator/Inputs/SpecialCaseAPI.json
+++ b/test/Migrator/Inputs/SpecialCaseAPI.json
@@ -13,5 +13,10 @@
"DiffItemKind": "SpecialCaseDiffItem",
"Usr": "s:7MySwift0A6DoubleV3absyS2dFZ",
"SpecialCaseId": "StaticAbsToSwiftAbs"
+ },
+ {
+ "DiffItemKind": "SpecialCaseDiffItem",
+ "Usr": "s:8MyAppKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSSSgAItF",
+ "SpecialCaseId": "UIApplicationMain"
}
]
diff --git a/test/Migrator/api-special-cases.swift b/test/Migrator/api-special-cases.swift
index ad30ca8..821543b 100644
--- a/test/Migrator/api-special-cases.swift
+++ b/test/Migrator/api-special-cases.swift
@@ -8,10 +8,16 @@
import MyAppKit
import MySwift
-func foo(_ Opt: NSOpenGLOption) {
+func foo(_ Opt: NSOpenGLOption, _ pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
var Value = 1
NSOpenGLSetOption(Opt, 1)
NSOpenGLGetOption(Opt, &Value)
+ UIApplicationMain(CommandLine.argc, pointer, "", "")
+ UIApplicationMain(
+ CommandLine.argc, pointer, "", "")
+ UIApplicationMain( CommandLine .
+ argc, pointer, "", "")
+ UIApplicationMain(10, pointer, "", "")
}
do {
diff --git a/test/Migrator/api-special-cases.swift.expected b/test/Migrator/api-special-cases.swift.expected
index e2fd657..70424e8 100644
--- a/test/Migrator/api-special-cases.swift.expected
+++ b/test/Migrator/api-special-cases.swift.expected
@@ -8,10 +8,16 @@
import MyAppKit
import MySwift
-func foo(_ Opt: NSOpenGLOption) {
+func foo(_ Opt: NSOpenGLOption, _ pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
var Value = 1
Opt.globalValue = 1
Value = Opt.globalValue
+ UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, "", "")
+ UIApplicationMain(
+ CommandLine.argc, CommandLine.unsafeArgv, "", "")
+ UIApplicationMain( CommandLine .
+ argc, CommandLine.unsafeArgv, "", "")
+ UIApplicationMain(10, pointer, "", "")
}
do {
diff --git a/test/Migrator/ui-application-main.swift b/test/Migrator/ui-application-main.swift
new file mode 100644
index 0000000..d0ebd8c
--- /dev/null
+++ b/test/Migrator/ui-application-main.swift
@@ -0,0 +1,14 @@
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 3
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 4
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+
+// REQUIRES: OS=ios
+// REQUIRES: objc_interop
+
+import UIKit
+
+func foo(pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
+ UIApplicationMain(CommandLine.argc, pointer, "", "")
+ UIApplicationMain(2, pointer, "", "")
+}
diff --git a/test/Migrator/ui-application-main.swift.expected b/test/Migrator/ui-application-main.swift.expected
new file mode 100644
index 0000000..69fd82c
--- /dev/null
+++ b/test/Migrator/ui-application-main.swift.expected
@@ -0,0 +1,14 @@
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 3
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 4
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+
+// REQUIRES: OS=ios
+// REQUIRES: objc_interop
+
+import UIKit
+
+func foo(pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
+ UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, "", "")
+ UIApplicationMain(2, pointer, "", "")
+}
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index 3b201d4..214b201 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -148,7 +148,7 @@
case Ladd, Elliott, Sixteenth, Harrison
}
-enum RawTypeCircularityA : RawTypeCircularityB, ExpressibleByIntegerLiteral { // expected-error {{circular enum raw types 'RawTypeCircularityA' -> 'RawTypeCircularityB' -> 'RawTypeCircularityA'}} FIXME: expected-error{{RawRepresentable}}
+enum RawTypeCircularityA : RawTypeCircularityB, ExpressibleByIntegerLiteral { // expected-error {{'RawTypeCircularityA' has a raw type that depends on itself}}
case Morrison, Belmont, Madison, Hawthorne
init(integerLiteral value: Int) {
diff --git a/test/Runtime/Inputs/synthesized_decl_uniqueness.swift b/test/Runtime/Inputs/synthesized_decl_uniqueness.swift
new file mode 100644
index 0000000..5157acc
--- /dev/null
+++ b/test/Runtime/Inputs/synthesized_decl_uniqueness.swift
@@ -0,0 +1,9 @@
+import CoreLocation
+
+public func getCLError() -> Any.Type {
+ return CLError.self
+}
+
+public func getCLErrorCode() -> Any.Type {
+ return CLError.Code.self
+}
diff --git a/test/Runtime/demangleToMetadataObjC.swift b/test/Runtime/demangleToMetadataObjC.swift
index 2712138..2b5b920 100644
--- a/test/Runtime/demangleToMetadataObjC.swift
+++ b/test/Runtime/demangleToMetadataObjC.swift
@@ -5,6 +5,7 @@
import StdlibUnittest
import Foundation
import CoreFoundation
+import CoreLocation
let DemangleToMetadataTests = TestSuite("DemangleToMetadataObjC")
@@ -74,5 +75,15 @@
expectNil(_typeByMangledName("4main3CG4CyAA1DCAA1DCG"))
}
+DemangleToMetadataTests.test("synthesized declarations") {
+ expectEqual(CLError.self, _typeByMangledName("SC7CLErrorLeV")!)
+ expectNil(_typeByMangledName("SC7CLErrorV"))
+ expectEqual(CLError.Code.self, _typeByMangledName("So7CLErrorV")!)
+
+ let error = NSError(domain: NSCocoaErrorDomain, code: 0)
+ let reflectionString = String(reflecting: CLError(_nsError: error))
+ expectTrue(reflectionString.hasPrefix("__C_Synthesized.related decl 'e' for CLError(_nsError:"))
+}
+
runAllTests()
diff --git a/test/Runtime/synthesized_decl_uniqueness.swift b/test/Runtime/synthesized_decl_uniqueness.swift
new file mode 100644
index 0000000..e47aea0
--- /dev/null
+++ b/test/Runtime/synthesized_decl_uniqueness.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -parse-as-library -force-single-frontend-invocation %S/Inputs/synthesized_decl_uniqueness.swift -emit-object -o %t/A.o -module-name A -emit-module-path %t/A.swiftmodule
+// RUN: %target-build-swift -parse-as-library -force-single-frontend-invocation %S/Inputs/synthesized_decl_uniqueness.swift -emit-object -o %t/B.o -module-name B -emit-module-path %t/B.swiftmodule
+// RUN: %target-build-swift -I %t %s %t/A.o %t/B.o -o %t/a.out
+// RUN: %target-run %t/a.out
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import A
+import B
+
+var tests = TestSuite("metadata identity for synthesized types")
+
+tests.test("synthesized type identity across modules") {
+ expectEqual(A.getCLError(), B.getCLError())
+ expectEqual(A.getCLErrorCode(), B.getCLErrorCode())
+}
+
+runAllTests()
diff --git a/test/SILGen/access_marker_gen.swift b/test/SILGen/access_marker_gen.swift
index 174881c..188226a 100644
--- a/test/SILGen/access_marker_gen.swift
+++ b/test/SILGen/access_marker_gen.swift
@@ -150,5 +150,6 @@
// CHECK: bb0([[D:%.*]] : @guaranteed $D
// CHECK: [[METHOD:%.*]] = class_method [[D]] : $D, #D.x!materializeForSet.1
// CHECK: apply [[METHOD]]({{.*}}, [[D]])
+// CHECK: begin_access [modify] [unsafe]
// CHECK-NOT: begin_access
diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift
index e4ea9c5..be4fb40 100644
--- a/test/SILGen/accessors.swift
+++ b/test/SILGen/accessors.swift
@@ -58,9 +58,10 @@
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on [[ARG]] : $A
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*OrdinarySub
// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
// CHECK-NEXT: [[SETTER:%.*]] = function_ref @$S9accessors11OrdinarySubVyS2icis
-// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
+// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ACCESS]])
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
@@ -68,12 +69,13 @@
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
// CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*A
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick A.Type
-// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*OrdinarySub to $Builtin.RawPointer
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ACCESS]] : $*OrdinarySub to $Builtin.RawPointer
// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
// CHECK-NEXT: dealloc_stack [[TEMP2]]
// CHECK-NEXT: br [[CONT]]
// CHECK: [[CONT]]:
+// CHECK-NEXT: end_access [[ACCESS]] : $*OrdinarySub
// CHECK-NEXT: dealloc_stack [[BUFFER]]
// CHECK-NEXT: dealloc_stack [[STORAGE]]
// CHECK-NEXT: dealloc_stack [[TEMP]]
@@ -114,9 +116,10 @@
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[ARG]] : $B
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*MutatingSub
// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.getter : (Swift.Int) -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors11MutatingSubVyS2icig : $@convention(method) (Int, @inout MutatingSub) -> Int
-// CHECK-NEXT: [[VALUE:%.*]] = apply [[T0]]([[INDEX1]], [[ADDR]])
+// CHECK-NEXT: [[VALUE:%.*]] = apply [[T0]]([[INDEX1]], [[ACCESS]])
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
@@ -124,13 +127,14 @@
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
-// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ACCESS]] : $*MutatingSub to $Builtin.RawPointer
// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
// CHECK-NEXT: dealloc_stack [[TEMP2]]
// CHECK-NEXT: br [[CONT]]
//
// CHECK: [[CONT]]:
// Formal access to LHS.
+// CHECK-NEXT: end_access [[ACCESS]] : $*MutatingSub
// CHECK-NEXT: [[STORAGE2:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[BUFFER2:%.*]] = alloc_stack $MutatingSub
// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER2]]
@@ -140,9 +144,10 @@
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[ARG]] : $B
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*MutatingSub
// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
// CHECK-NEXT: [[SETTER:%.*]] = function_ref @$S9accessors11MutatingSubVyS2icis : $@convention(method) (Int, Int, @inout MutatingSub) -> ()
-// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
+// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ACCESS]])
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
@@ -150,12 +155,13 @@
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
-// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ACCESS]] : $*MutatingSub to $Builtin.RawPointer
// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE2]], [[TEMP2]], [[T0]])
// CHECK-NEXT: dealloc_stack [[TEMP2]]
// CHECK-NEXT: br [[CONT]]
//
// CHECK: [[CONT]]:
+// CHECK-NEXT: end_access [[ACCESS]] : $*MutatingSub
// CHECK-NEXT: dealloc_stack [[BUFFER2]]
// CHECK-NEXT: dealloc_stack [[STORAGE2]]
// CHECK-NEXT: dealloc_stack [[BUFFER]]
diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift
index d49ce81..27119c5 100644
--- a/test/SILGen/addressors.swift
+++ b/test/SILGen/addressors.swift
@@ -59,7 +59,8 @@
// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[AVAL]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: [[Z:%.*]] = load [[T3]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T3]] : $*Int32
+// CHECK: [[Z:%.*]] = load [[ACCESS]] : $*Int32
let z = a[10]
// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
@@ -67,9 +68,10 @@
// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*Int32
// CHECK: load
// CHECK: sadd_with_overflow_Int{{32|64}}
-// CHECK: store {{%.*}} to [[T3]]
+// CHECK: store {{%.*}} to [[ACCESS]]
a[5] += z
// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
@@ -77,7 +79,8 @@
// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: store {{%.*}} to [[T3]]
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*Int32
+// CHECK: store {{%.*}} to [[ACCESS]]
a[3] = 6
}
@@ -90,7 +93,8 @@
// CHECK: [[PTR:%.*]] = apply [[ACCESSOR]]({{%.*}}, [[A]]) : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
// CHECK: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: [[T2:%.*]] = load [[T1]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T1]] : $*Int32
+// CHECK: [[T2:%.*]] = load [[ACCESS]] : $*Int32
// CHECK: return [[T2]] : $Int32
return A()[0]
}
@@ -116,7 +120,8 @@
// CHECK: [[T1:%.*]] = apply [[T0]]() : $@convention(thin) () -> UnsafePointer<Int32>
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: [[T4:%.*]] = load [[T3]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T3]] : $*Int32
+// CHECK: [[T4:%.*]] = load [[ACCESS]] : $*Int32
// CHECK: return [[T4]] : $Int32
// Test that having generated trivial accessors for something because
@@ -142,11 +147,12 @@
// CHECK: [[PTR:%.*]] = apply [[T0]]([[INDEX]], [[WRITE]])
// CHECK: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
// CHECK: [[ADDR:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
// Accept either of struct_extract+load or load+struct_element_addr.
// CHECK: load
// CHECK: [[T1:%.*]] = builtin "or_Int32"
// CHECK: [[T2:%.*]] = struct $Int32 ([[T1]] : $Builtin.Int32)
-// CHECK: store [[T2]] to [[ADDR]] : $*Int32
+// CHECK: store [[T2]] to [[ACCESS]] : $*Int32
func test_B(_ b: inout B) {
b[0] |= 7
}
@@ -170,7 +176,8 @@
// CHECK: [[T1:%.*]] = apply [[T0]]<(Int32) -> Int32>({{%.*}}, [[WRITE]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<(Int32) -> Int32>, #UnsafeMutablePointer._rawValue
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
-// CHECK: store {{%.*}} to [[T3]] :
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
+// CHECK: store {{%.*}} to [[ACCESS]] :
array[0] = id_int
// CHECK: [[READ:%.*]] = begin_access [read] [static] [[ARRAY]] : $*CArray<(Int32) -> Int32>
@@ -179,7 +186,8 @@
// CHECK: [[T2:%.*]] = apply [[T1]]<(Int32) -> Int32>({{%.*}}, [[T0]])
// CHECK: [[T3:%.*]] = struct_extract [[T2]] : $UnsafePointer<(Int32) -> Int32>, #UnsafePointer._rawValue
// CHECK: [[T4:%.*]] = pointer_to_address [[T3]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
-// CHECK: [[T5:%.*]] = load [[T4]]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T4]] : $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
+// CHECK: [[T5:%.*]] = load [[ACCESS]]
return array[1](5)
}
@@ -196,12 +204,13 @@
// SILGEN: debug_value [[VALUE]] : $Int32
// SILGEN: debug_value [[I]] : $Int32
// SILGEN: debug_value_addr [[SELF]]
-// SILGEN: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF]] : $*D // users: %12, %8
+// SILGEN: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF]] : $*D
// SILGEN: [[T0:%.*]] = function_ref @$S10addressors1DVys5Int32VAEciau{{.*}}
// SILGEN: [[PTR:%.*]] = apply [[T0]]([[I]], [[ACCESS]])
// SILGEN: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
// SILGEN: [[ADDR:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
-// SILGEN: assign [[VALUE]] to [[ADDR]] : $*Int32
+// SILGEN: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
+// SILGEN: assign [[VALUE]] to [[ACCESS]] : $*Int32
// materializeForSet.
// SILGEN-LABEL: sil hidden [transparent] @$S10addressors1DVys5Int32VAEcim
@@ -228,7 +237,8 @@
// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
// CHECK: [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: store [[V]] to [[ADDR]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
+// CHECK: store [[V]] to [[ACCESS]] : $*Int32
array[0] = make_int()
// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*D
@@ -236,8 +246,9 @@
// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
// CHECK: [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
// CHECK: [[FN:%.*]] = function_ref @$S10addressors14take_int_inoutyys5Int32VzF
-// CHECK: apply [[FN]]([[ADDR]])
+// CHECK: apply [[FN]]([[ACCESS]])
take_int_inout(&array[1])
// CHECK: [[READ:%.*]] = begin_access [read] [static] [[ARRAY]] : $*D
@@ -261,7 +272,8 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[E]])
// CHECK: [[T2:%.*]] = struct_extract [[T1]]
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]]
-// CHECK: store {{%.*}} to [[T3]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*Int32
+// CHECK: store {{%.*}} to [[ACCESS]] : $*Int32
func test_e(_ e: E) {
e.value = 0
}
@@ -294,7 +306,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK: [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
// CHECK-NOT: strong_release [[SELF]] : $F
// CHECK: return [[VALUE]] : $Int32
@@ -313,7 +326,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK: store [[VALUE]] to [[ACCESS]] : $*Int32
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
// CHECK-NOT: strong_release [[SELF]] : $F
@@ -338,7 +352,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK: [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
// CHECK: return [[VALUE]] : $Int32
@@ -351,7 +366,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK: store [[VALUE]] to [[ACCESS]] : $*Int32
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
// materializeForSet callback for G.value
@@ -415,7 +431,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK: [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
// CHECK-NOT: strong_release [[SELF]] : $H
// CHECK: return [[VALUE]] : $Int32
@@ -434,7 +451,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK: store [[VALUE]] to [[ACCESS]] : $*Int32
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
// CHECK-NOT: strong_release [[SELF]] : $H
@@ -459,7 +477,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK: [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
// CHECK: return [[VALUE]] : $Int32
@@ -472,7 +491,8 @@
// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK: store [[VALUE]] to [[ACCESS]] : $*Int32
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
// materializeForSet callback for I.value
diff --git a/test/SILGen/errors.swift b/test/SILGen/errors.swift
index d6c00f4..a84f825 100644
--- a/test/SILGen/errors.swift
+++ b/test/SILGen/errors.swift
@@ -541,8 +541,9 @@
// CHECK: [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
// CHECK: [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK: [[T5:%.*]] = begin_access [modify] [unsafe] [[T4]] : $*B.Structure
// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
-// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T4]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
// CHECK: switch_enum [[CALLBACK]]
@@ -577,8 +578,9 @@
// CHECK: [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
// CHECK: [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK: [[T5:%.*]] = begin_access [modify] [unsafe] [[T4]] : $*B.Structure
// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
-// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T4]]) : $@convention(witness_method: Supportable) <τ_0_0 where τ_0_0 : Supportable> (@inout τ_0_0) -> @error Error, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T5]]) : $@convention(witness_method: Supportable) <τ_0_0 where τ_0_0 : Supportable> (@inout τ_0_0) -> @error Error, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
// CHECK: switch_enum [[CALLBACK]] : ${{.*}}, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
@@ -691,15 +693,18 @@
// CHECK-NEXT: [[T3:%.*]] = struct_extract [[T1]]
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T5]] : $*Pylon
// CHECK: [[SUPPORT:%.*]] = function_ref @$S6errors5PylonV7supportyyKF
-// CHECK-NEXT: try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK-NEXT: try_apply [[SUPPORT]]([[ACCESS]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
+// CHECK-NEXT: end_access [[ACCESS]] : $*Pylon
// CHECK-NEXT: end_access [[WRITE]]
// CHECK-NEXT: destroy_value [[OWNER]] : $AnyObject
// CHECK-NEXT: destroy_value [[ARG2_COPY]] : $String
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error):
+// CHECK-NEXT: end_access [[ACCESS]] : $*Pylon
// CHECK-NEXT: destroy_value [[OWNER]] : $AnyObject
// CHECK-NEXT: end_access [[WRITE]]
// CHECK-NEXT: destroy_value [[ARG2_COPY]] : $String
@@ -734,15 +739,18 @@
// CHECK-NEXT: [[T3:%.*]] = struct_extract [[T1]]
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T5]] : $*Pylon
// CHECK: [[SUPPORT:%.*]] = function_ref @$S6errors5PylonV7supportyyKF
-// CHECK-NEXT: try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK-NEXT: try_apply [[SUPPORT]]([[ACCESS]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
+// CHECK-NEXT: end_access [[ACCESS]] : $*Pylon
// CHECK-NEXT: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
// CHECK-NEXT: end_access [[WRITE]]
// CHECK-NEXT: destroy_value [[ARG2_COPY]] : $String
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error):
+// CHECK-NEXT: end_access [[ACCESS]] : $*Pylon
// CHECK-NEXT: [[OWNER_COPY:%.*]] = copy_value [[OWNER]]
// CHECK-NEXT: strong_unpin [[OWNER_COPY]] : $Optional<Builtin.NativeObject>
// CHECK-NEXT: destroy_value [[OWNER]]
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index cac4901..0eb53ce 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -309,9 +309,11 @@
// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet012HasStoredDidC0C6storedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasStoredDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasStoredDidSet):
// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
-// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivg
-// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
-// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
+// CHECK: [[T0:%.*]] = ref_element_addr [[SELF]] : $HasStoredDidSet, #HasStoredDidSet.stored
+// CHECK: [[T1:%.*]] = begin_access [read] [dynamic] [[T0]] : $*Int
+// CHECK: [[VALUE:%.*]] = load [trivial] [[T1]] : $*Int
+// CHECK: end_access [[T1]] : $*Int
+// CHECK: store [[VALUE]] to [trivial] [[T2]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
diff --git a/test/SILGen/objc_properties.swift b/test/SILGen/objc_properties.swift
index 6916e03..b0a8148 100644
--- a/test/SILGen/objc_properties.swift
+++ b/test/SILGen/objc_properties.swift
@@ -201,9 +201,10 @@
// CHECK: [[RAW_POINTER:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
// CHECK: [[OBJECT:%.*]] = pointer_to_address [[RAW_POINTER]] : $Builtin.RawPointer to [strict] $*NSObject
// CHECK: [[OBJECT_DEP:%.*]] = mark_dependence [[OBJECT]] : $*NSObject on [[ARG]]
- // CHECK: [[LOADED_OBJECT:%.*]] = load_borrow [[OBJECT_DEP]]
+ // CHECK: [[OBJECT_ACCESS:%.*]] = begin_access [modify] [unsafe] [[OBJECT_DEP]] : $*NSObject
+ // CHECK: [[LOADED_OBJECT:%.*]] = load_borrow [[OBJECT_ACCESS]]
// CHECK: [[UNMANAGED_OBJECT:%.*]] = ref_to_unmanaged [[LOADED_OBJECT]] : $NSObject to $@sil_unmanaged NSObject
- // CHECK: end_borrow [[LOADED_OBJECT]] from [[OBJECT_DEP]]
+ // CHECK: end_borrow [[LOADED_OBJECT]] from [[OBJECT_ACCESS]]
func useProperty() {
useAutoreleasingUnsafeMutablePointer(&property)
}
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 748cc83..8f3fc4c 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -209,8 +209,9 @@
// CHECK: [[T0:%.*]] = tuple_extract [[MAT_RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
// CHECK: [[OPT_CALLBACK:%.*]] = tuple_extract [[MAT_RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 1
// CHECK: [[T1:%[0-9]+]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Val
- // CHECK: [[VAL_REF_VAL_PROP_MAT:%.*]] = mark_dependence [[T1]] : $*Val on [[VAL_REF]]
+ // CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Val on [[VAL_REF]]
// CHECK: end_borrow [[VAL_REF_BORROWED]] from [[VAL_REF]]
+ // CHECK: [[VAL_REF_VAL_PROP_MAT:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Val
// -- val.ref.val_prop.z_tuple
// CHECK: [[V_R_VP_Z_TUPLE_MAT:%[0-9]+]] = alloc_stack $(Int, Int)
// CHECK: [[LD:%[0-9]+]] = load_borrow [[VAL_REF_VAL_PROP_MAT]]
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index f38954c..42a477b 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -407,13 +407,14 @@
// CHECK: [[CALLBACK:%.*]] = tuple_extract [[RESULT]]
// CHECK: [[TEMPORARY_ADDR_TMP:%.*]] = pointer_to_address [[TEMPORARY]] : $Builtin.RawPointer to [strict] $*Int
// CHECK: [[TEMPORARY_ADDR:%.*]] = mark_dependence [[TEMPORARY_ADDR_TMP]] : $*Int on [[WRITE]] : $*T
+// CHECK: [[TEMPORARY_ACCESS:%.*]] = begin_access [modify] [unsafe] [[TEMPORARY_ADDR]] : $*Int
// CHECK: [[MODIFY_FN:%.*]] = function_ref @$S9protocols6modifyyySizF
-// CHECK: apply [[MODIFY_FN]]([[TEMPORARY_ADDR]])
+// CHECK: apply [[MODIFY_FN]]([[TEMPORARY_ACCESS]])
// CHECK: switch_enum [[CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2
// CHECK: bb1([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
// CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]]
// CHECK: [[METATYPE:%.*]] = metatype $@thick T.Type
-// CHECK: [[TEMPORARY:%.*]] = address_to_pointer [[TEMPORARY_ADDR]] : $*Int to $Builtin.RawPointer
+// CHECK: [[TEMPORARY:%.*]] = address_to_pointer [[TEMPORARY_ACCESS]] : $*Int to $Builtin.RawPointer
// CHECK: apply [[CALLBACK]]<T>
public struct Val {
diff --git a/test/SILGen/tsan_instrumentation.swift b/test/SILGen/tsan_instrumentation.swift
index 989ff62..a601766 100644
--- a/test/SILGen/tsan_instrumentation.swift
+++ b/test/SILGen/tsan_instrumentation.swift
@@ -57,9 +57,10 @@
// CHECK: [[BUFFER_ADDRESS:%.*]] = pointer_to_address [[TEMPORARY_BUFFER]] : $Builtin.RawPointer to [strict] $*Int
// CHECK: [[BUFFER_ADDRESS_DEPENDENCE:%.*]] = mark_dependence [[BUFFER_ADDRESS]] : $*Int on [[LOADED_CLASS]] : $MyClass
// CHECK: end_borrow [[BORROWED_CLASS]] from [[LOADED_CLASS]] : $MyClass, $MyClass
-// CHECK: {{%.*}} builtin "tsanInoutAccess"([[BUFFER_ADDRESS_DEPENDENCE]] : $*Int) : $()
+// CHECK: [[BUFFER_ADDRESS_ACCESS:%.*]] = begin_access [modify] [unsafe] [[BUFFER_ADDRESS_DEPENDENCE]]
+// CHECK: {{%.*}} builtin "tsanInoutAccess"([[BUFFER_ADDRESS_ACCESS]] : $*Int) : $()
// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @$S20tsan_instrumentation10takesInoutyySizF : $@convention(thin) (@inout Int) -> ()
-// CHECK: {{%.*}} apply [[TAKES_INOUT_FUNC]]([[BUFFER_ADDRESS_DEPENDENCE]]) : $@convention(thin) (@inout Int) -> ()
+// CHECK: {{%.*}} apply [[TAKES_INOUT_FUNC]]([[BUFFER_ADDRESS_ACCESS]]) : $@convention(thin) (@inout Int) -> ()
func inoutGlobalClassStoredProperty() {
// This generates two TSan inout instrumentations. One for the value
// buffer that is passed inout to materializeForSet and one for the
diff --git a/test/SILOptimizer/Inputs/access_wmo_def.swift b/test/SILOptimizer/Inputs/access_wmo_def.swift
new file mode 100644
index 0000000..e23e758
--- /dev/null
+++ b/test/SILOptimizer/Inputs/access_wmo_def.swift
@@ -0,0 +1,15 @@
+// Input for access-enforcement-wmo multi-file test cases.
+
+var internalGlobal: Int = 0
+
+public var publicGlobal: Int = 0
+
+public class C {
+ var setterProp: Int = 0 // Only modified via setter.
+ final var finalProp: Int = 0 // modified directly.
+ var inlinedProp: Int = 0 // modification via materializeForSet inlined.
+ var internalProp: Int = 0 // modified opaquely via materializeForSet.
+ var keyPathProp: Int = 0 // modified via a keypath.
+ final var finalKeyPathProp: Int = 0 // modified via a keypath.
+ public var publicProp: Int = 0
+}
diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift
index 58a7198..edea97a 100644
--- a/test/SILOptimizer/access_marker_verify.swift
+++ b/test/SILOptimizer/access_marker_verify.swift
@@ -575,8 +575,8 @@
// CHECK: apply
// CHECK: struct_extract
// CHECK: [[ADR:%.*]] = pointer_to_address
-// CHECK-NOT: begin_access
-// CHECK: load [trivial] [[ADR]] : $*Int
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[ADR]] : $*Int
+// CHECK: load [trivial] [[ACCESS]] : $*Int
// CHECK: return
// CHECK-LABEL: } // end sil function '$S20access_marker_verify13testAddressor1pSiSPySiG_tF'
@@ -992,8 +992,8 @@
// CHECK: [[POINTEE:%.*]] = apply %{{.*}}<Int>(%1) : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
// CHECK: [[RAWPTR:%.*]] = struct_extract [[POINTEE]] : $UnsafeMutablePointer<Int>, #UnsafeMutablePointer._rawValue
// CHECK: [[ADR:%.*]] = pointer_to_address [[RAWPTR]] : $Builtin.RawPointer to [strict] $*Int
-// CHECK-NOT: begin_access
-// CHECK: assign %0 to [[ADR]] : $*Int
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADR]] : $*Int
+// CHECK: assign %0 to [[ACCESS]] : $*Int
// CHECK-LABEL: } // end sil function '$S20access_marker_verify15testPointerInit1x1yySi_SpySiGtF'
// Verification should ignore the address operand of init_existential_addr.
@@ -1022,3 +1022,22 @@
// CHECK: store %{{.*}} to [trivial] [[PROJ]] : $*SomeError
// CHECK: throw [[BOXALLOC]] : $Error
// CHECK-LABEL: } // end sil function '$S20access_marker_verify11testInitBoxyyKF'
+
+public final class HasStaticProp {
+ public static let empty: HasStaticProp = HasStaticProp()
+}
+
+// A global addressor produces an unenforced RawPointer. This looke
+// like an Unidentified access with no access marker. Ensure that
+// verification doesn't assert.
+public func getStaticProp() -> HasStaticProp {
+ return .empty
+}
+
+// CHECK-LABEL: sil @$S20access_marker_verify13getStaticPropAA03HaseF0CyF : $@convention(thin) () -> @owned HasStaticProp {
+// function_ref HasStaticProp.empty.unsafeMutableAddressor
+// CHECK: [[F:%.*]] = function_ref @$S20access_marker_verify13HasStaticPropC5emptyACvau : $@convention(thin) () -> Builtin.RawPointer
+// CHECK: [[RP:%.*]] = apply [[F]]() : $@convention(thin) () -> Builtin.RawPointer
+// CHECK: [[ADR:%.*]] = pointer_to_address [[RP]] : $Builtin.RawPointer to [strict] $*HasStaticProp
+// CHECK: load [copy] [[ADR]] : $*HasStaticProp
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify13getStaticPropAA03HaseF0CyF'
diff --git a/test/SILOptimizer/access_wmo.sil b/test/SILOptimizer/access_wmo.sil
new file mode 100644
index 0000000..26f7102
--- /dev/null
+++ b/test/SILOptimizer/access_wmo.sil
@@ -0,0 +1,338 @@
+// RUN: %target-sil-opt -wmo -access-enforcement-wmo -assume-parsing-unqualified-ownership-sil %s -enable-sil-verify-all | %FileCheck %s
+//
+// Test the AccessEnforcementWMO pass in isolation. This ensures that
+// no upstream passes have removed SIL-level access markers that are
+// required to ensure the pass is not overly optimistic. It also
+// checks generated getters and setters are handled as expected.
+
+sil_stage canonical
+
+import Builtin
+import Swift
+import SwiftShims
+
+var internalGlobal: Int64
+
+public var publicGlobal: Int64
+
+public class C {
+ @sil_stored var setterProp: Int64 { get set }
+ @sil_stored final var finalProp: Int64 { get set }
+ @sil_stored var inlinedProp: Int64 { get set }
+ @sil_stored var internalProp: Int64 { get set }
+ @sil_stored var keyPathProp: Int64 { get set }
+ @sil_stored final var finalKeyPathProp: Int64 { get set }
+ @sil_stored public var publicProp: Int64 { get set }
+ init()
+ deinit
+}
+
+// internalGlobal
+sil_global hidden @$S10access_wmo14internalGlobalSivp : $Int64 = {
+ %0 = integer_literal $Builtin.Int64, 0 // user: %1
+ %initval = struct $Int64 (%0 : $Builtin.Int64)
+}
+
+
+// publicGlobal
+sil_global @$S10access_wmo12publicGlobalSivp : $Int64 = {
+ %0 = integer_literal $Builtin.Int64, 0 // user: %1
+ %initval = struct $Int64 (%0 : $Builtin.Int64)
+}
+
+// readGlobal()
+// CHECK-LABEL: sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int64 {
+//
+// The internal global is promoted to static.
+// CHECK: [[G1:%.]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[G1]] : $*Int64
+//
+// The public global remains dynamic.
+// CHECK: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[G2]] : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo10readGlobalSiyF'
+sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int64 {
+bb0:
+ %0 = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+ %1 = begin_access [read] [dynamic] [no_nested_conflict] %0 : $*Int64
+ %2 = struct_element_addr %1 : $*Int64, #Int64._value
+ %3 = load %2 : $*Builtin.Int64
+ end_access %1 : $*Int64
+ %5 = global_addr @$S10access_wmo12publicGlobalSivp : $*Int64
+ %6 = begin_access [read] [dynamic] [no_nested_conflict] %5 : $*Int64
+ %7 = struct_element_addr %6 : $*Int64, #Int64._value
+ %8 = load %7 : $*Builtin.Int64
+ end_access %6 : $*Int64
+ %10 = integer_literal $Builtin.Int1, -1
+ %11 = builtin "sadd_with_overflow_Int64"(%3 : $Builtin.Int64, %8 : $Builtin.Int64, %10 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %12 = tuple_extract %11 : $(Builtin.Int64, Builtin.Int1), 0
+ %13 = tuple_extract %11 : $(Builtin.Int64, Builtin.Int1), 1
+ cond_fail %13 : $Builtin.Int1
+ %15 = struct $Int64 (%12 : $Builtin.Int64)
+ return %15 : $Int64
+} // end sil function '$S10access_wmo10readGlobalSiyF'
+
+// setInt(_:_:)
+sil [noinline] @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int64, Int64) -> ()
+
+// testAccessGlobal(v:)
+// CHECK-LABEL: sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int64) -> () {
+// CHECK: [[G1:%.*]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+// CHECK: begin_access [modify] [static] [no_nested_conflict] [[G1]] : $*Int64
+// CHECK: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int64
+// CHECK: begin_access [modify] [dynamic] [no_nested_conflict] [[G2]] : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int64) -> () {
+// %0 // users: %9, %5, %1
+bb0(%0 : $Int64):
+ %1 = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+ %2 = begin_access [modify] [dynamic] [no_nested_conflict] %1 : $*Int64
+ // function_ref setInt(_:_:)
+ %3 = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int64, Int64) -> ()
+ %4 = apply %3(%2, %0) : $@convention(thin) (@inout Int64, Int64) -> ()
+ end_access %2 : $*Int64
+ %6 = global_addr @$S10access_wmo12publicGlobalSivp : $*Int64
+ %7 = begin_access [modify] [dynamic] [no_nested_conflict] %6 : $*Int64
+ %8 = apply %3(%7, %0) : $@convention(thin) (@inout Int64, Int64) -> ()
+ end_access %7 : $*Int64
+ %10 = tuple ()
+ return %10 : $()
+} // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+
+// setKeyPath(_:_:_:)
+sil [noinline] @$S10access_wmo10setKeyPathyyAA1CC_s017ReferenceWritabledE0CyADSiGSitF : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+
+// readProp(c:)
+//
+// See the explanation in access_wmo.swift for why some non-public
+// properties cannot currently be promoted to static enforcement.
+//
+// CHECK-LABEL: sil @$S10access_wmo8readProp1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+// CHECK: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[E1]] : $*Int64
+// CHECK: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[E2]] : $*Int64
+// CHECK: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E3]] : $*Int64
+// CHECK: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E4]] : $*Int64
+// CHECK: [[E5:%.*]] = ref_element_addr %0 : $C, #C.keyPathProp
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[E5]] : $*Int64
+// CHECK: [[E5:%.*]] = ref_element_addr %0 : $C, #C.finalKeyPathProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E5]] : $*Int64
+// CHECK: [[E6:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E6]] : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo8readProp1cyAA1CC_tF'
+sil @$S10access_wmo8readProp1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+// %0
+bb0(%0 : $C):
+ %1 = ref_element_addr %0 : $C, #C.setterProp
+ %2 = begin_access [read] [dynamic] [no_nested_conflict] %1 : $*Int64
+ %3 = struct_element_addr %2 : $*Int64, #Int64._value
+ %4 = load %3 : $*Builtin.Int64
+ end_access %2 : $*Int64
+ %6 = ref_element_addr %0 : $C, #C.finalProp
+ %7 = begin_access [read] [dynamic] [no_nested_conflict] %6 : $*Int64
+ %8 = struct_element_addr %7 : $*Int64, #Int64._value
+ %9 = load %8 : $*Builtin.Int64
+ end_access %7 : $*Int64
+ %11 = ref_element_addr %0 : $C, #C.inlinedProp
+ %12 = begin_access [read] [dynamic] [no_nested_conflict] %11 : $*Int64
+ %13 = struct_element_addr %12 : $*Int64, #Int64._value
+ %14 = load %13 : $*Builtin.Int64
+ end_access %12 : $*Int64
+ %16 = ref_element_addr %0 : $C, #C.internalProp
+ %17 = begin_access [read] [dynamic] [no_nested_conflict] %16 : $*Int64
+ %18 = struct_element_addr %17 : $*Int64, #Int64._value
+ %19 = load %18 : $*Builtin.Int64
+ end_access %17 : $*Int64
+ %21 = ref_element_addr %0 : $C, #C.keyPathProp
+ %22 = begin_access [read] [dynamic] [no_nested_conflict] %21 : $*Int64
+ %23 = struct_element_addr %22 : $*Int64, #Int64._value
+ %24 = load %23 : $*Builtin.Int64
+ end_access %22 : $*Int64
+ %26 = ref_element_addr %0 : $C, #C.finalKeyPathProp
+ %27 = begin_access [read] [dynamic] [no_nested_conflict] %26 : $*Int64
+ %28 = struct_element_addr %27 : $*Int64, #Int64._value
+ %29 = load %28 : $*Builtin.Int64
+ end_access %27 : $*Int64
+ %31 = ref_element_addr %0 : $C, #C.publicProp
+ %32 = begin_access [read] [dynamic] [no_nested_conflict] %31 : $*Int64
+ %33 = struct_element_addr %32 : $*Int64, #Int64._value
+ %34 = load %33 : $*Builtin.Int64
+ end_access %32 : $*Int64
+ %36 = tuple ()
+ return %36 : $()
+} // end sil function '$S10access_wmo8readProp1cyAA1CC_tF'
+
+// testAccessProp(c:v:)
+// CHECK-LABEL: sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int64) -> () {
+// CHECK: bb0(%0 : $C, %1 : $Int64):
+// CHECK: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// CHECK: begin_access [modify] [static] [no_nested_conflict] [[E1]] : $*Int64
+// CHECK: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// CHECK: begin_access [modify] [static] [no_nested_conflict] [[E2]] : $*Int64
+// CHECK: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// CHECK: begin_unpaired_access [modify] [dynamic] [[E3]] : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// CHECK: begin_unpaired_access [modify] [dynamic] [[E4]] : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK: keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; settable_property $Int64, id #C.keyPathProp!getter.1 : (C) -> () -> Int64, getter @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64, setter @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> ())
+// CHECK: keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; stored_property #C.finalKeyPathProp : $Int64)
+// CHECK: [[E5:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// CHECK: begin_unpaired_access [modify] [dynamic] [[E5]] : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK-LABEL: } // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
+sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int64) -> () {
+bb0(%0 : $C, %1 : $Int64):
+ %2 = ref_element_addr %0 : $C, #C.setterProp
+ %3 = begin_access [modify] [dynamic] [no_nested_conflict] %2 : $*Int64
+ store %1 to %3 : $*Int64
+ end_access %3 : $*Int64
+ %6 = ref_element_addr %0 : $C, #C.finalProp
+ %7 = begin_access [modify] [dynamic] [no_nested_conflict] %6 : $*Int64
+ // function_ref setInt(_:_:)
+ %8 = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int64, Int64) -> ()
+ %9 = apply %8(%7, %1) : $@convention(thin) (@inout Int64, Int64) -> ()
+ end_access %7 : $*Int64
+ %11 = alloc_stack $Builtin.UnsafeValueBuffer
+ %12 = ref_element_addr %0 : $C, #C.inlinedProp
+ begin_unpaired_access [modify] [dynamic] %12 : $*Int64, %11 : $*Builtin.UnsafeValueBuffer
+ %14 = mark_dependence %12 : $*Int64 on %0 : $C
+ store %1 to %14 : $*Int64
+ end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
+ dealloc_stack %11 : $*Builtin.UnsafeValueBuffer
+ %18 = alloc_stack $Builtin.UnsafeValueBuffer
+ %19 = ref_element_addr %0 : $C, #C.internalProp
+ begin_unpaired_access [modify] [dynamic] %19 : $*Int64, %18 : $*Builtin.UnsafeValueBuffer
+ %21 = mark_dependence %19 : $*Int64 on %0 : $C
+ %22 = apply %8(%21, %1) : $@convention(thin) (@inout Int64, Int64) -> ()
+ end_unpaired_access [dynamic] %18 : $*Builtin.UnsafeValueBuffer
+ dealloc_stack %18 : $*Builtin.UnsafeValueBuffer
+ %25 = keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; settable_property $Int64, id #C.keyPathProp!getter.1 : (C) -> () -> Int64, getter @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64, setter @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> ())
+ // function_ref setKeyPath(_:_:_:)
+ %26 = function_ref @$S10access_wmo10setKeyPathyyAA1CC_s017ReferenceWritabledE0CyADSiGSitF : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+ %27 = apply %26(%0, %25, %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+ strong_release %25 : $ReferenceWritableKeyPath<C, Int64>
+ %29 = keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; stored_property #C.finalKeyPathProp : $Int64)
+ %30 = apply %26(%0, %29, %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+ strong_release %29 : $ReferenceWritableKeyPath<C, Int64>
+ %32 = alloc_stack $Builtin.UnsafeValueBuffer
+ %33 = ref_element_addr %0 : $C, #C.publicProp
+ begin_unpaired_access [modify] [dynamic] %33 : $*Int64, %32 : $*Builtin.UnsafeValueBuffer
+ %35 = mark_dependence %33 : $*Int64 on %0 : $C
+ %36 = apply %8(%35, %1) : $@convention(thin) (@inout Int64, Int64) -> ()
+ end_unpaired_access [dynamic] %32 : $*Builtin.UnsafeValueBuffer
+ dealloc_stack %32 : $*Builtin.UnsafeValueBuffer
+ %39 = tuple ()
+ return %39 : $()
+} // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
+
+// key path getter for C.keyPathProp : C
+//
+// CHECK-LABEL: sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64 {
+// CHECK: begin_access [read] [static] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC11keyPathPropSivpACTK'
+sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64 {
+bb0(%0 : $*Int64, %1 : $*C):
+ %2 = load %1 : $*C // user: %3
+ %3 = ref_element_addr %2 : $C, #C.keyPathProp // user: %4
+ %4 = begin_access [read] [dynamic] [no_nested_conflict] %3 : $*Int64 // users: %6, %5
+ %5 = load %4 : $*Int64 // user: %7
+ end_access %4 : $*Int64 // id: %6
+ store %5 to %0 : $*Int64 // id: %7
+ %8 = tuple () // user: %9
+ return %8 : $() // id: %9
+} // end sil function '$S10access_wmo1CC11keyPathPropSivpACTK'
+
+// key path setter for C.keyPathProp : C
+//
+// CHECK-LABEL: sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> () {
+// CHECK: begin_access [modify] [static] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC11keyPathPropSivpACTk'
+sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> () {
+bb0(%0 : $*Int64, %1 : $*C):
+ %2 = load %0 : $*Int64 // user: %6
+ %3 = load %1 : $*C // user: %4
+ %4 = ref_element_addr %3 : $C, #C.keyPathProp // user: %5
+ %5 = begin_access [modify] [dynamic] [no_nested_conflict] %4 : $*Int64 // users: %7, %6
+ store %2 to %5 : $*Int64 // id: %6
+ end_access %5 : $*Int64 // id: %7
+ %8 = tuple () // user: %9
+ return %8 : $() // id: %9
+} // end sil function '$S10access_wmo1CC11keyPathPropSivpACTk'
+
+// C.keyPathProp.getter
+// CHECK-LABEL: sil hidden [transparent] @$S10access_wmo1CC11keyPathPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// CHECK: begin_access [read] [static] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC11keyPathPropSivg'
+sil hidden [transparent] @$S10access_wmo1CC11keyPathPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// %0
+bb0(%0 : $C):
+ %1 = ref_element_addr %0 : $C, #C.keyPathProp // user: %2
+ %2 = begin_access [read] [dynamic] [no_nested_conflict] %1 : $*Int64 // users: %4, %3
+ %3 = load %2 : $*Int64 // user: %5
+ end_access %2 : $*Int64 // id: %4
+ return %3 : $Int64 // id: %5
+} // end sil function '$S10access_wmo1CC11keyPathPropSivg'
+
+// variable initialization expression of C.publicProp
+sil [transparent] @$S10access_wmo1CC10publicPropSivpfi : $@convention(thin) () -> Int64 {
+bb0:
+ %0 = integer_literal $Builtin.Int64, 0
+ %1 = struct $Int64 (%0 : $Builtin.Int64)
+ return %1 : $Int64
+} // end sil function '$S10access_wmo1CC10publicPropSivpfi'
+
+// C.publicProp.getter
+//
+// CHECK-LABEL: sil [transparent] @$S10access_wmo1CC10publicPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC10publicPropSivg'
+sil [transparent] @$S10access_wmo1CC10publicPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// %0
+bb0(%0 : $C):
+ %1 = ref_element_addr %0 : $C, #C.publicProp // user: %2
+ %2 = begin_access [read] [dynamic] [no_nested_conflict] %1 : $*Int64 // users: %4, %3
+ %3 = load %2 : $*Int64 // user: %5
+ end_access %2 : $*Int64 // id: %4
+ return %3 : $Int64 // id: %5
+} // end sil function '$S10access_wmo1CC10publicPropSivg'
+
+// C.publicProp.setter
+// CHECK-LABEL: sil [transparent] @$S10access_wmo1CC10publicPropSivs : $@convention(method) (Int64, @guaranteed C) -> () {
+// CHECK: bb0(%0 : $Int64, %1 : $C):
+// CHECK: begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC10publicPropSivs'
+sil [transparent] @$S10access_wmo1CC10publicPropSivs : $@convention(method) (Int64, @guaranteed C) -> () {
+bb0(%0 : $Int64, %1 : $C):
+ %2 = ref_element_addr %1 : $C, #C.publicProp // user: %3
+ %3 = begin_access [modify] [dynamic] [no_nested_conflict] %2 : $*Int64 // users: %5, %4
+ store %0 to %3 : $*Int64 // id: %4
+ end_access %3 : $*Int64 // id: %5
+ %6 = tuple () // user: %7
+ return %6 : $() // id: %7
+} // end sil function '$S10access_wmo1CC10publicPropSivs'
+
+// closure #1 in C.publicProp.materializeForSet
+sil shared [transparent] @$S10access_wmo1CC10publicPropSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> () {
+bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*C, %3 : $@thick C.Type):
+ end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+ %5 = tuple ()
+ return %5 : $()
+} // end sil function '$S10access_wmo1CC10publicPropSivmytfU_'
+
+// C.publicProp.materializeForSet
+// CHECK-LABEL: sil [transparent] @$S10access_wmo1CC10publicPropSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed C) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: begin_unpaired_access [modify] [dynamic] %{{.*}} : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC10publicPropSivm'
+sil [transparent] @$S10access_wmo1CC10publicPropSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed C) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $C):
+ %3 = ref_element_addr %2 : $C, #C.publicProp
+ begin_unpaired_access [modify] [dynamic] %3 : $*Int64, %1 : $*Builtin.UnsafeValueBuffer
+ %5 = address_to_pointer %3 : $*Int64 to $Builtin.RawPointer
+ // function_ref closure #1 in C.publicProp.materializeForSet
+ %6 = function_ref @$S10access_wmo1CC10publicPropSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> ()
+ %7 = thin_function_to_pointer %6 : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> () to $Builtin.RawPointer
+ %8 = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, %7 : $Builtin.RawPointer
+ %9 = tuple (%5 : $Builtin.RawPointer, %8 : $Optional<Builtin.RawPointer>)
+ return %9 : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+} // end sil function '$S10access_wmo1CC10publicPropSivm'
diff --git a/test/SILOptimizer/access_wmo.swift b/test/SILOptimizer/access_wmo.swift
new file mode 100644
index 0000000..d9612b4
--- /dev/null
+++ b/test/SILOptimizer/access_wmo.swift
@@ -0,0 +1,242 @@
+// RUN: %target-swift-frontend -parse-as-library -emit-sil -enforce-exclusivity=checked -O -primary-file %s %S/Inputs/access_wmo_def.swift | %FileCheck %s --check-prefix=PRIMARY
+// RUN: %target-swift-frontend -parse-as-library -emit-sil -enforce-exclusivity=checked -O %s %S/Inputs/access_wmo_def.swift | %FileCheck %s --check-prefix=WMO
+
+// ===---------------------------------------------------------------------===//
+// testAccessGlobal: Access a global defined in another file.
+//
+// In -primary-file mode, all begin_access markers remain dynamic.
+//
+// With WMO, only the begin_access markers for the internal global should be
+// promoted to static.
+// ===---------------------------------------------------------------------===//
+
+// readGlobal():
+// PRIMARY-LABEL: sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int {
+// function_ref internalGlobal.unsafeMutableAddressor
+// PRIMARY: [[F1:%.*]] = function_ref @$S10access_wmo14internalGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G1:%.*]] = apply [[F1]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P1:%.*]] = pointer_to_address [[G1]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A1:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P1]] : $*Int
+// PRIMARY: end_access [[A1]] : $*Int
+// function_ref publicGlobal.unsafeMutableAddressor
+// PRIMARY: [[F2:%.*]] = function_ref @$S10access_wmo12publicGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G2:%.*]] = apply [[F2]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P2:%.*]] = pointer_to_address [[G2]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P2]] : $*Int
+// PRIMARY: end_access [[A2]] : $*Int
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo10readGlobalSiyF'
+//
+// WMO-LABEL: sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int {
+// WMO: [[G1:%.*]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int
+// WMO: [[A1:%.*]] = begin_access [read] [static] [no_nested_conflict] [[G1]] : $*Int
+// WMO: end_access [[A1]] : $*Int
+// WMO: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int
+// WMO: [[A2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[G2]] : $*Int
+// WMO: end_access [[A2]] : $*Int
+// WMO-LABEL: } // end sil function '$S10access_wmo10readGlobalSiyF'
+public func readGlobal() -> Int {
+ return internalGlobal + publicGlobal
+}
+
+@inline(never)
+func setInt(_ i: inout Int, _ v: Int) {
+ i = v
+}
+
+func inlinedSetInt(_ i: inout Int, _ v: Int) {
+ i = v
+}
+
+// testAccessGlobal(v:)
+// PRIMARY-LABEL: sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int) -> () {
+// PRIMARY: bb0(%0 : $Int):
+//
+// function_ref internalGlobal.unsafeMutableAddressor
+// PRIMARY: [[F1:%.*]] = function_ref @$S10access_wmo14internalGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G1:%.*]] = apply [[F1]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P1:%.*]] = pointer_to_address [[G1]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A1:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[P1]] : $*Int
+// function_ref setInt(_:_:)
+// PRIMARY: [[F2:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: apply [[F2]]([[A1]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: end_access [[A1]] : $*Int
+//
+// function_ref publicGlobal.unsafeMutableAddressor
+// PRIMARY: [[F3:%.*]] = function_ref @$S10access_wmo12publicGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G2:%.*]] = apply [[F3]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P2:%.*]] = pointer_to_address [[G2]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[P2]] : $*Int
+// PRIMARY: apply [[F2]]([[A2]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: end_access [[A2]] : $*Int
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+//
+// WMO-LABEL: sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int) -> () {
+// WMO: bb0(%0 : $Int):
+// WMO: [[G1:%.*]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int
+// WMO: [[A1:%.*]] = begin_access [modify] [static] [no_nested_conflict] [[G1]] : $*Int
+// function_ref setInt(_:_:)
+// WMO: [[F:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: apply [[F]]([[A1]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_access [[A1]] : $*Int
+//
+// WMO: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int
+// WMO: [[A2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[G2]] : $*Int
+// function_ref setInt(_:_:)
+// WMO: apply [[F]]([[A2]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_access [[A2]] : $*Int
+// WMO-LABEL: } // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+public func testAccessGlobal(v: Int) {
+ setInt(&internalGlobal, v)
+ setInt(&publicGlobal, v)
+}
+
+@inline(never)
+func setKeyPath(_ c: C, _ kp: ReferenceWritableKeyPath<C, Int>, _ v: Int) {
+ c[keyPath: kp] = v
+}
+
+// ===---------------------------------------------------------------------===//
+// testAccessProp: Access a class property defined in another file.
+//
+// In -primary-file mode, all nonfinal access is behind
+// getter, setter, or materializeForSet calls. The final access remains
+// dynamic because the property is "visibleExternally". i.e. the compiler can't
+// see how other files are using it.
+//
+// With WMO...
+//
+// access to setterProp and finalProp are promoted to static.
+// setterProp is a setter call, and finalProp is non-polymorphic.
+//
+// inlinedProp and internalProp could be also be promoted to static, but are
+// accessed via begin_unpaired_access in materializeForSet. (When the class
+// definition is in another file, the compiler unfortunately and unnecessarilly
+// generates materializeForSet calls even in "wmo" mode). These unpaired access
+// cannot (easily) be marked [no_nested_conflict]. Failing to mark the modify
+// as [no_nested_access] in turn inhibits optimization of the property reads.
+// Rather than teach the WMO to handle unpaired access, better solutions would
+// be either:
+//
+// - The inlinedProp case could be handled with a separate pass that promotes
+// obvious unpaired access patterns to regular scoped access.
+//
+// - To handle internalProp SILGen could stop using materializeForSet for
+// stored properties:
+//
+// See <rdar://problem/41302183> [exclusivity] Optimize formal access from
+// inlined materializeForSet.
+//
+// keyPathProp is promoted to static enforcement because a settable_property
+// keypath can only be formally accessed within the getter and setter, which
+// the compiler can already see.
+//
+// Perversely, finalKeyPathProp *cannot* be promoted to static enforcement
+// because a storedProperty keypath is formed. The compiler does not currently
+// attempt to track down all uses of a storedProperty keypath. The actual
+// access occurs via a Builtin that takes a RawPointer. The formation of a
+// stored_property keypath is always conservatively considered a possible
+// nested access.
+// ===---------------------------------------------------------------------===//
+public func readProp(c: C) -> Int {
+ return c.setterProp + c.finalProp + c.inlinedProp + c.internalProp
+ + c.keyPathProp + c.finalKeyPathProp + c.publicProp
+}
+public func testAccessProp(c: C, v: Int) {
+ c.setterProp = v
+ setInt(&c.finalProp, v)
+ inlinedSetInt(&c.inlinedProp, v)
+ setInt(&c.internalProp, v)
+ setKeyPath(c, \C.keyPathProp, v)
+ setKeyPath(c, \C.finalKeyPathProp, v)
+ setInt(&c.publicProp, v)
+}
+
+// PRIMARY-LABEL: sil @$S10access_wmo8readProp1cSiAA1CC_tF : $@convention(thin) (@guaranteed C) -> Int {
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY: [[E1:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// PRIMARY: [[A1:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E1]] : $*Int
+// PRIMARY: end_access [[A1]] : $*Int
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalKeyPathProp
+// PRIMARY: [[A2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E2]] : $*Int
+// PRIMARY: end_access [[A2]] : $*Int
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo8readProp1cSiAA1CC_tF'
+//
+// WMO-LABEL: sil @$S10access_wmo8readProp1cSiAA1CC_tF : $@convention(thin) (@guaranteed C) -> Int {
+// WMO: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// WMO: [[A1:%.*]] = begin_access [read] [static] [no_nested_conflict] [[E1]] : $*Int
+// WMO: end_access [[A1]] : $*Int
+//
+// WMO: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// WMO: [[A2:%.*]] = begin_access [read] [static] [no_nested_conflict] [[E2]] : $*Int
+// WMO: end_access [[A2]] : $*Int
+//
+// WMO: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// WMO: [[A3:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E3]] : $*Int
+// WMO: end_access [[A3]] : $*Int
+//
+// WMO: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// WMO: [[A4:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E4]] : $*Int
+// WMO: end_access [[A4]] : $*Int
+//
+// WMO: [[E5:%.*]] = ref_element_addr %0 : $C, #C.keyPathProp
+// WMO: [[A5:%.*]] = begin_access [read] [static] [no_nested_conflict] [[E5]] : $*Int
+// WMO: end_access [[A5]] : $*Int
+//
+// WMO: [[E6:%.*]] = ref_element_addr %0 : $C, #C.finalKeyPathProp
+// WMO: [[A6:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E6]] : $*Int
+// WMO: end_access [[A6]] : $*Int
+//
+// WMO: [[E7:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// WMO: [[A7:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E7]] : $*Int
+// WMO: end_access [[A7]] : $*Int
+// WMO-LABEL: } // end sil function '$S10access_wmo8readProp1cSiAA1CC_tF'
+
+// PRIMARY-LABEL: sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int) -> () {
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY: [[E1:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// PRIMARY: [[A1:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[E1]] : $*Int
+// function_ref setInt(_:_:)
+// PRIMARY: [[F1:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: apply [[F1]]([[A1]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: end_access [[A1]] : $*Int
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
+
+// WMO-LABEL: sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int) -> () {
+// WMO: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// WMO: [[A1:%.*]] = begin_access [modify] [static] [no_nested_conflict] [[E1]] : $*Int
+// WMO: end_access [[A1]] : $*Int
+//
+// WMO: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// WMO: [[A2:%.*]] = begin_access [modify] [static] [no_nested_conflict] [[E2]] : $*Int
+// function_ref setInt(_:_:)
+// WMO: [[F1:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: apply [[F1]]([[A2]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_access [[A2]] : $*Int
+//
+// WMO: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// WMO: begin_unpaired_access [modify] [dynamic] [[E3]] : $*Int, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO: end_unpaired_access [dynamic] %{{.*}} : $*Builtin.UnsafeValueBuffer
+//
+// WMO: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// WMO: begin_unpaired_access [modify] [dynamic] [[E4]] : $*Int, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO: [[D4:%.*]] = mark_dependence [[E4]] : $*Int on %0 : $C
+// WMO: apply [[F1]]([[D4]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_unpaired_access [dynamic] %{{.*}} : $*Builtin.UnsafeValueBuffer
+//
+// WMO: [[KP:%.*]] = keypath $ReferenceWritableKeyPath<C, Int>, (root $C; settable_property $Int, id #C.keyPathProp!getter.1 : (C) -> () -> Int, getter @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+// function_ref setKeyPath(_:_:_:)
+// WMO: [[F2:%.*]] = function_ref @$S10access_wmo10setKeyPathyyAA1CC_s017ReferenceWritabledE0CyADSiGSitF : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int>, Int) -> ()
+// WMO: apply [[F2]](%0, [[KP]], %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int>, Int) -> ()
+//
+// WMO: [[FKP:%.*]] = keypath $ReferenceWritableKeyPath<C, Int>, (root $C; stored_property #C.finalKeyPathProp : $Int)
+// WMO: apply [[F2]](%0, [[FKP]], %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int>, Int) -> ()
+//
+// WMO: [[E4:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// WMO: begin_unpaired_access [modify] [dynamic] [[E4]] : $*Int, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO: [[D4:%.*]] = mark_dependence [[E4]] : $*Int on %0 : $C
+// WMO: apply [[F1]]([[D4]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_unpaired_access [dynamic] %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO-LABEL: } // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
diff --git a/test/SILOptimizer/access_wmo_diagnose.swift b/test/SILOptimizer/access_wmo_diagnose.swift
new file mode 100644
index 0000000..018bdcd
--- /dev/null
+++ b/test/SILOptimizer/access_wmo_diagnose.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -parse-as-library -emit-sil -enforce-exclusivity=checked -primary-file %s -o /dev/null -verify
+
+// AccessEnforcementWMO assumes that the only way to address a global or static
+// property is via a formal begin_access. If we ever allow keypaths for static
+// properties, which I think is conceivable, then this test will fail to produce
+// a diagnostic error and AccessEnforcementWMO must be fixed to handle "meta"
+// keypaths.
+public class C {
+ public static var globalProp: Int = 0
+}
+
+public func testGlobalProp() {
+ let a: AnyKeyPath = \C.globalProp // expected-error{{type of expression is ambiguous without more context}}
+}
diff --git a/test/SILOptimizer/array_mutable_assertonly.swift b/test/SILOptimizer/array_mutable_assertonly.swift
index cddf041..013cd3b0 100644
--- a/test/SILOptimizer/array_mutable_assertonly.swift
+++ b/test/SILOptimizer/array_mutable_assertonly.swift
@@ -87,6 +87,7 @@
// TEST6-LABEL: COW Array Opts in Func {{.*}}test2DArrayLoop{{.*}}
// TEST6: Array Opts in Loop Loop at depth 2
// TEST6-NOT: COW Array Opts in
+// TEST6: Hoisting make_mutable
// TEST6: Array Opts in Loop Loop at depth 1
// TEST6-NOT: COW Array Opts in
// TEST6: Hoisting make_mutable
diff --git a/test/SILOptimizer/exclusivity_static_diagnostics.sil b/test/SILOptimizer/exclusivity_static_diagnostics.sil
index 4bb8a33..81b8a22 100644
--- a/test/SILOptimizer/exclusivity_static_diagnostics.sil
+++ b/test/SILOptimizer/exclusivity_static_diagnostics.sil
@@ -1022,3 +1022,25 @@
%9999 = tuple()
return %9999 : $()
}
+
+sil @addressor : $@convention(thin) () -> UnsafeMutablePointer<Int32>
+
+// An addressor produces an unsafely accessed RawPointer. Pass the
+// address to an inout can result in an enforced (unknown) access on
+// the unsafe address. We need to handle this case without asserting.
+sil @addressorAccess : $@convention(thin) (@guaranteed ClassWithStoredProperty, Int32) -> () {
+bb0(%0 : $ClassWithStoredProperty, %1 : $Int32):
+ %f = function_ref @addressor : $@convention(thin) () -> UnsafeMutablePointer<Int32>
+ %up = apply %f() : $@convention(thin) () -> UnsafeMutablePointer<Int32>
+ %o = unchecked_ref_cast %0 : $ClassWithStoredProperty to $Builtin.NativeObject
+ %ptr = struct_extract %up : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+ %adr = pointer_to_address %ptr : $Builtin.RawPointer to [strict] $*Int32
+ %dep = mark_dependence %adr : $*Int32 on %o : $Builtin.NativeObject
+ %a1 = begin_access [modify] [unsafe] %dep : $*Int32
+ %a2 = begin_access [modify] [static] %a1 : $*Int32
+ store %1 to [trivial] %a2 : $*Int32
+ end_access %a2 : $*Int32
+ end_access %a1 : $*Int32
+ %v = tuple ()
+ return %v : $()
+}
diff --git a/test/SILOptimizer/licm_exclusivity.swift b/test/SILOptimizer/licm_exclusivity.swift
index 335b738..93cbc9c 100644
--- a/test/SILOptimizer/licm_exclusivity.swift
+++ b/test/SILOptimizer/licm_exclusivity.swift
@@ -1,7 +1,7 @@
// RUN: %target-swift-frontend -O -enforce-exclusivity=checked -emit-sil -Xllvm -debug-only=sil-licm -primary-file %s 2>&1 | %FileCheck %s --check-prefix=TEST1
// RUN: %target-swift-frontend -O -enforce-exclusivity=checked -emit-sil -Xllvm -debug-only=sil-licm -primary-file %s 2>&1 | %FileCheck %s --check-prefix=TEST2
// RUN: %target-swift-frontend -O -enforce-exclusivity=checked -emit-sil -primary-file %s | %FileCheck %s --check-prefix=TESTSIL
-// REQUIRES: optimized_stdlib
+// REQUIRES: optimized_stdlib,asserts
// TEST1-LABEL: Processing loops in {{.*}}run_ReversedArray{{.*}}
// TEST1: Hoist and Sink pairs attempt
diff --git a/test/Sema/diag_ownership_lazy.swift b/test/Sema/diag_ownership_lazy.swift
index 3c07322..bffa394 100644
--- a/test/Sema/diag_ownership_lazy.swift
+++ b/test/Sema/diag_ownership_lazy.swift
@@ -6,7 +6,13 @@
lazy weak var weakValue = LazyReferenceClass()
// expected-error@-1 {{lazy properties cannot be 'weak'}}
+ // expected-warning@-2 {{instance will be immediately deallocated because property 'weakValue' is 'weak'}}
+ // expected-note@-3 {{'weakValue' declared here}}
+ // expected-note@-4 {{a strong reference is required to prevent the instance from being deallocated}}
unowned lazy var unownedValue = LazyReferenceClass()
// expected-error@-1 {{lazy properties cannot be 'unowned'}}
+ // expected-warning@-2 {{instance will be immediately deallocated because property 'unownedValue' is 'unowned'}}
+ // expected-note@-3 {{'unownedValue' declared here}}
+ // expected-note@-4 {{a strong reference is required to prevent the instance from being deallocated}}
}
diff --git a/test/TBD/class.swift b/test/TBD/class.swift
index 5c1a750..d7e77cf 100644
--- a/test/TBD/class.swift
+++ b/test/TBD/class.swift
@@ -1,24 +1,29 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -O %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -O %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
open class OpenNothing {}
open class OpenInit {
public init() {}
- public init(public_: Int) {}
+ public init(public_: Int, default_: Int = 0) {}
- internal init(internal_: Int) {}
+ internal init(internal_: Int, default_: Int = 0) {}
deinit {}
}
open class OpenMethods {
public init() {}
- public func publicMethod() {}
- internal func internalMethod() {}
- private func privateMethod() {}
+ public func publicMethod(default_: Int = 0) {}
+ internal func internalMethod(default_: Int = 0) {}
+ private func privateMethod(default_: Int = 0) {}
}
open class OpenProperties {
@@ -49,9 +54,9 @@
}
open class OpenStatics {
- public static func publicStaticFunc() {}
- internal static func internalStaticFunc() {}
- private static func privateStaticFunc() {}
+ public static func publicStaticFunc(default_: Int = 0) {}
+ internal static func internalStaticFunc(default_: Int = 0) {}
+ private static func privateStaticFunc(default_: Int = 0) {}
public static let publicLet: Int = 0
internal static let internalLet: Int = 0
@@ -107,18 +112,18 @@
public class PublicInit {
public init() {}
- public init(public_: Int) {}
+ public init(public_: Int, default_: Int = 0) {}
- internal init(internal_: Int) {}
+ internal init(internal_: Int, default_: Int = 0) {}
deinit {}
}
public class PublicMethods {
public init() {}
- public func publicMethod() {}
- internal func internalMethod() {}
- private func privateMethod() {}
+ public func publicMethod(default_: Int = 0) {}
+ internal func internalMethod(default_: Int = 0) {}
+ private func privateMethod(default_: Int = 0) {}
}
public class PublicProperties {
@@ -149,9 +154,9 @@
}
public class PublicStatics {
- public static func publicStaticFunc() {}
- internal static func internalStaticFunc() {}
- private static func privateStaticFunc() {}
+ public static func publicStaticFunc(default_: Int = 0) {}
+ internal static func internalStaticFunc(default_: Int = 0) {}
+ private static func privateStaticFunc(default_: Int = 0) {}
public static let publicLet: Int = 0
internal static let internalLet: Int = 0
@@ -188,19 +193,19 @@
internal var internalVarConcrete: Int = 0
private var privateVarConcrete: Int = 0
- public init<S>(t: T, u: U, v: V, _: S) {
+ public init<S>(t: T, u: U, v: V, _: S, default_: Int = 0) {
publicVar = t
internalVar = u
privateVar = v
}
- public func publicGeneric<A>(_: A) {}
- internal func internalGeneric<A>(_: A) {}
- private func privateGeneric<A>(_: A) {}
+ public func publicGeneric<A>(_: A, default_: Int = 0) {}
+ internal func internalGeneric<A>(_: A, default_: Int = 0) {}
+ private func privateGeneric<A>(_: A, default_: Int = 0) {}
- public static func publicStaticGeneric<A>(_: A) {}
- internal static func internalStaticGeneric<A>(_: A) {}
- private static func privateStaticGeneric<A>(_: A) {}
+ public static func publicStaticGeneric<A>(_: A, default_: Int = 0) {}
+ internal static func internalStaticGeneric<A>(_: A, default_: Int = 0) {}
+ private static func privateStaticGeneric<A>(_: A, default_: Int = 0) {}
}
@@ -208,14 +213,14 @@
internal class InternalInit {
internal init() {}
- internal init(internal_: Int) {}
- private init(private_: Int) {}
+ internal init(internal_: Int, default_: Int = 0) {}
+ private init(private_: Int, default_: Int = 0) {}
}
internal class InternalMethods {
internal init() {}
- internal func internalMethod() {}
- private func privateMethod() {}
+ internal func internalMethod(default_: Int = 0) {}
+ private func privateMethod(default_: Int = 0) {}
}
internal class InternalProperties {
@@ -239,8 +244,8 @@
}
internal class InternalStatics {
- internal static func internalStaticFunc() {}
- private static func privateStaticFunc() {}
+ internal static func internalStaticFunc(default_: Int = 0) {}
+ private static func privateStaticFunc(default_: Int = 0) {}
internal static let internalLet: Int = 0
private static let privateLet: Int = 0
@@ -268,16 +273,16 @@
internal var internalVarConcrete: Int = 0
private var privateVarConcrete: Int = 0
- internal init<S>(t: T, u: U, v: V, _: S) {
+ internal init<S>(t: T, u: U, v: V, _: S, default_: Int = 0) {
internalVar = u
privateVar = v
}
- internal func internalGeneric<A>(_: A) {}
- private func privateGeneric<A>(_: A) {}
+ internal func internalGeneric<A>(_: A, default_: Int = 0) {}
+ private func privateGeneric<A>(_: A, default_: Int = 0) {}
- internal static func internalStaticGeneric<A>(_: A) {}
- private static func privateStaticGeneric<A>(_: A) {}
+ internal static func internalStaticGeneric<A>(_: A, default_: Int = 0) {}
+ private static func privateStaticGeneric<A>(_: A, default_: Int = 0) {}
}
@@ -285,12 +290,12 @@
private class PrivateInit {
private init() {}
- private init(private_: Int) {}
+ private init(private_: Int, default_: Int = 0) {}
}
private class PrivateMethods {
private init() {}
- private func privateMethod() {}
+ private func privateMethod(default_: Int = 0) {}
}
private class PrivateProperties {
@@ -307,7 +312,7 @@
}
private class PrivateStatics {
- private static func privateStaticFunc() {}
+ private static func privateStaticFunc(default_: Int = 0) {}
private static let privateLet: Int = 0
@@ -326,11 +331,11 @@
private var privateVarConcrete: Int = 0
- private init<S>(t: T, u: U, v: V, _: S) {
+ private init<S>(t: T, u: U, v: V, _: S, default_: Int = 0) {
privateVar = v
}
- private func privateGeneric<A>(_: A) {}
+ private func privateGeneric<A>(_: A, default_: Int = 0) {}
- private static func privateStaticGeneric<A>(_: A) {}
+ private static func privateStaticGeneric<A>(_: A, default_: Int = 0) {}
}
diff --git a/test/TBD/class_objc.swift.gyb b/test/TBD/class_objc.swift.gyb
index ecc1277..61f59df 100644
--- a/test/TBD/class_objc.swift.gyb
+++ b/test/TBD/class_objc.swift.gyb
@@ -1,15 +1,23 @@
// RUN: %empty-directory(%t)
// RUN: %gyb %s > %t/main.swift
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module -O
+
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module -O
// With -enable-testing:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing -O
+
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing -O
// REQUIRES: objc_interop
diff --git a/test/TBD/enum.swift b/test/TBD/enum.swift
index 28d49d5..c08f7a7 100644
--- a/test/TBD/enum.swift
+++ b/test/TBD/enum.swift
@@ -1,17 +1,25 @@
// Swift 3:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
// Swift 4:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -O
// With -enable-testing:
// Swift 3:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
// Swift 4:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing -O
public protocol P {}
diff --git a/test/TBD/extension.swift.gyb b/test/TBD/extension.swift.gyb
index 23676d4..ac251e1 100644
--- a/test/TBD/extension.swift.gyb
+++ b/test/TBD/extension.swift.gyb
@@ -6,22 +6,30 @@
// RUN: %target-build-swift %S/Inputs/extension_types.swift -module-name ExtensionTypes -emit-module -emit-module-path %t/types/ExtensionTypes.swiftmodule
// This module is both not resilient:
// RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift
+// RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -O
// ... and resilient:
// RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience
+// RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience -O
// The same, but with -enable-testing:
// RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-testing -O
// RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience -enable-testing -O
// Other module is resilient:
// RUN: %empty-directory(%t/types)
// RUN: %target-build-swift %S/Inputs/extension_types.swift -module-name ExtensionTypes -emit-module -emit-module-path %t/types/ExtensionTypes.swiftmodule -Xfrontend -enable-resilience
// This module is both not resilient:
// RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -O
// ... and resilient:
// RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience -O
// The same but with -enable-testing:
// RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-testing -O
// RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience -enable-testing -O
import ExtensionTypes
diff --git a/test/TBD/function.swift b/test/TBD/function.swift
index aed48e2..fda9187 100644
--- a/test/TBD/function.swift
+++ b/test/TBD/function.swift
@@ -1,7 +1,11 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -enable-testing
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -enable-testing -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -enable-testing -O
public func publicNoArgs() {}
public func publicSomeArgs(_: Int, x: Int) {}
diff --git a/test/TBD/global.swift b/test/TBD/global.swift
index 0a206c4..7866677 100644
--- a/test/TBD/global.swift
+++ b/test/TBD/global.swift
@@ -1,7 +1,11 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience -enable-testing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience -enable-testing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience -enable-testing %s -O
public let publicLet: Int = 0
internal let internalLet: Int = 0
diff --git a/test/TBD/main.swift b/test/TBD/main.swift
index e62c8c0..b86b01b 100644
--- a/test/TBD/main.swift
+++ b/test/TBD/main.swift
@@ -1,3 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -module-name test -validate-tbd-against-ir=all %s -O
// Top-level code (i.e. implicit `main`) should be handled
diff --git a/test/TBD/protocol.swift b/test/TBD/protocol.swift
index a4b13e3..b7b752f 100644
--- a/test/TBD/protocol.swift
+++ b/test/TBD/protocol.swift
@@ -1,7 +1,12 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
public protocol Public {
func publicMethod()
diff --git a/test/TBD/struct.swift b/test/TBD/struct.swift
index fb7415a..893f0b2 100644
--- a/test/TBD/struct.swift
+++ b/test/TBD/struct.swift
@@ -1,7 +1,11 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -enable-testing -O
public struct PublicNothing {}
diff --git a/test/TBD/subclass.swift.gyb b/test/TBD/subclass.swift.gyb
index 48406e3..4637400 100644
--- a/test/TBD/subclass.swift.gyb
+++ b/test/TBD/subclass.swift.gyb
@@ -2,27 +2,41 @@
// RUN: %gyb %s > %t/main.swift
// Same-module superclass, both resilient and not, and enable-testing and not:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing -O
// Other-module superclass is not resilient:
// RUN: %empty-directory(%t/super)
// RUN: %target-build-swift %S/Inputs/subclass_super.swift -emit-library -emit-module -o %t/super/subclass_super.%target-dylib-extension
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
// Other-module superclass is resilient:
// RUN: %empty-directory(%t/super)
// RUN: %target-build-swift %S/Inputs/subclass_super.swift -emit-library -emit-module -o %t/super/subclass_super.%target-dylib-extension -Xfrontend -enable-resilience
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
#if SAME_MODULE
open class Super {
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 5dd01c9..da83057 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -1655,7 +1655,7 @@
init() {}
@IBOutlet weak var goodOutlet: Class_ObjC1!
- // CHECK-LABEL: {{^}} @IBOutlet @_implicitly_unwrapped_optional @objc weak var goodOutlet: @sil_weak Class_ObjC1!
+ // CHECK-LABEL: {{^}} @objc @IBOutlet @_implicitly_unwrapped_optional weak var goodOutlet: @sil_weak Class_ObjC1!
@IBOutlet var badOutlet: PlainStruct
// expected-error@-1 {{@IBOutlet property cannot have non-object type 'PlainStruct'}} {{3-13=}}
@@ -1672,7 +1672,7 @@
// CHECK-LABEL: {{^}}class HasIBAction {
class HasIBAction {
@IBAction func goodAction(_ sender: AnyObject?) { }
- // CHECK: {{^}} @IBAction @objc func goodAction(_ sender: AnyObject?) {
+ // CHECK: {{^}} @objc @IBAction func goodAction(_ sender: AnyObject?) {
@IBAction func badAction(_ sender: PlainStruct?) { }
// expected-error@-1{{argument to @IBAction method cannot have non-object type 'PlainStruct?'}}
@@ -1686,7 +1686,7 @@
// CHECK-LABEL: {{^}}class HasIBInspectable {
class HasIBInspectable {
@IBInspectable var goodProperty: AnyObject?
- // CHECK: {{^}} @IBInspectable @objc var goodProperty: AnyObject?
+ // CHECK: {{^}} @objc @IBInspectable var goodProperty: AnyObject?
}
//===---
@@ -1696,7 +1696,7 @@
// CHECK-LABEL: {{^}}class HasGKInspectable {
class HasGKInspectable {
@GKInspectable var goodProperty: AnyObject?
- // CHECK: {{^}} @GKInspectable @objc var goodProperty: AnyObject?
+ // CHECK: {{^}} @objc @GKInspectable var goodProperty: AnyObject?
}
//===---
@@ -1710,7 +1710,7 @@
@NSManaged
var goodManaged: Class_ObjC1
- // CHECK-LABEL: {{^}} @NSManaged @objc dynamic var goodManaged: Class_ObjC1
+ // CHECK-LABEL: {{^}} @objc @NSManaged dynamic var goodManaged: Class_ObjC1
@NSManaged
var badManaged: PlainStruct
diff --git a/test/decl/class/circular_inheritance.swift b/test/decl/class/circular_inheritance.swift
index f75e56c..642b2f9 100644
--- a/test/decl/class/circular_inheritance.swift
+++ b/test/decl/class/circular_inheritance.swift
@@ -8,19 +8,6 @@
// Check that we produced superclass type requests.
// RUN: %{python} %utils/process-stats-dir.py --evaluate 'SuperclassTypeRequest == 16' %t/stats-dir
-class C : B { } // expected-error{{circular class inheritance 'C' -> 'B' -> 'A' -> 'C'}}
-class B : A { } // expected-note{{class 'B' declared here}}
-class A : C { } // expected-note{{class 'A' declared here}}
-
-class TrivialCycle : TrivialCycle {} // expected-error{{circular class inheritance TrivialCycle}}
-protocol P : P {} // expected-error {{circular protocol inheritance P}}
-
-class Isomorphism : Automorphism { }
-class Automorphism : Automorphism { } // expected-error{{circular class inheritance Automorphism}}
-
-// FIXME: Useless error
-let _ = A() // expected-error{{'A' cannot be constructed because it has no accessible initializers}}
-
class Left
: Right.Hand {
class Hand {}
@@ -31,6 +18,19 @@
class Hand {}
}
+class C : B { } // expected-error{{'C' inherits from itself}}
+class B : A { } // expected-note{{class 'B' declared here}}
+class A : C { } // expected-note{{class 'A' declared here}}
+
+class TrivialCycle : TrivialCycle {} // expected-error{{'TrivialCycle' inherits from itself}}
+protocol P : P {} // expected-error {{protocol 'P' refines itself}}
+
+class Isomorphism : Automorphism { }
+class Automorphism : Automorphism { } // expected-error{{'Automorphism' inherits from itself}}
+
+// FIXME: Useless error
+let _ = A() // expected-error{{'A' cannot be constructed because it has no accessible initializers}}
+
class Outer {
class Inner : Outer {}
}
diff --git a/test/decl/inherit/inherit.swift b/test/decl/inherit/inherit.swift
index 938a35e..b9df433 100644
--- a/test/decl/inherit/inherit.swift
+++ b/test/decl/inherit/inherit.swift
@@ -8,6 +8,9 @@
// Duplicate inheritance from protocol
class B2 : P, P { } // expected-error{{duplicate inheritance from 'P'}}{{13-16=}}
+// FIXME: These are unnecessary
+// expected-note@-2 {{'B2' declares conformance to protocol 'P' here}}
+// expected-error@-3 {{redundant conformance of 'B2' to protocol 'P'}}
// Multiple inheritance
class C : B, A { } // expected-error{{multiple inheritance from classes 'B' and 'A'}}
diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift
index ab62acb..509dcf8 100644
--- a/test/decl/nested/type_in_function.swift
+++ b/test/decl/nested/type_in_function.swift
@@ -130,7 +130,7 @@
// expected-error@-1 {{type 'First' cannot be nested in generic function 'genericFunction(t:)'}}
class Second<T> : Second { }
// expected-error@-1 {{type 'Second' cannot be nested in generic function 'genericFunction(t:)'}}
- // expected-error@-2 2 {{circular class inheritance Second}}
+ // expected-error@-2 2 {{'Second' inherits from itself}}
}
// Spurious "Self or associated type requirements" diagnostic.
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index 15439ee..2e7dc74 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -98,16 +98,15 @@
// Circular protocols
-protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error {{circular protocol inheritance CircleMiddle}}
-// expected-error@-1{{circular protocol inheritance 'CircleMiddle' -> 'CircleStart' -> 'CircleEnd' -> 'CircleMiddle'}}
+protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error 2 {{protocol 'CircleMiddle' refines itself}}
protocol CircleStart : CircleEnd { func circle_start() }
// expected-note@-1{{protocol 'CircleStart' declared here}}
-// expected-error@-2{{circular protocol inheritance CircleStart}}
+// expected-error@-2{{protocol 'CircleStart' refines itself}}
protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note{{protocol 'CircleEnd' declared here}}
-// expected-error@-1{{circular protocol inheritance CircleEnd}}
+// expected-error@-1{{protocol 'CircleEnd' refines itself}}
protocol CircleEntry : CircleTrivial { }
-protocol CircleTrivial : CircleTrivial { } // expected-error 2{{circular protocol inheritance CircleTrivial}}
+protocol CircleTrivial : CircleTrivial { } // expected-error 2{{protocol 'CircleTrivial' refines itself}}
struct Circle {
func circle_start() {}
diff --git a/test/decl/var/lazy_properties.swift b/test/decl/var/lazy_properties.swift
index a435ed4..f908eac 100644
--- a/test/decl/var/lazy_properties.swift
+++ b/test/decl/var/lazy_properties.swift
@@ -86,7 +86,7 @@
// property type and also as part of the getter
class WeShouldNotReTypeCheckStatements {
lazy var firstCase = {
- _ = nil // expected-error {{'nil' requires a contextual type}}
+ _ = nil // expected-error{{'nil' requires a contextual type}}
_ = ()
}
diff --git a/test/expr/capture/dynamic_self.swift b/test/expr/capture/dynamic_self.swift
index c37fbf3..f1dda7b 100644
--- a/test/expr/capture/dynamic_self.swift
+++ b/test/expr/capture/dynamic_self.swift
@@ -4,7 +4,7 @@
class Android {
func clone() -> Self {
- // CHECK: closure_expr type='() -> Self' {{.*}} discriminator=0 captures=(<dynamic_self> self)
+ // CHECK: closure_expr type='() -> Self' {{.*}} discriminator=0 captures=(<dynamic_self> self<direct>)
let fn = { return self }
return fn()
}
diff --git a/test/expr/capture/generic_params.swift b/test/expr/capture/generic_params.swift
index 135b51a..bea2d55 100644
--- a/test/expr/capture/generic_params.swift
+++ b/test/expr/capture/generic_params.swift
@@ -6,16 +6,16 @@
func outerGeneric<T>(t: T, x: AnyObject) {
// Simple case -- closure captures outer generic parameter
- // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=0 captures=(<generic> t) escaping single-expression
+ // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=0 captures=(<generic> t<direct>) escaping single-expression
_ = { doSomething(t) }
// Special case -- closure does not capture outer generic parameters
- // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=1 captures=(x) escaping single-expression
+ // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=1 captures=(x<direct>) escaping single-expression
_ = { doSomething(x) }
// Special case -- closure captures outer generic parameter, but it does not
// appear as the type of any expression
- // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=2 captures=(<generic> x)
+ // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=2 captures=(<generic> x<direct>)
_ = { if x is T {} }
// Nested generic functions always capture outer generic parameters, even if
diff --git a/test/expr/capture/nested.swift b/test/expr/capture/nested.swift
index 6d4790a..dd6b021 100644
--- a/test/expr/capture/nested.swift
+++ b/test/expr/capture/nested.swift
@@ -4,7 +4,7 @@
func foo2(_ x: Int) -> (Int) -> (Int) -> Int {
// CHECK: closure_expr type='(Int) -> (Int) -> Int' {{.*}} discriminator=0 captures=(x)
return {(bar: Int) -> (Int) -> Int in
- // CHECK: closure_expr type='(Int) -> Int' {{.*}} discriminator=0 captures=(x, bar)
+ // CHECK: closure_expr type='(Int) -> Int' {{.*}} discriminator=0 captures=(x<direct>, bar<direct>)
return {(bas: Int) -> Int in
return x + bar + bas
}
diff --git a/test/expr/capture/top-level-guard.swift b/test/expr/capture/top-level-guard.swift
index 744c896..bb1f1f9 100644
--- a/test/expr/capture/top-level-guard.swift
+++ b/test/expr/capture/top-level-guard.swift
@@ -32,7 +32,7 @@
// CHECK: location={{.*}}top-level-guard.swift:[[@LINE+5]]
// CHECK: (closure_expr
// CHECK: location={{.*}}top-level-guard.swift:[[@LINE+3]]
-// CHECK: captures=(x)
+// CHECK: captures=(x<direct>)
// CHECK: (var_decl{{.*}}"closureCapture"
let closureCapture: () -> Void = { [x] in
_ = x
diff --git a/test/stdlib/AnyHashableCasts.swift.gyb b/test/stdlib/AnyHashableCasts.swift.gyb
index 4eaaf50..3a6f81f 100644
--- a/test/stdlib/AnyHashableCasts.swift.gyb
+++ b/test/stdlib/AnyHashableCasts.swift.gyb
@@ -1,10 +1,10 @@
// RUN: %empty-directory(%t)
//
// RUN: %gyb %s -o %t/AnyHashableCasts.swift
-// RUN: %target-build-swift -g -module-name a %t/AnyHashableCasts.swift -o %t.out
-// RUN: %target-run %t.out
-// RUN: %target-build-swift -g -O -module-name a %t/AnyHashableCasts.swift -o %t.out.optimized
-// RUN: %target-run %t.out.optimized
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-build-swift -g -module-name a %t/AnyHashableCasts.swift -o %t.out
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-run %t.out
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-build-swift -g -O -module-name a %t/AnyHashableCasts.swift -o %t.out.optimized
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-run %t.out.optimized
// REQUIRES: executable_test
import StdlibUnittest
@@ -117,34 +117,129 @@
% end
#if _runtime(_ObjC)
+// A wrapper type around Int that bridges to NSNumber.
+struct IntWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+ let rawValue: Int
+}
+
+// A wrapper type around Int that bridges to NSNumber.
+struct IntWrapper2: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+ let rawValue: Int
+}
+
+AnyHashableCasts.test("Wrappers around bridged integers") {
+ let wrapper1: AnyHashable = IntWrapper1(rawValue: 42)
+ let wrapper2: AnyHashable = IntWrapper2(rawValue: 42)
+ let integer: AnyHashable = 42 as Int
+ let byte: AnyHashable = 42 as UInt8
+ let double: AnyHashable = 42.0 as Double
+ let number: AnyHashable = 42 as NSNumber
+
+ // Wrappers compare equal to their wrapped value as AnyHashable.
+ expectEqual(wrapper1, wrapper2)
+ expectEqual(wrapper1, integer)
+ expectEqual(wrapper1, byte)
+ expectEqual(wrapper1, double)
+ expectEqual(wrapper1, number)
+
+ // Original types are preserved in the base property.
+ expectTrue(wrapper1.base is IntWrapper1)
+ expectTrue(wrapper2.base is IntWrapper2)
+ expectTrue(integer.base is Int)
+ expectTrue(byte.base is UInt8)
+ expectTrue(double.base is Double)
+ expectTrue(number.base is NSNumber) // Through bridging
+
+ // AnyHashable forms can be casted to any standard numeric type that can hold
+ // their value.
+ expectNotNil(wrapper1 as? IntWrapper1)
+ expectNotNil(wrapper1 as? IntWrapper2)
+ expectNotNil(wrapper1 as? Int)
+ expectNotNil(wrapper1 as? UInt8)
+ expectNotNil(wrapper1 as? Double)
+ expectNotNil(wrapper1 as? NSNumber)
+
+ expectNotNil(byte as? IntWrapper1)
+ expectNotNil(byte as? IntWrapper2)
+ expectNotNil(byte as? Int)
+ expectNotNil(byte as? UInt8)
+ expectNotNil(byte as? Double)
+ expectNotNil(byte as? NSNumber)
+
+ expectNotNil(integer as? IntWrapper1)
+ expectNotNil(integer as? IntWrapper2)
+ expectNotNil(integer as? Int)
+ expectNotNil(integer as? UInt8)
+ expectNotNil(integer as? Double)
+ expectNotNil(integer as? NSNumber)
+
+ expectNotNil(double as? IntWrapper1)
+ expectNotNil(double as? IntWrapper2)
+ expectNotNil(double as? Int)
+ expectNotNil(double as? UInt8)
+ expectNotNil(double as? Double)
+ expectNotNil(double as? NSNumber)
+
+ expectNotNil(number as? IntWrapper1)
+ expectNotNil(number as? IntWrapper2)
+ expectNotNil(number as? Int)
+ expectNotNil(number as? UInt8)
+ expectNotNil(number as? Double)
+ expectNotNil(number as? NSNumber)
+
+ // We can't cast to a numeric type that can't hold the value.
+ let big: AnyHashable = Int32.max
+ expectNotNil(big as? IntWrapper1)
+ expectNotNil(big as? IntWrapper2)
+ expectNotNil(big as? Int)
+ expectNil(big as? UInt8) // <--
+ expectNotNil(big as? Double)
+ expectNotNil(big as? NSNumber)
+}
+
// A wrapper type around a String that bridges to NSString.
-struct StringWrapper1 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+struct StringWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
let rawValue: String
}
// A wrapper type around a String that bridges to NSString.
-struct StringWrapper2 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+struct StringWrapper2: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
let rawValue: String
}
-AnyHashableCasts.test("Wrappers around bridged types") {
+AnyHashableCasts.test("Wrappers around bridged strings") {
let wrapper1Hello: AnyHashable = StringWrapper1(rawValue: "hello")
+ let wrapper2Hello: AnyHashable = StringWrapper2(rawValue: "hello")
let stringHello: AnyHashable = "hello" as String
let nsStringHello: AnyHashable = "hello" as NSString
- // Casting from Swift wrapper maintains type identity
+ // Wrappers compare equal to their wrapped value as AnyHashable.
+ expectEqual(wrapper1Hello, wrapper2Hello)
+ expectEqual(wrapper1Hello, stringHello)
+ expectEqual(wrapper1Hello, nsStringHello)
+ expectEqual(wrapper2Hello, stringHello)
+ expectEqual(wrapper2Hello, nsStringHello)
+ expectEqual(stringHello, nsStringHello)
+
+ // Type identity is maintained through the base property.
+ expectTrue(wrapper1Hello.base is StringWrapper1)
+ expectTrue(wrapper2Hello.base is StringWrapper2)
+ expectTrue(stringHello.base is String)
+ expectTrue(nsStringHello.base is NSString) // Through bridging
+
+ // Swift wrapper's AnyHashable form doesn't enfore type identity.
expectNotNil(wrapper1Hello as? StringWrapper1)
- expectNil(wrapper1Hello as? StringWrapper2)
- expectNil(wrapper1Hello as? String)
+ expectNotNil(wrapper1Hello as? StringWrapper2)
+ expectNotNil(wrapper1Hello as? String)
expectNotNil(wrapper1Hello as? NSString)
- // Casting from String maintains type identity
- expectNil(stringHello as? StringWrapper1)
- expectNil(stringHello as? StringWrapper2)
+ // String's AnyHashable form doesn't enfore type identity.
+ expectNotNil(stringHello as? StringWrapper1)
+ expectNotNil(stringHello as? StringWrapper2)
expectNotNil(stringHello as? String)
expectNotNil(stringHello as? NSString)
- // Casting form NSString works with anything.
+ // NSString's AnyHashable form doesn't enfore type identity.
expectNotNil(nsStringHello as? StringWrapper1)
expectNotNil(nsStringHello as? StringWrapper2)
expectNotNil(nsStringHello as? String)
diff --git a/test/stdlib/BinaryIntegerRequirements.swift b/test/stdlib/BinaryIntegerRequirements.swift
index 4436295..cb238bd 100644
--- a/test/stdlib/BinaryIntegerRequirements.swift
+++ b/test/stdlib/BinaryIntegerRequirements.swift
@@ -1,9 +1,6 @@
// RUN: %target-typecheck-verify-swift -swift-version 4
struct MyInt: FixedWidthInteger { // expected-error {{type 'MyInt' does not conform to protocol 'BinaryInteger'}}
- // expected-error@-1 {{unavailable operator function '&=' was used to satisfy a requirement of protocol 'BinaryInteger'}}
- // expected-error@-2 {{unavailable operator function '|=' was used to satisfy a requirement of protocol 'BinaryInteger'}}
- // expected-error@-3 {{unavailable operator function '^=' was used to satisfy a requirement of protocol 'BinaryInteger'}}
typealias IntegerLiteralType = Int
static let isSigned = false
init(integerLiteral value: Int) { fatalError() }
diff --git a/test/stdlib/Character.swift b/test/stdlib/Character.swift
index 1924f04..12649db 100644
--- a/test/stdlib/Character.swift
+++ b/test/stdlib/Character.swift
@@ -202,6 +202,9 @@
// Only run it on ObjC platforms. Supported Linux versions do not have a
// recent enough ICU for Unicode 9 support.
#if _runtime(_ObjC)
+ // Check for Unicode 9 or later
+ guard #available(iOS 10.0, macOS 10.12, *) else { return }
+
let flags = "🇺🇸🇨🇦🇩🇰🏳️🌈"
expectEqual(4, flags.count)
expectEqual(flags.reversed().count, flags.count)
diff --git a/test/stdlib/CodableTests.swift b/test/stdlib/CodableTests.swift
index 566398c..2a7b60a 100644
--- a/test/stdlib/CodableTests.swift
+++ b/test/stdlib/CodableTests.swift
@@ -22,7 +22,7 @@
#endif
// MARK: - Helper Functions
-@available(OSX 10.11, iOS 9.0, *)
+@available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
func makePersonNameComponents(namePrefix: String? = nil,
givenName: String? = nil,
middleName: String? = nil,
@@ -220,7 +220,7 @@
#line : CGAffineTransform(a: 0.498, b: -0.284, c: -0.742, d: 0.3248, tx: 12, ty: 44)
]
- if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+ if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
values[#line] = CGAffineTransform(rotationAngle: .pi / 2)
}
@@ -246,7 +246,7 @@
#line : CGPoint(x: 10, y: 20)
]
- if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+ if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
// Limit on magnitude in JSON. See rdar://problem/12717407
values[#line] = CGPoint(x: CGFloat.greatestFiniteMagnitude,
y: CGFloat.greatestFiniteMagnitude)
@@ -274,7 +274,7 @@
#line : CGSize(width: 30, height: 40)
]
- if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+ if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
// Limit on magnitude in JSON. See rdar://problem/12717407
values[#line] = CGSize(width: CGFloat.greatestFiniteMagnitude,
height: CGFloat.greatestFiniteMagnitude)
@@ -303,7 +303,7 @@
#line : CGRect(x: 10, y: 20, width: 30, height: 40)
]
- if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+ if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
// Limit on magnitude in JSON. See rdar://problem/12717407
values[#line] = CGRect.infinite
}
@@ -330,7 +330,7 @@
#line : CGVector(dx: 0.0, dy: -9.81)
]
- if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+ if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
// Limit on magnitude in JSON. See rdar://problem/12717407
values[#line] = CGVector(dx: CGFloat.greatestFiniteMagnitude,
dy: CGFloat.greatestFiniteMagnitude)
@@ -371,7 +371,7 @@
}
// MARK: - DateInterval
- @available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *)
+ @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
lazy var dateIntervalValues: [Int : DateInterval] = [
#line : DateInterval(),
#line : DateInterval(start: Date.distantPast, end: Date()),
@@ -379,14 +379,14 @@
#line : DateInterval(start: Date.distantPast, end: Date.distantFuture)
]
- @available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *)
+ @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
func test_DateInterval_JSON() {
for (testLine, interval) in dateIntervalValues {
expectRoundTripEqualityThroughJSON(for: interval, lineNumber: testLine)
}
}
- @available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *)
+ @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
func test_DateInterval_Plist() {
for (testLine, interval) in dateIntervalValues {
expectRoundTripEqualityThroughPlist(for: interval, lineNumber: testLine)
@@ -482,21 +482,21 @@
}
// MARK: - Measurement
- @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+ @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
lazy var unitValues: [Int : Dimension] = [
#line : UnitAcceleration.metersPerSecondSquared,
#line : UnitMass.kilograms,
#line : UnitLength.miles
]
- @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+ @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
func test_Measurement_JSON() {
for (testLine, unit) in unitValues {
expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: unit), lineNumber: testLine)
}
}
- @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+ @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
func test_Measurement_Plist() {
for (testLine, unit) in unitValues {
expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: unit), lineNumber: testLine)
@@ -523,21 +523,21 @@
}
// MARK: - PersonNameComponents
- @available(OSX 10.11, iOS 9.0, *)
+ @available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
lazy var personNameComponentsValues: [Int : PersonNameComponents] = [
#line : makePersonNameComponents(givenName: "John", familyName: "Appleseed"),
#line : makePersonNameComponents(givenName: "John", familyName: "Appleseed", nickname: "Johnny"),
#line : makePersonNameComponents(namePrefix: "Dr.", givenName: "Jane", middleName: "A.", familyName: "Appleseed", nameSuffix: "Esq.", nickname: "Janie")
]
- @available(OSX 10.11, iOS 9.0, *)
+ @available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
func test_PersonNameComponents_JSON() {
for (testLine, components) in personNameComponentsValues {
expectRoundTripEqualityThroughJSON(for: components, lineNumber: testLine)
}
}
- @available(OSX 10.11, iOS 9.0, *)
+ @available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
func test_PersonNameComponents_Plist() {
for (testLine, components) in personNameComponentsValues {
expectRoundTripEqualityThroughPlist(for: components, lineNumber: testLine)
@@ -572,7 +572,7 @@
#line : URL(string: "documentation", relativeTo: URL(string: "http://swift.org")!)!
]
- if #available(OSX 10.11, iOS 9.0, *) {
+ if #available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *) {
values[#line] = URL(fileURLWithPath: "bin/sh", relativeTo: URL(fileURLWithPath: "/"))
}
@@ -770,8 +770,6 @@
"test_TimeZone_Plist" : TestCodable.test_TimeZone_Plist,
"test_URL_JSON" : TestCodable.test_URL_JSON,
"test_URL_Plist" : TestCodable.test_URL_Plist,
- "test_URLComponents_JSON" : TestCodable.test_URLComponents_JSON,
- "test_URLComponents_Plist" : TestCodable.test_URLComponents_Plist,
"test_UUID_JSON" : TestCodable.test_UUID_JSON,
"test_UUID_Plist" : TestCodable.test_UUID_Plist,
]
@@ -781,18 +779,23 @@
tests["test_AffineTransform_Plist"] = TestCodable.test_AffineTransform_Plist
#endif
-if #available(OSX 10.11, iOS 9.0, *) {
+if #available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *) {
tests["test_PersonNameComponents_JSON"] = TestCodable.test_PersonNameComponents_JSON
tests["test_PersonNameComponents_Plist"] = TestCodable.test_PersonNameComponents_Plist
}
-if #available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *) {
+if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
// tests["test_DateInterval_JSON"] = TestCodable.test_DateInterval_JSON
tests["test_DateInterval_Plist"] = TestCodable.test_DateInterval_Plist
// tests["test_Measurement_JSON"] = TestCodable.test_Measurement_JSON
// tests["test_Measurement_Plist"] = TestCodable.test_Measurement_Plist
}
+if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
+ tests["test_URLComponents_JSON"] = TestCodable.test_URLComponents_JSON
+ tests["test_URLComponents_Plist"] = TestCodable.test_URLComponents_Plist
+}
+
var CodableTests = TestSuite("TestCodable")
for (name, test) in tests {
CodableTests.test(name) { test(TestCodable())() }
diff --git a/test/stdlib/ErrorBridged.swift b/test/stdlib/ErrorBridged.swift
index dcce4ae..05121d1 100644
--- a/test/stdlib/ErrorBridged.swift
+++ b/test/stdlib/ErrorBridged.swift
@@ -276,6 +276,16 @@
expectEqual(NoisyErrorDeathCount, NoisyErrorLifeCount)
}
+ErrorBridgingTests.test("NSError-to-error bridging in bridged container") {
+ autoreleasepool {
+ let error = NSError(domain: "domain", code: 42, userInfo: nil)
+ let nsdictionary = ["error": error] as NSDictionary
+ let dictionary = nsdictionary as? Dictionary<String, Error>
+ expectNotNil(dictionary)
+ expectEqual(error, dictionary?["error"] as NSError?)
+ }
+}
+
ErrorBridgingTests.test("enum-to-NSError round trip") {
autoreleasepool {
// Emulate throwing an error from Objective-C.
diff --git a/test/stdlib/IndexDistanceRemoval.swift b/test/stdlib/IndexDistanceRemoval.swift
index 5c81ccf..3922d6c 100644
--- a/test/stdlib/IndexDistanceRemoval.swift
+++ b/test/stdlib/IndexDistanceRemoval.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -swift-version 4
struct Int64Distance<Element>: Collection {
let _storage: [Element]
diff --git a/test/stdlib/StringCompatibility.swift b/test/stdlib/StringCompatibility.swift
index 22c68d1..1251d25 100644
--- a/test/stdlib/StringCompatibility.swift
+++ b/test/stdlib/StringCompatibility.swift
@@ -279,8 +279,10 @@
var sub = s[s.startIndex ..< s.endIndex]
var subsub = sub[s.startIndex ..< s.endIndex]
- expectType(ExpectedConcreteSlice.self, &sub)
- expectType(ExpectedConcreteSlice.self, &subsub)
+ // slicing a String in Swift 3 produces a String
+ // but slicing a Substring should still produce a Substring
+ expectType(Substring.self, &sub)
+ expectType(Substring.self, &subsub)
}
Tests.test("Substring/ClosedRange/Slice/ExpectedType/\(swift)") {
diff --git a/test/stdlib/TestURL.swift b/test/stdlib/TestURL.swift
index 8c0128c..21f9205 100644
--- a/test/stdlib/TestURL.swift
+++ b/test/stdlib/TestURL.swift
@@ -178,8 +178,8 @@
func testURLComponents() {
// Not meant to be a test of all URL components functionality, just some basic bridging stuff
- let s = "http://www.apple.com/us/search/ipad?src=globalnav"
- let components = URLComponents(string: s)!
+ let s = "http://www.apple.com/us/search/ipad?src=global%7Cnav"
+ var components = URLComponents(string: s)!
expectNotNil(components)
expectNotNil(components.host)
@@ -201,7 +201,45 @@
expectEqual("src", first.name)
expectNotNil(first.value)
- expectEqual("globalnav", first.value)
+ expectEqual("global|nav", first.value)
+ }
+
+ if #available(OSX 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) {
+ components.percentEncodedQuery = "name1%E2%80%A2=value1%E2%80%A2&name2%E2%80%A2=value2%E2%80%A2"
+ var qi = components.queryItems!
+ expectNotNil(qi)
+
+ expectEqual(2, qi.count)
+
+ expectEqual("name1•", qi[0].name)
+ expectNotNil(qi[0].value)
+ expectEqual("value1•", qi[0].value)
+
+ expectEqual("name2•", qi[1].name)
+ expectNotNil(qi[1].value)
+ expectEqual("value2•", qi[1].value)
+
+ qi = components.percentEncodedQueryItems!
+ expectNotNil(qi)
+
+ expectEqual(2, qi.count)
+
+ expectEqual("name1%E2%80%A2", qi[0].name)
+ expectNotNil(qi[0].value)
+ expectEqual("value1%E2%80%A2", qi[0].value)
+
+ expectEqual("name2%E2%80%A2", qi[1].name)
+ expectNotNil(qi[0].value)
+ expectEqual("value2%E2%80%A2", qi[1].value)
+
+ qi[0].name = "%E2%80%A2name1"
+ qi[0].value = "%E2%80%A2value1"
+ qi[1].name = "%E2%80%A2name2"
+ qi[1].value = "%E2%80%A2value2"
+
+ components.percentEncodedQueryItems = qi
+
+ expectEqual("%E2%80%A2name1=%E2%80%A2value1&%E2%80%A2name2=%E2%80%A2value2", components.percentEncodedQuery)
}
}
diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
index 7c009cc..9bb3fcf 100644
--- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h
+++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
@@ -190,7 +190,6 @@
class EditorConsumer {
virtual void anchor();
-
public:
virtual ~EditorConsumer() { }
@@ -518,7 +517,6 @@
codeCompleteSetCustom(ArrayRef<CustomCompletionInfo> completions) = 0;
virtual void editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
- bool EnableSyntaxMap,
EditorConsumer &Consumer,
ArrayRef<const char *> Args) = 0;
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 23d9ba8..7a0d175 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -2027,7 +2027,6 @@
//===----------------------------------------------------------------------===//
void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
- bool EnableSyntaxMap,
EditorConsumer &Consumer,
ArrayRef<const char *> Args) {
@@ -2084,7 +2083,8 @@
// EditorReplaceText
//===----------------------------------------------------------------------===//
-void SwiftLangSupport::editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf,
+void SwiftLangSupport::editorReplaceText(StringRef Name,
+ llvm::MemoryBuffer *Buf,
unsigned Offset, unsigned Length,
EditorConsumer &Consumer) {
auto EditorDoc = EditorDocuments.getByUnresolvedName(Name);
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index b1bf255..b90d5b6 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -397,7 +397,7 @@
void
codeCompleteSetCustom(ArrayRef<CustomCompletionInfo> completions) override;
- void editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, bool EnableSyntaxMap,
+ void editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
EditorConsumer &Consumer,
ArrayRef<const char *> Args) override;
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 740f99f..d88d0f4 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -68,6 +68,15 @@
return StringRef(Name);
}
};
+
+struct SKEditorConsumerOptions {
+ bool EnableSyntaxMap = false;
+ bool EnableStructure = false;
+ bool EnableDiagnostics = false;
+ bool EnableSyntaxTree = false;
+ bool SyntacticOnly = false;
+};
+
} // anonymous namespace
#define REQUEST(NAME, CONTENT) static LazySKDUID Request##NAME(CONTENT);
@@ -151,9 +160,8 @@
static sourcekitd_response_t codeCompleteClose(StringRef name, int64_t Offset);
static sourcekitd_response_t
-editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, bool EnableSyntaxMap,
- bool EnableStructure, bool EnableDiagnostics, bool EnableSyntaxTree,
- bool SyntacticOnly, ArrayRef<const char *> Args);
+editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
+ SKEditorConsumerOptions Opts, ArrayRef<const char *> Args);
static sourcekitd_response_t
editorOpenInterface(StringRef Name, StringRef ModuleName,
@@ -186,9 +194,7 @@
static sourcekitd_response_t
editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf, unsigned Offset,
- unsigned Length, bool EnableSyntaxMap, bool EnableStructure,
- bool EnableDiagnostics, bool EnableSyntaxTree,
- bool SyntacticOnly);
+ unsigned Length, SKEditorConsumerOptions Opts);
static void
editorApplyFormatOptions(StringRef Name, RequestDict &FmtOptions);
@@ -429,9 +435,14 @@
Req.getInt64(KeyEnableSyntaxTree, EnableSyntaxTree, /*isOptional=*/true);
int64_t SyntacticOnly = false;
Req.getInt64(KeySyntacticOnly, SyntacticOnly, /*isOptional=*/true);
- return Rec(editorOpen(*Name, InputBuf.get(), EnableSyntaxMap, EnableStructure,
- EnableDiagnostics, EnableSyntaxTree, SyntacticOnly,
- Args));
+
+ SKEditorConsumerOptions Opts;
+ Opts.EnableSyntaxMap = EnableSyntaxMap;
+ Opts.EnableStructure = EnableStructure;
+ Opts.EnableDiagnostics = EnableDiagnostics;
+ Opts.EnableSyntaxTree = EnableSyntaxTree;
+ Opts.SyntacticOnly = SyntacticOnly;
+ return Rec(editorOpen(*Name, InputBuf.get(), Opts, Args));
}
if (ReqUID == RequestEditorClose) {
Optional<StringRef> Name = Req.getString(KeyName);
@@ -465,10 +476,15 @@
Req.getInt64(KeyEnableSyntaxTree, EnableSyntaxTree, /*isOptional=*/true);
int64_t SyntacticOnly = false;
Req.getInt64(KeySyntacticOnly, SyntacticOnly, /*isOptional=*/true);
- return Rec(editorReplaceText(*Name, InputBuf.get(), Offset, Length,
- EnableSyntaxMap, EnableStructure,
- EnableDiagnostics, EnableSyntaxTree,
- SyntacticOnly));
+
+ SKEditorConsumerOptions Opts;
+ Opts.EnableSyntaxMap = EnableSyntaxMap;
+ Opts.EnableStructure = EnableStructure;
+ Opts.EnableDiagnostics = EnableDiagnostics;
+ Opts.EnableSyntaxTree = EnableSyntaxTree;
+ Opts.SyntacticOnly = SyntacticOnly;
+
+ return Rec(editorReplaceText(*Name, InputBuf.get(), Offset, Length, Opts));
}
if (ReqUID == RequestEditorFormatText) {
Optional<StringRef> Name = Req.getString(KeyName);
@@ -1984,35 +2000,22 @@
ResponseBuilder::Array Diags;
sourcekitd_response_t Error = nullptr;
- bool EnableSyntaxMap;
- bool EnableStructure;
- bool EnableDiagnostics;
- bool EnableSyntaxTree;
- bool SyntacticOnly;
+ SKEditorConsumerOptions Opts;
public:
- SKEditorConsumer(bool EnableSyntaxMap, bool EnableStructure,
- bool EnableDiagnostics, bool EnableSyntaxTree,
- bool SyntacticOnly)
- : EnableSyntaxMap(EnableSyntaxMap), EnableStructure(EnableStructure),
- EnableDiagnostics(EnableDiagnostics), EnableSyntaxTree(EnableSyntaxTree),
- SyntacticOnly(SyntacticOnly) {
-
+ SKEditorConsumer(SKEditorConsumerOptions Opts) : Opts(Opts) {
Dict = RespBuilder.getDictionary();
}
- SKEditorConsumer(ResponseReceiver RespReceiver, bool EnableSyntaxMap,
- bool EnableStructure, bool EnableDiagnostics,
- bool EnableSyntaxTree, bool SyntacticOnly)
- : SKEditorConsumer(EnableSyntaxMap, EnableStructure,
- EnableDiagnostics, EnableSyntaxTree, SyntacticOnly) {
+ SKEditorConsumer(ResponseReceiver RespReceiver, SKEditorConsumerOptions Opts)
+ : SKEditorConsumer(Opts) {
this->RespReceiver = RespReceiver;
}
sourcekitd_response_t createResponse();
bool needsSemanticInfo() override {
- return !SyntacticOnly && !isSemanticEditorDisabled();
+ return !Opts.SyntacticOnly && !isSemanticEditorDisabled();
}
void handleRequestError(const char *Description) override;
@@ -2056,7 +2059,7 @@
bool handleSourceText(StringRef Text) override;
bool handleSerializedSyntaxTree(StringRef Text) override;
- virtual bool syntaxTreeEnabled() override;
+ bool syntaxTreeEnabled() override { return Opts.EnableSyntaxTree; }
void finished() override {
if (RespReceiver)
RespReceiver(createResponse());
@@ -2066,13 +2069,11 @@
} // end anonymous namespace
static sourcekitd_response_t
-editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, bool EnableSyntaxMap,
- bool EnableStructure, bool EnableDiagnostics, bool EnableSyntaxTree,
- bool SyntacticOnly, ArrayRef<const char *> Args) {
- SKEditorConsumer EditC(EnableSyntaxMap, EnableStructure,
- EnableDiagnostics, EnableSyntaxTree, SyntacticOnly);
+editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, SKEditorConsumerOptions Opts,
+ ArrayRef<const char *> Args) {
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
- Lang.editorOpen(Name, Buf, EnableSyntaxMap, EditC, Args);
+ Lang.editorOpen(Name, Buf, EditC, Args);
return EditC.createResponse();
}
@@ -2081,11 +2082,10 @@
Optional<StringRef> Group, ArrayRef<const char *> Args,
bool SynthesizedExtensions,
Optional<StringRef> InterestedUSR) {
- SKEditorConsumer EditC(/*EnableSyntaxMap=*/true,
- /*EnableStructure=*/true,
- /*EnableDiagnostics=*/false,
- /*EnableSyntaxTree=*/false,
- /*SyntacticOnly=*/false);
+ SKEditorConsumerOptions Opts;
+ Opts.EnableSyntaxMap = true;
+ Opts.EnableStructure = true;
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorOpenInterface(EditC, Name, ModuleName, Group, Args,
SynthesizedExtensions, InterestedUSR);
@@ -2099,12 +2099,10 @@
editorOpenSwiftSourceInterface(StringRef Name, StringRef HeaderName,
ArrayRef<const char *> Args,
ResponseReceiver Rec) {
- auto EditC = std::make_shared<SKEditorConsumer>(Rec,
- /*EnableSyntaxMap=*/true,
- /*EnableStructure=*/true,
- /*EnableDiagnostics=*/false,
- /*EnableSyntaxTree=*/false,
- /*SyntacticOnly=*/false);
+ SKEditorConsumerOptions Opts;
+ Opts.EnableSyntaxMap = true;
+ Opts.EnableStructure = true;
+ auto EditC = std::make_shared<SKEditorConsumer>(Rec, Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorOpenSwiftSourceInterface(Name, HeaderName, Args, EditC);
}
@@ -2112,33 +2110,27 @@
static void
editorOpenSwiftTypeInterface(StringRef TypeUsr, ArrayRef<const char *> Args,
ResponseReceiver Rec) {
- auto EditC = std::make_shared<SKEditorConsumer>(Rec,
- /*EnableSyntaxMap=*/true,
- /*EnableStructure=*/true,
- /*EnableDiagnostics=*/false,
- /*EnableSyntaxTree=*/false,
- /*SyntacticOnly=*/false);
+ SKEditorConsumerOptions Opts;
+ Opts.EnableSyntaxMap = true;
+ Opts.EnableStructure = true;
+ auto EditC = std::make_shared<SKEditorConsumer>(Rec, Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorOpenTypeInterface(*EditC, Args, TypeUsr);
}
static sourcekitd_response_t editorExtractTextFromComment(StringRef Source) {
- SKEditorConsumer EditC(/*EnableSyntaxMap=*/false,
- /*EnableStructure=*/false,
- /*EnableDiagnostics=*/false,
- /*EnableSyntaxTree=*/false,
- /*SyntacticOnly=*/true);
+ SKEditorConsumerOptions Opts;
+ Opts.SyntacticOnly = true;
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorExtractTextFromComment(Source, EditC);
return EditC.createResponse();
}
static sourcekitd_response_t editorConvertMarkupToXML(StringRef Source) {
- SKEditorConsumer EditC(/*EnableSyntaxMap=*/false,
- /*EnableStructure=*/false,
- /*EnableDiagnostics=*/false,
- /*EnableSyntaxTree=*/false,
- /*SyntacticOnly=*/true);
+ SKEditorConsumerOptions Opts;
+ Opts.SyntacticOnly = true;
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorConvertMarkupToXML(Source, EditC);
return EditC.createResponse();
@@ -2150,11 +2142,10 @@
bool UsingSwiftArgs,
bool SynthesizedExtensions,
StringRef swiftVersion) {
- SKEditorConsumer EditC(/*EnableSyntaxMap=*/true,
- /*EnableStructure=*/true,
- /*EnableDiagnostics=*/false,
- /*EnableSyntaxTree=*/false,
- /*SyntacticOnly=*/false);
+ SKEditorConsumerOptions Opts;
+ Opts.EnableSyntaxMap = true;
+ Opts.EnableStructure = true;
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorOpenHeaderInterface(EditC, Name, HeaderName, Args, UsingSwiftArgs,
SynthesizedExtensions, swiftVersion);
@@ -2171,11 +2162,8 @@
static sourcekitd_response_t
editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf, unsigned Offset,
- unsigned Length, bool EnableSyntaxMap, bool EnableStructure,
- bool EnableDiagnostics, bool EnableSyntaxTree,
- bool SyntacticOnly) {
- SKEditorConsumer EditC(EnableSyntaxMap, EnableStructure,
- EnableDiagnostics, EnableSyntaxTree, SyntacticOnly);
+ unsigned Length, SKEditorConsumerOptions Opts) {
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorReplaceText(Name, Buf, Offset, Length, EditC);
return EditC.createResponse();
@@ -2190,8 +2178,9 @@
static sourcekitd_response_t
editorFormatText(StringRef Name, unsigned Line, unsigned Length) {
- SKEditorConsumer EditC(false, false, false, false,
- /*SyntacticOnly=*/true);
+ SKEditorConsumerOptions Opts;
+ Opts.SyntacticOnly = true;
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorFormatText(Name, Line, Length, EditC);
return EditC.createResponse();
@@ -2199,8 +2188,9 @@
static sourcekitd_response_t
editorExpandPlaceholder(StringRef Name, unsigned Offset, unsigned Length) {
- SKEditorConsumer EditC(false, false, false, false,
- /*SyntacticOnly=*/true);
+ SKEditorConsumerOptions Opts;
+ Opts.SyntacticOnly = true;
+ SKEditorConsumer EditC(Opts);
LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
Lang.editorExpandPlaceholder(Name, Offset, Length, EditC);
return EditC.createResponse();
@@ -2210,7 +2200,7 @@
if (Error)
return Error;
- if (EnableSyntaxMap) {
+ if (Opts.EnableSyntaxMap) {
Dict.setCustomBuffer(KeySyntaxMap,
CustomBufferKind::TokenAnnotationsArray,
SyntaxMap.createBuffer());
@@ -2220,7 +2210,7 @@
CustomBufferKind::TokenAnnotationsArray,
SemanticAnnotations.createBuffer());
}
- if (EnableStructure) {
+ if (Opts.EnableStructure) {
Dict.setCustomBuffer(KeySubStructure, CustomBufferKind::DocStructureArray,
DocStructure.createBuffer());
}
@@ -2241,7 +2231,7 @@
bool SKEditorConsumer::handleSyntaxMap(unsigned Offset, unsigned Length,
UIdent Kind) {
- if (!EnableSyntaxMap)
+ if (!Opts.EnableSyntaxMap)
return true;
SyntaxMap.add(Kind, Offset, Length, /*IsSystem=*/false);
@@ -2273,7 +2263,7 @@
StringRef SelectorName,
ArrayRef<StringRef> InheritedTypes,
ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
- if (EnableStructure) {
+ if (Opts.EnableStructure) {
DocStructure.beginSubStructure(
Offset, Length, Kind, AccessLevel, SetterAccessLevel, NameOffset,
NameLength, BodyOffset, BodyLength, DocOffset, DocLength, DisplayName,
@@ -2283,7 +2273,7 @@
}
bool SKEditorConsumer::endDocumentSubStructure() {
- if (EnableStructure)
+ if (Opts.EnableStructure)
DocStructure.endSubStructure();
return true;
}
@@ -2291,7 +2281,7 @@
bool SKEditorConsumer::handleDocumentSubStructureElement(UIdent Kind,
unsigned Offset,
unsigned Length) {
- if (EnableStructure)
+ if (Opts.EnableStructure)
DocStructure.addElement(Kind, Offset, Length);
return true;
}
@@ -2387,7 +2377,7 @@
bool SKEditorConsumer::handleDiagnostic(const DiagnosticEntryInfo &Info,
UIdent DiagStage) {
- if (!EnableDiagnostics)
+ if (!Opts.EnableDiagnostics)
return true;
ResponseBuilder::Array &Arr = Diags;
@@ -2405,12 +2395,8 @@
return true;
}
-bool SKEditorConsumer::syntaxTreeEnabled() {
- return EnableSyntaxTree;
-}
-
bool SKEditorConsumer::handleSerializedSyntaxTree(StringRef Text) {
- if (EnableSyntaxTree)
+ if (syntaxTreeEnabled())
Dict.set(KeySerializedSyntaxTree, Text);
return true;
}
diff --git a/tools/driver/modulewrap_main.cpp b/tools/driver/modulewrap_main.cpp
index 663799e..6c1a07d 100644
--- a/tools/driver/modulewrap_main.cpp
+++ b/tools/driver/modulewrap_main.cpp
@@ -171,6 +171,8 @@
LangOpts.Target = Invocation.getTargetTriple();
ASTContext &ASTCtx = *ASTContext::get(LangOpts, SearchPathOpts, SrcMgr,
Instance.getDiags());
+ registerTypeCheckerRequestFunctions(ASTCtx.evaluator);
+
ClangImporterOptions ClangImporterOpts;
ASTCtx.addModuleLoader(ClangImporter::create(ASTCtx, ClangImporterOpts, ""),
true);
diff --git a/unittests/AST/ArithmeticEvaluator.cpp b/unittests/AST/ArithmeticEvaluator.cpp
index 0d2f697..cfa6165 100644
--- a/unittests/AST/ArithmeticEvaluator.cpp
+++ b/unittests/AST/ArithmeticEvaluator.cpp
@@ -87,9 +87,8 @@
: public SimpleRequest<Derived, Caching, double, ArithmeticExpr *>
{
using SimpleRequest<Derived, Caching, double, ArithmeticExpr *>::SimpleRequest;
- using SimpleRequest<Derived, Caching, double, ArithmeticExpr *>::operator();
- double operator()(Evaluator &evaluator, ArithmeticExpr *expr) const {
+ double evaluate(Evaluator &evaluator, ArithmeticExpr *expr) const {
switch (expr->kind) {
case ArithmeticExpr::Kind::Literal:
return static_cast<Literal *>(expr)->value;
@@ -179,16 +178,25 @@
// Define the arithmetic evaluator's zone.
namespace swift {
-#define SWIFT_TYPEID_ZONE 255
+#define SWIFT_ARITHMETIC_EVALUATOR_ZONE 255
+#define SWIFT_TYPEID_ZONE SWIFT_ARITHMETIC_EVALUATOR_ZONE
#define SWIFT_TYPEID_HEADER "ArithmeticEvaluatorTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"
-#define SWIFT_TYPEID_ZONE 255
+#define SWIFT_TYPEID_ZONE SWIFT_ARITHMETIC_EVALUATOR_ZONE
#define SWIFT_TYPEID_HEADER "ArithmeticEvaluatorTypeIDZone.def"
#include "swift/Basic/ImplementTypeIDZone.h"
}
+/// All of the arithmetic request functions.
+static AbstractRequestFunction *arithmeticRequestFunctions[] = {
+#define SWIFT_TYPEID(Name) \
+ reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
+#include "ArithmeticEvaluatorTypeIDZone.def"
+#undef SWIFT_TYPEID
+};
+
TEST(ArithmeticEvaluator, Simple) {
// (3.14159 + 2.71828) * 42
ArithmeticExpr *pi = new Literal(3.14159);
@@ -201,6 +209,8 @@
SourceManager sourceMgr;
DiagnosticEngine diags(sourceMgr);
Evaluator evaluator(diags, CycleDiagnosticKind::FullDiagnose);
+ evaluator.registerRequestFunctions(SWIFT_ARITHMETIC_EVALUATOR_ZONE,
+ arithmeticRequestFunctions);
const double expectedResult = (3.14159 + 2.71828) * 42.0;
EXPECT_EQ(evaluator(InternallyCachedEvaluationRule(product)),
@@ -321,6 +331,8 @@
SourceManager sourceMgr;
DiagnosticEngine diags(sourceMgr);
Evaluator evaluator(diags, CycleDiagnosticKind::FullDiagnose);
+ evaluator.registerRequestFunctions(SWIFT_ARITHMETIC_EVALUATOR_ZONE,
+ arithmeticRequestFunctions);
// Evaluate when there is a cycle.
UncachedEvaluationRule::brokeCycle = false;
diff --git a/unittests/AST/TestContext.cpp b/unittests/AST/TestContext.cpp
index cd1366a..6890661 100644
--- a/unittests/AST/TestContext.cpp
+++ b/unittests/AST/TestContext.cpp
@@ -13,6 +13,7 @@
#include "TestContext.h"
#include "swift/AST/Module.h"
#include "swift/Strings.h"
+#include "swift/Subsystems.h"
using namespace swift;
using namespace swift::unittest;
@@ -34,6 +35,7 @@
TestContext::TestContext(ShouldDeclareOptionalTypes optionals)
: Ctx(*ASTContext::get(LangOpts, SearchPathOpts, SourceMgr, Diags)) {
+ registerTypeCheckerRequestFunctions(Ctx.evaluator);
auto stdlibID = Ctx.getIdentifier(STDLIB_NAME);
auto *module = ModuleDecl::create(stdlibID, Ctx);
Ctx.LoadedModules[stdlibID] = module;
diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
index 4b314a2..3477e8d 100644
--- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
+++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
@@ -136,8 +136,7 @@
auto Args = CArgs.hasValue() ? makeArgs(DocName, *CArgs)
: std::vector<const char *>{};
auto Buf = MemoryBuffer::getMemBufferCopy(Text, DocName);
- getLang().editorOpen(DocName, Buf.get(), /*EnableSyntaxMap=*/false,
- Consumer, Args);
+ getLang().editorOpen(DocName, Buf.get(), Consumer, Args);
}
void replaceText(StringRef DocName, unsigned Offset, unsigned Length,
diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp
index 0c61b0f..bc7d217 100644
--- a/unittests/SourceKit/SwiftLang/EditingTest.cpp
+++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp
@@ -157,8 +157,7 @@
EditorConsumer &Consumer) {
auto Args = makeArgs(DocName, CArgs);
auto Buf = MemoryBuffer::getMemBufferCopy(Text, DocName);
- getLang().editorOpen(DocName, Buf.get(), /*EnableSyntaxMap=*/false, Consumer,
- Args);
+ getLang().editorOpen(DocName, Buf.get(), Consumer, Args);
}
void close(const char *DocName) {
diff --git a/validation-test/IDE/crashers/032-swift-expr-propagatelvalueaccesskind.swift b/validation-test/IDE/crashers/032-swift-expr-propagatelvalueaccesskind.swift
deleted file mode 100644
index f7bf01e..0000000
--- a/validation-test/IDE/crashers/032-swift-expr-propagatelvalueaccesskind.swift
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
-// REQUIRES: asserts
-{()=(var a{#^A^#
diff --git a/validation-test/IDE/crashers_fixed/032-swift-expr-propagatelvalueaccesskind.swift b/validation-test/IDE/crashers_fixed/032-swift-expr-propagatelvalueaccesskind.swift
new file mode 100644
index 0000000..6eec7a0
--- /dev/null
+++ b/validation-test/IDE/crashers_fixed/032-swift-expr-propagatelvalueaccesskind.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+{()=(var a{#^A^#
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift b/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift
index 5525c1a..1eef996 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift
@@ -13,7 +13,10 @@
var description : String {
return "\(i)" + Stringly(format: "%.2f", x) +
"\(i+1)" + Stringly(format: "%.2f", x) +
- "\(i+2)" + Stringly(format: "%.2f", x)
+ "\(i+2)" + Stringly(format: "%.2f", x) +
+ "\(i+3)" + Stringly(format: "%.2f", x) +
+ "\(i+4)" + Stringly(format: "%.2f", x) +
+ "\(i+5)" + Stringly(format: "%.2f", x)
// expected-error@-1 {{reasonable time}}
}
}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift b/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
index 9e0f15d..a640a29 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
@@ -9,5 +9,9 @@
[Int](0..<1).map {
// expected-error@-1 {{reasonable time}}
- print(Stringly(format: "%d: ", $0 * 2 * 42) + ["a", "b", "c", "d", "e", "f", "g"][$0 * 2] + "," + "," + ",")
+ print(Stringly(format: "%d: ",
+ $0 * 2 * 42 +
+ $0 * 2 * 42 +
+ $0 * 2 * 42
+ ) + ["a", "b", "c", "d", "e", "f", "g"][$0 * 2] + "," + "," + ",")
}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift b/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift
index cd2d914..9ccd3b5 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift
@@ -3,7 +3,7 @@
func test(n: Int) -> Int {
return n == 0 ? 0 : (0..<n).reduce(0) {
- // expected-error@-1 {{reasonable time}}
- ($0 > 0 && $1 % 2 == 0) ? (($0 + $1) / ($1 - $0)) : $0
+ // expected-error@-1 {{reasonable time}}
+ ($0 > 0 && $1 % 2 == 0) ? ((($0 + $1) - ($0 + $1)) / ($1 - $0)) + (($0 + $1) / ($1 - $0)) : $0
}
}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift b/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift
index fc29dbd..1ee4dc3 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift
@@ -1,5 +1,5 @@
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1
// REQUIRES: tools-release,no_asserts
-_ = [0,1,2,3].lazy.map { String($0)+"hi" }.sorted(by: { $0 > $1 })
+_ = [0,1,2,3].lazy.map { String($0)+"hi" }.sorted(by: { $0 > $1 && $1 < $0 && ($1 + $0) < 1000 })
// expected-error@-1 {{reasonable time}}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift b/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift
index 1410c5d..c75dff8 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift
@@ -3,5 +3,5 @@
let _ = [0].reduce([Int]()) {
// expected-error@-1 {{reasonable time}}
- return $0.count == 0 && $1 == 0 ? [] : $0 + [$1]
+ return $0.count == 0 && ($1 == 0 || $1 == 2 || $1 == 3) ? [] : $0 + [$1]
}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift b/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift
index 2cf28a1..4942edb 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift
@@ -6,6 +6,6 @@
func rdar23861629(_ a: [S]) {
_ = a.reduce("") {
// expected-error@-1 {{reasonable time}}
- ($0 == "") ? ($1.s ?? "") : $0 + "," + ($1.s ?? "")
+ ($0 == "") ? ($1.s ?? "") : ($0 + "," + ($1.s ?? "")) + ($1.s ?? "test") + ($1.s ?? "okay")
}
}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift b/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift
index a4819a6..4907dbb 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift
@@ -2,6 +2,6 @@
// REQUIRES: tools-release,no_asserts
func rdar31742586() -> Double {
- return -(1 + 2) + -(3 + 4) + 5
+ return -(1 + 2) + -(3 + 4) + 5 - (-(1 + 2) + -(3 + 4) + 5)
// expected-error@-1 {{reasonable time}}
}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift b/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift
index da38c36..3e13c52 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift
@@ -2,7 +2,8 @@
// REQUIRES: tools-release,no_asserts
func rdar32998180(value: UInt16) -> UInt16 {
- var result = (((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1
+ var result = ((((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1)
+ | (((((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1) << 1)
// expected-error@-1 {{reasonable time}}
return result
}
diff --git a/validation-test/compiler_crashers_2_fixed/0165-sr5427.swift b/validation-test/compiler_crashers_2_fixed/0165-sr5427.swift
new file mode 100644
index 0000000..845d263
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0165-sr5427.swift
@@ -0,0 +1,7 @@
+// RUN: %target-typecheck-verify-swift
+
+// Used to crash with: apply expression is not marked as throwing or
+// non-throwing
+struct SR5427 : Error {}
+func sr5427(op: (() throws -> Void)?) rethrows { try op?() }
+try? sr5427(op: { throw SR5427() })
diff --git a/validation-test/compiler_crashers/28847-type-hasunboundgenerictype.swift b/validation-test/compiler_crashers_fixed/28847-type-hasunboundgenerictype.swift
similarity index 84%
rename from validation-test/compiler_crashers/28847-type-hasunboundgenerictype.swift
rename to validation-test/compiler_crashers_fixed/28847-type-hasunboundgenerictype.swift
index 1d8ad46..fb6f0bf 100644
--- a/validation-test/compiler_crashers/28847-type-hasunboundgenerictype.swift
+++ b/validation-test/compiler_crashers_fixed/28847-type-hasunboundgenerictype.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
extension a{protocol P{}}class a<a{var f=a a{}func a:P&
diff --git a/validation-test/stdlib/AnyHashable.swift.gyb b/validation-test/stdlib/AnyHashable.swift.gyb
index 05084ad..c6fa6cf 100644
--- a/validation-test/stdlib/AnyHashable.swift.gyb
+++ b/validation-test/stdlib/AnyHashable.swift.gyb
@@ -767,6 +767,132 @@
expectEqual(MinimalHashableRCSwiftError.self, type(of: ah.base))
}
+AnyHashableTests.test("AnyHashable(NumericTypes)/Hashable") {
+ // Numeric types holding mathematically equal values must compare equal and
+ // hash the same way when converted to AnyHashable.
+ let groups: [[AnyHashable]] = [
+ [
+ 1 as Int,
+ 1 as UInt,
+ 1 as Int8,
+ 1 as UInt8,
+ 1 as Int16,
+ 1 as UInt16,
+ 1 as Int32,
+ 1 as UInt32,
+ 1 as Int64,
+ 1 as UInt64,
+ 1 as Float,
+ 1 as Double,
+ ],
+ [
+ 42 as Int,
+ 42 as UInt,
+ 42 as Int8,
+ 42 as UInt8,
+ 42 as Int16,
+ 42 as UInt16,
+ 42 as Int32,
+ 42 as UInt32,
+ 42 as Int64,
+ 42 as UInt64,
+ 42 as Float,
+ 42 as Double,
+ ],
+ [
+ Int(Int32.max),
+ UInt(Int32.max),
+ Int32.max,
+ UInt32(Int32.max),
+ Int64(Int32.max),
+ UInt64(Int32.max),
+ Double(Int32.max),
+ ],
+ [
+ Float.infinity,
+ Double.infinity,
+ ],
+ [
+ 0x1.aP1 as Float, // 3.25
+ 0x1.aP1 as Double,
+ ],
+ [
+ 0x1.a000000000001P1, // 3.25.nextUp, not representable by a Float
+ ]
+ ]
+ checkHashableGroups(groups)
+}
+
+#if !os(Windows) && (arch(i386) || arch(x86_64))
+AnyHashableTests.test("AnyHashable(Float80)/Hashable") {
+ let groups: [[AnyHashable]] = [
+ [
+ 42 as Int,
+ 42 as Float,
+ 42 as Double,
+ 42 as Float80,
+ ],
+ [
+ Float.infinity,
+ Double.infinity,
+ Float80.infinity,
+ ],
+ [
+ 3.25 as Float,
+ 3.25 as Double,
+ 3.25 as Float80,
+ ],
+ [
+ 0x1.a000000000001P1 as Double, // 3.25.nextUp
+ 0x1.a000000000001P1 as Float80,
+ ],
+ [
+ 0x1.a000000000000002p1 as Float80, // (3.25 as Float80).nextUp
+ ],
+ ]
+ checkHashableGroups(groups)
+}
+#endif
+
+#if _runtime(_ObjC)
+// A wrapper type around an Int that bridges to NSNumber.
+struct IntWrapper1 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+ let rawValue: Int
+}
+
+// A wrapper type around an Int that bridges to NSNumber.
+struct IntWrapper2 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+ let rawValue: Int
+}
+
+// A wrapper type around an Int that bridges to NSNumber.
+struct Int8Wrapper : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+ let rawValue: Int8
+}
+
+AnyHashableTests.test("AnyHashable(IntWrappers)/Hashable") {
+ let groups: [[AnyHashable]] = [
+ [
+ IntWrapper1(rawValue: 42),
+ IntWrapper2(rawValue: 42),
+ Int8Wrapper(rawValue: 42),
+ 42,
+ 42 as Double,
+ 42 as NSNumber,
+ ],
+ [
+ IntWrapper1(rawValue: -23),
+ IntWrapper2(rawValue: -23),
+ Int8Wrapper(rawValue: -23),
+ -23,
+ -23 as Double,
+ -23 as NSNumber,
+ ],
+ ]
+ checkHashableGroups(groups)
+}
+#endif
+
#if _runtime(_ObjC)
// A wrapper type around a String that bridges to NSString.
struct StringWrapper1 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
@@ -778,126 +904,101 @@
let rawValue: String
}
-AnyHashableTests.test("AnyHashable(Wrappers)/Hashable") {
- let values: [AnyHashable] = [
- StringWrapper1(rawValue: "hello"),
- StringWrapper2(rawValue: "hello"),
- "hello" as String,
- "hello" as NSString,
- StringWrapper1(rawValue: "world"),
- StringWrapper2(rawValue: "world"),
- "world" as String,
- "world" as NSString,
+AnyHashableTests.test("AnyHashable(StringWrappers)/Hashable") {
+ let groups: [[AnyHashable]] = [
+ [
+ StringWrapper1(rawValue: "hello"),
+ StringWrapper2(rawValue: "hello"),
+ "hello" as String,
+ "hello" as NSString,
+ ],
+ [
+ StringWrapper1(rawValue: "world"),
+ StringWrapper2(rawValue: "world"),
+ "world" as String,
+ "world" as NSString,
+ ]
]
-
- func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
- // Elements in [0, 3] match 3.
- if lhs == 3 { return rhs >= 0 && rhs <= 3 }
- if rhs == 3 { return lhs >= 0 && lhs <= 3 }
-
- // Elements in [4, 7] match 7.
- if lhs == 7 { return rhs >= 4 && rhs <= 7 }
- if rhs == 7 { return lhs >= 4 && lhs <= 7 }
-
- return lhs == rhs
- }
-
- func hashEqualityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
- // Elements in [0, 3] hash the same, as do elements in [4, 7].
- return lhs / 4 == rhs / 4
- }
-
- checkHashable(
- values,
- equalityOracle: equalityOracle,
- hashEqualityOracle: hashEqualityOracle,
- allowBrokenTransitivity: true)
+ checkHashableGroups(groups)
}
AnyHashableTests.test("AnyHashable(Set)/Hashable") {
- let values: [AnyHashable] = [
- Set([1, 2, 3]),
- NSSet(set: [1, 2, 3]),
- Set([2, 3, 4]),
- NSSet(set: [2, 3, 4]),
- Set([Set([1, 2]), Set([3, 4])]),
- NSSet(set: [NSSet(set: [1, 2]), NSSet(set: [3, 4])]),
- Set([Set([1, 3]), Set([2, 4])]),
- NSSet(set: [NSSet(set: [1, 3]), NSSet(set: [2, 4])]),
+ let groups: [[AnyHashable]] = [
+ [
+ Set([1, 2, 3]),
+ Set([1, 2, 3] as [Int8]),
+ Set([1, 2, 3] as [Float]),
+ NSSet(set: [1, 2, 3]),
+ ],
+ [
+ Set([2, 3, 4]),
+ NSSet(set: [2, 3, 4]),
+ ],
+ [
+ Set([Set([1, 2]), Set([3, 4])]),
+ NSSet(set: [NSSet(set: [1, 2]), NSSet(set: [3, 4])]),
+ ],
+ [
+ Set([Set([1, 3]), Set([2, 4])]),
+ NSSet(set: [NSSet(set: [1, 3]), NSSet(set: [2, 4])]),
+ ],
]
-
- func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
- switch (lhs, rhs) {
- case (0...1, 0...1): return true
- case (2...3, 2...3): return true
- case (4...5, 4...5): return true
- case (6...7, 6...7): return true
- default: return false
- }
- }
-
- checkHashable(
- values,
- equalityOracle: equalityOracle,
- allowBrokenTransitivity: true)
+ checkHashableGroups(groups)
}
AnyHashableTests.test("AnyHashable(Array)/Hashable") {
- let values: [AnyHashable] = [
- [1, 2, 3],
- NSArray(array: [1, 2, 3]),
- [3, 2, 1],
- NSArray(array: [3, 2, 1]),
- [[1, 2], [3, 4]],
- NSArray(array: [NSArray(array: [1, 2]), NSArray(array: [3, 4])]),
- [[3, 4], [1, 2]],
- NSArray(array: [NSArray(array: [3, 4]), NSArray(array: [1, 2])]),
+ let groups: [[AnyHashable]] = [
+ [
+ [1, 2, 3],
+ [1, 2, 3] as [Int8],
+ [1, 2, 3] as [Double],
+ NSArray(array: [1, 2, 3]),
+ ],
+ [
+ [3, 2, 1],
+ [3, 2, 1] as [AnyHashable],
+ NSArray(array: [3, 2, 1]),
+ ],
+ [
+ [[1, 2], [3, 4]],
+ NSArray(array: [NSArray(array: [1, 2]), NSArray(array: [3, 4])]),
+ ],
+ [
+ [[3, 4], [1, 2]],
+ NSArray(array: [NSArray(array: [3, 4]), NSArray(array: [1, 2])]),
+ ]
]
-
- func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
- switch (lhs, rhs) {
- case (0...1, 0...1): return true
- case (2...3, 2...3): return true
- case (4...5, 4...5): return true
- case (6...7, 6...7): return true
- default: return false
- }
- }
-
- checkHashable(values, equalityOracle: equalityOracle,
- allowBrokenTransitivity: true)
+ checkHashableGroups(groups)
}
AnyHashableTests.test("AnyHashable(Dictionary)/Hashable") {
- let values: [AnyHashable] = [
- ["hello": 1, "world": 2],
- NSDictionary(dictionary: ["hello": 1, "world": 2]),
- ["hello": 2, "world": 1],
- NSDictionary(dictionary: ["hello": 2, "world": 1]),
- ["hello": ["foo": 1, "bar": 2],
- "world": ["foo": 2, "bar": 1]],
- NSDictionary(dictionary: [
- "hello": ["foo": 1, "bar": 2],
- "world": ["foo": 2, "bar": 1]]),
- ["hello": ["foo": 2, "bar": 1],
- "world": ["foo": 1, "bar": 2]],
- NSDictionary(dictionary: [
- "hello": ["foo": 2, "bar": 1],
- "world": ["foo": 1, "bar": 2]]),
+ let groups: [[AnyHashable]] = [
+ [
+ ["hello": 1, "world": 2] as [String: Int],
+ ["hello": 1, "world": 2] as [String: Int16],
+ ["hello": 1, "world": 2] as [String: Float],
+ NSDictionary(dictionary: ["hello": 1, "world": 2]),
+ ],
+ [
+ ["hello": 2, "world": 1],
+ NSDictionary(dictionary: ["hello": 2, "world": 1]),
+ ],
+ [
+ ["hello": ["foo": 1, "bar": 2],
+ "world": ["foo": 2, "bar": 1]],
+ NSDictionary(dictionary: [
+ "hello": ["foo": 1, "bar": 2],
+ "world": ["foo": 2, "bar": 1]]),
+ ],
+ [
+ ["hello": ["foo": 2, "bar": 1],
+ "world": ["foo": 1, "bar": 2]],
+ NSDictionary(dictionary: [
+ "hello": ["foo": 2, "bar": 1],
+ "world": ["foo": 1, "bar": 2]]),
+ ],
]
-
- func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
- switch (lhs, rhs) {
- case (0...1, 0...1): return true
- case (2...3, 2...3): return true
- case (4...5, 4...5): return true
- case (6...7, 6...7): return true
- default: return false
- }
- }
-
- checkHashable(values, equalityOracle: equalityOracle,
- allowBrokenTransitivity: true)
+ checkHashableGroups(groups)
}
AnyHashableTests.test("AnyHashable(_SwiftNativeNSError(MinimalHashablePODSwiftError))/Hashable") {
diff --git a/validation-test/stdlib/BoolDiagnostics_Dataflow.swift b/validation-test/stdlib/BoolDiagnostics_Dataflow.swift
index 29774a6..576b4d0 100644
--- a/validation-test/stdlib/BoolDiagnostics_Dataflow.swift
+++ b/validation-test/stdlib/BoolDiagnostics_Dataflow.swift
@@ -55,5 +55,5 @@
}
} // expected-error {{missing return in a function expected to return 'Int'}}
-// expected-warning@+1 {{'ExpressibleByStringInterpolation' is deprecated: it will be replaced or redesigned in Swift 4.0. Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'}}
+// expected-warning@+1 {{'ExpressibleByStringInterpolation' is deprecated: it will be replaced or redesigned in Swift 5.0. Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'}}
typealias X = ExpressibleByStringInterpolation
diff --git a/validation-test/stdlib/CollectionCompatibility.swift b/validation-test/stdlib/CollectionCompatibility.swift
index 4040c41..4049393 100644
--- a/validation-test/stdlib/CollectionCompatibility.swift
+++ b/validation-test/stdlib/CollectionCompatibility.swift
@@ -24,7 +24,7 @@
}
//===--- MyBidiCollection -------------------------------------------------===//
-/// A simple collection that attempts to use an Int16 IndexDistance
+/// A simple collection that doesn't declare an IndexDistance
struct MyBidiCollection<Element>: BidirectionalCollection {
var _elements: [Element]
@@ -45,12 +45,12 @@
CollectionDistance.test("Int16/distance") {
let c = MyCollection<Int>(_elements: [1,2,3])
- let d: Int16 = c.distance(from: c.startIndex, to: c.endIndex)
+ var d: Int16 = c.distance(from: c.startIndex, to: c.endIndex)
expectEqual(3, d)
+ expectType(MyCollection<Int>.IndexDistance.self, &d)
// without type context, you now get an Int
var i = c.distance(from: c.startIndex, to: c.endIndex)
expectType(Int.self, &i)
- expectType(MyCollection<Int>.IndexDistance.self, &i)
}
CollectionDistance.test("Int16/advance") {
@@ -76,12 +76,10 @@
CollectionDistance.test("Int64/distance") {
let c = MyBidiCollection<Int>(_elements: [1,2,3])
- let d: Int16 = c.distance(from: c.startIndex, to: c.endIndex)
+ var d = c.distance(from: c.startIndex, to: c.endIndex)
expectEqual(3, d)
- // without type context, you now get an Int
- var i = c.distance(from: c.startIndex, to: c.endIndex)
- expectType(Int.self, &i)
- expectType(MyCollection<Int>.IndexDistance.self, &i)
+ expectType(Int.self, &d)
+ expectType(MyBidiCollection<Int>.IndexDistance.self, &d)
}
CollectionDistance.test("Int64/advance") {
@@ -106,4 +104,15 @@
checkBidirectionalCollection(c, [1,2,3])
}
+extension Collection where Index == Int, IndexDistance == Int {
+ var myCount: Int {
+ return distance(from: startIndex, to: endIndex)
+ }
+}
+
+CollectionDistance.test("IndexDistance/constraint") {
+ let n = [1,2,3].myCount
+ expectEqual(3, n)
+}
+
runAllTests()
diff --git a/validation-test/stdlib/CollectionDiagnostics.swift b/validation-test/stdlib/CollectionDiagnostics.swift
index f1158bc..78cee40 100644
--- a/validation-test/stdlib/CollectionDiagnostics.swift
+++ b/validation-test/stdlib/CollectionDiagnostics.swift
@@ -48,7 +48,8 @@
array.sorted { $0 < $1 } // expected-warning {{result of call to 'sorted(by:)' is unused}}
}
-// expected-warning@+1 {{'Indexable' is deprecated: it will be removed in Swift 4.0. Please use 'Collection' instead}}
+// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 5.0. Please use 'Collection' instead}}
+// expected-note@+1 {{use 'Collection' instead}}
struct GoodIndexable : Indexable {
func index(after i: Int) -> Int { return i + 1 }
var startIndex: Int { return 0 }
@@ -59,7 +60,8 @@
}
-// expected-warning@+1 {{'Indexable' is deprecated: it will be removed in Swift 4.0. Please use 'Collection' instead}}
+// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 5.0. Please use 'Collection' instead}}
+// expected-note@+1 {{use 'Collection' instead}}
struct AnotherGoodIndexable1 : Indexable {
func index(after i: Int) -> Int { return i + 1 }
var startIndex: Int { return 0 }
@@ -68,8 +70,9 @@
subscript(pos: Int) -> Int { return 0 }
}
-// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 4.0. Please use 'Collection' instead}}
-// expected-error@+1 {{type 'BadIndexable2' does not conform to protocol 'Collection'}}
+// expected-warning@+3 {{'Indexable' is deprecated: it will be removed in Swift 5.0. Please use 'Collection' instead}}
+// expected-error@+2 {{type 'BadIndexable2' does not conform to protocol 'Collection'}}
+// expected-note@+1 {{use 'Collection' instead}}
struct BadIndexable2 : Indexable {
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
@@ -79,7 +82,8 @@
// Missing index(after:) -> Int
}
-// expected-warning@+1 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 4.0. Please use 'BidirectionalCollection' instead}}
+// expected-warning@+2 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 5.0. Please use 'BidirectionalCollection' instead}}
+// expected-note@+1 {{use 'BidirectionalCollection' instead}}
struct GoodBidirectionalIndexable1 : BidirectionalIndexable {
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
@@ -92,7 +96,8 @@
// We'd like to see: {{type 'BadBidirectionalIndexable' does not conform to protocol 'BidirectionalIndexable'}}
// But the compiler doesn't generate that error.
-// expected-warning@+1 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 4.0. Please use 'BidirectionalCollection' instead}}
+// expected-warning@+2 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 5.0. Please use 'BidirectionalCollection' instead}}
+// expected-note@+1 {{use 'BidirectionalCollection' instead}}
struct BadBidirectionalIndexable : BidirectionalIndexable {
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
diff --git a/validation-test/stdlib/DictionaryAnyHashableExtensions.swift b/validation-test/stdlib/DictionaryAnyHashableExtensions.swift
index 8cfaaa6..9d57794 100644
--- a/validation-test/stdlib/DictionaryAnyHashableExtensions.swift
+++ b/validation-test/stdlib/DictionaryAnyHashableExtensions.swift
@@ -6,26 +6,73 @@
var DictionaryTests = TestSuite("Dictionary")
DictionaryTests.test("index<Hashable>(forKey:)") {
- let d: [AnyHashable : Int] = [
- AnyHashable(10) : 1010,
- AnyHashable(20) : 2020,
- AnyHashable(30.0) : 3030,
+ let a = AnyHashable(10 as UInt16)
+ let b = AnyHashable(20)
+ let c = AnyHashable(30.0)
+ let d: [AnyHashable: Int] = [
+ a: 1010,
+ b: 2020,
+ c: 3030,
]
- expectEqual(1010, d[d.index(forKey: 10)!].value)
- expectEqual(2020, d[d.index(forKey: 20)!].value)
- expectEqual(3030, d[d.index(forKey: 30.0)!].value)
+ for (key, k, value) in [(a, 10, 1010), (b, 20, 2020), (c, 30, 3030)] {
+ let index = d.index(forKey: key)!
+ expectEqual(value, d[index].value)
+ // We must be able to look up the same number in any representation.
+ expectEqual(index, d.index(forKey: UInt8(k)))
+ expectEqual(index, d.index(forKey: UInt16(k)))
+ expectEqual(index, d.index(forKey: UInt32(k)))
+ expectEqual(index, d.index(forKey: UInt64(k)))
+ expectEqual(index, d.index(forKey: UInt(k)))
+ expectEqual(index, d.index(forKey: Int8(k)))
+ expectEqual(index, d.index(forKey: Int16(k)))
+ expectEqual(index, d.index(forKey: Int32(k)))
+ expectEqual(index, d.index(forKey: Int64(k)))
+ expectEqual(index, d.index(forKey: Int(k)))
+ expectEqual(index, d.index(forKey: Float(k)))
+ expectEqual(index, d.index(forKey: Double(k)))
- expectNil(d.index(forKey: 10.0))
- expectNil(d.index(forKey: 20.0))
- expectNil(d.index(forKey: 30))
+ expectNil(d.index(forKey: String(k)))
+ }
}
DictionaryTests.test("subscript<Hashable>(_:)") {
- var d: [AnyHashable : Int] = [
- AnyHashable(10) : 1010,
- AnyHashable(20) : 2020,
- AnyHashable(30.0) : 3030,
+ let a = AnyHashable(10 as UInt16)
+ let b = AnyHashable(20)
+ let c = AnyHashable(30.0)
+ let d: [AnyHashable: Int] = [
+ a: 1010,
+ b: 2020,
+ c: 3030,
+ ]
+
+ for (key, k, value) in [(a, 10, 1010), (b, 20, 2020), (c, 30, 3030)] {
+ let index = d.index(forKey: key)!
+ expectEqual(value, d[key])
+ // We must be able to look up the same number in any representation.
+ expectEqual(value, d[UInt8(k)])
+ expectEqual(value, d[UInt16(k)])
+ expectEqual(value, d[UInt32(k)])
+ expectEqual(value, d[UInt64(k)])
+ expectEqual(value, d[UInt(k)])
+ expectEqual(value, d[Int8(k)])
+ expectEqual(value, d[Int16(k)])
+ expectEqual(value, d[Int32(k)])
+ expectEqual(value, d[Int64(k)])
+ expectEqual(value, d[Int(k)])
+ expectEqual(value, d[Float(k)])
+ expectEqual(value, d[Double(k)])
+
+ expectNil(d[String(k)])
+ }
+}
+
+
+DictionaryTests.test("subscript<Hashable>(_:)/2") {
+ var d: [AnyHashable: Int] = [
+ AnyHashable(10): 1010,
+ AnyHashable(20): 2020,
+ AnyHashable(30.0): 3030,
]
expectEqual(1010, d[10])
@@ -100,57 +147,61 @@
expectEqual(expected, d)
}
- expectNil(d.updateValue(4040, forKey: 10.0))
+ expectEqual(101010, d.updateValue(4040, forKey: 10.0))
do {
let expected: [AnyHashable : Int] = [
- AnyHashable(10) : 101010,
+ AnyHashable(10) : 4040,
AnyHashable(20) : 202020,
AnyHashable(30.0) : 303030,
- AnyHashable(10.0) : 4040,
]
expectEqual(expected, d)
}
- expectNil(d.updateValue(5050, forKey: 20.0))
+ expectEqual(202020, d.updateValue(5050, forKey: 20.0))
do {
let expected: [AnyHashable : Int] = [
- AnyHashable(10) : 101010,
- AnyHashable(20) : 202020,
+ AnyHashable(10) : 4040,
+ AnyHashable(20) : 5050,
AnyHashable(30.0) : 303030,
- AnyHashable(10.0) : 4040,
- AnyHashable(20.0) : 5050,
]
expectEqual(expected, d)
}
- expectNil(d.updateValue(6060, forKey: 30))
+ expectEqual(303030, d.updateValue(6060, forKey: 30))
do {
let expected: [AnyHashable : Int] = [
- AnyHashable(10) : 101010,
- AnyHashable(20) : 202020,
- AnyHashable(30.0) : 303030,
- AnyHashable(10.0) : 4040,
- AnyHashable(20.0) : 5050,
- AnyHashable(30) : 6060,
+ AnyHashable(10) : 4040,
+ AnyHashable(20) : 5050,
+ AnyHashable(30.0) : 6060,
]
expectEqual(expected, d)
}
}
DictionaryTests.test("removeValue<Hashable>(forKey:)") {
- var d: [AnyHashable : Int] = [
- AnyHashable(10) : 1010,
+ let d: [AnyHashable : Int] = [
+ AnyHashable(10 as UInt8) : 1010,
AnyHashable(20) : 2020,
AnyHashable(30.0) : 3030,
]
- expectNil(d.removeValue(forKey: 10.0))
- expectNil(d.removeValue(forKey: 20.0))
- expectNil(d.removeValue(forKey: 30))
+ for (key, value) in [(10, 1010), (20, 2020), (30, 3030)] {
+ var dd = d
+ expectEqual(value, dd.removeValue(forKey: UInt8(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: UInt16(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: UInt32(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: UInt64(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: UInt(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Int8(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Int16(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Int32(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Int64(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Int(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Float(key)))
+ dd = d; expectEqual(value, dd.removeValue(forKey: Double(key)))
- expectEqual(1010, d.removeValue(forKey: 10)!)
- expectEqual(2020, d.removeValue(forKey: 20)!)
- expectEqual(3030, d.removeValue(forKey: 30.0)!)
+ dd = d; expectNil(dd.removeValue(forKey: String(key)))
+ }
}
runAllTests()
diff --git a/validation-test/stdlib/FixedPoint.swift.gyb b/validation-test/stdlib/FixedPoint.swift.gyb
index 7ac2f9d..dd371bf 100644
--- a/validation-test/stdlib/FixedPoint.swift.gyb
+++ b/validation-test/stdlib/FixedPoint.swift.gyb
@@ -233,22 +233,26 @@
% for self_ty in all_integer_types(word_bits):
% Self = self_ty.stdlib_name
-FixedPoint.test("${Self}.hashValue") {
+FixedPoint.test("${Self}.hash(into:)") {
% for bit_pattern in test_bit_patterns:
do {
% input = prepare_bit_pattern(bit_pattern, self_ty.bits, self_ty.is_signed)
let input = get${Self}(${input})
- let output = getInt(input.hashValue)
+ var hasher = Hasher()
+ input.hash(into: &hasher)
+ let output = getInt(hasher.finalize())
- var hasher = _SipHash13(_seed: Hasher._seed)
-% if prepare_bit_pattern(input, word_bits, self_ty.is_signed) == input:
- hasher._combine(UInt(truncatingIfNeeded: ${input} as ${"" if self_ty.is_signed else "U"}Int))
+% reference = prepare_bit_pattern(bit_pattern, self_ty.bits, False)
+% if self_ty.bits == 64:
+ let expected = Hasher._hash(seed: Hasher._seed, ${reference} as UInt64)
% else:
- hasher._combine(UInt64(truncatingIfNeeded: input))
+ let expected = Hasher._hash(
+ seed: Hasher._seed,
+ bytes: ${reference},
+ count: ${self_ty.bits / 8})
% end
- let expected = getInt(Int(truncatingIfNeeded: hasher.finalize()))
expectEqual(expected, output, "input: \(input)")
}
diff --git a/validation-test/stdlib/SetAnyHashableExtensions.swift b/validation-test/stdlib/SetAnyHashableExtensions.swift
index 3ab8cea..54ef1f7 100644
--- a/validation-test/stdlib/SetAnyHashableExtensions.swift
+++ b/validation-test/stdlib/SetAnyHashableExtensions.swift
@@ -28,28 +28,45 @@
SetTests.test("contains<Hashable>(_:)") {
let s: Set<AnyHashable> = [
- AnyHashable(1010), AnyHashable(2020), AnyHashable(3030.0)
+ AnyHashable(1010 as UInt16), AnyHashable(2020), AnyHashable(3030.0)
]
- expectTrue(s.contains(1010))
- expectTrue(s.contains(2020))
- expectTrue(s.contains(3030.0))
+ for i in [1010, 2020, 3030] {
+ // We must be able to look up the same number in any representation.
+ expectTrue(s.contains(UInt16(i)))
+ expectTrue(s.contains(UInt32(i)))
+ expectTrue(s.contains(UInt64(i)))
+ expectTrue(s.contains(UInt(i)))
+ expectTrue(s.contains(Int16(i)))
+ expectTrue(s.contains(Int32(i)))
+ expectTrue(s.contains(Int64(i)))
+ expectTrue(s.contains(Int(i)))
+ expectTrue(s.contains(Float(i)))
+ expectTrue(s.contains(Double(i)))
- expectFalse(s.contains(1010.0))
- expectFalse(s.contains(2020.0))
- expectFalse(s.contains(3030))
+ expectFalse(s.contains(String(i)))
+ }
}
SetTests.test("index<Hashable>(of:)") {
- let s: Set<AnyHashable> = [
- AnyHashable(1010), AnyHashable(2020), AnyHashable(3030.0)
- ]
- expectEqual(AnyHashable(1010), s[s.firstIndex(of: 1010)!])
- expectEqual(AnyHashable(2020), s[s.firstIndex(of: 2020)!])
- expectEqual(AnyHashable(3030.0), s[s.firstIndex(of: 3030.0)!])
+ let a = AnyHashable(1010 as UInt16)
+ let b = AnyHashable(2020)
+ let c = AnyHashable(3030.0)
+ let s: Set<AnyHashable> = [a, b, c]
+ for (element, i) in [(a, 1010), (b, 2020), (c, 3030)] {
+ let index = s.firstIndex(of: element)!
- expectNil(s.firstIndex(of: 1010.0))
- expectNil(s.firstIndex(of: 2020.0))
- expectNil(s.firstIndex(of: 3030))
+ // We must be able to look up the same number in any representation.
+ expectEqual(index, s.firstIndex(of: UInt16(i)))
+ expectEqual(index, s.firstIndex(of: UInt32(i)))
+ expectEqual(index, s.firstIndex(of: UInt64(i)))
+ expectEqual(index, s.firstIndex(of: UInt(i)))
+ expectEqual(index, s.firstIndex(of: Int16(i)))
+ expectEqual(index, s.firstIndex(of: Int32(i)))
+ expectEqual(index, s.firstIndex(of: Int64(i)))
+ expectEqual(index, s.firstIndex(of: Int(i)))
+ expectEqual(index, s.firstIndex(of: Float(i)))
+ expectEqual(index, s.firstIndex(of: Double(i)))
+ }
}
SetTests.test("insert<Hashable>(_:)") {
@@ -230,5 +247,28 @@
s.remove(TestHashableDerivedB(2020, identity: 2))
}
+SetTests.test("Hashable/Conversions") {
+ let input: [Set<AnyHashable>] = [
+ [10 as UInt8, 20 as UInt8, 30 as UInt8],
+ [10 as UInt16, 20 as UInt16, 30 as UInt16],
+ [10 as UInt32, 20 as UInt32, 30 as UInt32],
+ [10 as UInt64, 20 as UInt64, 30 as UInt64],
+ [10 as UInt, 20 as UInt, 30 as UInt],
+ [10 as Int8, 20 as Int8, 30 as Int8],
+ [10 as Int16, 20 as Int16, 30 as Int16],
+ [10 as Int32, 20 as Int32, 30 as Int32],
+ [10 as Int64, 20 as Int64, 30 as Int64],
+ [10 as Int, 20 as Int, 30 as Int],
+ [10 as Float, 20 as Float, 30 as Float],
+ [10 as Double, 20 as Double, 30 as Double],
+ [[1, 2, 3] as Set<Int>, [2, 3, 4] as Set<UInt8>, [3, 4, 5] as Set<Float>],
+ [[1, 2, 3] as Set<Int8>, [2, 3, 4] as Set<Double>, [3, 4, 5] as Set<Int32>],
+ [[1, 2, 3] as Set<UInt32>, [2, 3, 4] as Set<Int16>, [3, 4, 5] as Set<UInt>],
+ ]
+
+ checkHashable(input, equalityOracle: { ($0 < 12) == ($1 < 12) })
+}
+
+
runAllTests()