Merge pull request #21421 from harlanhaskins/oops-indeed-5.0
[5.0] [TBDGen] Allow #warning/#error in protocols
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e4ce32..80380e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,12 +23,49 @@
Swift 5.0
---------
+
+* Swift 3 mode has been removed. Supported values for the `-swift-version`
+ flag are `4`, `4.2`, and `5`.
+
+* [SE-0228][]:
+
+ String interpolation has been overhauled to improve its performance,
+ clarity, and efficiency.
+
+ Note that the old `_ExpressibleByStringInterpolation` protocol has been
+ removed; any code making use of this protocol will need to be updated
+ for the new design. An `#if compiler` block can be used to conditionalize
+ code between 4.2 and 5.0, for example:
+
+ ```swift
+ #if compiler(<5.0)
+ extension MyType : _ExpressibleByStringInterpolation { ... }
+ #else
+ extension MyType : ExpressibleByStringInterpolation { ... }
+ #endif
+ ```
+
+* [SE-0213][]:
+
+ If `T` conforms to one of the `ExpressibleBy*` protocols and `literal` is a
+ literal expression, then `T(literal)` will construct a literal of type `T`
+ using the corresponding protocol, rather than calling a constructor member
+ of `T` with a value of the protocol's default literal type.
+
+ For example, expressions like `UInt64(0xffff_ffff_ffff_ffff)` are now valid,
+ where previously they would overflow the default integer literal type of `Int`.
+
+* [SE-0230][]:
+
+ In Swift 5 mode, `try?` with an expression of Optional type will flatten the
+ resulting Optional, instead of returning an Optional of an Optional.
+
* [SR-5719][]:
- Starting from `-swift-version 5`, implicit `@autoclosure` function type
- forwarding has been disabled, and new a diagnostic has been added suggesting
- to add `()` to call the function value in such case. The call itself would be
- wrapped in an implicit closure and passed to the corresponding parameter.
+ In Swift 5 mode, `@autoclosure` parameters can no longer be forwarded to
+ `@autoclosure` arguments in another function call. Instead, you must explicitly
+ call the function value with `()`; the call itself is wrapped inside an
+ implicit closure, guaranteeing the same behavior as in Swift 4 mode.
Example:
@@ -40,6 +77,56 @@
}
```
+* [SR-8109][]:
+
+ Single-element labeled tuple expressions, for example `(label: 123)`, were
+ allowed in some contexts but often resulted in surprising, inconsistent
+ behavior that varied across compiler releases. They are now completely
+ disallowed.
+
+ Note that single-element labeled _types_, for example `var x: (label: Int)`,
+ have already been prohibited since Swift 3.
+
+* [SR-695][]:
+
+ In Swift 5 mode, a class method returning `Self` can no longer be overridden
+ with a method returning a non-final concrete class type. Such code is not
+ type safe and will need to be updated.
+
+ For example,
+
+ ```swift
+ class Base {
+ class func factory() -> Self { ... }
+ }
+
+ class Derived : Base {
+ class override func factory() -> Derived { ... }
+ }
+ ```
+
+* In Swift 5 mode, the type of `self` in a convenience initializer of a non-final
+ class is now the dynamic `Self` type, and not the concrete class type.
+
+* [SR-5581][]:
+
+ Protocols can now constrain their conforming types to those that subclasses a
+ given class. Two equivalent forms are supported:
+
+ ```swift
+ protocol MyView : UIView { ... }
+ protocol MyView where Self : UIView { ... }
+ ```
+
+ Note that Swift 4.2 accepted the second form, but it was not fully implemented
+ and could sometimes crash at compile time or run time.
+
+* [SR-631][]:
+
+ Extension binding now supports extensions of nested types which themselves are
+ defined inside extensions. Previously this could fail with some declaration orders,
+ producing spurious "undeclared type" errors.
+
* [SR-7139][]:
Exclusive memory access is now enforced at runtime by default in
@@ -129,7 +216,7 @@
* [SE-0214][]:
- Renamed the `DictionaryLiteral` type to `KeyValuePairs`.
+ The `DictionaryLiteral` type has been renamed to `KeyValuePairs`.
A typealias preserves the old name for compatibility.
* [SR-2608][]
@@ -137,8 +224,16 @@
Default arguments are now printed in SourceKit-generated interfaces for Swift
modules, instead of just using a placeholder `default`.
-* Notable bug fix: unowned and unowned(unsafe) variables now support optional
- types.
+* `unowned` and `unowned(unsafe)` variables now support Optional types.
+
+* Designated initializers with variadic parameters are now correctly inherited
+ in subclasses.
+
+* Extensions of concrete subclasses of generic classes can now contain
+ `@objc` members.
+
+* Complex recursive type definitions involving classes and generics that would
+ previously cause deadlocks at run time are now fully supported.
* [SR-419][]
@@ -7309,9 +7404,13 @@
[SE-0225]: <https://github.com/apple/swift-evolution/blob/master/proposals/0225-binaryinteger-iseven-isodd-ismultiple.md>
[SE-0226]: <https://github.com/apple/swift-evolution/blob/master/proposals/0226-package-manager-target-based-dep-resolution.md>
[SE-0227]: <https://github.com/apple/swift-evolution/blob/master/proposals/0227-identity-keypath.md>
+[SE-0228]: <https://github.com/apple/swift-evolution/blob/master/proposals/0228-fix-expressiblebystringinterpolation.md>
+[SE-0230]: <https://github.com/apple/swift-evolution/blob/master/proposals/0230-flatten-optional-try.md>
[SR-106]: <https://bugs.swift.org/browse/SR-106>
[SR-419]: <https://bugs.swift.org/browse/SR-419>
+[SR-631]: <https://bugs.swift.org/browse/SR-631>
+[SR-695]: <https://bugs.swift.org/browse/SR-695>
[SR-1009]: <https://bugs.swift.org/browse/SR-1009>
[SR-1446]: <https://bugs.swift.org/browse/SR-1446>
[SR-1529]: <https://bugs.swift.org/browse/SR-1529>
@@ -7320,6 +7419,8 @@
[SR-2394]: <https://bugs.swift.org/browse/SR-2394>
[SR-2608]: <https://bugs.swift.org/browse/SR-2608>
[SR-4248]: <https://bugs.swift.org/browse/SR-4248>
+[SR-5581]: <https://bugs.swift.org/browse/SR-5581>
+[SR-5719]: <https://bugs.swift.org/browse/SR-5719>
[SR-7139]: <https://bugs.swift.org/browse/SR-7139>
[SR-7251]: <https://bugs.swift.org/browse/SR-7251>
-[SR-5719]: <https://bugs.swift.org/browse/SR-5719>
+[SR-8109]: <https://bugs.swift.org/browse/SR-8109>
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 3d30e7d..e23ae1e 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -432,12 +432,14 @@
# we need to add the math library, which is linked implicitly by libc++.
list(APPEND result "-nostdlib++" "-lm")
if("${LFLAGS_ARCH}" MATCHES armv7)
- list(APPEND result "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so")
+ set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a")
elseif("${LFLAGS_ARCH}" MATCHES aarch64)
- list(APPEND result "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so")
+ set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a")
else()
message(SEND_ERROR "unknown architecture (${LFLAGS_ARCH}) for android")
endif()
+ list(APPEND link_libraries "${android_libcxx_path}/libc++abi.a")
+ list(APPEND link_libraries "${android_libcxx_path}/libc++_shared.so")
swift_android_lib_for_arch(${LFLAGS_ARCH} ${LFLAGS_ARCH}_LIB)
foreach(path IN LISTS ${LFLAGS_ARCH}_LIB)
list(APPEND library_search_directories ${path})
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 1f44445..41829c7 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -633,7 +633,7 @@
::
concrete-protocol-conformance ::= type protocol-conformance-ref any-protocol-conformance-list 'HC'
- protocol-conformance-ref ::= protocol module?
+ protocol-conformance-ref ::= protocol module? 'HP'
any-protocol-conformance ::= concrete-protocol-conformance
any-protocol-conformance ::= dependent-protocol-conformance
diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h
index c8253a2..7d610e4 100644
--- a/include/swift/AST/Type.h
+++ b/include/swift/AST/Type.h
@@ -647,7 +647,8 @@
template<> struct DenseMapInfo<swift::CanType>
: public DenseMapInfo<swift::Type> {
static swift::CanType getEmptyKey() {
- return swift::CanType(nullptr);
+ return swift::CanType(llvm::DenseMapInfo<swift::
+ TypeBase*>::getEmptyKey());
}
static swift::CanType getTombstoneKey() {
return swift::CanType(llvm::DenseMapInfo<swift::
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index d3f0857..c752958 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -5281,6 +5281,7 @@
inline bool CanType::isActuallyCanonicalOrNull() const {
return getPointer() == nullptr ||
+ getPointer() == llvm::DenseMapInfo<TypeBase *>::getEmptyKey() ||
getPointer() == llvm::DenseMapInfo<TypeBase *>::getTombstoneKey() ||
getPointer()->isCanonical();
}
diff --git a/include/swift/Demangling/Demangler.h b/include/swift/Demangling/Demangler.h
index ea52235..b416b7e 100644
--- a/include/swift/Demangling/Demangler.h
+++ b/include/swift/Demangling/Demangler.h
@@ -458,7 +458,7 @@
NodePointer getDependentGenericParamType(int depth, int index);
NodePointer demangleGenericParamIndex();
NodePointer popProtocolConformance();
- NodePointer popProtocolConformanceRef();
+ NodePointer demangleProtocolConformanceRef();
NodePointer popAnyProtocolConformance();
NodePointer demangleConcreteProtocolConformance();
NodePointer popDependentProtocolConformance();
diff --git a/include/swift/Migrator/Migrator.h b/include/swift/Migrator/Migrator.h
index a43ef1a..8f88559 100644
--- a/include/swift/Migrator/Migrator.h
+++ b/include/swift/Migrator/Migrator.h
@@ -31,6 +31,11 @@
bool updateCodeAndEmitRemapIfNeeded(CompilerInstance *Instance,
const CompilerInvocation &Invocation);
+/// Specify options when running syntactic migration pass.
+struct SyntacticPassOptions {
+ bool RunOptionalTryMigration = false;
+};
+
struct Migrator {
CompilerInstance *StartInstance;
const CompilerInvocation &StartInvocation;
@@ -69,7 +74,7 @@
/// Returns true if failed:
/// - Setting up the Swift CompilerInstance failed.
/// - performSema emitted fatal errors along the way.
- bool performSyntacticPasses();
+ bool performSyntacticPasses(SyntacticPassOptions Opts);
/// Emit a replacement map from the very start state's output text to the
/// final state's output text to the StartInvocation's output file.
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index fd2f0e2..d009098 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -2293,6 +2293,8 @@
// are global anyway.
if (isRetroactiveConformance(conformance))
appendModule(conformance->getDeclContext()->getParentModule());
+
+ appendOperator("HP");
}
/// Retrieve the index of the conformance requirement indicated by the
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 69e6f8d..2cd878c 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -104,6 +104,7 @@
result.OmitNameOfInaccessibleProperties = true;
result.FunctionDefinitions = true;
result.CollapseSingleGetterProperty = false;
+ result.VarInitializers = true;
result.FunctionBody = [](const ValueDecl *decl, ASTPrinter &printer) {
auto AFD = dyn_cast<AbstractFunctionDecl>(decl);
@@ -2099,20 +2100,19 @@
}
if (Options.VarInitializers) {
- // FIXME: Implement once we can pretty-print expressions.
+ auto vd = entry.getAnchoringVarDecl();
+ if (entry.hasInitStringRepresentation() &&
+ vd->isInitExposedToClients()) {
+ SmallString<128> scratch;
+ Printer << " = " << entry.getInitStringRepresentation(scratch);
+ }
}
- auto vd = entry.getAnchoringVarDecl();
- if (entry.hasInitStringRepresentation() &&
- vd->isInitExposedToClients()) {
- SmallString<128> scratch;
- Printer << " = " << entry.getInitStringRepresentation(scratch);
- }
-
- // HACK: If we're just printing a single pattern and it has accessors,
- // print the accessors here.
- if (decl->getNumPatternEntries() == 1) {
- printAccessors(vd);
+ // If we're just printing a single pattern and it has accessors,
+ // print the accessors here. It is an error to add accessors to a
+ // pattern binding with multiple entries.
+ if (auto var = decl->getSingleVar()) {
+ printAccessors(var);
}
}
}
@@ -3230,7 +3230,7 @@
// Stored variables in Swift source will be picked up by the
// PatternBindingDecl.
if (auto *VD = dyn_cast<VarDecl>(this)) {
- if (!VD->hasClangNode() && VD->getImplInfo().isSimpleStored())
+ if (!VD->hasClangNode() && VD->hasStorage())
return false;
}
@@ -3241,7 +3241,7 @@
auto pattern =
pbd->getPatternList()[0].getPattern()->getSemanticsProvidingPattern();
if (auto named = dyn_cast<NamedPattern>(pattern)) {
- if (!named->getDecl()->getImplInfo().isSimpleStored())
+ if (!named->getDecl()->hasStorage())
return false;
}
}
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index c1e71d0..30831bd 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -24,6 +24,7 @@
#include "swift/AST/Types.h"
#include "swift/Basic/STLExtras.h"
#include <functional>
+#include "GenericSignatureBuilderImpl.h"
using namespace swift;
@@ -667,11 +668,17 @@
!isa<DependentMemberType>(component))
return None;
- // Find the equivalence class for this dependent member type.
- auto equivClass =
- builder.resolveEquivalenceClass(
- Type(component),
- ArchetypeResolutionKind::CompleteWellFormed);
+ // Find the equivalence class for this dependent type.
+ auto resolved = builder.maybeResolveEquivalenceClass(
+ Type(component),
+ ArchetypeResolutionKind::CompleteWellFormed,
+ /*wantExactPotentialArchetype=*/false);
+ if (!resolved) return None;
+
+ if (auto concrete = resolved.getAsConcreteType())
+ return getCanonicalTypeInContext(concrete, builder);
+
+ auto equivClass = resolved.getEquivalenceClass(builder);
if (!equivClass) return None;
if (equivClass->concreteType) {
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 89afeac..ff8e6cc 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -44,6 +44,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
#include <algorithm>
+#include "GenericSignatureBuilderImpl.h"
using namespace swift;
using llvm::DenseMap;
@@ -1856,96 +1857,6 @@
}
}
-class GenericSignatureBuilder::ResolvedType {
- llvm::PointerUnion<PotentialArchetype *, Type> type;
- EquivalenceClass *equivClass;
-
- /// For a type that could not be resolved further unless the given
- /// equivalence class changes.
- ResolvedType(EquivalenceClass *equivClass)
- : type(), equivClass(equivClass) { }
-
-public:
- /// A specific resolved potential archetype.
- ResolvedType(PotentialArchetype *pa)
- : type(pa), equivClass(pa->getEquivalenceClassIfPresent()) { }
-
- /// A resolved type within the given equivalence class.
- ResolvedType(Type type, EquivalenceClass *equivClass)
- : type(type), equivClass(equivClass) {
- assert(type->isTypeParameter() == static_cast<bool>(equivClass) &&
- "type parameters must have equivalence classes");
- }
-
- /// Return an unresolved result, which could be resolved when we
- /// learn more information about the given equivalence class.
- static ResolvedType forUnresolved(EquivalenceClass *equivClass) {
- return ResolvedType(equivClass);
- }
-
- /// Return a result for a concrete type.
- static ResolvedType forConcrete(Type concreteType) {
- return ResolvedType(concreteType, nullptr);
- }
-
- /// Determine whether this result was resolved.
- explicit operator bool() const { return !type.isNull(); }
-
- /// Retrieve the dependent type.
- Type getDependentType(GenericSignatureBuilder &builder) const;
-
- /// Retrieve the concrete type, or a null type if this result doesn't store
- /// a concrete type.
- Type getAsConcreteType() const {
- assert(*this && "Doesn't contain any result");
- if (equivClass) return Type();
- return type.dyn_cast<Type>();
- }
-
- /// Realize a potential archetype for this type parameter.
- PotentialArchetype *realizePotentialArchetype(
- GenericSignatureBuilder &builder);
-
- /// Retrieve the potential archetype, if already known.
- PotentialArchetype *getPotentialArchetypeIfKnown() const {
- return type.dyn_cast<PotentialArchetype *>();
- }
-
- /// Retrieve the equivalence class into which a resolved type refers.
- EquivalenceClass *getEquivalenceClass(
- GenericSignatureBuilder &builder) const {
- assert(*this && "Only for resolved types");
- if (equivClass) return equivClass;
-
- // Create the equivalence class now.
- return type.get<PotentialArchetype *>()
- ->getOrCreateEquivalenceClass(builder);
- }
-
- /// Retrieve the equivalence class into which a resolved type refers.
- EquivalenceClass *getEquivalenceClassIfPresent() const {
- assert(*this && "Only for resolved types");
- if (equivClass) return equivClass;
-
- // Create the equivalence class now.
- return type.get<PotentialArchetype *>()->getEquivalenceClassIfPresent();
- }
-
- /// Retrieve the unresolved result.
- EquivalenceClass *getUnresolvedEquivClass() const {
- assert(!*this);
- return equivClass;
- }
-
- /// Return an unresolved type.
- ///
- /// This loses equivalence-class information that could be useful, which
- /// is unfortunate.
- UnresolvedType getUnresolvedType() const {
- return type;
- }
-};
-
bool EquivalenceClass::recordConformanceConstraint(
GenericSignatureBuilder &builder,
ResolvedType type,
diff --git a/lib/AST/GenericSignatureBuilderImpl.h b/lib/AST/GenericSignatureBuilderImpl.h
new file mode 100644
index 0000000..88467f5
--- /dev/null
+++ b/lib/AST/GenericSignatureBuilderImpl.h
@@ -0,0 +1,107 @@
+//
+// GenericSignatureBuilderImpl.h
+// Swift
+//
+// Created by Doug Gregor on 12/17/18.
+//
+
+#ifndef SWIFT_AST_GENERIC_SIGNATURE_BUILDER_IMPL_H
+#define SWIFT_AST_GENERIC_SIGNATURE_BUILDER_IMPL_H
+
+#include "swift/AST/GenericSignatureBuilder.h"
+
+namespace swift {
+
+class GenericSignatureBuilder::ResolvedType {
+ llvm::PointerUnion<PotentialArchetype *, Type> type;
+ EquivalenceClass *equivClass;
+
+ /// For a type that could not be resolved further unless the given
+ /// equivalence class changes.
+ ResolvedType(EquivalenceClass *equivClass)
+ : type(), equivClass(equivClass) { }
+
+public:
+ /// A specific resolved potential archetype.
+ ResolvedType(PotentialArchetype *pa)
+ : type(pa), equivClass(pa->getEquivalenceClassIfPresent()) { }
+
+ /// A resolved type within the given equivalence class.
+ ResolvedType(Type type, EquivalenceClass *equivClass)
+ : type(type), equivClass(equivClass) {
+ assert(type->isTypeParameter() == static_cast<bool>(equivClass) &&
+ "type parameters must have equivalence classes");
+ }
+
+ /// Return an unresolved result, which could be resolved when we
+ /// learn more information about the given equivalence class.
+ static ResolvedType forUnresolved(EquivalenceClass *equivClass) {
+ return ResolvedType(equivClass);
+ }
+
+ /// Return a result for a concrete type.
+ static ResolvedType forConcrete(Type concreteType) {
+ return ResolvedType(concreteType, nullptr);
+ }
+
+ /// Determine whether this result was resolved.
+ explicit operator bool() const { return !type.isNull(); }
+
+ /// Retrieve the dependent type.
+ Type getDependentType(GenericSignatureBuilder &builder) const;
+
+ /// Retrieve the concrete type, or a null type if this result doesn't store
+ /// a concrete type.
+ Type getAsConcreteType() const {
+ assert(*this && "Doesn't contain any result");
+ if (equivClass) return Type();
+ return type.dyn_cast<Type>();
+ }
+
+ /// Realize a potential archetype for this type parameter.
+ PotentialArchetype *realizePotentialArchetype(
+ GenericSignatureBuilder &builder);
+
+ /// Retrieve the potential archetype, if already known.
+ PotentialArchetype *getPotentialArchetypeIfKnown() const {
+ return type.dyn_cast<PotentialArchetype *>();
+ }
+
+ /// Retrieve the equivalence class into which a resolved type refers.
+ EquivalenceClass *getEquivalenceClass(
+ GenericSignatureBuilder &builder) const {
+ assert(*this && "Only for resolved types");
+ if (equivClass) return equivClass;
+
+ // Create the equivalence class now.
+ return type.get<PotentialArchetype *>()
+ ->getOrCreateEquivalenceClass(builder);
+ }
+
+ /// Retrieve the equivalence class into which a resolved type refers.
+ EquivalenceClass *getEquivalenceClassIfPresent() const {
+ assert(*this && "Only for resolved types");
+ if (equivClass) return equivClass;
+
+ // Create the equivalence class now.
+ return type.get<PotentialArchetype *>()->getEquivalenceClassIfPresent();
+ }
+
+ /// Retrieve the unresolved result.
+ EquivalenceClass *getUnresolvedEquivClass() const {
+ assert(!*this);
+ return equivClass;
+ }
+
+ /// Return an unresolved type.
+ ///
+ /// This loses equivalence-class information that could be useful, which
+ /// is unfortunate.
+ UnresolvedType getUnresolvedType() const {
+ return type;
+ }
+};
+
+} // end namepsace swift
+
+#endif // SWIFT_AST_GENERIC_SIGNATURE_BUILDER_IMPL_H
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index 6f46836..61a8866 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -249,6 +249,24 @@
break;
}
+ // Prefer declarations in the any module over those in the standard
+ // library module.
+ if (auto swiftModule = ctx.getStdlibModule()) {
+ if ((firstModule == swiftModule) != (secondModule == swiftModule)) {
+ // If the second module is the standard library module, the second
+ // declaration is shadowed by the first.
+ if (secondModule == swiftModule) {
+ shadowed.insert(secondDecl);
+ continue;
+ }
+
+ // Otherwise, the first declaration is shadowed by the second. There is
+ // no point in continuing to compare the first declaration to others.
+ shadowed.insert(firstDecl);
+ break;
+ }
+ }
+
// Prefer declarations in an overlay to similar declarations in
// the Clang module it customizes.
if (firstDecl->hasClangNode() != secondDecl->hasClangNode()) {
@@ -331,26 +349,33 @@
}
}
- // We need an interface type here.
- if (typeResolver)
- typeResolver->resolveDeclSignature(decl);
+ CanType signature;
- // If the decl is currently being validated, this is likely a recursive
- // reference and we'll want to skip ahead so as to avoid having its type
- // attempt to desugar itself.
- if (!decl->hasValidSignature())
+ if (!isa<TypeDecl>(decl)) {
+ // We need an interface type here.
+ if (typeResolver)
+ typeResolver->resolveDeclSignature(decl);
+
+ // If the decl is currently being validated, this is likely a recursive
+ // reference and we'll want to skip ahead so as to avoid having its type
+ // attempt to desugar itself.
+ if (!decl->hasValidSignature())
+ continue;
+
+ // FIXME: the canonical type makes a poor signature, because we don't
+ // canonicalize away default arguments.
+ signature = decl->getInterfaceType()->getCanonicalType();
+
+ // FIXME: The type of a variable or subscript doesn't include
+ // enough context to distinguish entities from different
+ // constrained extensions, so use the overload signature's
+ // type. This is layering a partial fix upon a total hack.
+ if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
+ signature = asd->getOverloadSignatureType();
+ } else if (decl->getDeclContext()->isTypeContext()) {
+ // Do not apply shadowing rules for member types.
continue;
-
- // FIXME: the canonical type makes a poor signature, because we don't
- // canonicalize away default arguments.
- auto signature = decl->getInterfaceType()->getCanonicalType();
-
- // FIXME: The type of a variable or subscript doesn't include
- // enough context to distinguish entities from different
- // constrained extensions, so use the overload signature's
- // type. This is layering a partial fix upon a total hack.
- if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
- signature = asd->getOverloadSignatureType();
+ }
// Record this declaration based on its signature.
auto &known = collisions[signature];
@@ -1169,6 +1194,11 @@
lookupInModule(&M, {}, Name, CurModuleResults, NLKind::UnqualifiedLookup,
resolutionKind, TypeResolver, DC, extraImports);
+ // Always perform name shadowing for type lookup.
+ if (options.contains(Flags::TypeLookup)) {
+ removeShadowedDecls(CurModuleResults, &M);
+ }
+
for (auto VD : CurModuleResults)
Results.push_back(LookupResultEntry(VD));
diff --git a/lib/ClangImporter/MappedTypes.def b/lib/ClangImporter/MappedTypes.def
index 0fd435a..9afc664 100644
--- a/lib/ClangImporter/MappedTypes.def
+++ b/lib/ClangImporter/MappedTypes.def
@@ -161,6 +161,9 @@
// CoreFoundation types.
// Note that we're preserving the typealias for CFIndex.
+MAP_STDLIB_TYPE("CFTypeID", UnsignedWord, 0, "UInt", false, DefineAndUse)
+MAP_STDLIB_TYPE("CFOptionFlags", UnsignedWord, 0, "UInt", false, DefineAndUse)
+MAP_STDLIB_TYPE("CFHashCode", UnsignedWord, 0, "UInt", false, DefineAndUse)
MAP_STDLIB_TYPE("CFIndex", SignedWord, 0, "Int", false, DefineAndUse)
// Foundation types.
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index dd9b798..d9729b7 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -610,6 +610,7 @@
case 'C': return demangleConcreteProtocolConformance();
case 'D': return demangleDependentProtocolConformanceRoot();
case 'I': return demangleDependentProtocolConformanceInherited();
+ case 'P': return demangleProtocolConformanceRef();
default:
pushBack();
pushBack();
@@ -1294,7 +1295,7 @@
});
}
-NodePointer Demangler::popProtocolConformanceRef() {
+NodePointer Demangler::demangleProtocolConformanceRef() {
NodePointer module = popModule();
NodePointer proto = popProtocol();
auto protocolConformanceRef =
@@ -1309,7 +1310,7 @@
NodePointer Demangler::demangleConcreteProtocolConformance() {
NodePointer conditionalConformanceList = popAnyProtocolConformanceList();
- NodePointer conformanceRef = popProtocolConformanceRef();
+ NodePointer conformanceRef = popNode(Node::Kind::ProtocolConformanceRef);
NodePointer type = popNode(Node::Kind::Type);
return createWithChildren(Node::Kind::ConcreteProtocolConformance,
type, conformanceRef, conditionalConformanceList);
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 5f6afbb..0f61baf 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -1657,6 +1657,7 @@
manglePureProtocol(node->getChild(0));
if (node->getNumChildren() > 1)
mangleChildNode(node, 1);
+ Buffer << "HP";
}
void Remangler::mangleConcreteProtocolConformance(Node *node) {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 9d900ef..c00be92 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1079,8 +1079,11 @@
return false;
}
-static std::string getScriptFileName(StringRef name) {
- return (Twine(name) + "4" + ".json").str();
+static std::string getScriptFileName(StringRef name, version::Version &ver) {
+ if (ver.isVersionAtLeast(4, 2))
+ return (Twine(name) + "42" + ".json").str();
+ else
+ return (Twine(name) + "4" + ".json").str();
}
static bool ParseMigratorArgs(MigratorOptions &Opts,
@@ -1124,20 +1127,20 @@
bool Supported = true;
llvm::SmallString<128> dataPath(basePath);
-
+ auto &langVer = LangOpts.EffectiveLanguageVersion;
if (Triple.isMacOSX())
- llvm::sys::path::append(dataPath, getScriptFileName("macos"));
+ llvm::sys::path::append(dataPath, getScriptFileName("macos", langVer));
else if (Triple.isiOS())
- llvm::sys::path::append(dataPath, getScriptFileName("ios"));
+ llvm::sys::path::append(dataPath, getScriptFileName("ios", langVer));
else if (Triple.isTvOS())
- llvm::sys::path::append(dataPath, getScriptFileName("tvos"));
+ llvm::sys::path::append(dataPath, getScriptFileName("tvos", langVer));
else if (Triple.isWatchOS())
- llvm::sys::path::append(dataPath, getScriptFileName("watchos"));
+ llvm::sys::path::append(dataPath, getScriptFileName("watchos", langVer));
else
Supported = false;
if (Supported) {
llvm::SmallString<128> authoredDataPath(basePath);
- llvm::sys::path::append(authoredDataPath, getScriptFileName("overlay"));
+ llvm::sys::path::append(authoredDataPath, getScriptFileName("overlay", langVer));
// Add authored list first to take higher priority.
Opts.APIDigesterDataStorePaths.push_back(authoredDataPath.str());
Opts.APIDigesterDataStorePaths.push_back(dataPath.str());
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index bbe3496..69023b0 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -1099,30 +1099,8 @@
while (!LazyTypeMetadata.empty() ||
!LazyTypeContextDescriptors.empty() ||
!LazyFunctionDefinitions.empty() ||
- !LazyFieldTypes.empty() ||
!LazyWitnessTables.empty()) {
- while (!LazyFieldTypes.empty()) {
- auto info = LazyFieldTypes.pop_back_val();
- auto &IGM = *info.IGM;
-
- for (auto fieldType : info.fieldTypes) {
- if (fieldType->hasArchetype())
- continue;
-
- // All of the required attributes are going to be preserved
- // by field reflection metadata in the mangled name, so
- // there is no need to worry about ownership semantics here.
- if (auto refStorTy = dyn_cast<ReferenceStorageType>(fieldType))
- fieldType = refStorTy.getReferentType();
-
- // Make sure that all of the field type metadata is forced,
- // otherwise there might be a problem when fields are accessed
- // through reflection.
- (void)irgen::getOrCreateTypeMetadataAccessFunction(IGM, fieldType);
- }
- }
-
// Emit any lazy type metadata we require.
while (!LazyTypeMetadata.empty()) {
NominalTypeDecl *type = LazyTypeMetadata.pop_back_val();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 08d9344..2b43e02 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1198,37 +1198,6 @@
}
return numFields;
}
-
- /// Track the field types of a struct or class for reflection metadata
- /// emission.
- static void
- addFieldTypes(IRGenModule &IGM, NominalTypeDecl *type,
- NominalTypeDecl::StoredPropertyRange storedProperties) {
- SmallVector<CanType, 4> types;
- for (VarDecl *prop : storedProperties) {
- auto propertyType = type->mapTypeIntoContext(prop->getInterfaceType())
- ->getCanonicalType();
- types.push_back(propertyType);
- }
-
- IGM.addFieldTypes(types);
- }
-
- /// Track the payload types of an enum for reflection metadata
- /// emission.
- static void addFieldTypes(IRGenModule &IGM,
- ArrayRef<EnumImplStrategy::Element> enumElements) {
- SmallVector<CanType, 4> types;
-
- for (auto &elt : enumElements) {
- auto caseType = elt.decl->getParentEnum()->mapTypeIntoContext(
- elt.decl->getArgumentInterfaceType())
- ->getCanonicalType();
- types.push_back(caseType);
- }
-
- IGM.addFieldTypes(types);
- }
class StructContextDescriptorBuilder
: public TypeContextDescriptorBuilderBase<StructContextDescriptorBuilder,
@@ -1264,7 +1233,9 @@
// uint32_t FieldOffsetVectorOffset;
B.addInt32(FieldVectorOffset / IGM.getPointerSize());
- addFieldTypes(IGM, getType(), properties);
+ // For any nominal type metadata required for reflection.
+ for (auto *prop : properties)
+ IGM.IRGen.noteUseOfTypeMetadata(prop->getValueInterfaceType());
}
uint16_t getKindSpecificFlags() {
@@ -1336,7 +1307,9 @@
// uint32_t NumEmptyCases;
B.addInt32(Strategy.getElementsWithNoPayload().size());
- addFieldTypes(IGM, Strategy.getElementsWithPayload());
+ // For any nominal type metadata required for reflection.
+ for (auto elt : Strategy.getElementsWithPayload())
+ IGM.IRGen.noteUseOfTypeMetadata(elt.decl->getArgumentInterfaceType());
}
uint16_t getKindSpecificFlags() {
@@ -1646,7 +1619,9 @@
// uint32_t FieldOffsetVectorOffset;
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
- addFieldTypes(IGM, getType(), properties);
+ // For any nominal type metadata required for reflection.
+ for (auto *prop : properties)
+ IGM.IRGen.noteUseOfTypeMetadata(prop->getValueInterfaceType());
}
};
} // end anonymous namespace
@@ -1772,10 +1747,6 @@
[&]{ AnonymousContextDescriptorBuilder(*this, DC).emit(); });
}
-void IRGenModule::addFieldTypes(ArrayRef<CanType> fieldTypes) {
- IRGen.addFieldTypes(fieldTypes, this);
-}
-
static void emitInitializeFieldOffsetVector(IRGenFunction &IGF,
SILType T,
llvm::Value *metadata,
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 6d41125..47de693 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -241,14 +241,6 @@
llvm::SetVector<SILFunction*> DynamicReplacements;
- struct FieldTypeMetadata {
- IRGenModule *IGM;
- std::vector<CanType> fieldTypes;
- };
-
- /// Field types we need to verify are present.
- llvm::SmallVector<FieldTypeMetadata, 4> LazyFieldTypes;
-
/// SIL functions that we need to emit lazily.
llvm::SmallVector<SILFunction*, 4> LazyFunctionDefinitions;
@@ -367,6 +359,13 @@
noteUseOfTypeGlobals(type, true, RequireMetadata);
}
+ void noteUseOfTypeMetadata(Type type) {
+ type.visit([&](Type t) {
+ if (auto *nominal = t->getAnyNominal())
+ noteUseOfTypeMetadata(nominal);
+ });
+ }
+
void noteUseOfTypeContextDescriptor(NominalTypeDecl *type,
RequireMetadata_t requireMetadata) {
noteUseOfTypeGlobals(type, false, requireMetadata);
@@ -386,9 +385,6 @@
/// Adds \p Conf to LazyWitnessTables if it has not been added yet.
void addLazyWitnessTable(const ProtocolConformance *Conf);
- void addFieldTypes(ArrayRef<CanType> fieldTypes, IRGenModule *IGM) {
- LazyFieldTypes.push_back({IGM, {fieldTypes.begin(), fieldTypes.end()}});
- }
void addClassForEagerInitialization(ClassDecl *ClassDecl);
@@ -850,7 +846,6 @@
void addUsedGlobal(llvm::GlobalValue *global);
void addCompilerUsedGlobal(llvm::GlobalValue *global);
void addObjCClass(llvm::Constant *addr, bool nonlazy);
- void addFieldTypes(ArrayRef<CanType> fieldTypes);
void addProtocolConformance(ConformanceDescription &&conformance);
llvm::Constant *emitSwiftProtocols();
diff --git a/lib/Migrator/CMakeLists.txt b/lib/Migrator/CMakeLists.txt
index 1b28f1f..c7ad2c7 100644
--- a/lib/Migrator/CMakeLists.txt
+++ b/lib/Migrator/CMakeLists.txt
@@ -4,6 +4,11 @@
tvos4.json
watchos4.json
overlay4.json
+ macos42.json
+ ios42.json
+ tvos42.json
+ watchos42.json
+ overlay42.json
)
set(SWIFTLIB_DIR
"${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib/swift")
diff --git a/lib/Migrator/Migrator.cpp b/lib/Migrator/Migrator.cpp
index afa0696..d324289 100644
--- a/lib/Migrator/Migrator.cpp
+++ b/lib/Migrator/Migrator.cpp
@@ -59,7 +59,11 @@
// Phase 2: Syntactic Transformations
// Don't run these passes if we're already in newest Swift version.
if (EffectiveVersion != CurrentVersion) {
- auto FailedSyntacticPasses = M.performSyntacticPasses();
+ SyntacticPassOptions Opts;
+
+ // Type of optional try changes since Swift 5.
+ Opts.RunOptionalTryMigration = !EffectiveVersion.isVersionAtLeast(5);
+ auto FailedSyntacticPasses = M.performSyntacticPasses(Opts);
if (FailedSyntacticPasses) {
return true;
}
@@ -173,7 +177,7 @@
return Instance;
}
-bool Migrator::performSyntacticPasses() {
+bool Migrator::performSyntacticPasses(SyntacticPassOptions Opts) {
clang::FileSystemOptions ClangFileSystemOptions;
clang::FileManager ClangFileManager { ClangFileSystemOptions };
@@ -197,8 +201,10 @@
runAPIDiffMigratorPass(Editor, StartInstance->getPrimarySourceFile(),
getMigratorOptions());
- runOptionalTryMigratorPass(Editor, StartInstance->getPrimarySourceFile(),
- getMigratorOptions());
+ if (Opts.RunOptionalTryMigration) {
+ runOptionalTryMigratorPass(Editor, StartInstance->getPrimarySourceFile(),
+ getMigratorOptions());
+ }
Edits.commit(Editor.getEdits());
diff --git a/lib/Migrator/ios42.json b/lib/Migrator/ios42.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/lib/Migrator/ios42.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/lib/Migrator/macos42.json b/lib/Migrator/macos42.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/lib/Migrator/macos42.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/lib/Migrator/overlay4.json b/lib/Migrator/overlay4.json
index c5475de..d5fb336 100644
--- a/lib/Migrator/overlay4.json
+++ b/lib/Migrator/overlay4.json
@@ -1320,5 +1320,16 @@
"DiffItemKind": "SpecialCaseDiffItem",
"Usr": "s:5UIKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSgSSSgAJtF",
"SpecialCaseId": "UIApplicationMain"
- }
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "Rename",
+ "ChildIndex": "0",
+ "LeftUsr": "s:SlsSQ7ElementRpzrlE5index2of5IndexQzSgAB_tF",
+ "LeftComment": "index",
+ "RightUsr": "",
+ "RightComment": "firstIndex",
+ "ModuleName": "Swift"
+ },
]
diff --git a/lib/Migrator/overlay42.json b/lib/Migrator/overlay42.json
new file mode 100644
index 0000000..cc6d339
--- /dev/null
+++ b/lib/Migrator/overlay42.json
@@ -0,0 +1,13 @@
+[
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "Rename",
+ "ChildIndex": "0",
+ "LeftUsr": "s:SlsSQ7ElementRpzrlE5index2of5IndexQzSgAB_tF",
+ "LeftComment": "index",
+ "RightUsr": "",
+ "RightComment": "firstIndex",
+ "ModuleName": "Swift"
+ },
+]
diff --git a/lib/Migrator/tvos42.json b/lib/Migrator/tvos42.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/lib/Migrator/tvos42.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/lib/Migrator/watchos42.json b/lib/Migrator/watchos42.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/lib/Migrator/watchos42.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
index b63c6ed..33ac9b6 100644
--- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
@@ -1055,7 +1055,7 @@
// Try to speed up the trivial case of single release/dealloc.
if (isa<StrongReleaseInst>(User) || isa<DeallocBoxInst>(User) ||
- isa<DestroyValueInst>(User)) {
+ isa<DestroyValueInst>(User) || isa<ReleaseValueInst>(User)) {
if (!seenRelease)
OneRelease = User;
else
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 7bed4bc..d502b3a 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -403,14 +403,15 @@
// Build and type check the string literal index value to the specific
// string type expected by the subscript.
Expr *nameExpr = new (ctx) StringLiteralExpr(name, loc, /*implicit*/true);
+ (void)cs.TC.typeCheckExpression(nameExpr, dc);
+ cs.cacheExprTypes(nameExpr);
// Build a tuple so that the argument has a label.
Expr *tuple = TupleExpr::create(ctx, loc, nameExpr, ctx.Id_dynamicMember,
loc, loc, /*hasTrailingClosure*/false,
/*implicit*/true);
- (void)cs.TC.typeCheckExpression(tuple, dc, TypeLoc::withoutLoc(ty),
- CTP_CallArgument);
- cs.cacheExprTypes(tuple);
+ cs.setType(tuple, ty);
+ tuple->setType(ty);
return tuple;
}
@@ -2824,23 +2825,14 @@
return simplifyExprType(expr);
}
- Type subExprType = cs.getType(expr->getSubExpr());
- Type targetType = simplifyType(subExprType);
-
- // If the subexpression is not optional, wrap it in
- // an InjectIntoOptionalExpr. Then use the type of the
- // subexpression as the type of the 'try?' expr
- bool subExprIsOptional = (bool) subExprType->getOptionalObjectType();
-
- if (!subExprIsOptional) {
- targetType = OptionalType::get(targetType);
- auto subExpr = coerceToType(expr->getSubExpr(), targetType,
- cs.getConstraintLocator(expr));
- if (!subExpr) return nullptr;
- expr->setSubExpr(subExpr);
- }
-
- cs.setType(expr, targetType);
+ Type exprType = simplifyType(cs.getType(expr));
+
+ auto subExpr = coerceToType(expr->getSubExpr(), exprType,
+ cs.getConstraintLocator(expr));
+ if (!subExpr) return nullptr;
+ expr->setSubExpr(subExpr);
+
+ cs.setType(expr, exprType);
return expr;
}
@@ -4430,13 +4422,17 @@
auto loc = origComponent.getLoc();
auto fieldName =
foundDecl->choice.getName().getBaseIdentifier().str();
- auto index = buildDynamicMemberLookupIndexExpr(fieldName, indexType,
- loc, dc, cs);
-
+
+ Expr *nameExpr = new (ctx) StringLiteralExpr(fieldName, loc,
+ /*implicit*/true);
+ (void)cs.TC.typeCheckExpression(nameExpr, dc);
+ cs.cacheExprTypes(nameExpr);
+
origComponent = KeyPathExpr::Component::
- forUnresolvedSubscript(ctx, loc, index, {}, loc, loc,
- /*trailingClosure*/nullptr);
- cs.setType(origComponent.getIndexExpr(), index->getType());
+ forUnresolvedSubscript(ctx, loc,
+ {nameExpr}, {ctx.Id_dynamicMember}, {loc},
+ loc, /*trailingClosure*/nullptr);
+ cs.setType(origComponent.getIndexExpr(), indexType);
}
auto subscriptType =
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 656f1c8..5100bd6 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -423,6 +423,27 @@
const CalleeCandidateInfo &candidates,
TCCOptions options = TCCOptions());
+ void getPossibleTypesOfExpressionWithoutApplying(
+ Expr *&expr, DeclContext *dc, SmallPtrSetImpl<TypeBase *> &types,
+ FreeTypeVariableBinding allowFreeTypeVariables =
+ FreeTypeVariableBinding::Disallow,
+ ExprTypeCheckListener *listener = nullptr) {
+ CS.TC.getPossibleTypesOfExpressionWithoutApplying(
+ expr, dc, types, allowFreeTypeVariables, listener);
+ CS.cacheExprTypes(expr);
+ }
+
+ Type getTypeOfExpressionWithoutApplying(
+ Expr *&expr, DeclContext *dc, ConcreteDeclRef &referencedDecl,
+ FreeTypeVariableBinding allowFreeTypeVariables =
+ FreeTypeVariableBinding::Disallow,
+ ExprTypeCheckListener *listener = nullptr) {
+ auto type = CS.TC.getTypeOfExpressionWithoutApplying(expr, dc, referencedDecl,
+ allowFreeTypeVariables, listener);
+ CS.cacheExprTypes(expr);
+ return type;
+ }
+
/// Diagnose common failures due to applications of an argument list to an
/// ApplyExpr or SubscriptExpr.
bool diagnoseParameterErrors(CalleeCandidateInfo &CCI,
@@ -452,6 +473,10 @@
Type contextualType,
ContextualTypePurpose CTP);
+ bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
+ CalleeCandidateInfo &CCI,
+ ArrayRef<Identifier> argLabels);
+
private:
/// Validate potential contextual type for type-checking one of the
/// sub-expressions, usually correct/valid types are the ones which
@@ -3194,10 +3219,9 @@
return result;
}
-static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
- CalleeCandidateInfo &CCI,
- ArrayRef<Identifier> argLabels,
- ConstraintSystem &CS) {
+bool FailureDiagnosis::diagnoseImplicitSelfErrors(
+ Expr *fnExpr, Expr *argExpr, CalleeCandidateInfo &CCI,
+ ArrayRef<Identifier> argLabels) {
// If candidate list is empty it means that problem is somewhere else,
// since we need to have candidates which might be shadowing other funcs.
if (CCI.empty() || !CCI[0].getDecl())
@@ -3251,8 +3275,7 @@
for (unsigned i = 0, e = argTuple->getNumElements(); i < e; ++i) {
ConcreteDeclRef ref = nullptr;
auto *el = argTuple->getElement(i);
- auto typeResult =
- TC.getTypeOfExpressionWithoutApplying(el, CS.DC, ref);
+ auto typeResult = getTypeOfExpressionWithoutApplying(el, CS.DC, ref);
if (!typeResult)
return false;
auto flags = ParameterTypeFlags().withInOut(typeResult->is<InOutType>());
@@ -4226,7 +4249,7 @@
}
// Try to diagnose errors related to the use of implicit self reference.
- if (diagnoseImplicitSelfErrors(fnExpr, argExpr, CCI, argLabels, CS))
+ if (diagnoseImplicitSelfErrors(fnExpr, argExpr, CCI, argLabels))
return true;
if (diagnoseInstanceMethodAsCurriedMemberOnType(CCI, fnExpr, argExpr))
@@ -4368,7 +4391,7 @@
ConcreteDeclRef decl = nullptr;
message = diag::cannot_subscript_with_index;
- if (CS.TC.getTypeOfExpressionWithoutApplying(expr, CS.DC, decl))
+ if (getTypeOfExpressionWithoutApplying(expr, CS.DC, decl))
return false;
// If we are down to a single candidate but with an unresolved
@@ -4932,7 +4955,7 @@
if (currentType->hasTypeVariable() || currentType->hasUnresolvedType()) {
auto contextualType = CS.getContextualType();
CallResultListener listener(contextualType);
- CS.TC.getPossibleTypesOfExpressionWithoutApplying(
+ getPossibleTypesOfExpressionWithoutApplying(
fnExpr, CS.DC, possibleTypes, FreeTypeVariableBinding::UnresolvedType,
&listener);
@@ -5037,9 +5060,9 @@
auto &TC = CS.TC;
auto *DC = CS.DC;
- auto typeCheckExpr = [](TypeChecker &TC, Expr *expr, DeclContext *DC,
- SmallPtrSetImpl<TypeBase *> &types) {
- TC.getPossibleTypesOfExpressionWithoutApplying(
+ auto typeCheckExpr = [&](TypeChecker &TC, Expr *expr, DeclContext *DC,
+ SmallPtrSetImpl<TypeBase *> &types) {
+ getPossibleTypesOfExpressionWithoutApplying(
expr, DC, types, FreeTypeVariableBinding::Disallow);
};
@@ -5165,14 +5188,14 @@
// unresolved result let's not re-typecheck the function expression,
// because it might produce unrelated diagnostics due to lack of
// contextual information.
-static bool shouldTypeCheckFunctionExpr(TypeChecker &TC, DeclContext *DC,
+static bool shouldTypeCheckFunctionExpr(FailureDiagnosis &FD, DeclContext *DC,
Expr *fnExpr) {
if (!isa<UnresolvedDotExpr>(fnExpr))
return true;
SmallPtrSet<TypeBase *, 4> fnTypes;
- TC.getPossibleTypesOfExpressionWithoutApplying(fnExpr, DC, fnTypes,
- FreeTypeVariableBinding::UnresolvedType);
+ FD.getPossibleTypesOfExpressionWithoutApplying(
+ fnExpr, DC, fnTypes, FreeTypeVariableBinding::UnresolvedType);
if (fnTypes.size() == 1) {
// Some member types depend on the arguments to produce a result type,
@@ -5232,7 +5255,7 @@
auto *fnExpr = callExpr->getFn();
auto originalFnType = CS.getType(callExpr->getFn());
- if (shouldTypeCheckFunctionExpr(CS.TC, CS.DC, fnExpr)) {
+ if (shouldTypeCheckFunctionExpr(*this, CS.DC, fnExpr)) {
// If we are misusing a subscript, diagnose that and provide a fixit.
// We diagnose this here to have enough context to offer an appropriate fixit.
@@ -5269,7 +5292,7 @@
fnExpr = callExpr->getFn();
SmallPtrSet<TypeBase *, 4> types;
- CS.TC.getPossibleTypesOfExpressionWithoutApplying(fnExpr, CS.DC, types);
+ getPossibleTypesOfExpressionWithoutApplying(fnExpr, CS.DC, types);
auto isFunctionType = [getFuncType](Type type) -> bool {
return type && getFuncType(type)->is<AnyFunctionType>();
@@ -5309,7 +5332,7 @@
"unexpected declaration reference");
ConcreteDeclRef decl = nullptr;
- Type type = CS.TC.getTypeOfExpressionWithoutApplying(
+ Type type = getTypeOfExpressionWithoutApplying(
fnExpr, CS.DC, decl, FreeTypeVariableBinding::UnresolvedType,
&listener);
@@ -5893,7 +5916,7 @@
ExprTypeSaverAndEraser eraser(srcExpr);
ConcreteDeclRef ref = nullptr;
- auto type = CS.TC.getTypeOfExpressionWithoutApplying(srcExpr, CS.DC, ref);
+ auto type = getTypeOfExpressionWithoutApplying(srcExpr, CS.DC, ref);
if (type && !type->isEqual(contextualType))
return diagnoseContextualConversionError(
@@ -6391,7 +6414,7 @@
// diagnose situations where contextual type expected one result
// type but actual closure produces a different one without explicitly
// declaring it (e.g. by using anonymous parameters).
- auto type = CS.TC.getTypeOfExpressionWithoutApplying(
+ auto type = getTypeOfExpressionWithoutApplying(
closure, CS.DC, decl, FreeTypeVariableBinding::Disallow);
if (type && resultTypeProcessor(type, expectedResultType))
@@ -6900,7 +6923,7 @@
KeyPathListener listener(klass, parentType, rootType);
ConcreteDeclRef concreteDecl;
- auto derivedType = CS.TC.getTypeOfExpressionWithoutApplying(
+ auto derivedType = getTypeOfExpressionWithoutApplying(
expr, CS.DC, concreteDecl, FreeTypeVariableBinding::Disallow,
&listener);
@@ -8058,7 +8081,7 @@
// successfully type-checked its type cleanup is going to be disabled
// (we are allowing unresolved types), and as a side-effect it might
// also be transformed e.g. OverloadedDeclRefExpr -> DeclRefExpr.
- auto type = CS.TC.getTypeOfExpressionWithoutApplying(
+ auto type = getTypeOfExpressionWithoutApplying(
resultExpr, CS.DC, decl, FreeTypeVariableBinding::UnresolvedType);
if (type)
resultType = type;
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 8e7159d..3c030eb 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -3368,6 +3368,20 @@
assert(!isa<ImplicitConversionExpr>(expr) &&
"ImplicitConversionExpr should be eliminated in walkToExprPre");
+ auto buildMemberRef = [&](Type memberType, Expr *base, SourceLoc dotLoc,
+ ConcreteDeclRef member, DeclNameLoc memberLoc,
+ bool implicit) -> Expr * {
+ auto *memberRef = new (TC.Context)
+ MemberRefExpr(base, dotLoc, member, memberLoc, implicit);
+
+ if (memberType) {
+ memberRef->setType(memberType);
+ return CS.cacheType(memberRef);
+ }
+
+ return memberRef;
+ };
+
// A DotSyntaxCallExpr is a member reference that has already been
// type-checked down to a call; turn it back into an overloaded
// member reference expression.
@@ -3377,21 +3391,23 @@
memberLoc);
if (memberAndFunctionRef.first) {
assert(!isa<ImplicitConversionExpr>(dotCall->getBase()));
- return new (TC.Context) MemberRefExpr(dotCall->getBase(),
- dotCall->getDotLoc(),
- memberAndFunctionRef.first,
- memberLoc, expr->isImplicit());
+ return buildMemberRef(dotCall->getType(),
+ dotCall->getBase(),
+ dotCall->getDotLoc(),
+ memberAndFunctionRef.first,
+ memberLoc, expr->isImplicit());
}
}
if (auto *dynamicMember = dyn_cast<DynamicMemberRefExpr>(expr)) {
if (auto memberRef = dynamicMember->getMember()) {
assert(!isa<ImplicitConversionExpr>(dynamicMember->getBase()));
- return new (TC.Context) MemberRefExpr(dynamicMember->getBase(),
- dynamicMember->getDotLoc(),
- memberRef,
- dynamicMember->getNameLoc(),
- expr->isImplicit());
+ return buildMemberRef(dynamicMember->getType(),
+ dynamicMember->getBase(),
+ dynamicMember->getDotLoc(),
+ memberRef,
+ dynamicMember->getNameLoc(),
+ expr->isImplicit());
}
}
@@ -3405,10 +3421,11 @@
memberLoc);
if (memberAndFunctionRef.first) {
assert(!isa<ImplicitConversionExpr>(dotIgnored->getLHS()));
- return new (TC.Context) MemberRefExpr(dotIgnored->getLHS(),
- dotIgnored->getDotLoc(),
- memberAndFunctionRef.first,
- memberLoc, expr->isImplicit());
+ return buildMemberRef(dotIgnored->getType(),
+ dotIgnored->getLHS(),
+ dotIgnored->getDotLoc(),
+ memberAndFunctionRef.first,
+ memberLoc, expr->isImplicit());
}
}
return expr;
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 61b6fe1..99b24e1 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1173,6 +1173,17 @@
!params[0].isVariadic());
};
+ auto canImplodeParams = [&](ArrayRef<AnyFunctionType::Param> params) {
+ if (params.size() == 1)
+ return false;
+
+ for (auto param : params)
+ if (param.isVariadic() || param.isInOut())
+ return false;
+
+ return true;
+ };
+
auto implodeParams = [&](SmallVectorImpl<AnyFunctionType::Param> ¶ms) {
auto input = AnyFunctionType::composeInput(getASTContext(), params,
/*canonicalVararg=*/false);
@@ -1193,21 +1204,18 @@
if (last != path.rend()) {
if (last->getKind() == ConstraintLocator::ApplyArgToParam) {
- if (isSingleParam(func2Params)) {
- if (!isSingleParam(func1Params)) {
- implodeParams(func1Params);
- }
- } else if (getASTContext().isSwiftVersionAtLeast(4)
- && !getASTContext().isSwiftVersionAtLeast(5)
- && !isSingleParam(func2Params)) {
+ if (isSingleParam(func2Params) &&
+ canImplodeParams(func1Params)) {
+ implodeParams(func1Params);
+ } else if (!getASTContext().isSwiftVersionAtLeast(5) &&
+ isSingleParam(func1Params) &&
+ canImplodeParams(func2Params)) {
auto *simplified = locator.trySimplifyToExpr();
// We somehow let tuple unsplatting function conversions
// through in some cases in Swift 4, so let's let that
// continue to work, but only for Swift 4.
if (simplified && isa<DeclRefExpr>(simplified)) {
- if (isSingleParam(func1Params)) {
- implodeParams(func2Params);
- }
+ implodeParams(func2Params);
}
}
}
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 7abc16f..791b63b 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -226,10 +226,10 @@
getter->setImplicit();
// If we're stealing the 'self' from a lazy initializer, set it now.
- if (selfDecl) {
+ // Note that we don't re-parent the 'self' declaration to be part of
+ // the getter until we synthesize the body of the getter later.
+ if (selfDecl)
*getter->getImplicitSelfDeclStorage() = selfDecl;
- selfDecl->setDeclContext(getter);
- }
// We need to install the generic environment here because:
// 1) validating the getter will change the implicit self decl's DC to it,
@@ -1315,6 +1315,7 @@
// Recontextualize any closure declcontexts nested in the initializer to
// realize that they are in the getter function.
+ Get->getImplicitSelfDecl()->setDeclContext(Get);
InitValue->walk(RecontextualizeClosures(Get));
// Wrap the initializer in a LazyInitializerExpr to avoid problems with
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index a7f46c2..d13c775 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -203,10 +203,6 @@
while (auto Conv = dyn_cast<ImplicitConversionExpr>(Base))
Base = Conv->getSubExpr();
- // Record call arguments.
- if (auto Call = dyn_cast<CallExpr>(Base))
- CallArgs.insert(Call->getArg());
-
if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
// Verify metatype uses.
if (isa<TypeDecl>(DRE->getDecl())) {
@@ -235,7 +231,14 @@
if (isa<TypeExpr>(Base))
checkUseOfMetaTypeName(Base);
+ if (auto *TSE = dyn_cast<TupleShuffleExpr>(E)) {
+ if (CallArgs.count(TSE))
+ CallArgs.insert(TSE->getSubExpr());
+ }
+
if (auto *SE = dyn_cast<SubscriptExpr>(E)) {
+ CallArgs.insert(SE->getIndex());
+
// Implicit InOutExpr's are allowed in the base of a subscript expr.
if (auto *IOE = dyn_cast<InOutExpr>(SE->getBase()))
if (IOE->isImplicit())
@@ -248,6 +251,13 @@
});
}
+ if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
+ for (auto Comp : KPE->getComponents()) {
+ if (auto *Arg = Comp.getIndexExpr())
+ CallArgs.insert(Arg);
+ }
+ }
+
if (auto *AE = dyn_cast<CollectionExpr>(E)) {
visitCollectionElements(AE, [&](unsigned argIndex, Expr *arg) {
arg = lookThroughArgument(arg);
@@ -266,6 +276,9 @@
// Check function calls, looking through implicit conversions on the
// function and inspecting the arguments directly.
if (auto *Call = dyn_cast<ApplyExpr>(E)) {
+ // Record call arguments.
+ CallArgs.insert(Call->getArg());
+
// Warn about surprising implicit optional promotions.
checkOptionalPromotions(Call);
@@ -381,6 +394,18 @@
}
}
+ // Diagnose single-element tuple expressions.
+ if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
+ if (!CallArgs.count(tupleExpr)) {
+ if (tupleExpr->getNumElements() == 1) {
+ TC.diagnose(tupleExpr->getElementNameLoc(0),
+ diag::tuple_single_element)
+ .fixItRemoveChars(tupleExpr->getElementNameLoc(0),
+ tupleExpr->getElement(0)->getStartLoc());
+ }
+ }
+ }
+
return { true, E };
}
diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp
index fa82ed3..685300e 100644
--- a/lib/Sema/TypeCheckCaptures.cpp
+++ b/lib/Sema/TypeCheckCaptures.cpp
@@ -283,15 +283,14 @@
// 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;
+ // If we have a getter with a body, we're already re-parented
+ // everything so pretend we're inside the getter.
+ if (auto getter = lazyVar->getGetter()) {
+ if (getter->getBody(/*canSynthesize=*/false)) {
+ TmpDC = getter;
+ continue;
+ }
+ }
}
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 0928bcb..13e4f1a 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -3563,7 +3563,11 @@
/// Validate the underlying type of the given typealias.
static void validateTypealiasType(TypeChecker &tc, TypeAliasDecl *typeAlias) {
- TypeResolutionOptions options(TypeResolverContext::TypeAliasDecl);
+ TypeResolutionOptions options(
+ (typeAlias->getGenericParams() ?
+ TypeResolverContext::GenericTypeAliasDecl :
+ TypeResolverContext::TypeAliasDecl));
+
if (!typeAlias->getDeclContext()->isCascadingContextForLookup(
/*functionsAreNonCascading*/true)) {
options |= TypeResolutionFlags::KnownNonCascadingDependency;
@@ -4566,7 +4570,10 @@
if (typealias->isBeingValidated()) return;
auto helper = [&] {
- TypeResolutionOptions options(TypeResolverContext::TypeAliasDecl);
+ TypeResolutionOptions options(
+ (typealias->getGenericParams() ?
+ TypeResolverContext::GenericTypeAliasDecl :
+ TypeResolverContext::TypeAliasDecl));
if (validateType(typealias->getUnderlyingTypeLoc(),
TypeResolution::forStructural(typealias), options)) {
typealias->setInvalid();
@@ -4844,26 +4851,21 @@
/// Form the interface type of an extension from the raw type and the
/// extension's list of generic parameters.
-static Type formExtensionInterfaceType(TypeChecker &tc, ExtensionDecl *ext,
- Type type,
- GenericParamList *genericParams,
- bool &mustInferRequirements) {
+static Type formExtensionInterfaceType(
+ TypeChecker &tc, ExtensionDecl *ext,
+ Type type,
+ GenericParamList *genericParams,
+ SmallVectorImpl<std::pair<Type, Type>> &sameTypeReqs,
+ bool &mustInferRequirements) {
if (type->is<ErrorType>())
return type;
// Find the nominal type declaration and its parent type.
- Type parentType;
- GenericTypeDecl *genericDecl;
- if (auto unbound = type->getAs<UnboundGenericType>()) {
- parentType = unbound->getParent();
- genericDecl = unbound->getDecl();
- } else {
- if (type->is<ProtocolCompositionType>())
- type = type->getCanonicalType();
- auto nominalType = type->castTo<NominalType>();
- parentType = nominalType->getParent();
- genericDecl = nominalType->getDecl();
- }
+ if (type->is<ProtocolCompositionType>())
+ type = type->getCanonicalType();
+
+ Type parentType = type->getNominalParent();
+ GenericTypeDecl *genericDecl = type->getAnyGeneric();
// Reconstruct the parent, if there is one.
if (parentType) {
@@ -4873,7 +4875,7 @@
: genericParams;
parentType =
formExtensionInterfaceType(tc, ext, parentType, parentGenericParams,
- mustInferRequirements);
+ sameTypeReqs, mustInferRequirements);
}
// Find the nominal type.
@@ -4891,9 +4893,20 @@
resultType = NominalType::get(nominal, parentType,
nominal->getASTContext());
} else {
+ auto currentBoundType = type->getAs<BoundGenericType>();
+
// Form the bound generic type with the type parameters provided.
+ unsigned gpIndex = 0;
for (auto gp : *genericParams) {
- genericArgs.push_back(gp->getDeclaredInterfaceType());
+ SWIFT_DEFER { ++gpIndex; };
+
+ auto gpType = gp->getDeclaredInterfaceType();
+ genericArgs.push_back(gpType);
+
+ if (currentBoundType) {
+ sameTypeReqs.push_back({gpType,
+ currentBoundType->getGenericArgs()[gpIndex]});
+ }
}
resultType = BoundGenericType::get(nominal, parentType, genericArgs);
@@ -4930,8 +4943,9 @@
// Form the interface type of the extension.
bool mustInferRequirements = false;
+ SmallVector<std::pair<Type, Type>, 4> sameTypeReqs;
Type extInterfaceType =
- formExtensionInterfaceType(tc, ext, type, genericParams,
+ formExtensionInterfaceType(tc, ext, type, genericParams, sameTypeReqs,
mustInferRequirements);
// Local function used to infer requirements from the extended type.
@@ -4943,6 +4957,13 @@
extInterfaceType,
nullptr,
source);
+
+ for (const auto &sameTypeReq : sameTypeReqs) {
+ builder.addRequirement(
+ Requirement(RequirementKind::SameType, sameTypeReq.first,
+ sameTypeReq.second),
+ source, ext->getModuleContext());
+ }
};
// Validate the generic type signature.
@@ -4950,11 +4971,20 @@
ext->getDeclContext(), nullptr,
/*allowConcreteGenericParams=*/true,
ext, inferExtendedTypeReqs,
- mustInferRequirements);
+ (mustInferRequirements ||
+ !sameTypeReqs.empty()));
return { env, extInterfaceType };
}
+static bool isNonGenericTypeAliasType(Type type) {
+ // A non-generic typealias can extend a specialized type.
+ if (auto *aliasType = dyn_cast<NameAliasType>(type.getPointer()))
+ return aliasType->getDecl()->getGenericParamsOfContext() == nullptr;
+
+ return false;
+}
+
static void validateExtendedType(ExtensionDecl *ext, TypeChecker &tc) {
// If we didn't parse a type, fill in an error type and bail out.
if (!ext->getExtendedTypeLoc().getTypeRepr()) {
@@ -4998,20 +5028,22 @@
return;
}
- // Cannot extend a bound generic type.
- if (extendedType->isSpecialized()) {
- tc.diagnose(ext->getLoc(), diag::extension_specialization,
- extendedType->getAnyNominal()->getName())
+ // Cannot extend function types, tuple types, etc.
+ if (!extendedType->getAnyNominal()) {
+ tc.diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
.highlight(ext->getExtendedTypeLoc().getSourceRange());
ext->setInvalid();
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
return;
}
- // Cannot extend function types, tuple types, etc.
- if (!extendedType->getAnyNominal()) {
- tc.diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
- .highlight(ext->getExtendedTypeLoc().getSourceRange());
+ // Cannot extend a bound generic type, unless it's referenced via a
+ // non-generic typealias type.
+ if (extendedType->isSpecialized() &&
+ !isNonGenericTypeAliasType(extendedType)) {
+ tc.diagnose(ext->getLoc(), diag::extension_specialization,
+ extendedType->getAnyNominal()->getName())
+ .highlight(ext->getExtendedTypeLoc().getSourceRange());
ext->setInvalid();
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
return;
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index e60aa87..baf317e 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -476,19 +476,18 @@
genericParam->getDeclaredInterfaceType());
}
- // If we are referring to a type within its own context, and we have either
- // a generic type with no generic arguments or a non-generic type, use the
- // type within the context.
- if (auto nominalType = dyn_cast<NominalTypeDecl>(typeDecl)) {
- if (!isa<ProtocolDecl>(nominalType) &&
- (!nominalType->getGenericParams() || !isSpecialized)) {
- for (auto parentDC = fromDC;
+ if (!isSpecialized) {
+ // If we are referring to a type within its own context, and we have either
+ // a generic type with no generic arguments or a non-generic type, use the
+ // type within the context.
+ if (auto *nominalType = dyn_cast<NominalTypeDecl>(typeDecl)) {
+ for (auto *parentDC = fromDC;
!parentDC->isModuleScopeContext();
parentDC = parentDC->getParent()) {
auto *parentNominal = parentDC->getSelfNominalTypeDecl();
if (parentNominal == nominalType)
return resolution.mapTypeIntoContext(
- parentDC->getSelfInterfaceType());
+ parentDC->getDeclaredInterfaceType());
if (isa<ExtensionDecl>(parentDC)) {
auto *extendedType = parentNominal;
while (extendedType != nullptr) {
@@ -500,6 +499,27 @@
}
}
}
+
+ // If we're inside an extension of a type alias, allow the type alias to be
+ // referenced without generic arguments as well.
+ if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(typeDecl)) {
+ for (auto *parentDC = fromDC;
+ !parentDC->isModuleScopeContext();
+ parentDC = parentDC->getParent()) {
+ if (auto *ext = dyn_cast<ExtensionDecl>(parentDC)) {
+ auto extendedType = ext->getExtendedType();
+ if (auto *aliasType = dyn_cast<NameAliasType>(extendedType.getPointer())) {
+ if (aliasType->getDecl() == aliasDecl) {
+ return resolution.mapTypeIntoContext(
+ aliasDecl->getDeclaredInterfaceType());
+ }
+
+ extendedType = aliasType->getParent();
+ continue;
+ }
+ }
+ }
+ }
}
// Simple case -- the type is not nested inside of another type.
@@ -2894,6 +2914,7 @@
case TypeResolverContext::EnumElementDecl:
case TypeResolverContext::EnumPatternPayload:
case TypeResolverContext::TypeAliasDecl:
+ case TypeResolverContext::GenericTypeAliasDecl:
case TypeResolverContext::GenericRequirement:
case TypeResolverContext::ImmediateOptionalTypeArgument:
case TypeResolverContext::InExpression:
diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h
index 7b3c782..5bff7a6 100644
--- a/lib/Sema/TypeCheckType.h
+++ b/lib/Sema/TypeCheckType.h
@@ -118,9 +118,12 @@
/// Whether this is the payload subpattern of an enum pattern.
EnumPatternPayload,
- /// Whether we are checking the underlying type of a typealias.
+ /// Whether we are checking the underlying type of a non-generic typealias.
TypeAliasDecl,
+ /// Whether we are checking the underlying type of a generic typealias.
+ GenericTypeAliasDecl,
+
/// Whether we are in a requirement of a generic declaration
GenericRequirement,
@@ -207,6 +210,7 @@
case Context::EnumElementDecl:
case Context::EnumPatternPayload:
case Context::TypeAliasDecl:
+ case Context::GenericTypeAliasDecl:
case Context::GenericRequirement:
case Context::ImmediateOptionalTypeArgument:
case Context::AbstractFunctionDecl:
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index e06d4f0..f40a9ad 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1345,9 +1345,15 @@
void Serializer::writeInlinableBodyTextIfNeeded(
const AbstractFunctionDecl *AFD) {
using namespace decls_block;
+ // Only serialize the text for an inlinable function body if we're emitting
+ // a partial module. It's not needed in the final module file, but it's
+ // needed in partial modules so you can emit a parseable interface after
+ // merging them.
+ if (!SF) return;
if (AFD->getResilienceExpansion() != swift::ResilienceExpansion::Minimal)
return;
+
if (!AFD->hasInlinableBodyText()) return;
SmallString<128> scratch;
auto body = AFD->getInlinableBodyText(scratch);
diff --git a/stdlib/public/SDK/Foundation/CMakeLists.txt b/stdlib/public/SDK/Foundation/CMakeLists.txt
index 7a38578..4d18d84 100644
--- a/stdlib/public/SDK/Foundation/CMakeLists.txt
+++ b/stdlib/public/SDK/Foundation/CMakeLists.txt
@@ -8,7 +8,13 @@
Calendar.swift
CharacterSet.swift
Codable.swift
+ Collections+DataProtocol.swift
+ ContiguousBytes.swift
Data.swift
+ DataProtocol.swift
+ DispatchData+DataProtocol.swift
+ NSData+DataProtocol.swift
+ Pointers+DataProtocol.swift
DataThunks.m
Date.swift
DateComponents.swift
diff --git a/stdlib/public/SDK/Foundation/Collections+DataProtocol.swift b/stdlib/public/SDK/Foundation/Collections+DataProtocol.swift
new file mode 100644
index 0000000..3125f9a
--- /dev/null
+++ b/stdlib/public/SDK/Foundation/Collections+DataProtocol.swift
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+//===--- DataProtocol -----------------------------------------------------===//
+
+extension Array: DataProtocol where Element == UInt8 {
+ public var regions: CollectionOfOne<Array<UInt8>> {
+ return CollectionOfOne(self)
+ }
+}
+
+extension ArraySlice: DataProtocol where Element == UInt8 {
+ public var regions: CollectionOfOne<ArraySlice<UInt8>> {
+ return CollectionOfOne(self)
+ }
+}
+
+extension ContiguousArray: DataProtocol where Element == UInt8 {
+ public var regions: CollectionOfOne<ContiguousArray<UInt8>> {
+ return CollectionOfOne(self)
+ }
+}
+
+// FIXME: This currently crashes compilation in the Late Inliner.
+// extension CollectionOfOne : DataProtocol where Element == UInt8 {
+// public typealias Regions = CollectionOfOne<Data>
+//
+// public var regions: CollectionOfOne<Data> {
+// return CollectionOfOne<Data>(Data(self))
+// }
+// }
+
+extension EmptyCollection : DataProtocol where Element == UInt8 {
+ public var regions: EmptyCollection<Data> {
+ return EmptyCollection<Data>()
+ }
+}
+
+extension Repeated: DataProtocol where Element == UInt8 {
+ public typealias Regions = Repeated<Data>
+
+ public var regions: Repeated<Data> {
+ guard self.count > 0 else { return repeatElement(Data(), count: 0) }
+ return repeatElement(Data(CollectionOfOne(self.first!)), count: self.count)
+ }
+}
+
+//===--- MutableDataProtocol ----------------------------------------------===//
+
+extension Array: MutableDataProtocol where Element == UInt8 { }
+
+extension ContiguousArray: MutableDataProtocol where Element == UInt8 { }
diff --git a/stdlib/public/SDK/Foundation/ContiguousBytes.swift b/stdlib/public/SDK/Foundation/ContiguousBytes.swift
new file mode 100644
index 0000000..0d1f69b
--- /dev/null
+++ b/stdlib/public/SDK/Foundation/ContiguousBytes.swift
@@ -0,0 +1,100 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+//===--- ContiguousBytes --------------------------------------------------===//
+
+/// Indicates that the conforming type is a contiguous collection of raw bytes
+/// whose underlying storage is directly accessible by withUnsafeBytes.
+public protocol ContiguousBytes {
+ /// Calls the given closure with the contents of underlying storage.
+ ///
+ /// - note: Calling `withUnsafeBytes` multiple times does not guarantee that
+ /// the same buffer pointer will be passed in every time.
+ /// - warning: The buffer argument to the body should not be stored or used
+ /// outside of the lifetime of the call to the closure.
+ func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
+}
+
+//===--- Collection Conformances ------------------------------------------===//
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension Array : ContiguousBytes where Element == UInt8 { }
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension ArraySlice : ContiguousBytes where Element == UInt8 { }
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension ContiguousArray : ContiguousBytes where Element == UInt8 { }
+
+//===--- Pointer Conformances ---------------------------------------------===//
+
+extension UnsafeRawBufferPointer : ContiguousBytes {
+ @inlinable
+ public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+ return try body(self)
+ }
+}
+
+extension UnsafeMutableRawBufferPointer : ContiguousBytes {
+ @inlinable
+ public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+ return try body(UnsafeRawBufferPointer(self))
+ }
+}
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension UnsafeBufferPointer : ContiguousBytes where Element == UInt8 {
+ @inlinable
+ public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+ return try body(UnsafeRawBufferPointer(self))
+ }
+}
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension UnsafeMutableBufferPointer : ContiguousBytes where Element == UInt8 {
+ @inlinable
+ public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+ return try body(UnsafeRawBufferPointer(self))
+ }
+}
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension EmptyCollection : ContiguousBytes where Element == UInt8 {
+ @inlinable
+ public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+ return try body(UnsafeRawBufferPointer(start: nil, count: 0))
+ }
+}
+
+// FIXME: When possible, expand conformance to `where Element : Trivial`.
+extension CollectionOfOne : ContiguousBytes where Element == UInt8 {
+ @inlinable
+ public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+ let element = self.first!
+ return try Swift.withUnsafeBytes(of: element) {
+ return try body($0)
+ }
+ }
+}
+
+//===--- Conditional Conformances -----------------------------------------===//
+
+extension Slice : ContiguousBytes where Base : ContiguousBytes {
+ public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
+ let offset = base.distance(from: base.startIndex, to: self.startIndex)
+ return try base.withUnsafeBytes { ptr in
+ let slicePtr = ptr.baseAddress?.advanced(by: offset)
+ let sliceBuffer = UnsafeRawBufferPointer(start: slicePtr, count: self.count)
+ return try body(sliceBuffer)
+ }
+ }
+}
diff --git a/stdlib/public/SDK/Foundation/Data.swift b/stdlib/public/SDK/Foundation/Data.swift
index f666f0f..921f21d 100644
--- a/stdlib/public/SDK/Foundation/Data.swift
+++ b/stdlib/public/SDK/Foundation/Data.swift
@@ -16,6 +16,12 @@
import Darwin
#elseif os(Linux)
import Glibc
+
+@inlinable
+fileprivate func malloc_good_size(_ size: Int) -> Int {
+ return size
+}
+
#endif
import CoreFoundation
@@ -59,29 +65,11 @@
@usableFromInline
internal final class _DataStorage {
@usableFromInline
- enum Backing {
- // A mirror of the Objective-C implementation that is suitable to inline in Swift
- case swift
-
- // these two storage points for immutable and mutable data are reserved for references that are returned by "known"
- // cases from Foundation in which implement the backing of struct Data, these have signed up for the concept that
- // the backing bytes/mutableBytes pointer does not change per call (unless mutated) as well as the length is ok
- // to be cached, this means that as long as the backing reference is retained no further objc_msgSends need to be
- // dynamically dispatched out to the reference.
- case immutable(NSData) // This will most often (perhaps always) be NSConcreteData
- case mutable(NSMutableData) // This will often (perhaps always) be NSConcreteMutableData
-
- // These are reserved for foreign sources where neither Swift nor Foundation are fully certain whom they belong
- // to from an object inheritance standpoint, this means that all bets are off and the values of bytes, mutableBytes,
- // and length cannot be cached. This also means that all methods are expected to dynamically dispatch out to the
- // backing reference.
- case customReference(NSData) // tracks data references that are only known to be immutable
- case customMutableReference(NSMutableData) // tracks data references that are known to be mutable
- }
-
static let maxSize = Int.max >> 1
+ @usableFromInline
static let vmOpsThreshold = NSPageSize() * 4
+ @inlinable
static func allocate(_ size: Int, _ clear: Bool) -> UnsafeMutableRawPointer? {
if clear {
return calloc(1, size)
@@ -90,7 +78,7 @@
}
}
- @usableFromInline
+ @inlinable
static func move(_ dest_: UnsafeMutableRawPointer, _ source_: UnsafeRawPointer?, _ num_: Int) {
var dest = dest_
var source = source_
@@ -107,6 +95,7 @@
}
}
+ @inlinable
static func shouldAllocateCleared(_ size: Int) -> Bool {
return (size > (128 * 1024))
}
@@ -122,186 +111,152 @@
@usableFromInline
var _deallocator: ((UnsafeMutableRawPointer, Int) -> Void)?
@usableFromInline
- var _backing: Backing = .swift
- @usableFromInline
var _offset: Int
- @usableFromInline
+ @inlinable
var bytes: UnsafeRawPointer? {
- @inlinable
- get {
- switch _backing {
- case .swift:
- return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
- case .immutable:
- return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
- case .mutable:
- return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
- case .customReference(let d):
- return d.bytes.advanced(by: -_offset)
- case .customMutableReference(let d):
- return d.bytes.advanced(by: -_offset)
- @unknown default:
- fatalError("Unknown Data backing type")
- }
- }
+ return UnsafeRawPointer(_bytes)?.advanced(by: -_offset)
}
- @usableFromInline
+ @inlinable
@discardableResult
func withUnsafeBytes<Result>(in range: Range<Int>, apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
- switch _backing {
- case .swift: fallthrough
- case .immutable: fallthrough
- case .mutable:
- return try apply(UnsafeRawBufferPointer(start: _bytes?.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, _length)))
- case .customReference(let d):
- if __NSDataIsCompact(d) {
- let len = d.length
- guard len > 0 else {
- return try apply(UnsafeRawBufferPointer(start: nil, count: 0))
- }
- return try apply(UnsafeRawBufferPointer(start: d.bytes.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, len)))
- } else {
- var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: range.count, alignment: MemoryLayout<UInt>.alignment)
- defer { buffer.deallocate() }
-
- let sliceRange = NSRange(location: range.lowerBound - _offset, length: range.count)
- var enumerated = 0
- d.enumerateBytes { (ptr, byteRange, stop) in
- if byteRange.upperBound - _offset < range.lowerBound {
- // before the range that we are looking for...
- } else if byteRange.lowerBound - _offset > range.upperBound {
- stop.pointee = true // we are past the range in question so we need to stop
- } else {
- // the byteRange somehow intersects the range in question that we are looking for...
- let lower = Swift.max(byteRange.lowerBound - _offset, range.lowerBound)
- let upper = Swift.min(byteRange.upperBound - _offset, range.upperBound)
-
- let len = upper - lower
- memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr.advanced(by: lower - (byteRange.lowerBound - _offset)), len)
- enumerated += len
-
- if upper == range.upperBound {
- stop.pointee = true
- }
- }
- }
- return try apply(UnsafeRawBufferPointer(buffer))
- }
- case .customMutableReference(let d):
- if __NSDataIsCompact(d) {
- let len = d.length
- guard len > 0 else {
- return try apply(UnsafeRawBufferPointer(start: nil, count: 0))
- }
- return try apply(UnsafeRawBufferPointer(start: d.bytes.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, len)))
- } else {
- var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: range.count, alignment: MemoryLayout<UInt>.alignment)
- defer { buffer.deallocate() }
-
- var enumerated = 0
- d.enumerateBytes { (ptr, byteRange, stop) in
- if byteRange.upperBound - _offset < range.lowerBound {
- // before the range that we are looking for...
- } else if byteRange.lowerBound - _offset > range.upperBound {
- stop.pointee = true // we are past the range in question so we need to stop
- } else {
- // the byteRange somehow intersects the range in question that we are looking for...
- let lower = Swift.max(byteRange.lowerBound - _offset, range.lowerBound)
- let upper = Swift.min(byteRange.upperBound - _offset, range.upperBound)
-
- let len = upper - lower
- memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr.advanced(by: lower - (byteRange.lowerBound - _offset)), len)
- enumerated += len
-
- if upper == range.upperBound {
- stop.pointee = true
- }
- }
- }
- return try apply(UnsafeRawBufferPointer(buffer))
- }
- }
+ return try apply(UnsafeRawBufferPointer(start: _bytes?.advanced(by: range.lowerBound - _offset), count: Swift.min(range.upperBound - range.lowerBound, _length)))
}
- @usableFromInline
+ @inlinable
@discardableResult
func withUnsafeMutableBytes<Result>(in range: Range<Int>, apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
- switch _backing {
- case .swift: fallthrough
- case .mutable:
- return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
- case .customMutableReference(let d):
- let len = d.length
- return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- _backing = .mutable(data)
- _bytes = data.mutableBytes
- return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- _backing = .customMutableReference(data)
- let len = data.length
- return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
- }
+ return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.upperBound - range.lowerBound, _length)))
}
+ @inlinable
var mutableBytes: UnsafeMutableRawPointer? {
- @inlinable
- get {
- switch _backing {
- case .swift:
- return _bytes?.advanced(by: -_offset)
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.length = length
- _backing = .mutable(data)
- _bytes = data.mutableBytes
- return _bytes?.advanced(by: -_offset)
- case .mutable:
- return _bytes?.advanced(by: -_offset)
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.length = length
- _backing = .customMutableReference(data)
- return data.mutableBytes.advanced(by: -_offset)
- case .customMutableReference(let d):
- return d.mutableBytes.advanced(by: -_offset)
- @unknown default:
- fatalError("Unknown Data backing type")
- }
- }
+ return _bytes?.advanced(by: -_offset)
}
+
+ @inlinable
+ var capacity: Int { return _capacity }
-
- @usableFromInline
+ @inlinable
var length: Int {
- @inlinable
get {
- switch _backing {
- case .swift:
- return _length
- case .immutable:
- return _length
- case .mutable:
- return _length
- case .customReference(let d):
- return d.length
- case .customMutableReference(let d):
- return d.length
- @unknown default:
- fatalError("Unknown Data backing type")
- }
+ return _length
}
- @inlinable
set {
setLength(newValue)
}
}
+ @inlinable
+ var isExternallyOwned: Bool {
+ // all _DataStorages will have some sort of capacity, because empty cases hit the .empty enum _Representation
+ // anything with 0 capacity means that we have not allocated this pointer and concequently mutation is not ours to make.
+ return _capacity == 0
+ }
+ @inlinable
+ func ensureUniqueBufferReference(growingTo newLength: Int = 0, clear: Bool = false) {
+ guard isExternallyOwned || newLength > _capacity else { return }
+
+ if newLength == 0 {
+ if isExternallyOwned {
+ let newCapacity = malloc_good_size(_length)
+ let newBytes = _DataStorage.allocate(newCapacity, false)
+ _DataStorage.move(newBytes!, _bytes!, _length)
+ _freeBytes()
+ _bytes = newBytes
+ _capacity = newCapacity
+ _needToZero = false
+ }
+ } else if isExternallyOwned {
+ let newCapacity = malloc_good_size(newLength)
+ let newBytes = _DataStorage.allocate(newCapacity, clear)
+ if let bytes = _bytes {
+ _DataStorage.move(newBytes!, bytes, _length)
+ }
+ _freeBytes()
+ _bytes = newBytes
+ _capacity = newCapacity
+ _length = newLength
+ _needToZero = true
+ } else {
+ let cap = _capacity
+ var additionalCapacity = (newLength >> (_DataStorage.vmOpsThreshold <= newLength ? 2 : 1))
+ if Int.max - additionalCapacity < newLength {
+ additionalCapacity = 0
+ }
+ var newCapacity = malloc_good_size(Swift.max(cap, newLength + additionalCapacity))
+ let origLength = _length
+ var allocateCleared = clear && _DataStorage.shouldAllocateCleared(newCapacity)
+ var newBytes: UnsafeMutableRawPointer? = nil
+ if _bytes == nil {
+ newBytes = _DataStorage.allocate(newCapacity, allocateCleared)
+ if newBytes == nil {
+ /* Try again with minimum length */
+ allocateCleared = clear && _DataStorage.shouldAllocateCleared(newLength)
+ newBytes = _DataStorage.allocate(newLength, allocateCleared)
+ }
+ } else {
+ let tryCalloc = (origLength == 0 || (newLength / origLength) >= 4)
+ if allocateCleared && tryCalloc {
+ newBytes = _DataStorage.allocate(newCapacity, true)
+ if let newBytes = newBytes {
+ _DataStorage.move(newBytes, _bytes!, origLength)
+ _freeBytes()
+ }
+ }
+ /* Where calloc/memmove/free fails, realloc might succeed */
+ if newBytes == nil {
+ allocateCleared = false
+ if _deallocator != nil {
+ newBytes = _DataStorage.allocate(newCapacity, true)
+ if let newBytes = newBytes {
+ _DataStorage.move(newBytes, _bytes!, origLength)
+ _freeBytes()
+ }
+ } else {
+ newBytes = realloc(_bytes!, newCapacity)
+ }
+ }
+ /* Try again with minimum length */
+ if newBytes == nil {
+ newCapacity = malloc_good_size(newLength)
+ allocateCleared = clear && _DataStorage.shouldAllocateCleared(newCapacity)
+ if allocateCleared && tryCalloc {
+ newBytes = _DataStorage.allocate(newCapacity, true)
+ if let newBytes = newBytes {
+ _DataStorage.move(newBytes, _bytes!, origLength)
+ _freeBytes()
+ }
+ }
+ if newBytes == nil {
+ allocateCleared = false
+ newBytes = realloc(_bytes!, newCapacity)
+ }
+ }
+ }
+
+ if newBytes == nil {
+ /* Could not allocate bytes */
+ // At this point if the allocation cannot occur the process is likely out of memory
+ // and Bad-Things™ are going to happen anyhow
+ fatalError("unable to allocate memory for length (\(newLength))")
+ }
+
+ if origLength < newLength && clear && !allocateCleared {
+ memset(newBytes!.advanced(by: origLength), 0, newLength - origLength)
+ }
+
+ /* _length set by caller */
+ _bytes = newBytes
+ _capacity = newCapacity
+ /* Realloc/memset doesn't zero out the entire capacity, so we must be safe and clear next time we grow the length */
+ _needToZero = !allocateCleared
+ }
+ }
+
+ @inlinable
func _freeBytes() {
if let bytes = _bytes {
if let dealloc = _deallocator {
@@ -310,186 +265,39 @@
free(bytes)
}
}
+ _deallocator = nil
}
-
+
+ @usableFromInline
func enumerateBytes(in range: Range<Int>, _ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Data.Index, _ stop: inout Bool) -> Void) {
var stopv: Bool = false
- var data: NSData
- switch _backing {
- case .swift: fallthrough
- case .immutable: fallthrough
- case .mutable:
- block(UnsafeBufferPointer<UInt8>(start: _bytes?.advanced(by: range.lowerBound - _offset).assumingMemoryBound(to: UInt8.self), count: Swift.min(range.count, _length)), 0, &stopv)
- return
- case .customReference(let d):
- data = d
- break
- case .customMutableReference(let d):
- data = d
- break
- }
- data.enumerateBytes { (ptr, region, stop) in
- // any region that is not in the range should be skipped
- guard range.contains(region.lowerBound) || range.contains(region.upperBound) else { return }
- var regionAdjustment = 0
- if region.lowerBound < range.lowerBound {
- regionAdjustment = range.lowerBound - (region.lowerBound - _offset)
- }
- let bytePtr = ptr.advanced(by: regionAdjustment).assumingMemoryBound(to: UInt8.self)
- let effectiveLength = Swift.min((region.location - _offset) + region.length, range.upperBound) - (region.location - _offset)
- block(UnsafeBufferPointer(start: bytePtr, count: effectiveLength - regionAdjustment), region.location + regionAdjustment - _offset, &stopv)
- if stopv {
- stop.pointee = true
- }
- }
- }
-
- @usableFromInline
- @inline(never)
- func _grow(_ newLength: Int, _ clear: Bool) {
- let cap = _capacity
- var additionalCapacity = (newLength >> (_DataStorage.vmOpsThreshold <= newLength ? 2 : 1))
- if Int.max - additionalCapacity < newLength {
- additionalCapacity = 0
- }
- var newCapacity = Swift.max(cap, newLength + additionalCapacity)
- let origLength = _length
- var allocateCleared = clear && _DataStorage.shouldAllocateCleared(newCapacity)
- var newBytes: UnsafeMutableRawPointer? = nil
- if _bytes == nil {
- newBytes = _DataStorage.allocate(newCapacity, allocateCleared)
- if newBytes == nil {
- /* Try again with minimum length */
- allocateCleared = clear && _DataStorage.shouldAllocateCleared(newLength)
- newBytes = _DataStorage.allocate(newLength, allocateCleared)
- }
- } else {
- let tryCalloc = (origLength == 0 || (newLength / origLength) >= 4)
- if allocateCleared && tryCalloc {
- newBytes = _DataStorage.allocate(newCapacity, true)
- if let newBytes = newBytes {
- _DataStorage.move(newBytes, _bytes!, origLength)
- _freeBytes()
- }
- }
- /* Where calloc/memmove/free fails, realloc might succeed */
- if newBytes == nil {
- allocateCleared = false
- if _deallocator != nil {
- newBytes = _DataStorage.allocate(newCapacity, true)
- if let newBytes = newBytes {
- _DataStorage.move(newBytes, _bytes!, origLength)
- _freeBytes()
- _deallocator = nil
- }
- } else {
- newBytes = realloc(_bytes!, newCapacity)
- }
- }
-
- /* Try again with minimum length */
- if newBytes == nil {
- newCapacity = newLength
- allocateCleared = clear && _DataStorage.shouldAllocateCleared(newCapacity)
- if allocateCleared && tryCalloc {
- newBytes = _DataStorage.allocate(newCapacity, true)
- if let newBytes = newBytes {
- _DataStorage.move(newBytes, _bytes!, origLength)
- _freeBytes()
- }
- }
- if newBytes == nil {
- allocateCleared = false
- newBytes = realloc(_bytes!, newCapacity)
- }
- }
- }
-
- if newBytes == nil {
- /* Could not allocate bytes */
- // At this point if the allocation cannot occur the process is likely out of memory
- // and Bad-Things™ are going to happen anyhow
- fatalError("unable to allocate memory for length (\(newLength))")
- }
-
- if origLength < newLength && clear && !allocateCleared {
- memset(newBytes!.advanced(by: origLength), 0, newLength - origLength)
- }
-
- /* _length set by caller */
- _bytes = newBytes
- _capacity = newCapacity
- /* Realloc/memset doesn't zero out the entire capacity, so we must be safe and clear next time we grow the length */
- _needToZero = !allocateCleared
+ block(UnsafeBufferPointer<UInt8>(start: _bytes?.advanced(by: range.lowerBound - _offset).assumingMemoryBound(to: UInt8.self), count: Swift.min(range.upperBound - range.lowerBound, _length)), 0, &stopv)
}
@inlinable
func setLength(_ length: Int) {
- switch _backing {
- case .swift:
- let origLength = _length
- let newLength = length
- if _capacity < newLength || _bytes == nil {
- _grow(newLength, true)
- } else if origLength < newLength && _needToZero {
- memset(_bytes! + origLength, 0, newLength - origLength)
- } else if newLength < origLength {
- _needToZero = true
- }
- _length = newLength
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.length = length
- _backing = .mutable(data)
- _length = length
- _bytes = data.mutableBytes
- case .mutable(let d):
- d.length = length
- _length = length
- _bytes = d.mutableBytes
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.length = length
- _backing = .customMutableReference(data)
- case .customMutableReference(let d):
- d.length = length
- @unknown default:
- fatalError("Unknown Data backing type")
+ let origLength = _length
+ let newLength = length
+ if _capacity < newLength || _bytes == nil {
+ ensureUniqueBufferReference(growingTo: newLength, clear: true)
+ } else if origLength < newLength && _needToZero {
+ memset(_bytes! + origLength, 0, newLength - origLength)
+ } else if newLength < origLength {
+ _needToZero = true
}
+ _length = newLength
}
@inlinable
func append(_ bytes: UnsafeRawPointer, length: Int) {
precondition(length >= 0, "Length of appending bytes must not be negative")
- switch _backing {
- case .swift:
- let origLength = _length
- let newLength = origLength + length
- if _capacity < newLength || _bytes == nil {
- _grow(newLength, false)
- }
- _length = newLength
- _DataStorage.move(_bytes!.advanced(by: origLength), bytes, length)
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.append(bytes, length: length)
- _backing = .mutable(data)
- _length = data.length
- _bytes = data.mutableBytes
- case .mutable(let d):
- d.append(bytes, length: length)
- _length = d.length
- _bytes = d.mutableBytes
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.append(bytes, length: length)
- _backing = .customMutableReference(data)
- case .customMutableReference(let d):
- d.append(bytes, length: length)
- @unknown default:
- fatalError("Unknown Data backing type")
+ let origLength = _length
+ let newLength = origLength + length
+ if _capacity < newLength || _bytes == nil {
+ ensureUniqueBufferReference(growingTo: newLength, clear: false)
}
-
+ _length = newLength
+ _DataStorage.move(_bytes!.advanced(by: origLength), bytes, length)
}
// fast-path for appending directly from another data storage
@@ -504,131 +312,57 @@
@inlinable
func append(_ otherData: Data) {
- otherData.enumerateBytes { (buffer: UnsafeBufferPointer<UInt8>, _, _) in
- append(buffer.baseAddress!, length: buffer.count)
+ guard otherData.count > 0 else { return }
+ otherData.withUnsafeBytes {
+ append($0.baseAddress!, length: $0.count)
}
}
@inlinable
func increaseLength(by extraLength: Int) {
if extraLength == 0 { return }
- switch _backing {
- case .swift:
- let origLength = _length
- let newLength = origLength + extraLength
- if _capacity < newLength || _bytes == nil {
- _grow(newLength, true)
- } else if _needToZero {
- memset(_bytes!.advanced(by: origLength), 0, extraLength)
- }
- _length = newLength
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.increaseLength(by: extraLength)
- _backing = .mutable(data)
- _length += extraLength
- _bytes = data.mutableBytes
- case .mutable(let d):
- d.increaseLength(by: extraLength)
- _length += extraLength
- _bytes = d.mutableBytes
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.increaseLength(by: extraLength)
- _backing = .customReference(data)
- case .customMutableReference(let d):
- d.increaseLength(by: extraLength)
- @unknown default:
- fatalError("Unknown Data backing type")
- }
+ let origLength = _length
+ let newLength = origLength + extraLength
+ if _capacity < newLength || _bytes == nil {
+ ensureUniqueBufferReference(growingTo: newLength, clear: true)
+ } else if _needToZero {
+ memset(_bytes!.advanced(by: origLength), 0, extraLength)
+ }
+ _length = newLength
}
- @usableFromInline
+ @inlinable
func get(_ index: Int) -> UInt8 {
- switch _backing {
- case .swift: fallthrough
- case .immutable: fallthrough
- case .mutable:
- return _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
- case .customReference(let d):
- if __NSDataIsCompact(d) {
- return d.bytes.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
- } else {
- var byte: UInt8 = 0
- d.enumerateBytes { (ptr, range, stop) in
- if NSLocationInRange(index, range) {
- let offset = index - range.location - _offset
- byte = ptr.advanced(by: offset).assumingMemoryBound(to: UInt8.self).pointee
- stop.pointee = true
- }
- }
- return byte
- }
- case .customMutableReference(let d):
- if __NSDataIsCompact(d) {
- return d.bytes.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
- } else {
- var byte: UInt8 = 0
- d.enumerateBytes { (ptr, range, stop) in
- if NSLocationInRange(index, range) {
- let offset = index - range.location - _offset
- byte = ptr.advanced(by: offset).assumingMemoryBound(to: UInt8.self).pointee
- stop.pointee = true
- }
- }
- return byte
- }
- }
+ return _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
}
@inlinable
func set(_ index: Int, to value: UInt8) {
- switch _backing {
- case .swift:
- fallthrough
- case .mutable:
- _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee = value
- default:
- var theByte = value
- let range = NSRange(location: index, length: 1)
- replaceBytes(in: range, with: &theByte, length: 1)
- }
-
+ ensureUniqueBufferReference()
+ _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee = value
}
-
+
+ @inlinable
+ func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
+ let offsetPointer = UnsafeRawBufferPointer(start: _bytes?.advanced(by: range.lowerBound - _offset), count: Swift.min(range.upperBound - range.lowerBound, _length))
+ UnsafeMutableRawBufferPointer(start: pointer, count: range.upperBound - range.lowerBound).copyMemory(from: offsetPointer)
+ }
+
@inlinable
func replaceBytes(in range: NSRange, with bytes: UnsafeRawPointer?) {
if range.length == 0 { return }
- switch _backing {
- case .swift:
- if _length < range.location + range.length {
- let newLength = range.location + range.length
- if _capacity < newLength {
- _grow(newLength, false)
- }
- _length = newLength
+ if _length < range.location + range.length {
+ let newLength = range.location + range.length
+ if _capacity < newLength {
+ ensureUniqueBufferReference(growingTo: newLength, clear: false)
}
- _DataStorage.move(_bytes!.advanced(by: range.location - _offset), bytes!, range.length)
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
- _backing = .mutable(data)
- _length = data.length
- _bytes = data.mutableBytes
- case .mutable(let d):
- d.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
- _length = d.length
- _bytes = d.mutableBytes
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
- _backing = .customMutableReference(data)
- case .customMutableReference(let d):
- d.replaceBytes(in: NSRange(location: range.location - _offset, length: range.length), withBytes: bytes!)
- @unknown default:
- fatalError("Unknown Data backing type")
+ _length = newLength
+ } else {
+ ensureUniqueBufferReference()
}
+ _DataStorage.move(_bytes!.advanced(by: range.location - _offset), bytes!, range.length)
+
}
@inlinable
@@ -636,90 +370,51 @@
let range = NSRange(location: range_.location - _offset, length: range_.length)
let currentLength = _length
let resultingLength = currentLength - range.length + replacementLength
- switch _backing {
- case .swift:
- let shift = resultingLength - currentLength
- var mutableBytes = _bytes
- if resultingLength > currentLength {
- setLength(resultingLength)
- mutableBytes = _bytes!
+ let shift = resultingLength - currentLength
+ let mutableBytes: UnsafeMutableRawPointer
+ if resultingLength > currentLength {
+ ensureUniqueBufferReference(growingTo: resultingLength)
+ _length = resultingLength
+ } else {
+ ensureUniqueBufferReference()
+ }
+ mutableBytes = _bytes!
+ /* shift the trailing bytes */
+ let start = range.location
+ let length = range.length
+ if shift != 0 {
+ memmove(mutableBytes + start + replacementLength, mutableBytes + start + length, currentLength - start - length)
+ }
+ if replacementLength != 0 {
+ if let replacementBytes = replacementBytes {
+ memmove(mutableBytes + start, replacementBytes, replacementLength)
+ } else {
+ memset(mutableBytes + start, 0, replacementLength)
}
- /* shift the trailing bytes */
- let start = range.location
- let length = range.length
- if shift != 0 {
- memmove(mutableBytes! + start + replacementLength, mutableBytes! + start + length, currentLength - start - length)
- }
- if replacementLength != 0 {
- if let replacementBytes = replacementBytes {
- memmove(mutableBytes! + start, replacementBytes, replacementLength)
- } else {
- memset(mutableBytes! + start, 0, replacementLength)
- }
- }
-
- if resultingLength < currentLength {
- setLength(resultingLength)
- }
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
- _backing = .mutable(data)
- _length = data.length
- _bytes = data.mutableBytes
- case .mutable(let d):
- d.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
- _backing = .mutable(d)
- _length = d.length
- _bytes = d.mutableBytes
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
- _backing = .customMutableReference(data)
- case .customMutableReference(let d):
- d.replaceBytes(in: range, withBytes: replacementBytes, length: replacementLength)
- @unknown default:
- fatalError("Unknown Data backing type")
+ }
+
+ if resultingLength < currentLength {
+ setLength(resultingLength)
}
}
@inlinable
- func resetBytes(in range_: NSRange) {
- let range = NSRange(location: range_.location - _offset, length: range_.length)
+ func resetBytes(in range_: Range<Int>) {
+ let range = NSRange(location: range_.lowerBound - _offset, length: range_.upperBound - range_.lowerBound)
if range.length == 0 { return }
- switch _backing {
- case .swift:
- if _length < range.location + range.length {
- let newLength = range.location + range.length
- if _capacity < newLength {
- _grow(newLength, false)
- }
- _length = newLength
+ if _length < range.location + range.length {
+ let newLength = range.location + range.length
+ if _capacity <= newLength {
+ ensureUniqueBufferReference(growingTo: newLength, clear: false)
}
- memset(_bytes!.advanced(by: range.location), 0, range.length)
- case .immutable(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.resetBytes(in: range)
- _backing = .mutable(data)
- _length = data.length
- _bytes = data.mutableBytes
- case .mutable(let d):
- d.resetBytes(in: range)
- _length = d.length
- _bytes = d.mutableBytes
- case .customReference(let d):
- let data = d.mutableCopy() as! NSMutableData
- data.resetBytes(in: range)
- _backing = .customMutableReference(data)
- case .customMutableReference(let d):
- d.resetBytes(in: range)
- @unknown default:
- fatalError("Unknown Data backing type")
+ _length = newLength
+ } else {
+ ensureUniqueBufferReference()
}
-
+ memset(_bytes!.advanced(by: range.location), 0, range.length)
}
-
- @usableFromInline
+
+ @inlinable
convenience init() {
self.init(capacity: 0)
}
@@ -826,7 +521,7 @@
}
}
}
-
+
@usableFromInline
init(immutableReference: NSData, offset: Int) {
_offset = offset
@@ -834,7 +529,9 @@
_capacity = 0
_needToZero = false
_length = immutableReference.length
- _backing = .immutable(immutableReference)
+ _deallocator = { _, _ in
+ _fixLifetime(immutableReference)
+ }
}
@usableFromInline
@@ -844,145 +541,67 @@
_capacity = 0
_needToZero = false
_length = mutableReference.length
- _backing = .mutable(mutableReference)
+ _deallocator = { _, _ in
+ _fixLifetime(mutableReference)
+ }
}
@usableFromInline
init(customReference: NSData, offset: Int) {
_offset = offset
- _bytes = nil
+ _bytes = UnsafeMutableRawPointer(mutating: customReference.bytes)
_capacity = 0
_needToZero = false
- _length = 0
- _backing = .customReference(customReference)
+ _length = customReference.length
+ _deallocator = { _, _ in
+ _fixLifetime(customReference)
+ }
}
@usableFromInline
init(customMutableReference: NSMutableData, offset: Int) {
_offset = offset
- _bytes = nil
+ _bytes = customMutableReference.mutableBytes
_capacity = 0
_needToZero = false
- _length = 0
- _backing = .customMutableReference(customMutableReference)
+ _length = customMutableReference.length
+ _deallocator = { _, _ in
+ _fixLifetime(customMutableReference)
+ }
}
deinit {
- switch _backing {
- case .swift:
- _freeBytes()
- default:
- break
- }
+ _freeBytes()
}
@inlinable
func mutableCopy(_ range: Range<Int>) -> _DataStorage {
- switch _backing {
- case .swift:
- return _DataStorage(bytes: _bytes?.advanced(by: range.lowerBound - _offset), length: range.count, copy: true, deallocator: nil, offset: range.lowerBound)
- case .immutable(let d):
- if range.lowerBound == 0 && range.upperBound == _length {
- return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
- } else {
- return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
- }
- case .mutable(let d):
- if range.lowerBound == 0 && range.upperBound == _length {
- return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
- } else {
- return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
- }
- case .customReference(let d):
- if range.lowerBound == 0 && range.upperBound == _length {
- return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
- } else {
- return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
- }
- case .customMutableReference(let d):
- if range.lowerBound == 0 && range.upperBound == _length {
- return _DataStorage(mutableReference: d.mutableCopy() as! NSMutableData, offset: range.lowerBound)
- } else {
- return _DataStorage(mutableReference: d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC().mutableCopy() as! NSMutableData, offset: range.lowerBound)
- }
- @unknown default:
- fatalError("Unknown Data backing type")
- }
+ return _DataStorage(bytes: _bytes?.advanced(by: range.lowerBound - _offset), length: range.upperBound - range.lowerBound, copy: true, deallocator: nil, offset: range.lowerBound)
}
-
+
+ @inlinable
func withInteriorPointerReference<T>(_ range: Range<Int>, _ work: (NSData) throws -> T) rethrows -> T {
if range.isEmpty {
return try work(NSData()) // zero length data can be optimized as a singleton
}
-
- switch _backing {
- case .swift:
- return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.count, freeWhenDone: false))
- case .immutable(let d):
- guard range.lowerBound == 0 && range.upperBound == _length else {
- return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.count, freeWhenDone: false))
- }
- return try work(d)
- case .mutable(let d):
- guard range.lowerBound == 0 && range.upperBound == _length else {
- return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.count, freeWhenDone: false))
- }
- return try work(d)
- case .customReference(let d):
- guard range.lowerBound == 0 && range.upperBound == _length else {
-
- return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: d.bytes.advanced(by: range.lowerBound - _offset)), length: range.count, freeWhenDone: false))
- }
- return try work(d)
- case .customMutableReference(let d):
- guard range.lowerBound == 0 && range.upperBound == _length else {
- return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: d.bytes.advanced(by: range.lowerBound - _offset)), length: range.count, freeWhenDone: false))
- }
- return try work(d)
- }
+ return try work(NSData(bytesNoCopy: _bytes!.advanced(by: range.lowerBound - _offset), length: range.upperBound - range.lowerBound, freeWhenDone: false))
}
-
+
+ // This is used to create bridged Datas into Objective-C contexts, the class name is private and should not be emitted into clients.
+ // Consequently this should never be inlined.
+ @usableFromInline
+ @inline(never)
func bridgedReference(_ range: Range<Int>) -> NSData {
if range.isEmpty {
return NSData() // zero length data can be optimized as a singleton
}
-
- switch _backing {
- case .swift:
- return __NSSwiftData(backing: self, range: range)
- case .immutable(let d):
- guard range.lowerBound == 0 && range.upperBound == _length else {
- return __NSSwiftData(backing: self, range: range)
- }
- return d
- case .mutable(let d):
- guard range.lowerBound == 0 && range.upperBound == _length else {
- return __NSSwiftData(backing: self, range: range)
- }
- return d
- case .customReference(let d):
- guard range.lowerBound == 0 && range.upperBound == d.length else {
- return __NSSwiftData(backing: self, range: range)
- }
- return d
- case .customMutableReference(let d):
- guard range.lowerBound == 0 && range.upperBound == d.length else {
- return d.subdata(with: NSRange(location: range.lowerBound, length: range.count))._bridgeToObjectiveC()
- }
- return d.copy() as! NSData
- }
+
+ return __NSSwiftData(backing: self, range: range)
}
-
- @usableFromInline
+
+ @inlinable
func subdata(in range: Range<Data.Index>) -> Data {
- switch _backing {
- case .customReference(let d):
- return d.subdata(with: NSRange(location: range.lowerBound - _offset, length: range.count))
- case .customMutableReference(let d):
- return d.subdata(with: NSRange(location: range.lowerBound - _offset, length: range.count))
- default:
- return Data(bytes: _bytes!.advanced(by: range.lowerBound - _offset), count: range.count)
- }
+ return Data(bytes: _bytes!.advanced(by: range.lowerBound - _offset), count: range.upperBound - range.lowerBound)
}
}
@@ -992,17 +611,17 @@
internal class __NSSwiftData : NSData {
var _backing: _DataStorage!
var _range: Range<Data.Index>!
-
+
convenience init(backing: _DataStorage, range: Range<Data.Index>) {
self.init()
_backing = backing
_range = range
}
- override var length: Int {
- return _range.count
+ @objc override var length: Int {
+ return _range.upperBound - _range.lowerBound
}
-
- override var bytes: UnsafeRawPointer {
+
+ @objc override var bytes: UnsafeRawPointer {
// NSData's byte pointer methods are not annotated for nullability correctly
// (but assume non-null by the wrapping macro guards). This placeholder value
// is to work-around this bug. Any indirection to the underlying bytes of an NSData
@@ -1013,25 +632,25 @@
guard let bytes = _backing.bytes else {
return UnsafeRawPointer(bitPattern: 0xBAD0)!
}
-
+
return bytes.advanced(by: _range.lowerBound)
}
-
- override func copy(with zone: NSZone? = nil) -> Any {
+
+ @objc override func copy(with zone: NSZone? = nil) -> Any {
return self
}
-
- override func mutableCopy(with zone: NSZone? = nil) -> Any {
+
+ @objc override func mutableCopy(with zone: NSZone? = nil) -> Any {
return NSMutableData(bytes: bytes, length: length)
}
-
+
#if !DEPLOYMENT_RUNTIME_SWIFT
@objc override
func _isCompact() -> Bool {
return true
}
#endif
-
+
#if DEPLOYMENT_RUNTIME_SWIFT
override func _providesConcreteBacking() -> Bool {
return true
@@ -1044,21 +663,1206 @@
#endif
}
-public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
+@_fixed_layout
+public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, MutableDataProtocol, ContiguousBytes {
public typealias ReferenceType = NSData
-
+
public typealias ReadingOptions = NSData.ReadingOptions
public typealias WritingOptions = NSData.WritingOptions
public typealias SearchOptions = NSData.SearchOptions
public typealias Base64EncodingOptions = NSData.Base64EncodingOptions
public typealias Base64DecodingOptions = NSData.Base64DecodingOptions
-
+
public typealias Index = Int
public typealias Indices = Range<Int>
+
+ @usableFromInline
+ @_fixed_layout
+ internal struct InlineData {
+#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+ @usableFromInline
+ typealias Buffer = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
+ UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) //len //enum
+ @usableFromInline
+ var bytes: Buffer
+#elseif arch(i386) || arch(arm)
+ @usableFromInline
+ typealias Buffer = (UInt8, UInt8, UInt8, UInt8,
+ UInt8, UInt8) //len //enum
+ @usableFromInline
+ var bytes: Buffer
+#endif
+ @usableFromInline
+ var length: UInt8
+
+ @inlinable
+ static func canStore(count: Int) -> Bool {
+ return count <= MemoryLayout<Buffer>.size
+ }
+
+ @inlinable
+ init() {
+ self.init(count: 0)
+ }
+
+ @inlinable
+ init(_ srcBuffer: UnsafeRawBufferPointer) {
+ self.init(count: srcBuffer.count)
+ if srcBuffer.count > 0 {
+ Swift.withUnsafeMutableBytes(of: &bytes) { dstBuffer in
+ dstBuffer.baseAddress?.copyMemory(from: srcBuffer.baseAddress!, byteCount: srcBuffer.count)
+ }
+ }
+ }
+
+ @inlinable
+ init(count: Int) {
+ assert(count <= MemoryLayout<Buffer>.size)
+#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+ bytes = (UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0))
+#elseif arch(i386) || arch(arm)
+ bytes = (UInt8(0), UInt8(0), UInt8(0), UInt8(0),
+ UInt8(0), UInt8(0))
+#endif
+ length = UInt8(count)
+ }
+
+ @inlinable
+ init(_ slice: InlineSlice, count: Int) {
+ self.init(count: count)
+ Swift.withUnsafeMutableBytes(of: &bytes) { dstBuffer in
+ slice.withUnsafeBytes { srcBuffer in
+ dstBuffer.copyMemory(from: UnsafeRawBufferPointer(start: srcBuffer.baseAddress, count: count))
+ }
+ }
+ }
+
+ @inlinable
+ init(_ slice: LargeSlice, count: Int) {
+ self.init(count: count)
+ Swift.withUnsafeMutableBytes(of: &bytes) { dstBuffer in
+ slice.withUnsafeBytes { srcBuffer in
+ dstBuffer.copyMemory(from: UnsafeRawBufferPointer(start: srcBuffer.baseAddress, count: count))
+ }
+ }
+ }
+
+ @inlinable
+ var capacity: Int {
+ return MemoryLayout<Buffer>.size
+ }
+
+ @inlinable
+ var count: Int {
+ get {
+ return Int(length)
+ }
+ set(newValue) {
+ assert(newValue <= MemoryLayout<Buffer>.size)
+ length = UInt8(newValue)
+ }
+ }
+
+ @inlinable
+ var startIndex: Int { return 0 }
+
+ @inlinable
+ var endIndex: Int { return count }
+
+ @inlinable
+ func withUnsafeBytes<Result>(_ apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
+ let count = Int(length)
+ return try Swift.withUnsafeBytes(of: bytes) { (rawBuffer) throws -> Result in
+ return try apply(UnsafeRawBufferPointer(start: rawBuffer.baseAddress, count: count))
+ }
+ }
+
+ @inlinable
+ mutating func withUnsafeMutableBytes<Result>(_ apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
+ let count = Int(length)
+ return try Swift.withUnsafeMutableBytes(of: &bytes) { (rawBuffer) throws -> Result in
+ return try apply(UnsafeMutableRawBufferPointer(start: rawBuffer.baseAddress, count: count))
+ }
+ }
+
+ @inlinable
+ mutating func append(contentsOf buffer: UnsafeRawBufferPointer) {
+ guard buffer.count > 0 else { return }
+ assert(count + buffer.count <= MemoryLayout<Buffer>.size)
+ let cnt = count
+ _ = Swift.withUnsafeMutableBytes(of: &bytes) { rawBuffer in
+ rawBuffer.baseAddress?.advanced(by: cnt).copyMemory(from: buffer.baseAddress!, byteCount: buffer.count)
+ }
+ length += UInt8(buffer.count)
+
+ }
+
+ @inlinable
+ subscript(index: Index) -> UInt8 {
+ get {
+ assert(index <= MemoryLayout<Buffer>.size)
+ precondition(index < length, "index \(index) is out of bounds of 0..<\(length)")
+ return Swift.withUnsafeBytes(of: bytes) { rawBuffer -> UInt8 in
+ return rawBuffer[index]
+ }
+ }
+ set(newValue) {
+ assert(index <= MemoryLayout<Buffer>.size)
+ precondition(index < length, "index \(index) is out of bounds of 0..<\(length)")
+ Swift.withUnsafeMutableBytes(of: &bytes) { rawBuffer in
+ rawBuffer[index] = newValue
+ }
+ }
+ }
+
+ @inlinable
+ mutating func resetBytes(in range: Range<Index>) {
+ assert(range.lowerBound <= MemoryLayout<Buffer>.size)
+ assert(range.upperBound <= MemoryLayout<Buffer>.size)
+ precondition(range.lowerBound <= length, "index \(range.lowerBound) is out of bounds of 0..<\(length)")
+ if count < range.upperBound {
+ count = range.upperBound
+ }
+ let _ = Swift.withUnsafeMutableBytes(of: &bytes) { rawBuffer in
+ memset(rawBuffer.baseAddress?.advanced(by: range.lowerBound), 0, range.upperBound - range.lowerBound)
+ }
+ }
+
+ @inlinable
+ mutating func replaceSubrange(_ subrange: Range<Index>, with replacementBytes: UnsafeRawPointer?, count replacementLength: Int) {
+ assert(subrange.lowerBound <= MemoryLayout<Buffer>.size)
+ assert(subrange.upperBound <= MemoryLayout<Buffer>.size)
+ assert(count - (subrange.upperBound - subrange.lowerBound) + replacementLength <= MemoryLayout<Buffer>.size)
+ precondition(subrange.lowerBound <= length, "index \(subrange.lowerBound) is out of bounds of 0..<\(length)")
+ precondition(subrange.upperBound <= length, "index \(subrange.upperBound) is out of bounds of 0..<\(length)")
+ let currentLength = count
+ let resultingLength = currentLength - (subrange.upperBound - subrange.lowerBound) + replacementLength
+ let shift = resultingLength - currentLength
+ Swift.withUnsafeMutableBytes(of: &bytes) { mutableBytes in
+ /* shift the trailing bytes */
+ let start = subrange.lowerBound
+ let length = subrange.upperBound - subrange.lowerBound
+ if shift != 0 {
+ memmove(mutableBytes.baseAddress?.advanced(by: start + replacementLength), mutableBytes.baseAddress?.advanced(by: start + length), currentLength - start - length)
+ }
+ if replacementLength != 0 {
+ memmove(mutableBytes.baseAddress?.advanced(by: start), replacementBytes!, replacementLength)
+ }
+ }
+ count = resultingLength
+ }
+
+ @inlinable
+ func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
+ precondition(startIndex <= range.lowerBound, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(startIndex <= range.upperBound, "index \(range.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(range.upperBound <= endIndex, "index \(range.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+
+ Swift.withUnsafeBytes(of: bytes) {
+ let cnt = Swift.min($0.count, range.upperBound - range.lowerBound)
+ guard cnt > 0 else { return }
+ pointer.copyMemory(from: $0.baseAddress!.advanced(by: range.lowerBound), byteCount: cnt)
+ }
+ }
+
+ @inlinable
+ var hashValue: Int {
+ let count = Int(length)
+ return Swift.withUnsafeBytes(of: bytes) { (rawBuffer) -> Int in
+ return Int(bitPattern: CFHashBytes(UnsafeMutablePointer(mutating: rawBuffer.baseAddress?.assumingMemoryBound(to: UInt8.self)), count))
+ }
+ }
+ }
+
+#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
+ @usableFromInline
+ internal typealias HalfInt = Int32
+#elseif arch(i386) || arch(arm)
+ @usableFromInline
+ internal typealias HalfInt = Int16
+#endif
+
+ @usableFromInline
+ @_fixed_layout
+ internal struct InlineSlice {
+ // ***WARNING***
+ // These ivars are specifically laid out so that they cause the enum _Representation to be 16 bytes on 64 bit platforms. This means we _MUST_ have the class type thing last
+ @usableFromInline
+ var slice: Range<HalfInt>
+ @usableFromInline
+ var storage: _DataStorage
+
+ @inlinable
+ static func canStore(count: Int) -> Bool {
+ return count < HalfInt.max
+ }
+
+ @inlinable
+ init(_ buffer: UnsafeRawBufferPointer) {
+ assert(buffer.count < HalfInt.max)
+ self.init(_DataStorage(bytes: buffer.baseAddress, length: buffer.count), count: buffer.count)
+ }
+
+ @inlinable
+ init(capacity: Int) {
+ assert(capacity < HalfInt.max)
+ self.init(_DataStorage(capacity: capacity), count: 0)
+ }
+
+ @inlinable
+ init(count: Int) {
+ assert(count < HalfInt.max)
+ self.init(_DataStorage(length: count), count: count)
+ }
+
+ @inlinable
+ init(_ inline: InlineData) {
+ assert(inline.count < HalfInt.max)
+ self.init(inline.withUnsafeBytes { return _DataStorage(bytes: $0.baseAddress, length: $0.count) }, count: inline.count)
+ }
+
+ @inlinable
+ init(_ inline: InlineData, range: Range<Int>) {
+ assert(range.lowerBound < HalfInt.max)
+ assert(range.upperBound < HalfInt.max)
+ self.init(inline.withUnsafeBytes { return _DataStorage(bytes: $0.baseAddress, length: $0.count) }, range: range)
+ }
+
+ @inlinable
+ init(_ large: LargeSlice) {
+ assert(large.range.lowerBound < HalfInt.max)
+ assert(large.range.upperBound < HalfInt.max)
+ self.init(large.storage, range: large.range)
+ }
+
+ @inlinable
+ init(_ large: LargeSlice, range: Range<Int>) {
+ assert(range.lowerBound < HalfInt.max)
+ assert(range.upperBound < HalfInt.max)
+ self.init(large.storage, range: range)
+ }
+
+ @inlinable
+ init(_ storage: _DataStorage, count: Int) {
+ assert(count < HalfInt.max)
+ self.storage = storage
+ slice = 0..<HalfInt(count)
+ }
+
+ @inlinable
+ init(_ storage: _DataStorage, range: Range<Int>) {
+ assert(range.lowerBound < HalfInt.max)
+ assert(range.upperBound < HalfInt.max)
+ self.storage = storage
+ slice = HalfInt(range.lowerBound)..<HalfInt(range.upperBound)
+ }
+
+ @inlinable
+ mutating func ensureUniqueReference() {
+ if !isKnownUniquelyReferenced(&storage) {
+ storage = storage.mutableCopy(self.range)
+ }
+ }
+
+ @inlinable
+ var startIndex: Int { return Int(slice.lowerBound) }
+ @inlinable
+ var endIndex: Int { return Int(slice.upperBound) }
+
+ @inlinable
+ var capacity: Int {
+ return storage.capacity
+ }
+
+ @inlinable
+ mutating func reserveCapacity(_ minimumCapacity: Int) {
+ ensureUniqueReference()
+ // the current capacity can be zero (representing externally owned buffer), and count can be greater than the capacity
+ storage.ensureUniqueBufferReference(growingTo: Swift.max(minimumCapacity, count))
+ }
+
+ @inlinable
+ var count: Int {
+ get {
+ return Int(slice.upperBound - slice.lowerBound)
+ }
+ set(newValue) {
+ assert(newValue < HalfInt.max)
+ ensureUniqueReference()
+ storage.length = newValue
+ slice = slice.lowerBound..<(slice.lowerBound + HalfInt(newValue))
+ }
+ }
+
+ @inlinable
+ var range: Range<Int> {
+ get {
+ return Int(slice.lowerBound)..<Int(slice.upperBound)
+ }
+ set(newValue) {
+ assert(newValue.lowerBound < HalfInt.max)
+ assert(newValue.upperBound < HalfInt.max)
+ slice = HalfInt(newValue.lowerBound)..<HalfInt(newValue.upperBound)
+ }
+ }
+
+ @inlinable
+ func withUnsafeBytes<Result>(_ apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
+ return try storage.withUnsafeBytes(in: range, apply: apply)
+ }
+
+ @inlinable
+ mutating func withUnsafeMutableBytes<Result>(_ apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
+ ensureUniqueReference()
+ return try storage.withUnsafeMutableBytes(in: range, apply: apply)
+ }
+
+ @inlinable
+ mutating func append(contentsOf buffer: UnsafeRawBufferPointer) {
+ assert(endIndex + buffer.count < HalfInt.max)
+ ensureUniqueReference()
+ storage.replaceBytes(in: NSRange(location: range.upperBound, length: storage.length - (range.upperBound - storage._offset)), with: buffer.baseAddress, length: buffer.count)
+ slice = slice.lowerBound..<HalfInt(Int(slice.upperBound) + buffer.count)
+ }
+
+ @inlinable
+ subscript(index: Index) -> UInt8 {
+ get {
+ assert(index < HalfInt.max)
+ precondition(startIndex <= index, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(index < endIndex, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ return storage.get(index)
+ }
+ set(newValue) {
+ assert(index < HalfInt.max)
+ precondition(startIndex <= index, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(index < endIndex, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ ensureUniqueReference()
+ storage.set(index, to: newValue)
+ }
+ }
+
+ @inlinable
+ func bridgedReference() -> NSData {
+ return storage.bridgedReference(self.range)
+ }
+
+ @inlinable
+ mutating func resetBytes(in range: Range<Index>) {
+ assert(range.lowerBound < HalfInt.max)
+ assert(range.upperBound < HalfInt.max)
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ ensureUniqueReference()
+ storage.resetBytes(in: range)
+ if slice.upperBound < range.upperBound {
+ slice = slice.lowerBound..<HalfInt(range.upperBound)
+ }
+ }
+
+ @inlinable
+ mutating func replaceSubrange(_ subrange: Range<Index>, with bytes: UnsafeRawPointer?, count cnt: Int) {
+ precondition(startIndex <= subrange.lowerBound, "index \(subrange.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(subrange.lowerBound <= endIndex, "index \(subrange.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(startIndex <= subrange.upperBound, "index \(subrange.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(subrange.upperBound <= endIndex, "index \(subrange.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+
+ let nsRange = NSRange(location: subrange.lowerBound, length: subrange.upperBound - subrange.lowerBound)
+ ensureUniqueReference()
+ let upper = range.upperBound
+ storage.replaceBytes(in: nsRange, with: bytes, length: cnt)
+ let resultingUpper = upper - nsRange.length + cnt
+ slice = slice.lowerBound..<HalfInt(resultingUpper)
+ }
+
+ @inlinable
+ func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
+ precondition(startIndex <= range.lowerBound, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(startIndex <= range.upperBound, "index \(range.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(range.upperBound <= endIndex, "index \(range.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ storage.copyBytes(to: pointer, from: range)
+ }
+
+ @inlinable
+ var hashValue: Int {
+ let hashRange = startIndex..<Swift.min(startIndex + 80, endIndex)
+ return storage.withUnsafeBytes(in: hashRange) {
+ return Int(bitPattern: CFHashBytes(UnsafeMutablePointer(mutating: $0.baseAddress?.assumingMemoryBound(to: UInt8.self)), $0.count))
+ }
+ }
+ }
+
+ @usableFromInline
+ @_fixed_layout
+ internal final class RangeReference {
+ @usableFromInline
+ var range: Range<Int>
+
+ @inlinable
+ var lowerBound: Int { return range.lowerBound }
+
+ @inlinable
+ var upperBound: Int { return range.upperBound }
+
+ @inlinable
+ var count: Int { return range.upperBound - range.lowerBound }
+
+ @inlinable
+ init(_ range: Range<Int>) {
+ self.range = range
+ }
+ }
+
+ @usableFromInline
+ @_fixed_layout
+ internal struct LargeSlice {
+ // ***WARNING***
+ // These ivars are specifically laid out so that they cause the enum _Representation to be 16 bytes on 64 bit platforms. This means we _MUST_ have the class type thing last
+ @usableFromInline
+ var slice: RangeReference
+ @usableFromInline
+ var storage: _DataStorage
+
+ @inlinable
+ init(_ buffer: UnsafeRawBufferPointer) {
+ self.init(_DataStorage(bytes: buffer.baseAddress, length: buffer.count), count: buffer.count)
+ }
+
+ @inlinable
+ init(capacity: Int) {
+ self.init(_DataStorage(capacity: capacity), count: 0)
+ }
+
+ @inlinable
+ init(count: Int) {
+ self.init(_DataStorage(length: count), count: count)
+ }
+
+ @inlinable
+ init(_ inline: InlineData) {
+ self.init(inline.withUnsafeBytes { return _DataStorage(bytes: $0.baseAddress, length: $0.count) }, count: inline.count)
+ }
+
+ @inlinable
+ init(_ slice: InlineSlice) {
+ self.storage = slice.storage
+ self.slice = RangeReference(slice.range)
+ }
+
+ @inlinable
+ init(_ storage: _DataStorage, count: Int) {
+ self.storage = storage
+ slice = RangeReference(0..<count)
+ }
+
+ @inlinable
+ mutating func ensureUniqueReference() {
+ if !isKnownUniquelyReferenced(&storage) {
+ storage = storage.mutableCopy(range)
+ }
+ if !isKnownUniquelyReferenced(&slice) {
+ slice = RangeReference(range)
+ }
+ }
+
+ @inlinable
+ var startIndex: Int { return slice.range.lowerBound }
+
+ @inlinable
+ var endIndex: Int { return slice.range.upperBound }
+
+ @inlinable
+ var capacity: Int {
+ return storage.capacity
+ }
+
+ @inlinable
+ mutating func reserveCapacity(_ minimumCapacity: Int) {
+ ensureUniqueReference()
+ // the current capacity can be zero (representing externally owned buffer), and count can be greater than the capacity
+ storage.ensureUniqueBufferReference(growingTo: Swift.max(minimumCapacity, count))
+ }
+
+ @inlinable
+ var count: Int {
+ get {
+ return slice.count
+ }
+ set(newValue) {
+ ensureUniqueReference()
+ storage.length = newValue
+ slice.range = slice.range.lowerBound..<(slice.range.lowerBound + newValue)
+ }
+ }
+
+ @inlinable
+ var range: Range<Int> { return slice.range }
+
+ @inlinable
+ func withUnsafeBytes<Result>(_ apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
+ return try storage.withUnsafeBytes(in: range, apply: apply)
+ }
+
+ @inlinable
+ mutating func withUnsafeMutableBytes<Result>(_ apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
+ ensureUniqueReference()
+ return try storage.withUnsafeMutableBytes(in: range, apply: apply)
+ }
+
+ @inlinable
+ mutating func append(contentsOf buffer: UnsafeRawBufferPointer) {
+ ensureUniqueReference()
+ storage.replaceBytes(in: NSRange(location: range.upperBound, length: storage.length - (range.upperBound - storage._offset)), with: buffer.baseAddress, length: buffer.count)
+ slice.range = slice.range.lowerBound..<slice.range.upperBound + buffer.count
+ }
+
+ @inlinable
+ subscript(index: Index) -> UInt8 {
+ get {
+ precondition(startIndex <= index, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(index < endIndex, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ return storage.get(index)
+ }
+ set(newValue) {
+ precondition(startIndex <= index, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(index < endIndex, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
+ ensureUniqueReference()
+ storage.set(index, to: newValue)
+ }
+ }
+
+ @inlinable
+ func bridgedReference() -> NSData {
+ return storage.bridgedReference(self.range)
+ }
+
+ @inlinable
+ mutating func resetBytes(in range: Range<Int>) {
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ ensureUniqueReference()
+ storage.resetBytes(in: range)
+ if slice.range.upperBound < range.upperBound {
+ slice.range = slice.range.lowerBound..<range.upperBound
+ }
+ }
+
+ @inlinable
+ mutating func replaceSubrange(_ subrange: Range<Index>, with bytes: UnsafeRawPointer?, count cnt: Int) {
+ precondition(startIndex <= subrange.lowerBound, "index \(subrange.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(subrange.lowerBound <= endIndex, "index \(subrange.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(startIndex <= subrange.upperBound, "index \(subrange.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(subrange.upperBound <= endIndex, "index \(subrange.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+
+ let nsRange = NSRange(location: subrange.lowerBound, length: subrange.upperBound - subrange.lowerBound)
+ ensureUniqueReference()
+ let upper = range.upperBound
+ storage.replaceBytes(in: nsRange, with: bytes, length: cnt)
+ let resultingUpper = upper - nsRange.length + cnt
+ slice.range = slice.range.lowerBound..<resultingUpper
+ }
+
+ @inlinable
+ func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
+ precondition(startIndex <= range.lowerBound, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(startIndex <= range.upperBound, "index \(range.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ precondition(range.upperBound <= endIndex, "index \(range.upperBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ storage.copyBytes(to: pointer, from: range)
+ }
+
+ @inlinable
+ var hashValue: Int {
+ let hashRange = startIndex..<Swift.min(startIndex + 80, endIndex)
+ return storage.withUnsafeBytes(in: hashRange) {
+ return Int(bitPattern: CFHashBytes(UnsafeMutablePointer(mutating: $0.baseAddress?.assumingMemoryBound(to: UInt8.self)), CFIndex($0.count)))
+ }
+ }
+ }
+
+ @usableFromInline
+ @_frozen
+ internal enum _Representation {
+ case empty
+ case inline(InlineData)
+ case slice(InlineSlice)
+ case large(LargeSlice)
+
+ @inlinable
+ init(_ buffer: UnsafeRawBufferPointer) {
+ if buffer.count == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: buffer.count) {
+ self = .inline(InlineData(buffer))
+ } else if InlineSlice.canStore(count: buffer.count) {
+ self = .slice(InlineSlice(buffer))
+ } else {
+ self = .large(LargeSlice(buffer))
+ }
+ }
+
+ @inlinable
+ init(_ buffer: UnsafeRawBufferPointer, owner: AnyObject) {
+ if buffer.count == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: buffer.count) {
+ self = .inline(InlineData(buffer))
+ } else {
+ let count = buffer.count
+ let storage = _DataStorage(bytes: UnsafeMutableRawPointer(mutating: buffer.baseAddress), length: count, copy: false, deallocator: { _, _ in
+ _fixLifetime(owner)
+ }, offset: 0)
+ if InlineSlice.canStore(count: count) {
+ self = .slice(InlineSlice(storage, count: count))
+ } else {
+ self = .large(LargeSlice(storage, count: count))
+ }
+ }
+ }
+
+ @inlinable
+ init(capacity: Int) {
+ if capacity == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: capacity) {
+ self = .inline(InlineData())
+ } else if InlineSlice.canStore(count: capacity) {
+ self = .slice(InlineSlice(capacity: capacity))
+ } else {
+ self = .large(LargeSlice(capacity: capacity))
+ }
+ }
+
+ @inlinable
+ init(count: Int) {
+ if count == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: count) {
+ self = .inline(InlineData(count: count))
+ } else if InlineSlice.canStore(count: count) {
+ self = .slice(InlineSlice(count: count))
+ } else {
+ self = .large(LargeSlice(count: count))
+ }
+ }
+
+ @inlinable
+ init(_ storage: _DataStorage, count: Int) {
+ if count == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: count) {
+ self = .inline(storage.withUnsafeBytes(in: 0..<count) { InlineData($0) })
+ } else if InlineSlice.canStore(count: count) {
+ self = .slice(InlineSlice(storage, count: count))
+ } else {
+ self = .large(LargeSlice(storage, count: count))
+ }
+ }
+
+ @inlinable
+ mutating func reserveCapacity(_ minimumCapacity: Int) {
+ guard minimumCapacity > 0 else { return }
+ switch self {
+ case .empty:
+ if InlineData.canStore(count: minimumCapacity) {
+ self = .inline(InlineData())
+ } else if InlineSlice.canStore(count: minimumCapacity) {
+ self = .slice(InlineSlice(capacity: minimumCapacity))
+ } else {
+ self = .large(LargeSlice(capacity: minimumCapacity))
+ }
+ case .inline(let inline):
+ guard minimumCapacity > inline.capacity else { return }
+ // we know we are going to be heap promoted
+ if InlineSlice.canStore(count: minimumCapacity) {
+ var slice = InlineSlice(inline)
+ slice.reserveCapacity(minimumCapacity)
+ self = .slice(slice)
+ } else {
+ var slice = LargeSlice(inline)
+ slice.reserveCapacity(minimumCapacity)
+ self = .large(slice)
+ }
+ case .slice(var slice):
+ guard minimumCapacity > slice.capacity else { return }
+ if InlineSlice.canStore(count: minimumCapacity) {
+ self = .empty
+ slice.reserveCapacity(minimumCapacity)
+ self = .slice(slice)
+ } else {
+ var large = LargeSlice(slice)
+ large.reserveCapacity(minimumCapacity)
+ self = .large(large)
+ }
+ case .large(var slice):
+ guard minimumCapacity > slice.capacity else { return }
+ self = .empty
+ slice.reserveCapacity(minimumCapacity)
+ self = .large(slice)
+ }
+ }
+
+ @inlinable
+ var count: Int {
+ get {
+ switch self {
+ case .empty: return 0
+ case .inline(let inline): return inline.count
+ case .slice(let slice): return slice.count
+ case .large(let slice): return slice.count
+ }
+ }
+ set(newValue) {
+ @inline(__always)
+ func apply(_ representation: inout _Representation, _ newValue: Int) -> _Representation? {
+ switch representation {
+ case .empty:
+ if newValue == 0 {
+ return nil
+ } else if InlineData.canStore(count: newValue) {
+ return .inline(InlineData())
+ } else if InlineSlice.canStore(count: newValue) {
+ return .slice(InlineSlice(count: newValue))
+ } else {
+ return .large(LargeSlice(count: newValue))
+ }
+ case .inline(var inline):
+ if newValue == 0 {
+ return .empty
+ } else if InlineData.canStore(count: newValue) {
+ guard inline.count != newValue else { return nil }
+ inline.count = newValue
+ return .inline(inline)
+ } else if InlineSlice.canStore(count: newValue) {
+ var slice = InlineSlice(inline)
+ slice.count = newValue
+ return .slice(slice)
+ } else {
+ var slice = LargeSlice(inline)
+ slice.count = newValue
+ return .large(slice)
+ }
+ case .slice(var slice):
+ if newValue == 0 && slice.startIndex == 0 {
+ return .empty
+ } else if slice.startIndex == 0 && InlineData.canStore(count: newValue) {
+ return .inline(InlineData(slice, count: newValue))
+ } else if InlineSlice.canStore(count: newValue + slice.startIndex) {
+ guard slice.count != newValue else { return nil }
+ representation = .empty // TODO: remove this when mgottesman lands optimizations
+ slice.count = newValue
+ return .slice(slice)
+ } else {
+ var newSlice = LargeSlice(slice)
+ newSlice.count = newValue
+ return .large(newSlice)
+ }
+ case .large(var slice):
+ if newValue == 0 && slice.startIndex == 0 {
+ return .empty
+ } else if slice.startIndex == 0 && InlineData.canStore(count: newValue) {
+ return .inline(InlineData(slice, count: newValue))
+ } else {
+ guard slice.count != newValue else { return nil}
+ representation = .empty // TODO: remove this when mgottesman lands optimizations
+ slice.count = newValue
+ return .large(slice)
+ }
+ }
+ }
+
+ if let rep = apply(&self, newValue) {
+ self = rep
+ }
+ }
+ }
+
+ @inlinable
+ func withUnsafeBytes<Result>(_ apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
+ switch self {
+ case .empty:
+ let empty = InlineData()
+ return try empty.withUnsafeBytes(apply)
+ case .inline(let inline):
+ return try inline.withUnsafeBytes(apply)
+ case .slice(let slice):
+ return try slice.withUnsafeBytes(apply)
+ case .large(let slice):
+ return try slice.withUnsafeBytes(apply)
+ }
+ }
+
+ @inlinable
+ mutating func withUnsafeMutableBytes<Result>(_ apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
+ switch self {
+ case .empty:
+ var empty = InlineData()
+ return try empty.withUnsafeMutableBytes(apply)
+ case .inline(var inline):
+ defer { self = .inline(inline) }
+ return try inline.withUnsafeMutableBytes(apply)
+ case .slice(var slice):
+ self = .empty
+ defer { self = .slice(slice) }
+ return try slice.withUnsafeMutableBytes(apply)
+ case .large(var slice):
+ self = .empty
+ defer { self = .large(slice) }
+ return try slice.withUnsafeMutableBytes(apply)
+ }
+ }
+
+ @inlinable
+ func withInteriorPointerReference<T>(_ work: (NSData) throws -> T) rethrows -> T {
+ switch self {
+ case .empty:
+ return try work(NSData())
+ case .inline(let inline):
+ return try inline.withUnsafeBytes {
+ return try work(NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: $0.baseAddress ?? UnsafeRawPointer(bitPattern: 0xBAD0)!), length: $0.count, freeWhenDone: false))
+ }
+ case .slice(let slice):
+ return try slice.storage.withInteriorPointerReference(slice.range, work)
+ case .large(let slice):
+ return try slice.storage.withInteriorPointerReference(slice.range, work)
+ }
+ }
+
+ @inlinable
+ func enumerateBytes(_ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Index, _ stop: inout Bool) -> Void) {
+ switch self {
+ case .empty:
+ var stop = false
+ block(UnsafeBufferPointer<UInt8>(start: nil, count: 0), 0, &stop)
+ case .inline(let inline):
+ inline.withUnsafeBytes {
+ var stop = false
+ block(UnsafeBufferPointer<UInt8>(start: $0.baseAddress?.assumingMemoryBound(to: UInt8.self), count: $0.count), 0, &stop)
+ }
+ case .slice(let slice):
+ slice.storage.enumerateBytes(in: slice.range, block)
+ case .large(let slice):
+ slice.storage.enumerateBytes(in: slice.range, block)
+ }
+ }
+
+ @inlinable
+ mutating func append(contentsOf buffer: UnsafeRawBufferPointer) {
+ switch self {
+ case .empty:
+ self = _Representation(buffer)
+ case .inline(var inline):
+ if InlineData.canStore(count: inline.count + buffer.count) {
+ inline.append(contentsOf: buffer)
+ self = .inline(inline)
+ } else if InlineSlice.canStore(count: inline.count + buffer.count) {
+ var newSlice = InlineSlice(inline)
+ newSlice.append(contentsOf: buffer)
+ self = .slice(newSlice)
+ } else {
+ var newSlice = LargeSlice(inline)
+ newSlice.append(contentsOf: buffer)
+ self = .large(newSlice)
+ }
+ case .slice(var slice):
+ if InlineSlice.canStore(count: slice.range.upperBound + buffer.count) {
+ self = .empty
+ defer { self = .slice(slice) }
+ slice.append(contentsOf: buffer)
+ } else {
+ self = .empty
+ var newSlice = LargeSlice(slice)
+ newSlice.append(contentsOf: buffer)
+ self = .large(newSlice)
+ }
+ case .large(var slice):
+ self = .empty
+ defer { self = .large(slice) }
+ slice.append(contentsOf: buffer)
+ }
+ }
+
+ @inlinable
+ mutating func resetBytes(in range: Range<Index>) {
+ switch self {
+ case .empty:
+ if range.upperBound == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: range.upperBound) {
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ self = .inline(InlineData(count: range.upperBound))
+ } else if InlineSlice.canStore(count: range.upperBound) {
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ self = .slice(InlineSlice(count: range.upperBound))
+ } else {
+ precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
+ self = .large(LargeSlice(count: range.upperBound))
+ }
+ break
+ case .inline(var inline):
+
+ if inline.count < range.upperBound {
+ if InlineSlice.canStore(count: range.upperBound) {
+ var slice = InlineSlice(inline)
+ slice.resetBytes(in: range)
+ self = .slice(slice)
+ } else {
+ var slice = LargeSlice(inline)
+ slice.resetBytes(in: range)
+ self = .large(slice)
+ }
+ } else {
+ inline.resetBytes(in: range)
+ self = .inline(inline)
+ }
+ break
+ case .slice(var slice):
+ if InlineSlice.canStore(count: range.upperBound) {
+ self = .empty
+ slice.resetBytes(in: range)
+ self = .slice(slice)
+ } else {
+ self = .empty
+ var newSlice = LargeSlice(slice)
+ newSlice.resetBytes(in: range)
+ self = .large(newSlice)
+ }
+ break
+ case .large(var slice):
+ self = .empty
+ slice.resetBytes(in: range)
+ self = .large(slice)
+ }
+ }
+
+ @inlinable
+ mutating func replaceSubrange(_ subrange: Range<Index>, with bytes: UnsafeRawPointer?, count cnt: Int) {
+ switch self {
+ case .empty:
+ precondition(subrange.lowerBound == 0 && subrange.upperBound == 0, "range \(subrange) out of bounds of 0..<0")
+ if cnt == 0 {
+ return
+ } else if InlineData.canStore(count: cnt) {
+ self = .inline(InlineData(UnsafeRawBufferPointer(start: bytes, count: cnt)))
+ } else if InlineSlice.canStore(count: cnt) {
+ self = .slice(InlineSlice(UnsafeRawBufferPointer(start: bytes, count: cnt)))
+ } else {
+ self = .large(LargeSlice(UnsafeRawBufferPointer(start: bytes, count: cnt)))
+ }
+ break
+ case .inline(var inline):
+ let resultingCount = inline.count + cnt - (subrange.upperBound - subrange.lowerBound)
+ if resultingCount == 0 {
+ self = .empty
+ } else if InlineData.canStore(count: resultingCount) {
+ inline.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .inline(inline)
+ } else if InlineSlice.canStore(count: resultingCount) {
+ var slice = InlineSlice(inline)
+ slice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .slice(slice)
+ } else {
+ var slice = LargeSlice(inline)
+ slice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .large(slice)
+ }
+ break
+ case .slice(var slice):
+ let resultingUpper = slice.endIndex + cnt - (subrange.upperBound - subrange.lowerBound)
+ if slice.startIndex == 0 && resultingUpper == 0 {
+ self = .empty
+ } else if slice.startIndex == 0 && InlineData.canStore(count: resultingUpper) {
+ self = .empty
+ slice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .inline(InlineData(slice, count: slice.count))
+ } else if InlineSlice.canStore(count: resultingUpper) {
+ self = .empty
+ slice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .slice(slice)
+ } else {
+ self = .empty
+ var newSlice = LargeSlice(slice)
+ newSlice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .large(newSlice)
+ }
+ case .large(var slice):
+ let resultingUpper = slice.endIndex + cnt - (subrange.upperBound - subrange.lowerBound)
+ if slice.startIndex == 0 && resultingUpper == 0 {
+ self = .empty
+ } else if slice.startIndex == 0 && InlineData.canStore(count: resultingUpper) {
+ var inline = InlineData(count: resultingUpper)
+ inline.withUnsafeMutableBytes { inlineBuffer in
+ if cnt > 0 {
+ inlineBuffer.baseAddress?.advanced(by: subrange.lowerBound).copyMemory(from: bytes!, byteCount: cnt)
+ }
+ slice.withUnsafeBytes { buffer in
+ if subrange.lowerBound > 0 {
+ inlineBuffer.baseAddress?.copyMemory(from: buffer.baseAddress!, byteCount: subrange.lowerBound)
+ }
+ if subrange.upperBound < resultingUpper {
+ inlineBuffer.baseAddress?.advanced(by: subrange.upperBound).copyMemory(from: buffer.baseAddress!.advanced(by: subrange.upperBound), byteCount: resultingUpper - subrange.upperBound)
+ }
+ }
+ }
+ self = .inline(inline)
+ } else if InlineSlice.canStore(count: slice.startIndex) && InlineSlice.canStore(count: resultingUpper) {
+ self = .empty
+ var newSlice = InlineSlice(slice)
+ newSlice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .slice(newSlice)
+ } else {
+ self = .empty
+ slice.replaceSubrange(subrange, with: bytes, count: cnt)
+ self = .large(slice)
+ }
+ }
+ }
+
+ @inlinable
+ subscript(index: Index) -> UInt8 {
+ get {
+ switch self {
+ case .empty: preconditionFailure("index \(index) out of range of 0")
+ case .inline(let inline): return inline[index]
+ case .slice(let slice): return slice[index]
+ case .large(let slice): return slice[index]
+ }
+ }
+ set(newValue) {
+ switch self {
+ case .empty: preconditionFailure("index \(index) out of range of 0")
+ case .inline(var inline):
+ inline[index] = newValue
+ self = .inline(inline)
+ case .slice(var slice):
+ self = .empty
+ slice[index] = newValue
+ self = .slice(slice)
+ case .large(var slice):
+ self = .empty
+ slice[index] = newValue
+ self = .large(slice)
+ }
+ }
+ }
+
+ @inlinable
+ subscript(bounds: Range<Index>) -> Data {
+ get {
+ switch self {
+ case .empty:
+ precondition(bounds.lowerBound == 0 && (bounds.upperBound - bounds.lowerBound) == 0, "Range \(bounds) out of bounds 0..<0")
+ return Data()
+ case .inline(let inline):
+ precondition(bounds.upperBound <= inline.count, "Range \(bounds) out of bounds 0..<\(inline.count)")
+ if bounds.lowerBound == 0 {
+ var newInline = inline
+ newInline.count = bounds.upperBound
+ return Data(representation: .inline(newInline))
+ } else {
+ return Data(representation: .slice(InlineSlice(inline, range: bounds)))
+ }
+ case .slice(let slice):
+ precondition(slice.startIndex <= bounds.lowerBound, "Range \(bounds) out of bounds \(slice.range)")
+ precondition(bounds.lowerBound <= slice.endIndex, "Range \(bounds) out of bounds \(slice.range)")
+ precondition(slice.startIndex <= bounds.upperBound, "Range \(bounds) out of bounds \(slice.range)")
+ precondition(bounds.upperBound <= slice.endIndex, "Range \(bounds) out of bounds \(slice.range)")
+ if bounds.lowerBound == 0 && bounds.upperBound == 0 {
+ return Data()
+ } else if bounds.lowerBound == 0 && InlineData.canStore(count: bounds.count) {
+ return Data(representation: .inline(InlineData(slice, count: bounds.count)))
+ } else {
+ var newSlice = slice
+ newSlice.range = bounds
+ return Data(representation: .slice(newSlice))
+ }
+ case .large(let slice):
+ precondition(slice.startIndex <= bounds.lowerBound, "Range \(bounds) out of bounds \(slice.range)")
+ precondition(bounds.lowerBound <= slice.endIndex, "Range \(bounds) out of bounds \(slice.range)")
+ precondition(slice.startIndex <= bounds.upperBound, "Range \(bounds) out of bounds \(slice.range)")
+ precondition(bounds.upperBound <= slice.endIndex, "Range \(bounds) out of bounds \(slice.range)")
+ if bounds.lowerBound == 0 && bounds.upperBound == 0 {
+ return Data()
+ } else if bounds.lowerBound == 0 && InlineData.canStore(count: bounds.upperBound) {
+ return Data(representation: .inline(InlineData(slice, count: bounds.upperBound)))
+ } else if InlineSlice.canStore(count: bounds.lowerBound) && InlineSlice.canStore(count: bounds.upperBound) {
+ return Data(representation: .slice(InlineSlice(slice, range: bounds)))
+ } else {
+ var newSlice = slice
+ newSlice.slice = RangeReference(bounds)
+ return Data(representation: .large(newSlice))
+ }
+ }
+ }
+ }
+
+ @inlinable
+ var startIndex: Int {
+ switch self {
+ case .empty: return 0
+ case .inline: return 0
+ case .slice(let slice): return slice.startIndex
+ case .large(let slice): return slice.startIndex
+ }
+ }
+
+ @inlinable
+ var endIndex: Int {
+ switch self {
+ case .empty: return 0
+ case .inline(let inline): return inline.count
+ case .slice(let slice): return slice.endIndex
+ case .large(let slice): return slice.endIndex
+ }
+ }
+
+ @inlinable
+ func bridgedReference() -> NSData {
+ switch self {
+ case .empty: return NSData()
+ case .inline(let inline):
+ return inline.withUnsafeBytes {
+ return NSData(bytes: $0.baseAddress, length: $0.count)
+ }
+ case .slice(let slice):
+ return slice.bridgedReference()
+ case .large(let slice):
+ return slice.bridgedReference()
+ }
+ }
+
+ @inlinable
+ func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
+ switch self {
+ case .empty:
+ precondition(range.lowerBound == 0 && range.upperBound == 0, "Range \(range) out of bounds 0..<0")
+ return
+ case .inline(let inline):
+ inline.copyBytes(to: pointer, from: range)
+ break
+ case .slice(let slice):
+ slice.copyBytes(to: pointer, from: range)
+ case .large(let slice):
+ slice.copyBytes(to: pointer, from: range)
+ }
+ }
+
+ @inlinable
+ var hashValue: Int {
+ switch self {
+ case .empty:
+ return Int(bitPattern: CFHashBytes(nil, 0))
+ case .inline(let inline):
+ return inline.hashValue
+ case .slice(let slice):
+ return slice.hashValue
+ case .large(let slice):
+ return slice.hashValue
+ }
+ }
+ }
- @usableFromInline internal var _backing : _DataStorage
- @usableFromInline internal var _sliceRange: Range<Index>
-
+ @usableFromInline internal var _representation: _Representation
// A standard or custom deallocator for `Data`.
///
@@ -1081,7 +1885,8 @@
/// A custom deallocator.
case custom((UnsafeMutableRawPointer, Int) -> Void)
- fileprivate var _deallocator : ((UnsafeMutableRawPointer, Int) -> Void) {
+ @usableFromInline
+ internal var _deallocator : ((UnsafeMutableRawPointer, Int) -> Void) {
#if DEPLOYMENT_RUNTIME_SWIFT
switch self {
case .unmap:
@@ -1091,9 +1896,7 @@
case .none:
return { _, _ in }
case .custom(let b):
- return { (ptr, len) in
- b(ptr, len)
- }
+ return b
}
#else
switch self {
@@ -1106,9 +1909,7 @@
case .none:
return { _, _ in }
case .custom(let b):
- return { (ptr, len) in
- b(ptr, len)
- }
+ return b
}
#endif
}
@@ -1121,37 +1922,36 @@
///
/// - parameter bytes: A pointer to the memory. It will be copied.
/// - parameter count: The number of bytes to copy.
+ @inlinable
public init(bytes: UnsafeRawPointer, count: Int) {
- _backing = _DataStorage(bytes: bytes, length: count)
- _sliceRange = 0..<count
+ _representation = _Representation(UnsafeRawBufferPointer(start: bytes, count: count))
}
-
+
/// Initialize a `Data` with copied memory content.
///
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
+ @inlinable
public init<SourceType>(buffer: UnsafeBufferPointer<SourceType>) {
- let count = MemoryLayout<SourceType>.stride * buffer.count
- _backing = _DataStorage(bytes: buffer.baseAddress, length: count)
- _sliceRange = 0..<count
+ _representation = _Representation(UnsafeRawBufferPointer(buffer))
}
/// Initialize a `Data` with copied memory content.
///
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
+ @inlinable
public init<SourceType>(buffer: UnsafeMutableBufferPointer<SourceType>) {
- let count = MemoryLayout<SourceType>.stride * buffer.count
- _backing = _DataStorage(bytes: buffer.baseAddress, length: count)
- _sliceRange = 0..<count
+ _representation = _Representation(UnsafeRawBufferPointer(buffer))
}
/// Initialize a `Data` with a repeating byte pattern
///
/// - parameter repeatedValue: A byte to initialize the pattern
/// - parameter count: The number of bytes the data initially contains initialized to the repeatedValue
+ @inlinable
public init(repeating repeatedValue: UInt8, count: Int) {
self.init(count: count)
- withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) -> Void in
- memset(bytes, Int32(repeatedValue), count)
+ withUnsafeMutableBytes { (buffer: UnsafeMutableRawBufferPointer) -> Void in
+ memset(buffer.baseAddress, Int32(repeatedValue), buffer.count)
}
}
@@ -1164,23 +1964,23 @@
/// If the capacity specified in `capacity` is greater than four memory pages in size, this may round the amount of requested memory up to the nearest full page.
///
/// - parameter capacity: The size of the data.
+ @inlinable
public init(capacity: Int) {
- _backing = _DataStorage(capacity: capacity)
- _sliceRange = 0..<0
+ _representation = _Representation(capacity: capacity)
}
/// Initialize a `Data` with the specified count of zeroed bytes.
///
/// - parameter count: The number of bytes the data initially contains.
+ @inlinable
public init(count: Int) {
- _backing = _DataStorage(length: count)
- _sliceRange = 0..<count
+ _representation = _Representation(count: count)
}
/// Initialize an empty `Data`.
+ @inlinable
public init() {
- _backing = _DataStorage(length: 0)
- _sliceRange = 0..<0
+ _representation = .empty
}
@@ -1190,10 +1990,15 @@
/// - parameter bytes: A pointer to the bytes.
/// - parameter count: The size of the bytes.
/// - parameter deallocator: Specifies the mechanism to free the indicated buffer, or `.none`.
+ @inlinable
public init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Deallocator) {
let whichDeallocator = deallocator._deallocator
- _backing = _DataStorage(bytes: bytes, length: count, copy: false, deallocator: whichDeallocator, offset: 0)
- _sliceRange = 0..<count
+ if count == 0 {
+ deallocator._deallocator(bytes, count)
+ _representation = .empty
+ } else {
+ _representation = _Representation(_DataStorage(bytes: bytes, length: count, copy: false, deallocator: whichDeallocator, offset: 0), count: count)
+ }
}
/// Initialize a `Data` with the contents of a `URL`.
@@ -1201,10 +2006,10 @@
/// - parameter url: The `URL` to read.
/// - parameter options: Options for the read operation. Default value is `[]`.
/// - throws: An error in the Cocoa domain, if `url` cannot be read.
+ @inlinable
public init(contentsOf url: __shared URL, options: Data.ReadingOptions = []) throws {
let d = try NSData(contentsOf: url, options: ReadingOptions(rawValue: options.rawValue))
- _backing = _DataStorage(immutableReference: d, offset: 0)
- _sliceRange = 0..<d.length
+ self.init(bytes: d.bytes, count: d.length)
}
/// Initialize a `Data` from a Base-64 encoded String using the given options.
@@ -1212,10 +2017,10 @@
/// Returns nil when the input is not recognized as valid Base-64.
/// - parameter base64String: The string to parse.
/// - parameter options: Encoding options. Default value is `[]`.
+ @inlinable
public init?(base64Encoded base64String: __shared String, options: Data.Base64DecodingOptions = []) {
if let d = NSData(base64Encoded: base64String, options: Base64DecodingOptions(rawValue: options.rawValue)) {
- _backing = _DataStorage(immutableReference: d, offset: 0)
- _sliceRange = 0..<d.length
+ self.init(bytes: d.bytes, count: d.length)
} else {
return nil
}
@@ -1227,10 +2032,10 @@
///
/// - parameter base64Data: Base-64, UTF-8 encoded input data.
/// - parameter options: Decoding options. Default value is `[]`.
+ @inlinable
public init?(base64Encoded base64Data: __shared Data, options: Data.Base64DecodingOptions = []) {
if let d = NSData(base64Encoded: base64Data, options: Base64DecodingOptions(rawValue: options.rawValue)) {
- _backing = _DataStorage(immutableReference: d, offset: 0)
- _sliceRange = 0..<d.length
+ self.init(bytes: d.bytes, count: d.length)
} else {
return nil
}
@@ -1244,35 +2049,71 @@
///
/// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
public init(referencing reference: __shared NSData) {
-#if DEPLOYMENT_RUNTIME_SWIFT
- let providesConcreteBacking = reference._providesConcreteBacking()
-#else
- let providesConcreteBacking = (reference as AnyObject)._providesConcreteBacking?() ?? false
-#endif
- if providesConcreteBacking {
- _backing = _DataStorage(immutableReference: reference.copy() as! NSData, offset: 0)
- _sliceRange = 0..<reference.length
+ // This is not marked as inline because _providesConcreteBacking would need to be marked as usable from inline however that is a dynamic lookup in objc contexts.
+ let length = reference.length
+ if length == 0 {
+ _representation = .empty
} else {
- _backing = _DataStorage(customReference: reference.copy() as! NSData, offset: 0)
- _sliceRange = 0..<reference.length
+#if DEPLOYMENT_RUNTIME_SWIFT
+ let providesConcreteBacking = reference._providesConcreteBacking()
+#else
+ let providesConcreteBacking = (reference as AnyObject)._providesConcreteBacking?() ?? false
+#endif
+ if providesConcreteBacking {
+ _representation = _Representation(_DataStorage(immutableReference: reference.copy() as! NSData, offset: 0), count: length)
+ } else {
+ _representation = _Representation(_DataStorage(customReference: reference.copy() as! NSData, offset: 0), count: length)
+ }
}
}
// slightly faster paths for common sequences
@inlinable
- public init<S: Sequence>(_ elements: S) where S.Iterator.Element == UInt8 {
- let backing = _DataStorage(capacity: Swift.max(elements.underestimatedCount, 1))
- var (iter, endIndex) = elements._copyContents(initializing: UnsafeMutableBufferPointer(start: backing._bytes?.bindMemory(to: UInt8.self, capacity: backing._capacity), count: backing._capacity))
- backing._length = endIndex
- while var element = iter.next() {
- backing.append(&element, length: 1)
+ @inline(__always)
+ public init<S: Sequence>(_ elements: S) where S.Element == UInt8 {
+ // If the sequence is already contiguous, access the underlying raw memory directly.
+ if let contiguous = elements as? ContiguousBytes {
+ _representation = contiguous.withUnsafeBytes { return _Representation($0) }
+ return
}
- self.init(backing: backing, range: 0..<backing._length)
+
+ // The sequence might still be able to provide direct access to typed memory.
+ // NOTE: It's safe to do this because we're already guarding on S's element as `UInt8`. This would not be safe on arbitrary sequences.
+ let representation = elements.withContiguousStorageIfAvailable {
+ return _Representation(UnsafeRawBufferPointer($0))
+ }
+
+ if let representation = representation {
+ _representation = representation
+ } else {
+ // Dummy assignment so we can capture below.
+ _representation = _Representation(capacity: 0)
+
+ // Copy as much as we can in one shot from the sequence.
+ let underestimatedCount = Swift.max(elements.underestimatedCount, 1)
+ _withStackOrHeapBuffer(underestimatedCount) { (buffer) in
+ // In order to copy from the sequence, we have to bind the buffer to UInt8.
+ // This is safe since we'll copy out of this buffer as raw memory later.
+ let capacity = buffer.pointee.capacity
+ let base = buffer.pointee.memory.bindMemory(to: UInt8.self, capacity: capacity)
+ var (iter, endIndex) = elements._copyContents(initializing: UnsafeMutableBufferPointer(start: base, count: capacity))
+
+ // Copy the contents of buffer...
+ _representation = _Representation(UnsafeRawBufferPointer(start: base, count: endIndex))
+
+ // ... and append the rest byte-wise.
+ while let element = iter.next() {
+ Swift.withUnsafeBytes(of: element) {
+ _representation.append(contentsOf: $0)
+ }
+ }
+ }
+ }
}
@available(swift, introduced: 4.2)
- @inlinable
+ @available(swift, deprecated: 5, message: "use `init(_:)` instead")
public init<S: Sequence>(bytes elements: S) where S.Iterator.Element == UInt8 {
self.init(elements)
}
@@ -1286,68 +2127,67 @@
public init(bytes: ArraySlice<UInt8>) {
self.init(bytes)
}
-
- @usableFromInline
- internal init(backing: _DataStorage, range: Range<Index>) {
- _backing = backing
- _sliceRange = range
- }
- @usableFromInline
- internal func _validateIndex(_ index: Int, message: String? = nil) {
- precondition(_sliceRange.contains(index), message ?? "Index \(index) is out of bounds of range \(_sliceRange)")
- }
-
- @usableFromInline
- internal func _validateRange<R: RangeExpression>(_ range: R) where R.Bound == Int {
- let lower = R.Bound(_sliceRange.lowerBound)
- let upper = R.Bound(_sliceRange.upperBound)
- let r = range.relative(to: lower..<upper)
- precondition(r.lowerBound >= _sliceRange.lowerBound && r.lowerBound <= _sliceRange.upperBound, "Range \(r) is out of bounds of range \(_sliceRange)")
- precondition(r.upperBound >= _sliceRange.lowerBound && r.upperBound <= _sliceRange.upperBound, "Range \(r) is out of bounds of range \(_sliceRange)")
+ @inlinable
+ internal init(representation: _Representation) {
+ _representation = representation
}
// -----------------------------------
// MARK: - Properties and Functions
+
+ @inlinable
+ public mutating func reserveCapacity(_ minimumCapacity: Int) {
+ _representation.reserveCapacity(minimumCapacity)
+ }
/// The number of bytes in the data.
-
+ @inlinable
public var count: Int {
get {
- return _sliceRange.count
+ return _representation.count
}
- set {
- precondition(count >= 0, "count must not be negative")
- if !isKnownUniquelyReferenced(&_backing) {
- _backing = _backing.mutableCopy(_sliceRange)
- }
- _backing.length = newValue
- _sliceRange = _sliceRange.lowerBound..<(_sliceRange.lowerBound + newValue)
+ set(newValue) {
+ precondition(newValue >= 0, "count must not be negative")
+ _representation.count = newValue
}
}
+
+ @inlinable
+ public var regions: CollectionOfOne<Data> {
+ return CollectionOfOne(self)
+ }
/// Access the bytes in the data.
///
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
+ @available(swift, deprecated: 5, message: "use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead")
public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
- return try _backing.withUnsafeBytes(in: _sliceRange) {
+ return try _representation.withUnsafeBytes {
return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafePointer<ContentType>(bitPattern: 0xBAD0)!)
}
}
-
+ @inlinable
+ public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
+ return try _representation.withUnsafeBytes(body)
+ }
+
/// Mutate the bytes in the data.
///
/// This function assumes that you are mutating the contents.
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
+ @available(swift, deprecated: 5, message: "use `withUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R` instead")
public mutating func withUnsafeMutableBytes<ResultType, ContentType>(_ body: (UnsafeMutablePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
- if !isKnownUniquelyReferenced(&_backing) {
- _backing = _backing.mutableCopy(_sliceRange)
- }
- return try _backing.withUnsafeMutableBytes(in: _sliceRange) {
+ return try _representation.withUnsafeMutableBytes {
return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafeMutablePointer<ContentType>(bitPattern: 0xBAD0)!)
}
}
+
+ @inlinable
+ public mutating func withUnsafeMutableBytes<ResultType>(_ body: (UnsafeMutableRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
+ return try _representation.withUnsafeMutableBytes(body)
+ }
// MARK: -
// MARK: Copy Bytes
@@ -1357,19 +2197,17 @@
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
/// - parameter count: The number of bytes to copy.
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
+ @inlinable
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
precondition(count >= 0, "count of bytes to copy must not be negative")
if count == 0 { return }
- _backing.withUnsafeBytes(in: _sliceRange) {
- memcpy(UnsafeMutableRawPointer(pointer), $0.baseAddress!, Swift.min(count, $0.count))
- }
+ _copyBytesHelper(to: UnsafeMutableRawPointer(pointer), from: startIndex..<(startIndex + count))
}
- private func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: NSRange) {
- if range.length == 0 { return }
- _backing.withUnsafeBytes(in: range.lowerBound..<range.upperBound) {
- memcpy(UnsafeMutableRawPointer(pointer), $0.baseAddress!, Swift.min(range.length, $0.count))
- }
+ @inlinable
+ internal func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
+ if range.isEmpty { return }
+ _representation.copyBytes(to: pointer, from: range)
}
/// Copy a subset of the contents of the data to a pointer.
@@ -1377,8 +2215,9 @@
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
/// - parameter range: The range in the `Data` to copy.
/// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes.
+ @inlinable
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, from range: Range<Index>) {
- _copyBytesHelper(to: pointer, from: NSRange(range))
+ _copyBytesHelper(to: pointer, from: range)
}
// Copy the contents of the data into a buffer.
@@ -1388,6 +2227,7 @@
/// - parameter buffer: A buffer to copy the data into.
/// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied.
/// - returns: Number of bytes copied into the destination buffer.
+ @inlinable
public func copyBytes<DestinationType>(to buffer: UnsafeMutableBufferPointer<DestinationType>, from range: Range<Index>? = nil) -> Int {
let cnt = count
guard cnt > 0 else { return 0 }
@@ -1395,17 +2235,15 @@
let copyRange : Range<Index>
if let r = range {
guard !r.isEmpty else { return 0 }
- copyRange = r.lowerBound..<(r.lowerBound + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, r.count))
+ copyRange = r.lowerBound..<(r.lowerBound + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, r.upperBound - r.lowerBound))
} else {
copyRange = 0..<Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, cnt)
}
- _validateRange(copyRange)
guard !copyRange.isEmpty else { return 0 }
- let nsRange = NSRange(location: copyRange.lowerBound, length: copyRange.upperBound - copyRange.lowerBound)
- _copyBytesHelper(to: buffer.baseAddress!, from: nsRange)
- return copyRange.count
+ _copyBytesHelper(to: buffer.baseAddress!, from: copyRange)
+ return copyRange.upperBound - copyRange.lowerBound
}
// MARK: -
@@ -1431,7 +2269,8 @@
/// - parameter options: Options for writing the data. Default value is `[]`.
/// - throws: An error in the Cocoa domain, if there is an error writing to the `URL`.
public func write(to url: URL, options: Data.WritingOptions = []) throws {
- try _backing.withInteriorPointerReference(_sliceRange) {
+ // this should not be marked as inline since in objc contexts we correct atomicity via _shouldUseNonAtomicWriteReimplementation
+ try _representation.withInteriorPointerReference {
#if DEPLOYMENT_RUNTIME_SWIFT
try $0.write(to: url, options: WritingOptions(rawValue: options.rawValue))
#else
@@ -1454,15 +2293,15 @@
/// - parameter range: The range of this data in which to perform the search. Default value is `nil`, which means the entire content of this data.
/// - returns: A `Range` specifying the location of the found data, or nil if a match could not be found.
/// - precondition: `range` must be in the bounds of the Data.
+ @inlinable
public func range(of dataToFind: Data, options: Data.SearchOptions = [], in range: Range<Index>? = nil) -> Range<Index>? {
let nsRange : NSRange
if let r = range {
- _validateRange(r)
nsRange = NSRange(location: r.lowerBound - startIndex, length: r.upperBound - r.lowerBound)
} else {
nsRange = NSRange(location: 0, length: count)
}
- let result = _backing.withInteriorPointerReference(_sliceRange) {
+ let result = _representation.withInteriorPointerReference {
$0.range(of: dataToFind, options: options, in: nsRange)
}
if result.location == NSNotFound {
@@ -1475,38 +2314,40 @@
///
/// In some cases, (for example, a `Data` backed by a `dispatch_data_t`, the bytes may be stored discontiguously. In those cases, this function invokes the closure for each contiguous region of bytes.
/// - parameter block: The closure to invoke for each region of data. You may stop the enumeration by setting the `stop` parameter to `true`.
+ @available(swift, deprecated: 5, message: "use `regions` or `for-in` instead")
public func enumerateBytes(_ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Index, _ stop: inout Bool) -> Void) {
- _backing.enumerateBytes(in: _sliceRange, block)
+ _representation.enumerateBytes(block)
}
@inlinable
internal mutating func _append<SourceType>(_ buffer : UnsafeBufferPointer<SourceType>) {
if buffer.isEmpty { return }
- if !isKnownUniquelyReferenced(&_backing) {
- _backing = _backing.mutableCopy(_sliceRange)
- }
- _backing.replaceBytes(in: NSRange(location: _sliceRange.upperBound, length: _backing.length - (_sliceRange.upperBound - _backing._offset)), with: buffer.baseAddress, length: buffer.count * MemoryLayout<SourceType>.stride)
- _sliceRange = _sliceRange.lowerBound..<(_sliceRange.upperBound + buffer.count * MemoryLayout<SourceType>.stride)
+ _representation.append(contentsOf: UnsafeRawBufferPointer(buffer))
}
+ @inlinable
public mutating func append(_ bytes: UnsafePointer<UInt8>, count: Int) {
if count == 0 { return }
_append(UnsafeBufferPointer(start: bytes, count: count))
}
+ @inlinable
public mutating func append(_ other: Data) {
- other.enumerateBytes { (buffer, _, _) in
- _append(buffer)
+ guard other.count > 0 else { return }
+ other.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
+ _representation.append(contentsOf: buffer)
}
}
/// Append a buffer of bytes to the data.
///
/// - parameter buffer: The buffer of bytes to append. The size is calculated from `SourceType` and `buffer.count`.
+ @inlinable
public mutating func append<SourceType>(_ buffer : UnsafeBufferPointer<SourceType>) {
_append(buffer)
}
+ @inlinable
public mutating func append(contentsOf bytes: [UInt8]) {
bytes.withUnsafeBufferPointer { (buffer: UnsafeBufferPointer<UInt8>) -> Void in
_append(buffer)
@@ -1514,15 +2355,44 @@
}
@inlinable
- public mutating func append<S : Sequence>(contentsOf newElements: S) where S.Iterator.Element == Iterator.Element {
- let underestimatedCount = Swift.max(newElements.underestimatedCount, 1)
+ public mutating func append<S: Sequence>(contentsOf elements: S) where S.Element == Element {
+ // If the sequence is already contiguous, access the underlying raw memory directly.
+ if let contiguous = elements as? ContiguousBytes {
+ contiguous.withUnsafeBytes {
+ _representation.append(contentsOf: $0)
+ }
+
+ return
+ }
+
+ // The sequence might still be able to provide direct access to typed memory.
+ // NOTE: It's safe to do this because we're already guarding on S's element as `UInt8`. This would not be safe on arbitrary sequences.
+ var appended = false
+ elements.withContiguousStorageIfAvailable {
+ _representation.append(contentsOf: UnsafeRawBufferPointer($0))
+ appended = true
+ }
+
+ guard !appended else { return }
+
+ // The sequence is really not contiguous.
+ // Copy as much as we can in one shot.
+ let underestimatedCount = Swift.max(elements.underestimatedCount, 1)
_withStackOrHeapBuffer(underestimatedCount) { (buffer) in
+ // In order to copy from the sequence, we have to bind the temporary buffer to `UInt8`.
+ // This is safe since we're the only owners of the buffer and we copy out as raw memory below anyway.
let capacity = buffer.pointee.capacity
let base = buffer.pointee.memory.bindMemory(to: UInt8.self, capacity: capacity)
- var (iter, endIndex) = newElements._copyContents(initializing: UnsafeMutableBufferPointer(start: base, count: capacity))
- _append(UnsafeBufferPointer(start: base, count: endIndex))
- while var element = iter.next() {
- append(&element, count: 1)
+ var (iter, endIndex) = elements._copyContents(initializing: UnsafeMutableBufferPointer(start: base, count: capacity))
+
+ // Copy the contents of the buffer...
+ _representation.append(contentsOf: UnsafeRawBufferPointer(start: base, count: endIndex))
+
+ /// ... and append the rest byte-wise.
+ while let element = iter.next() {
+ Swift.withUnsafeBytes(of: element) {
+ _representation.append(contentsOf: $0)
+ }
}
}
}
@@ -1533,18 +2403,12 @@
///
/// If `range` exceeds the bounds of the data, then the data is resized to fit.
/// - parameter range: The range in the data to set to `0`.
+ @inlinable
public mutating func resetBytes(in range: Range<Index>) {
// it is worth noting that the range here may be out of bounds of the Data itself (which triggers a growth)
precondition(range.lowerBound >= 0, "Ranges must not be negative bounds")
precondition(range.upperBound >= 0, "Ranges must not be negative bounds")
- let range = NSRange(location: range.lowerBound, length: range.upperBound - range.lowerBound)
- if !isKnownUniquelyReferenced(&_backing) {
- _backing = _backing.mutableCopy(_sliceRange)
- }
- _backing.resetBytes(in: range)
- if _sliceRange.upperBound < range.upperBound {
- _sliceRange = _sliceRange.lowerBound..<range.upperBound
- }
+ _representation.resetBytes(in: range)
}
/// Replace a region of bytes in the data with new data.
@@ -1554,10 +2418,10 @@
/// - precondition: The bounds of `subrange` must be valid indices of the collection.
/// - parameter subrange: The range in the data to replace. If `subrange.lowerBound == data.count && subrange.count == 0` then this operation is an append.
/// - parameter data: The replacement data.
+ @inlinable
public mutating func replaceSubrange(_ subrange: Range<Index>, with data: Data) {
- let cnt = data.count
- data.withUnsafeBytes {
- replaceSubrange(subrange, with: $0, count: cnt)
+ data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
+ _representation.replaceSubrange(subrange, with: buffer.baseAddress, count: buffer.count)
}
}
@@ -1568,6 +2432,7 @@
/// - precondition: The bounds of `subrange` must be valid indices of the collection.
/// - parameter subrange: The range in the data to replace.
/// - parameter buffer: The replacement bytes.
+ @inlinable
public mutating func replaceSubrange<SourceType>(_ subrange: Range<Index>, with buffer: UnsafeBufferPointer<SourceType>) {
guard !buffer.isEmpty else { return }
replaceSubrange(subrange, with: buffer.baseAddress!, count: buffer.count * MemoryLayout<SourceType>.stride)
@@ -1580,9 +2445,9 @@
/// - precondition: The bounds of `subrange` must be valid indices of the collection.
/// - parameter subrange: The range in the data to replace.
/// - parameter newElements: The replacement bytes.
+ @inlinable
public mutating func replaceSubrange<ByteCollection : Collection>(_ subrange: Range<Index>, with newElements: ByteCollection) where ByteCollection.Iterator.Element == Data.Iterator.Element {
- _validateRange(subrange)
- let totalCount: Int = numericCast(newElements.count)
+ let totalCount = Int(newElements.count)
_withStackOrHeapBuffer(totalCount) { conditionalBuffer in
let buffer = UnsafeMutableBufferPointer(start: conditionalBuffer.pointee.memory.assumingMemoryBound(to: UInt8.self), count: totalCount)
var (iterator, index) = newElements._copyContents(initializing: buffer)
@@ -1594,27 +2459,24 @@
}
}
+ @inlinable
public mutating func replaceSubrange(_ subrange: Range<Index>, with bytes: UnsafeRawPointer, count cnt: Int) {
- _validateRange(subrange)
- let nsRange = NSRange(location: subrange.lowerBound, length: subrange.upperBound - subrange.lowerBound)
- if !isKnownUniquelyReferenced(&_backing) {
- _backing = _backing.mutableCopy(_sliceRange)
- }
- let upper = _sliceRange.upperBound
- _backing.replaceBytes(in: nsRange, with: bytes, length: cnt)
- let resultingUpper = upper - nsRange.length + cnt
- _sliceRange = _sliceRange.lowerBound..<resultingUpper
+ _representation.replaceSubrange(subrange, with: bytes, count: cnt)
}
/// Return a new copy of the data in a specified range.
///
/// - parameter range: The range to copy.
+ @inlinable
public func subdata(in range: Range<Index>) -> Data {
- _validateRange(range)
- if isEmpty {
+ if isEmpty || range.upperBound - range.lowerBound == 0 {
return Data()
}
- return _backing.subdata(in: range)
+ let slice = self[range]
+
+ return slice.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Data in
+ return Data(bytes: buffer.baseAddress!, count: buffer.count)
+ }
}
// MARK: -
@@ -1624,8 +2486,9 @@
///
/// - parameter options: The options to use for the encoding. Default value is `[]`.
/// - returns: The Base-64 encoded string.
+ @inlinable
public func base64EncodedString(options: Data.Base64EncodingOptions = []) -> String {
- return _backing.withInteriorPointerReference(_sliceRange) {
+ return _representation.withInteriorPointerReference {
return $0.base64EncodedString(options: options)
}
}
@@ -1634,8 +2497,9 @@
///
/// - parameter options: The options to use for the encoding. Default value is `[]`.
/// - returns: The Base-64 encoded data.
+ @inlinable
public func base64EncodedData(options: Data.Base64EncodingOptions = []) -> Data {
- return _backing.withInteriorPointerReference(_sliceRange) {
+ return _representation.withInteriorPointerReference {
return $0.base64EncodedData(options: options)
}
}
@@ -1644,26 +2508,17 @@
//
/// The hash value for the data.
+ @inlinable
public var hashValue: Int {
- var hashValue = 0
- let hashRange: Range<Int> = _sliceRange.lowerBound..<Swift.min(_sliceRange.lowerBound + 80, _sliceRange.upperBound)
- _withStackOrHeapBuffer(hashRange.count + 1) { buffer in
- if !hashRange.isEmpty {
- _backing.withUnsafeBytes(in: hashRange) {
- memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
- }
- }
- hashValue = Int(bitPattern: CFHashBytes(buffer.pointee.memory.assumingMemoryBound(to: UInt8.self), hashRange.count))
- }
- return hashValue
+ return _representation.hashValue
}
+ @inlinable
public func advanced(by amount: Int) -> Data {
- _validateIndex(startIndex + amount)
let length = count - amount
precondition(length > 0)
- return withUnsafeBytes { (ptr: UnsafePointer<UInt8>) -> Data in
- return Data(bytes: ptr.advanced(by: amount), count: length)
+ return withUnsafeBytes { (ptr: UnsafeRawBufferPointer) -> Data in
+ return Data(bytes: ptr.baseAddress!.advanced(by: amount), count: length)
}
}
@@ -1673,149 +2528,156 @@
// MARK: Index and Subscript
/// Sets or returns the byte at the specified index.
+ @inlinable
public subscript(index: Index) -> UInt8 {
get {
- _validateIndex(index)
- return _backing.get(index)
+ return _representation[index]
}
- set {
- _validateIndex(index)
- if !isKnownUniquelyReferenced(&_backing) {
- _backing = _backing.mutableCopy(_sliceRange)
- }
- _backing.set(index, to: newValue)
+ set(newValue) {
+ _representation[index] = newValue
}
}
+ @inlinable
public subscript(bounds: Range<Index>) -> Data {
get {
- _validateRange(bounds)
- return Data(backing: _backing, range: bounds)
+ return _representation[bounds]
}
set {
replaceSubrange(bounds, with: newValue)
}
}
+ @inlinable
public subscript<R: RangeExpression>(_ rangeExpression: R) -> Data
where R.Bound: FixedWidthInteger {
get {
- let lower = R.Bound(_sliceRange.lowerBound)
- let upper = R.Bound(_sliceRange.upperBound)
+ let lower = R.Bound(startIndex)
+ let upper = R.Bound(endIndex)
let range = rangeExpression.relative(to: lower..<upper)
- let start: Int = numericCast(range.lowerBound)
- let end: Int = numericCast(range.upperBound)
+ let start = Int(range.lowerBound)
+ let end = Int(range.upperBound)
let r: Range<Int> = start..<end
- _validateRange(r)
- return Data(backing: _backing, range: r)
+ return _representation[r]
}
set {
- let lower = R.Bound(_sliceRange.lowerBound)
- let upper = R.Bound(_sliceRange.upperBound)
+ let lower = R.Bound(startIndex)
+ let upper = R.Bound(endIndex)
let range = rangeExpression.relative(to: lower..<upper)
- let start: Int = numericCast(range.lowerBound)
- let end: Int = numericCast(range.upperBound)
+ let start = Int(range.lowerBound)
+ let end = Int(range.upperBound)
let r: Range<Int> = start..<end
- _validateRange(r)
replaceSubrange(r, with: newValue)
}
-
}
/// The start `Index` in the data.
+ @inlinable
public var startIndex: Index {
get {
- return _sliceRange.lowerBound
+ return _representation.startIndex
}
}
/// The end `Index` into the data.
///
/// This is the "one-past-the-end" position, and will always be equal to the `count`.
+ @inlinable
public var endIndex: Index {
get {
- return _sliceRange.upperBound
+ return _representation.endIndex
}
}
+ @inlinable
public func index(before i: Index) -> Index {
return i - 1
}
+ @inlinable
public func index(after i: Index) -> Index {
return i + 1
}
+ @inlinable
public var indices: Range<Int> {
get {
return startIndex..<endIndex
}
}
+ @inlinable
public func _copyContents(initializing buffer: UnsafeMutableBufferPointer<UInt8>) -> (Iterator, UnsafeMutableBufferPointer<UInt8>.Index) {
guard !isEmpty else { return (makeIterator(), buffer.startIndex) }
- guard let p = buffer.baseAddress else {
- preconditionFailure("Attempt to copy contents into nil buffer pointer")
+ let cnt = Swift.min(count, buffer.count)
+
+ withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
+ _ = memcpy(UnsafeMutableRawPointer(buffer.baseAddress), bytes.baseAddress, cnt)
}
- let cnt = count
- precondition(cnt <= buffer.count, "Insufficient space allocated to copy Data contents")
- withUnsafeBytes { p.initialize(from: $0, count: cnt) }
-
- return (Iterator(endOf: self), buffer.index(buffer.startIndex, offsetBy: cnt))
+ return (Iterator(self, at: startIndex + cnt), buffer.index(buffer.startIndex, offsetBy: cnt))
}
/// An iterator over the contents of the data.
///
/// The iterator will increment byte-by-byte.
+ @inlinable
public func makeIterator() -> Data.Iterator {
- return Iterator(self)
+ return Iterator(self, at: startIndex)
}
public struct Iterator : IteratorProtocol {
- // Both _data and _endIdx should be 'let' rather than 'var'.
- // They are 'var' so that the stored properties can be read
- // independently of the other contents of the struct. This prevents
- // an exclusivity violation when reading '_endIdx' and '_data'
- // while simultaneously mutating '_buffer' with the call to
- // withUnsafeMutablePointer(). Once we support accessing struct
- // let properties independently we should make these variables
- // 'let' again.
+ @usableFromInline
+ internal typealias Buffer = (
+ UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
+ UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
+ UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
+ UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)
- private var _data: Data
- private var _buffer: (
- UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
- UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
- UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
- UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)
- private var _idx: Data.Index
- private var _endIdx: Data.Index
+ @usableFromInline internal let _data: Data
+ @usableFromInline internal var _buffer: Buffer
+ @usableFromInline internal var _idx: Data.Index
+ @usableFromInline internal let _endIdx: Data.Index
- fileprivate init(_ data: Data) {
+ @usableFromInline
+ internal init(_ data: Data, at loc: Data.Index) {
+ // The let vars prevent this from being marked as @inlinable
_data = data
_buffer = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
- _idx = data.startIndex
+ _idx = loc
_endIdx = data.endIndex
+
+ let bufferSize = MemoryLayout<Buffer>.size
+ Swift.withUnsafeMutableBytes(of: &_buffer) {
+ let ptr = $0.bindMemory(to: UInt8.self)
+ let bufferIdx = (loc - data.startIndex) % bufferSize
+ data.copyBytes(to: ptr, from: (loc - bufferIdx)..<(data.endIndex - (loc - bufferIdx) > bufferSize ? (loc - bufferIdx) + bufferSize : data.endIndex))
+ }
}
- fileprivate init(endOf data: Data) {
- self._data = data
- _buffer = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
- _idx = data.endIndex
- _endIdx = data.endIndex
- }
-
+ @inlinable
public mutating func next() -> UInt8? {
- guard _idx < _endIdx else { return nil }
- defer { _idx += 1 }
- let bufferSize = MemoryLayout.size(ofValue: _buffer)
- return withUnsafeMutablePointer(to: &_buffer) { ptr_ in
- let ptr = UnsafeMutableRawPointer(ptr_).assumingMemoryBound(to: UInt8.self)
- let bufferIdx = (_idx - _data.startIndex) % bufferSize
- if bufferIdx == 0 {
+ let idx = _idx
+ let bufferSize = MemoryLayout<Buffer>.size
+
+ guard idx < _endIdx else { return nil }
+ _idx += 1
+
+ let bufferIdx = (idx - _data.startIndex) % bufferSize
+
+
+ if bufferIdx == 0 {
+ var buffer = _buffer
+ Swift.withUnsafeMutableBytes(of: &buffer) {
+ let ptr = $0.bindMemory(to: UInt8.self)
// populate the buffer
- _data.copyBytes(to: ptr, from: _idx..<(_endIdx - _idx > bufferSize ? _idx + bufferSize : _endIdx))
+ _data.copyBytes(to: ptr, from: idx..<(_endIdx - idx > bufferSize ? idx + bufferSize : _endIdx))
}
+ _buffer = buffer
+ }
+
+ return Swift.withUnsafeMutableBytes(of: &_buffer) {
+ let ptr = $0.bindMemory(to: UInt8.self)
return ptr[bufferIdx]
}
}
@@ -1837,27 +2699,16 @@
public var mutableBytes: UnsafeMutableRawPointer { fatalError() }
/// Returns `true` if the two `Data` arguments are equal.
+ @inlinable
public static func ==(d1 : Data, d2 : Data) -> Bool {
- let backing1 = d1._backing
- let backing2 = d2._backing
- if backing1 === backing2 {
- if d1._sliceRange == d2._sliceRange {
- return true
- }
- }
let length1 = d1.count
if length1 != d2.count {
return false
}
- if backing1.bytes == backing2.bytes {
- if d1._sliceRange == d2._sliceRange {
- return true
- }
- }
if length1 > 0 {
- return d1.withUnsafeBytes { (b1) in
- return d2.withUnsafeBytes { (b2) in
- return memcmp(b1, b2, length1) == 0
+ return d1.withUnsafeBytes { (b1: UnsafeRawBufferPointer) in
+ return d2.withUnsafeBytes { (b2: UnsafeRawBufferPointer) in
+ return memcmp(b1.baseAddress!, b2.baseAddress!, b2.count) == 0
}
}
}
@@ -1882,8 +2733,8 @@
var children: [(label: String?, value: Any)] = []
children.append((label: "count", value: nBytes))
- self.withUnsafeBytes { (bytes : UnsafePointer<UInt8>) in
- children.append((label: "pointer", value: bytes))
+ self.withUnsafeBytes { (bytes : UnsafeRawBufferPointer) in
+ children.append((label: "pointer", value: bytes.baseAddress!))
}
// Minimal size data is output as an array
@@ -1909,7 +2760,7 @@
extension Data : _ObjectiveCBridgeable {
@_semantics("convertToObjectiveC")
public func _bridgeToObjectiveC() -> NSData {
- return _backing.bridgedReference(_sliceRange)
+ return _representation.bridgedReference()
}
public static func _forceBridgeFromObjectiveC(_ input: NSData, result: inout Data?) {
@@ -1923,7 +2774,7 @@
return true
}
- @_effects(readonly)
+// @_effects(readonly)
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSData?) -> Data {
guard let src = source else { return Data() }
return Data(referencing: src)
@@ -1964,20 +2815,8 @@
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
-
- // Since enumerateBytes does not rethrow, we need to catch the error, stow it away, and rethrow if we stopped.
- var caughtError: Error? = nil
- self.enumerateBytes { (buffer: UnsafeBufferPointer<UInt8>, byteIndex: Data.Index, stop: inout Bool) in
- do {
- try container.encode(contentsOf: buffer)
- } catch {
- caughtError = error
- stop = true
- }
- }
-
- if let error = caughtError {
- throw error
+ try withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
+ try container.encode(contentsOf: buffer)
}
}
}
diff --git a/stdlib/public/SDK/Foundation/DataProtocol.swift b/stdlib/public/SDK/Foundation/DataProtocol.swift
new file mode 100644
index 0000000..00f3a03
--- /dev/null
+++ b/stdlib/public/SDK/Foundation/DataProtocol.swift
@@ -0,0 +1,299 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+#if os(macOS) || os(iOS)
+import Darwin
+#elseif os(Linux)
+import Glibc
+#endif
+
+//===--- DataProtocol -----------------------------------------------------===//
+
+public protocol DataProtocol : RandomAccessCollection where Element == UInt8, SubSequence : DataProtocol {
+ // FIXME: Remove in favor of opaque type on `regions`.
+ associatedtype Regions: BidirectionalCollection where Regions.Element : DataProtocol & ContiguousBytes, Regions.Element.SubSequence : ContiguousBytes
+
+ /// A `BidirectionalCollection` of `DataProtocol` elements which compose a
+ /// discontiguous buffer of memory. Each region is a contiguous buffer of
+ /// bytes.
+ ///
+ /// The sum of the lengths of the associated regions must equal `self.count`
+ /// (such that iterating `regions` and iterating `self` produces the same
+ /// sequence of indices in the same number of index advancements).
+ var regions: Regions { get }
+
+ /// Returns the first found range of the given data buffer.
+ ///
+ /// A default implementation is given in terms of `self.regions`.
+ func firstRange<D: DataProtocol, R: RangeExpression>(of: D, in: R) -> Range<Index>? where R.Bound == Index
+
+ /// Returns the last found range of the given data buffer.
+ ///
+ /// A default implementation is given in terms of `self.regions`.
+ func lastRange<D: DataProtocol, R: RangeExpression>(of: D, in: R) -> Range<Index>? where R.Bound == Index
+
+ /// Copies `count` bytes from the start of the buffer to the destination
+ /// buffer.
+ ///
+ /// A default implementation is given in terms of `copyBytes(to:from:)`.
+ @discardableResult
+ func copyBytes(to: UnsafeMutableRawBufferPointer, count: Int) -> Int
+
+ /// Copies `count` bytes from the start of the buffer to the destination
+ /// buffer.
+ ///
+ /// A default implementation is given in terms of `copyBytes(to:from:)`.
+ @discardableResult
+ func copyBytes<DestinationType>(to: UnsafeMutableBufferPointer<DestinationType>, count: Int) -> Int
+
+ /// Copies the bytes from the given range to the destination buffer.
+ ///
+ /// A default implementation is given in terms of `self.regions`.
+ @discardableResult
+ func copyBytes<R: RangeExpression>(to: UnsafeMutableRawBufferPointer, from: R) -> Int where R.Bound == Index
+
+ /// Copies the bytes from the given range to the destination buffer.
+ ///
+ /// A default implementation is given in terms of `self.regions`.
+ @discardableResult
+ func copyBytes<DestinationType, R: RangeExpression>(to: UnsafeMutableBufferPointer<DestinationType>, from: R) -> Int where R.Bound == Index
+}
+
+//===--- MutableDataProtocol ----------------------------------------------===//
+
+public protocol MutableDataProtocol : DataProtocol, MutableCollection, RangeReplaceableCollection {
+ /// Replaces the contents of the buffer at the given range with zeroes.
+ ///
+ /// A default implementation is given in terms of
+ /// `replaceSubrange(_:with:)`.
+ mutating func resetBytes<R: RangeExpression>(in range: R) where R.Bound == Index
+}
+
+//===--- DataProtocol Extensions ------------------------------------------===//
+
+extension DataProtocol {
+ public func firstRange<D: DataProtocol>(of data: D) -> Range<Index>? {
+ return self.firstRange(of: data, in: self.startIndex ..< self.endIndex)
+ }
+
+ public func lastRange<D: DataProtocol>(of data: D) -> Range<Index>? {
+ return self.lastRange(of: data, in: self.startIndex ..< self.endIndex)
+ }
+
+ @discardableResult
+ public func copyBytes(to ptr: UnsafeMutableRawBufferPointer) -> Int {
+ return copyBytes(to: ptr, from: self.startIndex ..< self.endIndex)
+ }
+
+ @discardableResult
+ public func copyBytes<DestinationType>(to ptr: UnsafeMutableBufferPointer<DestinationType>) -> Int {
+ return copyBytes(to: ptr, from: self.startIndex ..< self.endIndex)
+ }
+
+ @discardableResult
+ public func copyBytes(to ptr: UnsafeMutableRawBufferPointer, count: Int) -> Int {
+ return copyBytes(to: ptr, from: self.startIndex ..< self.index(self.startIndex, offsetBy: count))
+ }
+
+ @discardableResult
+ public func copyBytes<DestinationType>(to ptr: UnsafeMutableBufferPointer<DestinationType>, count: Int) -> Int {
+ return copyBytes(to: ptr, from: self.startIndex ..< self.index(self.startIndex, offsetBy: count))
+ }
+
+ @discardableResult
+ public func copyBytes<R: RangeExpression>(to ptr: UnsafeMutableRawBufferPointer, from range: R) -> Int where R.Bound == Index {
+ precondition(ptr.baseAddress != nil)
+
+ let concreteRange = range.relative(to: self)
+ let slice = self[concreteRange]
+
+ // The type isn't contiguous, so we need to copy one region at a time.
+ var offset = 0
+ let rangeCount = distance(from: concreteRange.lowerBound, to: concreteRange.upperBound)
+ var amountToCopy = Swift.min(ptr.count, rangeCount)
+ for region in slice.regions {
+ guard amountToCopy > 0 else {
+ break
+ }
+
+ region.withUnsafeBytes { buffer in
+ let offsetPtr = UnsafeMutableRawBufferPointer(rebasing: ptr[offset...])
+ let buf = UnsafeRawBufferPointer(start: buffer.baseAddress, count: Swift.min(buffer.count, amountToCopy))
+ offsetPtr.copyMemory(from: buf)
+ offset += buf.count
+ amountToCopy -= buf.count
+ }
+ }
+
+ return offset
+ }
+
+ @discardableResult
+ public func copyBytes<DestinationType, R: RangeExpression>(to ptr: UnsafeMutableBufferPointer<DestinationType>, from range: R) -> Int where R.Bound == Index {
+ return self.copyBytes(to: UnsafeMutableRawBufferPointer(start: ptr.baseAddress, count: ptr.count * MemoryLayout<DestinationType>.stride), from: range)
+ }
+
+ public func firstRange<D: DataProtocol, R: RangeExpression>(of data: D, in range: R) -> Range<Index>? where R.Bound == Index {
+ let r = range.relative(to: self)
+ let rangeCount = distance(from: r.lowerBound, to: r.upperBound)
+ if rangeCount < data.count {
+ return nil
+ }
+ var haystackIndex = r.lowerBound
+ let haystackEnd = index(r.upperBound, offsetBy: -data.count)
+ while haystackIndex < haystackEnd {
+ var compareIndex = haystackIndex
+ var needleIndex = data.startIndex
+ let needleEnd = data.endIndex
+ var matched = true
+ while compareIndex < haystackEnd && needleIndex < needleEnd {
+ if self[compareIndex] != data[needleIndex] {
+ matched = false
+ break
+ }
+ needleIndex = data.index(after: needleIndex)
+ compareIndex = index(after: compareIndex)
+ }
+ if matched {
+ return haystackIndex..<compareIndex
+ }
+ haystackIndex = index(after: haystackIndex)
+ }
+ return nil
+ }
+
+ public func lastRange<D: DataProtocol, R: RangeExpression>(of data: D, in range: R) -> Range<Index>? where R.Bound == Index {
+ let r = range.relative(to: self)
+ let rangeCount = distance(from: r.lowerBound, to: r.upperBound)
+ if rangeCount < data.count {
+ return nil
+ }
+ var haystackIndex = r.upperBound
+ let haystackStart = index(r.lowerBound, offsetBy: data.count)
+ while haystackIndex > haystackStart {
+ var compareIndex = haystackIndex
+ var needleIndex = data.endIndex
+ let needleStart = data.startIndex
+ var matched = true
+ while compareIndex > haystackStart && needleIndex > needleStart {
+ if self[compareIndex] != data[needleIndex] {
+ matched = false
+ break
+ }
+ needleIndex = data.index(before: needleIndex)
+ compareIndex = index(before: compareIndex)
+ }
+ if matched {
+ return compareIndex..<haystackIndex
+ }
+ haystackIndex = index(before: haystackIndex)
+ }
+ return nil
+ }
+}
+
+extension DataProtocol where Self : ContiguousBytes {
+ public func copyBytes<DestinationType, R: RangeExpression>(to ptr: UnsafeMutableBufferPointer<DestinationType>, from range: R) where R.Bound == Index {
+ precondition(ptr.baseAddress != nil)
+
+ let concreteRange = range.relative(to: self)
+ withUnsafeBytes { fullBuffer in
+ let adv = distance(from: startIndex, to: concreteRange.lowerBound)
+ let delta = distance(from: concreteRange.lowerBound, to: concreteRange.upperBound)
+ memcpy(ptr.baseAddress!, fullBuffer.baseAddress?.advanced(by: adv), delta)
+ }
+ }
+}
+
+//===--- MutableDataProtocol Extensions -----------------------------------===//
+
+extension MutableDataProtocol {
+ public mutating func resetBytes<R: RangeExpression>(in range: R) where R.Bound == Index {
+ let r = range.relative(to: self)
+ let count = distance(from: r.lowerBound, to: r.upperBound)
+ replaceSubrange(r, with: repeatElement(UInt8(0), count: count))
+ }
+}
+
+//===--- DataProtocol Conditional Conformances ----------------------------===//
+
+extension Slice : DataProtocol where Base : DataProtocol {
+ public typealias Regions = [Base.Regions.Element.SubSequence]
+
+ public var regions: [Base.Regions.Element.SubSequence] {
+ let sliceLowerBound = startIndex
+ let sliceUpperBound = endIndex
+ var regionUpperBound = base.startIndex
+
+ return base.regions.compactMap { (region) -> Base.Regions.Element.SubSequence? in
+ let regionLowerBound = regionUpperBound
+ regionUpperBound = base.index(regionUpperBound, offsetBy: region.count)
+
+ /*
+ [------ Region ------]
+ [--- Slice ---] =>
+
+ OR
+
+ [------ Region ------]
+ <= [--- Slice ---]
+ */
+ if sliceLowerBound >= regionLowerBound && sliceUpperBound <= regionUpperBound {
+ let regionRelativeSliceLowerBound = region.index(region.startIndex, offsetBy: base.distance(from: regionLowerBound, to: sliceLowerBound))
+ let regionRelativeSliceUpperBound = region.index(region.startIndex, offsetBy: base.distance(from: regionLowerBound, to: sliceUpperBound))
+ return region[regionRelativeSliceLowerBound..<regionRelativeSliceUpperBound]
+ }
+
+ /*
+ [--- Region ---] =>
+ [------ Slice ------]
+
+ OR
+
+ <= [--- Region ---]
+ [------ Slice ------]
+ */
+ if regionLowerBound >= sliceLowerBound && regionUpperBound <= sliceUpperBound {
+ return region[region.startIndex..<region.endIndex]
+ }
+
+ /*
+ [------ Region ------]
+ [------ Slice ------]
+ */
+ if sliceLowerBound >= regionLowerBound && sliceLowerBound <= regionUpperBound {
+ let regionRelativeSliceLowerBound = region.index(region.startIndex, offsetBy: base.distance(from: regionLowerBound, to: sliceLowerBound))
+ return region[regionRelativeSliceLowerBound..<region.endIndex]
+ }
+
+ /*
+ [------ Region ------]
+ [------ Slice ------]
+ */
+ if regionLowerBound >= sliceLowerBound && regionLowerBound <= sliceUpperBound {
+ let regionRelativeSliceUpperBound = region.index(region.startIndex, offsetBy: base.distance(from: regionLowerBound, to: sliceUpperBound))
+ return region[region.startIndex..<regionRelativeSliceUpperBound]
+ }
+
+ /*
+ [--- Region ---]
+ [--- Slice ---]
+
+ OR
+
+ [--- Region ---]
+ [--- Slice ---]
+ */
+ return nil
+ }
+ }
+}
diff --git a/stdlib/public/SDK/Foundation/DispatchData+DataProtocol.swift b/stdlib/public/SDK/Foundation/DispatchData+DataProtocol.swift
new file mode 100644
index 0000000..97b82e4
--- /dev/null
+++ b/stdlib/public/SDK/Foundation/DispatchData+DataProtocol.swift
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+
+import Dispatch
+
+extension DispatchData : DataProtocol {
+ public struct Region : DataProtocol, ContiguousBytes {
+ internal let bytes: UnsafeBufferPointer<UInt8>
+ internal let index: DispatchData.Index
+ internal let owner: DispatchData
+ internal init(bytes: UnsafeBufferPointer<UInt8>, index: DispatchData.Index, owner: DispatchData) {
+ self.bytes = bytes
+ self.index = index
+ self.owner = owner
+ }
+
+ public var regions: CollectionOfOne<Region> {
+ return CollectionOfOne(self)
+ }
+
+ public subscript(position: DispatchData.Index) -> UInt8 {
+ precondition(index <= position && position <= index + bytes.count)
+ return bytes[position - index]
+ }
+
+ public var startIndex: DispatchData.Index {
+ return index
+ }
+
+ public var endIndex: DispatchData.Index {
+ return index + bytes.count
+ }
+
+ public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
+ return try body(UnsafeRawBufferPointer(bytes))
+ }
+ }
+
+ public var regions: [Region] {
+ var regions = [Region]()
+ enumerateBytes { (bytes, index, stop) in
+ regions.append(Region(bytes: bytes, index: index, owner: self))
+ }
+ return regions
+ }
+}
diff --git a/stdlib/public/SDK/Foundation/NSData+DataProtocol.swift b/stdlib/public/SDK/Foundation/NSData+DataProtocol.swift
new file mode 100644
index 0000000..cc467dc
--- /dev/null
+++ b/stdlib/public/SDK/Foundation/NSData+DataProtocol.swift
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+
+extension NSData : DataProtocol {
+
+ @nonobjc
+ public var startIndex: Int { return 0 }
+
+ @nonobjc
+ public var endIndex: Int { return length }
+
+ @nonobjc
+ public func lastRange<D, R>(of data: D, in r: R) -> Range<Int>? where D : DataProtocol, R : RangeExpression, NSData.Index == R.Bound {
+ return Range<Int>(range(of: Data(data), options: .backwards, in: NSRange(r)))
+ }
+
+ @nonobjc
+ public func firstRange<D, R>(of data: D, in r: R) -> Range<Int>? where D : DataProtocol, R : RangeExpression, NSData.Index == R.Bound {
+ return Range<Int>(range(of: Data(data), in: NSRange(r)))
+ }
+
+ @nonobjc
+ public var regions: [Data] {
+ var datas = [Data]()
+ enumerateBytes { (ptr, range, stop) in
+ datas.append(Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: ptr), count: range.length, deallocator: .custom({ (ptr: UnsafeMutableRawPointer, count: Int) -> Void in
+ withExtendedLifetime(self) { }
+ })))
+ }
+ return datas
+ }
+
+ @nonobjc
+ public subscript(position: Int) -> UInt8 {
+ var byte = UInt8(0)
+ enumerateBytes { (ptr, range, stop) in
+ if range.location <= position && position < range.upperBound {
+ byte = ptr.load(fromByteOffset: range.location - position, as: UInt8.self)
+ stop.pointee = true
+ }
+ }
+ return byte
+ }
+}
diff --git a/stdlib/public/SDK/Foundation/Pointers+DataProtocol.swift b/stdlib/public/SDK/Foundation/Pointers+DataProtocol.swift
new file mode 100644
index 0000000..059fe87
--- /dev/null
+++ b/stdlib/public/SDK/Foundation/Pointers+DataProtocol.swift
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+
+extension UnsafeRawBufferPointer : DataProtocol {
+ public var regions: CollectionOfOne<UnsafeRawBufferPointer> {
+ return CollectionOfOne(self)
+ }
+}
+
+extension UnsafeBufferPointer : DataProtocol where Element == UInt8 {
+ public var regions: CollectionOfOne<UnsafeBufferPointer<Element>> {
+ return CollectionOfOne(self)
+ }
+}
diff --git a/stdlib/public/SDK/MediaPlayer/CMakeLists.txt b/stdlib/public/SDK/MediaPlayer/CMakeLists.txt
index 4fd2c10..0efa5ae 100644
--- a/stdlib/public/SDK/MediaPlayer/CMakeLists.txt
+++ b/stdlib/public/SDK/MediaPlayer/CMakeLists.txt
@@ -8,7 +8,7 @@
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS IOS IOS_SIMULATOR
- SWIFT_MODULE_DEPENDS_IOS Darwin AVFoundation CoreAudio CoreFoundation CoreGraphics CoreImage CoreMedia Dispatch Foundation Metal ObjectiveC QuartzCore simd SIMDOperators UIKit os CoreData # auto-updated
+ SWIFT_MODULE_DEPENDS_IOS Darwin AVFoundation CoreAudio CoreFoundation CoreGraphics CoreImage CoreMedia Dispatch Foundation Metal ObjectiveC QuartzCore simd UIKit os CoreData # auto-updated
FRAMEWORK_DEPENDS_WEAK MediaPlayer
DEPLOYMENT_VERSION_IOS ${SWIFTLIB_DEPLOYMENT_VERSION_MEDIAPLAYER_IOS}
diff --git a/stdlib/public/SDK/simd/Quaternion.swift.gyb b/stdlib/public/SDK/simd/Quaternion.swift.gyb
index c20d44e..4ac5f95 100644
--- a/stdlib/public/SDK/simd/Quaternion.swift.gyb
+++ b/stdlib/public/SDK/simd/Quaternion.swift.gyb
@@ -14,7 +14,6 @@
import Swift
import Darwin
-import SIMDOperators
@_exported import simd
%for scalar in ['Float','Double']:
diff --git a/stdlib/public/SDK/simd/simd.swift.gyb b/stdlib/public/SDK/simd/simd.swift.gyb
index b805db8..340fbbe 100644
--- a/stdlib/public/SDK/simd/simd.swift.gyb
+++ b/stdlib/public/SDK/simd/simd.swift.gyb
@@ -14,7 +14,6 @@
import Swift
import Darwin
-@_exported import SIMDOperators
@_exported import simd
public extension SIMD {
diff --git a/stdlib/public/SIMDOperators/Operators.swift b/stdlib/public/SIMDOperators/Operators.swift
index 797c100..68007d8 100644
--- a/stdlib/public/SIMDOperators/Operators.swift
+++ b/stdlib/public/SIMDOperators/Operators.swift
@@ -1,325 +1 @@
-// Implementations of integer operations. These should eventually all
-// be replaced with @_semantics to lower directly to vector IR nodes.
-public extension SIMD where Scalar : FixedWidthInteger {
- @_transparent
- var leadingZeroBitCount: Self {
- var result = Self()
- for i in indices { result[i] = Scalar(self[i].leadingZeroBitCount) }
- return result
- }
-
- @_transparent
- var trailingZeroBitCount: Self {
- var result = Self()
- for i in indices { result[i] = Scalar(self[i].trailingZeroBitCount) }
- return result
- }
-
- @_transparent
- var nonzeroBitCount: Self {
- var result = Self()
- for i in indices { result[i] = Scalar(self[i].nonzeroBitCount) }
- return result
- }
-
- @_transparent
- static prefix func ~(rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = ~rhs[i] }
- return result
- }
-
- @_transparent
- static func &(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] & rhs[i] }
- return result
- }
-
- @_transparent
- static func ^(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] ^ rhs[i] }
- return result
- }
-
- @_transparent
- static func |(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] | rhs[i] }
- return result
- }
-
- @_transparent
- static func &<<(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] &<< rhs[i] }
- return result
- }
-
- @_transparent
- static func &>>(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] &>> rhs[i] }
- return result
- }
-
- @_transparent
- static func &+(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] &+ rhs[i] }
- return result
- }
-
- @_transparent
- static func &-(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] &- rhs[i] }
- return result
- }
-
- @_transparent
- static func &*(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] &* rhs[i] }
- return result
- }
-
- @_transparent
- static func /(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] / rhs[i] }
- return result
- }
-
- @_transparent
- static func %(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] % rhs[i] }
- return result
- }
-}
-
-// Implementations of floating-point operations. These should eventually all
-// be replaced with @_semantics to lower directly to vector IR nodes.
-public extension SIMD where Scalar : FloatingPoint {
- @_transparent
- static func +(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] + rhs[i] }
- return result
- }
-
- @_transparent
- static func -(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] - rhs[i] }
- return result
- }
-
- @_transparent
- static func *(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] * rhs[i] }
- return result
- }
-
- @_transparent
- static func /(lhs: Self, rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = lhs[i] / rhs[i] }
- return result
- }
-
- @_transparent
- func addingProduct(_ lhs: Self, _ rhs: Self) -> Self {
- var result = Self()
- for i in result.indices { result[i] = self[i].addingProduct(lhs[i], rhs[i]) }
- return result
- }
-
- @_transparent
- func squareRoot( ) -> Self {
- var result = Self()
- for i in result.indices { result[i] = self[i].squareRoot() }
- return result
- }
-
- @_transparent
- func rounded(_ rule: FloatingPointRoundingRule) -> Self {
- var result = Self()
- for i in result.indices { result[i] = self[i].rounded(rule) }
- return result
- }
-}
-
-public extension SIMDMask {
- @_transparent
- static prefix func .!(rhs: SIMDMask) -> SIMDMask {
- return SIMDMask(~rhs._storage)
- }
-
- @_transparent
- static func .&(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask {
- return SIMDMask(lhs._storage & rhs._storage)
- }
-
- @_transparent
- static func .^(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask {
- return SIMDMask(lhs._storage ^ rhs._storage)
- }
-
- @_transparent
- static func .|(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask {
- return SIMDMask(lhs._storage | rhs._storage)
- }
-}
-
-// These operations should never need @_semantics; they should be trivial
-// wrappers around the core operations defined above.
-public extension SIMD where Scalar : FixedWidthInteger {
- @_transparent static func &(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) & rhs }
- @_transparent static func ^(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) ^ rhs }
- @_transparent static func |(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) | rhs }
- @_transparent static func &<<(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &<< rhs }
- @_transparent static func &>>(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &>> rhs }
- @_transparent static func &+(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &+ rhs }
- @_transparent static func &-(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &- rhs }
- @_transparent static func &*(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &* rhs }
- @_transparent static func /(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) / rhs }
- @_transparent static func %(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) % rhs }
-
- @_transparent static func &(lhs: Self, rhs: Scalar) -> Self { return lhs & Self(repeating: rhs) }
- @_transparent static func ^(lhs: Self, rhs: Scalar) -> Self { return lhs ^ Self(repeating: rhs) }
- @_transparent static func |(lhs: Self, rhs: Scalar) -> Self { return lhs | Self(repeating: rhs) }
- @_transparent static func &<<(lhs: Self, rhs: Scalar) -> Self { return lhs &<< Self(repeating: rhs) }
- @_transparent static func &>>(lhs: Self, rhs: Scalar) -> Self { return lhs &>> Self(repeating: rhs) }
- @_transparent static func &+(lhs: Self, rhs: Scalar) -> Self { return lhs &+ Self(repeating: rhs) }
- @_transparent static func &-(lhs: Self, rhs: Scalar) -> Self { return lhs &- Self(repeating: rhs) }
- @_transparent static func &*(lhs: Self, rhs: Scalar) -> Self { return lhs &* Self(repeating: rhs) }
- @_transparent static func /(lhs: Self, rhs: Scalar) -> Self { return lhs / Self(repeating: rhs) }
- @_transparent static func %(lhs: Self, rhs: Scalar) -> Self { return lhs % Self(repeating: rhs) }
-
- @_transparent static func &=(lhs: inout Self, rhs: Self) { lhs = lhs & rhs }
- @_transparent static func ^=(lhs: inout Self, rhs: Self) { lhs = lhs ^ rhs }
- @_transparent static func |=(lhs: inout Self, rhs: Self) { lhs = lhs | rhs }
- @_transparent static func &<<=(lhs: inout Self, rhs: Self) { lhs = lhs &<< rhs }
- @_transparent static func &>>=(lhs: inout Self, rhs: Self) { lhs = lhs &>> rhs }
- @_transparent static func &+=(lhs: inout Self, rhs: Self) { lhs = lhs &+ rhs }
- @_transparent static func &-=(lhs: inout Self, rhs: Self) { lhs = lhs &- rhs }
- @_transparent static func &*=(lhs: inout Self, rhs: Self) { lhs = lhs &* rhs }
- @_transparent static func /=(lhs: inout Self, rhs: Self) { lhs = lhs / rhs }
- @_transparent static func %=(lhs: inout Self, rhs: Self) { lhs = lhs % rhs }
-
- @_transparent static func &=(lhs: inout Self, rhs: Scalar) { lhs = lhs & rhs }
- @_transparent static func ^=(lhs: inout Self, rhs: Scalar) { lhs = lhs ^ rhs }
- @_transparent static func |=(lhs: inout Self, rhs: Scalar) { lhs = lhs | rhs }
- @_transparent static func &<<=(lhs: inout Self, rhs: Scalar) { lhs = lhs &<< rhs }
- @_transparent static func &>>=(lhs: inout Self, rhs: Scalar) { lhs = lhs &>> rhs }
- @_transparent static func &+=(lhs: inout Self, rhs: Scalar) { lhs = lhs &+ rhs }
- @_transparent static func &-=(lhs: inout Self, rhs: Scalar) { lhs = lhs &- rhs }
- @_transparent static func &*=(lhs: inout Self, rhs: Scalar) { lhs = lhs &* rhs }
- @_transparent static func /=(lhs: inout Self, rhs: Scalar) { lhs = lhs / rhs }
- @_transparent static func %=(lhs: inout Self, rhs: Scalar) { lhs = lhs % rhs }
-
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead")
- static func +(lhs: Self, rhs: Self) -> Self { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead")
- static func -(lhs: Self, rhs: Self) -> Self { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead")
- static func *(lhs: Self, rhs: Self) -> Self { fatalError() }
-
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead")
- static func +(lhs: Self, rhs: Scalar) -> Self { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead")
- static func -(lhs: Self, rhs: Scalar) -> Self { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead")
- static func *(lhs: Self, rhs: Scalar) -> Self { fatalError() }
-
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead")
- static func +(lhs: Scalar, rhs: Self) -> Self { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead")
- static func -(lhs: Scalar, rhs: Self) -> Self { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead")
- static func *(lhs: Scalar, rhs: Self) -> Self { fatalError() }
-
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+=' instead")
- static func +=(lhs: inout Self, rhs: Self) { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-=' instead")
- static func -=(lhs: inout Self, rhs: Self) { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*=' instead")
- static func *=(lhs: inout Self, rhs: Self) { fatalError() }
-
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+=' instead")
- static func +=(lhs: inout Self, rhs: Scalar) { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-=' instead")
- static func -=(lhs: inout Self, rhs: Scalar) { fatalError() }
- @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*=' instead")
- static func *=(lhs: inout Self, rhs: Scalar) { fatalError() }
-}
-
-public extension SIMD where Scalar : FloatingPoint {
- @_transparent static prefix func -(rhs: Self) -> Self { return 0 - rhs }
-
- @_transparent static func +(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) + rhs }
- @_transparent static func -(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) - rhs }
- @_transparent static func *(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) * rhs }
- @_transparent static func /(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) / rhs }
-
- @_transparent static func +(lhs: Self, rhs: Scalar) -> Self { return lhs + Self(repeating: rhs) }
- @_transparent static func -(lhs: Self, rhs: Scalar) -> Self { return lhs - Self(repeating: rhs) }
- @_transparent static func *(lhs: Self, rhs: Scalar) -> Self { return lhs * Self(repeating: rhs) }
- @_transparent static func /(lhs: Self, rhs: Scalar) -> Self { return lhs / Self(repeating: rhs) }
-
- @_transparent static func +=(lhs: inout Self, rhs: Self) { lhs = lhs + rhs }
- @_transparent static func -=(lhs: inout Self, rhs: Self) { lhs = lhs - rhs }
- @_transparent static func *=(lhs: inout Self, rhs: Self) { lhs = lhs * rhs }
- @_transparent static func /=(lhs: inout Self, rhs: Self) { lhs = lhs / rhs }
-
- @_transparent static func +=(lhs: inout Self, rhs: Scalar) { lhs = lhs + rhs }
- @_transparent static func -=(lhs: inout Self, rhs: Scalar) { lhs = lhs - rhs }
- @_transparent static func *=(lhs: inout Self, rhs: Scalar) { lhs = lhs * rhs }
- @_transparent static func /=(lhs: inout Self, rhs: Scalar) { lhs = lhs / rhs }
-
- @_transparent func addingProduct(_ lhs: Scalar, _ rhs: Self) -> Self {
- return self.addingProduct(Self(repeating: lhs), rhs)
- }
- @_transparent func addingProduct(_ lhs: Self, _ rhs: Scalar) -> Self {
- return self.addingProduct(lhs, Self(repeating: rhs))
- }
- @_transparent mutating func addProduct(_ lhs: Self, _ rhs: Self) {
- self = self.addingProduct(lhs, rhs)
- }
- @_transparent mutating func addProduct(_ lhs: Scalar, _ rhs: Self) {
- self = self.addingProduct(lhs, rhs)
- }
- @_transparent mutating func addProduct(_ lhs: Self, _ rhs: Scalar) {
- self = self.addingProduct(lhs, rhs)
- }
-
- @_transparent mutating func formSquareRoot( ) {
- self = self.squareRoot()
- }
-
- @_transparent mutating func round(_ rule: FloatingPointRoundingRule) {
- self = self.rounded(rule)
- }
-}
-
-public extension SIMDMask {
- @_transparent static func .&(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .& rhs }
- @_transparent static func .^(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .^ rhs }
- @_transparent static func .|(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .| rhs }
-
- @_transparent static func .&(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .& SIMDMask(repeating: rhs) }
- @_transparent static func .^(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .^ SIMDMask(repeating: rhs) }
- @_transparent static func .|(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .| SIMDMask(repeating: rhs) }
-
- @_transparent static func .&=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .& rhs }
- @_transparent static func .^=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .^ rhs }
- @_transparent static func .|=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .| rhs }
-
- @_transparent static func .&=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .& rhs }
- @_transparent static func .^=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .^ rhs }
- @_transparent static func .|=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .| rhs }
-}
+// This file intentionally left blank.
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 1e4500e..169941c 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -116,6 +116,7 @@
ReflectionMirror.swift
Repeat.swift
REPL.swift
+ Result.swift
Reverse.swift
Runtime.swift.gyb
RuntimeFunctionCounters.swift
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index cd66c3e..55d01d5 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -223,5 +223,8 @@
"Comparable.swift",
"Codable.swift",
"MigrationSupport.swift"
+ ],
+ "Result": [
+ "Result.swift"
]
}
diff --git a/stdlib/public/core/Result.swift b/stdlib/public/core/Result.swift
new file mode 100644
index 0000000..fdd742e
--- /dev/null
+++ b/stdlib/public/core/Result.swift
@@ -0,0 +1,168 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+/// A value that represents either a success or a failure, including an
+/// associated value in each case.
+@_frozen
+public enum Result<Success, Failure: Error> {
+ /// A success, storing a `Success` value.
+ case success(Success)
+
+ /// A failure, storing a `Failure` value.
+ case failure(Failure)
+
+ /// Returns a new result, mapping any success value using the given
+ /// transformation.
+ ///
+ /// Use this method when you need to transform the value of a `Result`
+ /// instance when it represents a success. The following example transforms
+ /// the integer success value of a result into a string:
+ ///
+ /// func getNextInteger() -> Result<Int, Error> { ... }
+ ///
+ /// let integerResult = getNextInteger()
+ /// // integerResult == .success(5)
+ /// let stringResult = integerResult.map({ String($0) })
+ /// // stringResult == .success("5")
+ ///
+ /// - Parameter transform: A closure that takes the success value of this
+ /// instance.
+ /// - Returns: A `Result` instance with the result of evaluating `transform`
+ /// as the new success value if this instance represents a success.
+ public func map<NewSuccess>(
+ _ transform: (Success) -> NewSuccess
+ ) -> Result<NewSuccess, Failure> {
+ switch self {
+ case let .success(success):
+ return .success(transform(success))
+ case let .failure(failure):
+ return .failure(failure)
+ }
+ }
+
+ /// Returns a new result, mapping any failure value using the given
+ /// transformation.
+ ///
+ /// Use this method when you need to transform the value of a `Result`
+ /// instance when it represents a failure. The following example transforms
+ /// the error value of a result by wrapping it in a custom `Error` type:
+ ///
+ /// struct DatedError: Error {
+ /// var error: Error
+ /// var date: Date
+ ///
+ /// init(_ error: Error) {
+ /// self.error = error
+ /// self.date = Date()
+ /// }
+ /// }
+ ///
+ /// let result: Result<Int, Error> = ...
+ /// // result == .failure(<error value>)
+ /// let resultWithDatedError = result.mapError({ e in DatedError(e) })
+ /// // result == .failure(DatedError(error: <error value>, date: <date>))
+ ///
+ /// - Parameter transform: A closure that takes the failure value of the
+ /// instance.
+ /// - Returns: A `Result` instance with the result of evaluating `transform`
+ /// as the new failure value if this instance represents a failure.
+ public func mapError<NewFailure>(
+ _ transform: (Failure) -> NewFailure
+ ) -> Result<Success, NewFailure> {
+ switch self {
+ case let .success(success):
+ return .success(success)
+ case let .failure(failure):
+ return .failure(transform(failure))
+ }
+ }
+
+ /// Returns a new result, mapping any success value using the given
+ /// transformation and unwrapping the produced result.
+ ///
+ /// - Parameter transform: A closure that takes the success value of the
+ /// instance.
+ /// - Returns: A `Result` instance with the result of evaluating `transform`
+ /// as the new failure value if this instance represents a failure.
+ public func flatMap<NewSuccess>(
+ _ transform: (Success) -> Result<NewSuccess, Failure>
+ ) -> Result<NewSuccess, Failure> {
+ switch self {
+ case let .success(success):
+ return transform(success)
+ case let .failure(failure):
+ return .failure(failure)
+ }
+ }
+
+ /// Returns a new result, mapping any failure value using the given
+ /// transformation and unwrapping the produced result.
+ ///
+ /// - Parameter transform: A closure that takes the failure value of the
+ /// instance.
+ /// - Returns: A `Result` instance, either from the closure or the previous
+ /// `.success`.
+ public func flatMapError<NewFailure>(
+ _ transform: (Failure) -> Result<Success, NewFailure>
+ ) -> Result<Success, NewFailure> {
+ switch self {
+ case let .success(success):
+ return .success(success)
+ case let .failure(failure):
+ return transform(failure)
+ }
+ }
+
+ /// Returns the success value as a throwing expression.
+ ///
+ /// Use this method to retrieve the value of this result if it represents a
+ /// success, or to catch the value if it represents a failure.
+ ///
+ /// let integerResult: Result<Int, Error> = .success(5)
+ /// do {
+ /// let value = try integerResult.get()
+ /// print("The value is \(value).")
+ /// } catch error {
+ /// print("Error retrieving the value: \(error)")
+ /// }
+ /// // Prints "The value is 5."
+ ///
+ /// - Returns: The success value, if the instance represent a success.
+ /// - Throws: The failure value, if the instance represents a failure.
+ public func get() throws -> Success {
+ switch self {
+ case let .success(success):
+ return success
+ case let .failure(failure):
+ throw failure
+ }
+ }
+}
+
+extension Result where Failure == Swift.Error {
+ /// Creates a new result by evaluating a throwing closure, capturing the
+ /// returned value as a success, or any thrown error as a failure.
+ ///
+ /// - Parameter body: A throwing closure to evaluate.
+ @_transparent
+ public init(catching body: () throws -> Success) {
+ do {
+ self = .success(try body())
+ } catch {
+ self = .failure(error)
+ }
+ }
+}
+
+extension Result: Equatable where Success: Equatable, Failure: Equatable { }
+
+extension Result: Hashable where Success: Hashable, Failure: Hashable { }
diff --git a/stdlib/public/core/SIMDVector.swift b/stdlib/public/core/SIMDVector.swift
index 540796a..e1ccb42 100644
--- a/stdlib/public/core/SIMDVector.swift
+++ b/stdlib/public/core/SIMDVector.swift
@@ -326,3 +326,329 @@
return SIMDMask.random(using: &g)
}
}
+
+// Implementations of integer operations. These should eventually all
+// be replaced with @_semantics to lower directly to vector IR nodes.
+public extension SIMD where Scalar : FixedWidthInteger {
+ @_transparent
+ var leadingZeroBitCount: Self {
+ var result = Self()
+ for i in indices { result[i] = Scalar(self[i].leadingZeroBitCount) }
+ return result
+ }
+
+ @_transparent
+ var trailingZeroBitCount: Self {
+ var result = Self()
+ for i in indices { result[i] = Scalar(self[i].trailingZeroBitCount) }
+ return result
+ }
+
+ @_transparent
+ var nonzeroBitCount: Self {
+ var result = Self()
+ for i in indices { result[i] = Scalar(self[i].nonzeroBitCount) }
+ return result
+ }
+
+ @_transparent
+ static prefix func ~(rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = ~rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func &(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] & rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func ^(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] ^ rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func |(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] | rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func &<<(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] &<< rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func &>>(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] &>> rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func &+(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] &+ rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func &-(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] &- rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func &*(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] &* rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func /(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] / rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func %(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] % rhs[i] }
+ return result
+ }
+}
+
+// Implementations of floating-point operations. These should eventually all
+// be replaced with @_semantics to lower directly to vector IR nodes.
+public extension SIMD where Scalar : FloatingPoint {
+ @_transparent
+ static func +(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] + rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func -(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] - rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func *(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] * rhs[i] }
+ return result
+ }
+
+ @_transparent
+ static func /(lhs: Self, rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = lhs[i] / rhs[i] }
+ return result
+ }
+
+ @_transparent
+ func addingProduct(_ lhs: Self, _ rhs: Self) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = self[i].addingProduct(lhs[i], rhs[i]) }
+ return result
+ }
+
+ @_transparent
+ func squareRoot( ) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = self[i].squareRoot() }
+ return result
+ }
+
+ @_transparent
+ func rounded(_ rule: FloatingPointRoundingRule) -> Self {
+ var result = Self()
+ for i in result.indices { result[i] = self[i].rounded(rule) }
+ return result
+ }
+}
+
+public extension SIMDMask {
+ @_transparent
+ static prefix func .!(rhs: SIMDMask) -> SIMDMask {
+ return SIMDMask(~rhs._storage)
+ }
+
+ @_transparent
+ static func .&(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask {
+ return SIMDMask(lhs._storage & rhs._storage)
+ }
+
+ @_transparent
+ static func .^(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask {
+ return SIMDMask(lhs._storage ^ rhs._storage)
+ }
+
+ @_transparent
+ static func .|(lhs: SIMDMask, rhs: SIMDMask) -> SIMDMask {
+ return SIMDMask(lhs._storage | rhs._storage)
+ }
+}
+
+// These operations should never need @_semantics; they should be trivial
+// wrappers around the core operations defined above.
+public extension SIMD where Scalar : FixedWidthInteger {
+ @_transparent static func &(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) & rhs }
+ @_transparent static func ^(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) ^ rhs }
+ @_transparent static func |(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) | rhs }
+ @_transparent static func &<<(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &<< rhs }
+ @_transparent static func &>>(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &>> rhs }
+ @_transparent static func &+(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &+ rhs }
+ @_transparent static func &-(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &- rhs }
+ @_transparent static func &*(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) &* rhs }
+ @_transparent static func /(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) / rhs }
+ @_transparent static func %(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) % rhs }
+
+ @_transparent static func &(lhs: Self, rhs: Scalar) -> Self { return lhs & Self(repeating: rhs) }
+ @_transparent static func ^(lhs: Self, rhs: Scalar) -> Self { return lhs ^ Self(repeating: rhs) }
+ @_transparent static func |(lhs: Self, rhs: Scalar) -> Self { return lhs | Self(repeating: rhs) }
+ @_transparent static func &<<(lhs: Self, rhs: Scalar) -> Self { return lhs &<< Self(repeating: rhs) }
+ @_transparent static func &>>(lhs: Self, rhs: Scalar) -> Self { return lhs &>> Self(repeating: rhs) }
+ @_transparent static func &+(lhs: Self, rhs: Scalar) -> Self { return lhs &+ Self(repeating: rhs) }
+ @_transparent static func &-(lhs: Self, rhs: Scalar) -> Self { return lhs &- Self(repeating: rhs) }
+ @_transparent static func &*(lhs: Self, rhs: Scalar) -> Self { return lhs &* Self(repeating: rhs) }
+ @_transparent static func /(lhs: Self, rhs: Scalar) -> Self { return lhs / Self(repeating: rhs) }
+ @_transparent static func %(lhs: Self, rhs: Scalar) -> Self { return lhs % Self(repeating: rhs) }
+
+ @_transparent static func &=(lhs: inout Self, rhs: Self) { lhs = lhs & rhs }
+ @_transparent static func ^=(lhs: inout Self, rhs: Self) { lhs = lhs ^ rhs }
+ @_transparent static func |=(lhs: inout Self, rhs: Self) { lhs = lhs | rhs }
+ @_transparent static func &<<=(lhs: inout Self, rhs: Self) { lhs = lhs &<< rhs }
+ @_transparent static func &>>=(lhs: inout Self, rhs: Self) { lhs = lhs &>> rhs }
+ @_transparent static func &+=(lhs: inout Self, rhs: Self) { lhs = lhs &+ rhs }
+ @_transparent static func &-=(lhs: inout Self, rhs: Self) { lhs = lhs &- rhs }
+ @_transparent static func &*=(lhs: inout Self, rhs: Self) { lhs = lhs &* rhs }
+ @_transparent static func /=(lhs: inout Self, rhs: Self) { lhs = lhs / rhs }
+ @_transparent static func %=(lhs: inout Self, rhs: Self) { lhs = lhs % rhs }
+
+ @_transparent static func &=(lhs: inout Self, rhs: Scalar) { lhs = lhs & rhs }
+ @_transparent static func ^=(lhs: inout Self, rhs: Scalar) { lhs = lhs ^ rhs }
+ @_transparent static func |=(lhs: inout Self, rhs: Scalar) { lhs = lhs | rhs }
+ @_transparent static func &<<=(lhs: inout Self, rhs: Scalar) { lhs = lhs &<< rhs }
+ @_transparent static func &>>=(lhs: inout Self, rhs: Scalar) { lhs = lhs &>> rhs }
+ @_transparent static func &+=(lhs: inout Self, rhs: Scalar) { lhs = lhs &+ rhs }
+ @_transparent static func &-=(lhs: inout Self, rhs: Scalar) { lhs = lhs &- rhs }
+ @_transparent static func &*=(lhs: inout Self, rhs: Scalar) { lhs = lhs &* rhs }
+ @_transparent static func /=(lhs: inout Self, rhs: Scalar) { lhs = lhs / rhs }
+ @_transparent static func %=(lhs: inout Self, rhs: Scalar) { lhs = lhs % rhs }
+
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead")
+ static func +(lhs: Self, rhs: Self) -> Self { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead")
+ static func -(lhs: Self, rhs: Self) -> Self { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead")
+ static func *(lhs: Self, rhs: Self) -> Self { fatalError() }
+
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead")
+ static func +(lhs: Self, rhs: Scalar) -> Self { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead")
+ static func -(lhs: Self, rhs: Scalar) -> Self { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead")
+ static func *(lhs: Self, rhs: Scalar) -> Self { fatalError() }
+
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+' instead")
+ static func +(lhs: Scalar, rhs: Self) -> Self { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-' instead")
+ static func -(lhs: Scalar, rhs: Self) -> Self { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*' instead")
+ static func *(lhs: Scalar, rhs: Self) -> Self { fatalError() }
+
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+=' instead")
+ static func +=(lhs: inout Self, rhs: Self) { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-=' instead")
+ static func -=(lhs: inout Self, rhs: Self) { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*=' instead")
+ static func *=(lhs: inout Self, rhs: Self) { fatalError() }
+
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&+=' instead")
+ static func +=(lhs: inout Self, rhs: Scalar) { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&-=' instead")
+ static func -=(lhs: inout Self, rhs: Scalar) { fatalError() }
+ @available(*, unavailable, message: "integer vector types do not support checked arithmetic; use the wrapping operator '&*=' instead")
+ static func *=(lhs: inout Self, rhs: Scalar) { fatalError() }
+}
+
+public extension SIMD where Scalar : FloatingPoint {
+ @_transparent static prefix func -(rhs: Self) -> Self { return 0 - rhs }
+
+ @_transparent static func +(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) + rhs }
+ @_transparent static func -(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) - rhs }
+ @_transparent static func *(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) * rhs }
+ @_transparent static func /(lhs: Scalar, rhs: Self) -> Self { return Self(repeating: lhs) / rhs }
+
+ @_transparent static func +(lhs: Self, rhs: Scalar) -> Self { return lhs + Self(repeating: rhs) }
+ @_transparent static func -(lhs: Self, rhs: Scalar) -> Self { return lhs - Self(repeating: rhs) }
+ @_transparent static func *(lhs: Self, rhs: Scalar) -> Self { return lhs * Self(repeating: rhs) }
+ @_transparent static func /(lhs: Self, rhs: Scalar) -> Self { return lhs / Self(repeating: rhs) }
+
+ @_transparent static func +=(lhs: inout Self, rhs: Self) { lhs = lhs + rhs }
+ @_transparent static func -=(lhs: inout Self, rhs: Self) { lhs = lhs - rhs }
+ @_transparent static func *=(lhs: inout Self, rhs: Self) { lhs = lhs * rhs }
+ @_transparent static func /=(lhs: inout Self, rhs: Self) { lhs = lhs / rhs }
+
+ @_transparent static func +=(lhs: inout Self, rhs: Scalar) { lhs = lhs + rhs }
+ @_transparent static func -=(lhs: inout Self, rhs: Scalar) { lhs = lhs - rhs }
+ @_transparent static func *=(lhs: inout Self, rhs: Scalar) { lhs = lhs * rhs }
+ @_transparent static func /=(lhs: inout Self, rhs: Scalar) { lhs = lhs / rhs }
+
+ @_transparent func addingProduct(_ lhs: Scalar, _ rhs: Self) -> Self {
+ return self.addingProduct(Self(repeating: lhs), rhs)
+ }
+ @_transparent func addingProduct(_ lhs: Self, _ rhs: Scalar) -> Self {
+ return self.addingProduct(lhs, Self(repeating: rhs))
+ }
+ @_transparent mutating func addProduct(_ lhs: Self, _ rhs: Self) {
+ self = self.addingProduct(lhs, rhs)
+ }
+ @_transparent mutating func addProduct(_ lhs: Scalar, _ rhs: Self) {
+ self = self.addingProduct(lhs, rhs)
+ }
+ @_transparent mutating func addProduct(_ lhs: Self, _ rhs: Scalar) {
+ self = self.addingProduct(lhs, rhs)
+ }
+
+ @_transparent mutating func formSquareRoot( ) {
+ self = self.squareRoot()
+ }
+
+ @_transparent mutating func round(_ rule: FloatingPointRoundingRule) {
+ self = self.rounded(rule)
+ }
+}
+
+public extension SIMDMask {
+ @_transparent static func .&(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .& rhs }
+ @_transparent static func .^(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .^ rhs }
+ @_transparent static func .|(lhs: Bool, rhs: SIMDMask) -> SIMDMask { return SIMDMask(repeating: lhs) .| rhs }
+
+ @_transparent static func .&(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .& SIMDMask(repeating: rhs) }
+ @_transparent static func .^(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .^ SIMDMask(repeating: rhs) }
+ @_transparent static func .|(lhs: SIMDMask, rhs: Bool) -> SIMDMask { return lhs .| SIMDMask(repeating: rhs) }
+
+ @_transparent static func .&=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .& rhs }
+ @_transparent static func .^=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .^ rhs }
+ @_transparent static func .|=(lhs: inout SIMDMask, rhs: SIMDMask) { lhs = lhs .| rhs }
+
+ @_transparent static func .&=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .& rhs }
+ @_transparent static func .^=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .^ rhs }
+ @_transparent static func .|=(lhs: inout SIMDMask, rhs: Bool) { lhs = lhs .| rhs }
+}
diff --git a/stdlib/public/core/SIMDVectorTypes.swift.gyb b/stdlib/public/core/SIMDVectorTypes.swift.gyb
index b5d91ce..a2ed3f5 100644
--- a/stdlib/public/core/SIMDVectorTypes.swift.gyb
+++ b/stdlib/public/core/SIMDVectorTypes.swift.gyb
@@ -109,6 +109,13 @@
}
}
+extension SIMD${n} : CustomDebugStringConvertible {
+ public var debugDescription: String {
+ return "SIMD${n}<\(Scalar.self)>(${', '.join(map(lambda c:
+ '\\(self['+ str(c) + '])',
+ xrange(n)))})"
+ }
+}
public extension SIMD${n} where Scalar : BinaryFloatingPoint {
@inlinable
diff --git a/test/ClangImporter/ctypes_parse_objc.swift b/test/ClangImporter/ctypes_parse_objc.swift
index 415eb49..9a5e396 100644
--- a/test/ClangImporter/ctypes_parse_objc.swift
+++ b/test/ClangImporter/ctypes_parse_objc.swift
@@ -70,8 +70,17 @@
}
func testImportCFTypes() {
- let t1_unqual: Int = CFIndex_test
- _ = t1_unqual as CoreFoundation.CFIndex
+ let t1_unqual: UInt = CFTypeID_test
+ _ = t1_unqual as CoreFoundation.CFTypeID
+
+ let t2_unqual: UInt = CFOptionFlags_test
+ _ = t2_unqual as CoreFoundation.CFOptionFlags
+
+ let t3_unqual: UInt = CFHashCode_test
+ _ = t3_unqual as CoreFoundation.CFHashCode
+
+ let t4_unqual: Int = CFIndex_test
+ _ = t4_unqual as CoreFoundation.CFIndex
}
func testImportSEL() {
diff --git a/test/Compatibility/tuple_arguments_4.swift b/test/Compatibility/tuple_arguments_4.swift
index dfc7026..bb15989 100644
--- a/test/Compatibility/tuple_arguments_4.swift
+++ b/test/Compatibility/tuple_arguments_4.swift
@@ -1,7 +1,5 @@
// RUN: %target-typecheck-verify-swift -swift-version 4
-// See test/Compatibility/tuple_arguments_3.swift for the Swift 3 behavior.
-
func concrete(_ x: Int) {}
func concreteLabeled(x: Int) {}
func concreteTwo(_ x: Int, _ y: Int) {} // expected-note 5 {{'concreteTwo' declared here}}
@@ -1671,7 +1669,6 @@
h() // expected-error {{missing argument for parameter #1 in call}}
}
-
// https://bugs.swift.org/browse/SR-7191
class Mappable<T> {
init(_: T) { }
@@ -1680,3 +1677,9 @@
let x = Mappable(())
_ = x.map { (_: Void) in return () }
+
+// https://bugs.swift.org/browse/SR-9470
+do {
+ func f(_: Int...) {}
+ let _ = [(1, 2, 3)].map(f) // expected-error {{cannot invoke 'map' with an argument list of type '((Int...) -> ())'}}
+}
\ No newline at end of file
diff --git a/test/Constraints/tuple.swift b/test/Constraints/tuple.swift
index 6e8df0f..b951841 100644
--- a/test/Constraints/tuple.swift
+++ b/test/Constraints/tuple.swift
@@ -56,7 +56,7 @@
// Tuples with existentials
var any : Any = ()
any = (1, 2)
-any = (label: 4)
+any = (label: 4) // expected-error {{cannot create a single-element tuple with an element label}}
// Scalars don't have .0/.1/etc
i = j.0 // expected-error{{value of type 'Int' has no member '0'}}
@@ -153,7 +153,7 @@
var a = a
var b = b
(a, b) = (b, a % b) // expected-error {{binary operator '%' cannot be applied to two 'T' operands}}
- // expected-note @-1 {{overloads for '%' exist with these partially matching parameter lists: (UInt8, UInt8), (Int8, Int8), (UInt16, UInt16), (Int16, Int16), (UInt32, UInt32), (Int32, Int32), (UInt64, UInt64), (Int64, Int64), (UInt, UInt), (Int, Int)}}
+ // expected-note @-1 {{overloads for '%' exist with these partially matching parameter lists}}
}
// <rdar://problem/24210190>
@@ -252,3 +252,11 @@
let y = ""
return b ? (x, y) : nil
}
+
+// Single element tuple expressions
+func singleElementTuple() {
+ let _ = (label: 123) // expected-error {{cannot create a single-element tuple with an element label}} {{12-19=}}
+ let _ = (label: 123).label // expected-error {{cannot create a single-element tuple with an element label}} {{12-19=}}
+ let _ = ((label: 123)) // expected-error {{cannot create a single-element tuple with an element label}} {{13-20=}}
+ let _ = ((label: 123)).label // expected-error {{cannot create a single-element tuple with an element label}} {{13-20=}}
+}
diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift
index 2dfe694..4ad4c93 100644
--- a/test/Constraints/tuple_arguments.swift
+++ b/test/Constraints/tuple_arguments.swift
@@ -1671,3 +1671,18 @@
func h(_: ()) {} // expected-note {{'h' declared here}}
h() // expected-error {{missing argument for parameter #1 in call}}
}
+
+// https://bugs.swift.org/browse/SR-7191
+class Mappable<T> {
+ init(_: T) { }
+ func map<U>(_ body: (T) -> U) -> U { fatalError() }
+}
+
+let x = Mappable(())
+_ = x.map { (_: Void) in return () }
+
+// https://bugs.swift.org/browse/SR-9470
+do {
+ func f(_: Int...) {}
+ let _ = [(1, 2, 3)].map(f) // expected-error {{cannot invoke 'map' with an argument list of type '((Int...) -> ())'}}
+}
\ No newline at end of file
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 1fcab70..4ff70e7 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -301,7 +301,7 @@
_T0So11CrappyColorVs16RawRepresentableSCMA ---> reflection metadata associated type descriptor __C.CrappyColor : Swift.RawRepresentable in __C_Synthesized
$S28protocol_conformance_records15NativeValueTypeVAA8RuncibleAAMc ---> protocol conformance descriptor for protocol_conformance_records.NativeValueType : protocol_conformance_records.Runcible in protocol_conformance_records
$SSC9SomeErrorLeVD ---> __C_Synthesized.related decl 'e' for SomeError
-$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg0_GF ---> mangling_retroactive.test1(mangling_retroactive.Z2<RetroactiveB.X>.Inner<RetroactiveB.Y>) -> ()
+$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAHPyHCg_AiJ1QAAHPyHCg1_GF ---> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()
_T0LiteralAByxGxd_tcfC ---> _T0LiteralAByxGxd_tcfC
_T0XZ ---> _T0XZ
_TTSf0os___TFVs17_LegacyStringCore15_invariantCheckfT_T_ ---> function signature specialization <Arg[0] = Guaranteed To Owned and Exploded> of Swift._LegacyStringCore._invariantCheck() -> ()
diff --git a/test/IRGen/lazy_field_metadata.swift b/test/IRGen/lazy_field_metadata.swift
new file mode 100644
index 0000000..702957e
--- /dev/null
+++ b/test/IRGen/lazy_field_metadata.swift
@@ -0,0 +1,18 @@
+// RUN: %target-swift-frontend -emit-ir -wmo -O %s | %FileCheck %s
+
+// Both should be emitted:
+
+// CHECK: @"$s19lazy_field_metadata011GenericWithD5FieldVMn" = hidden constant
+// CHECK: @"$s19lazy_field_metadata24GenericWithConcreteFieldVMn" = hidden constant
+
+struct GenericWithConcreteField<T> {
+ let z = 123
+}
+
+struct GenericWithGenericField<T> {
+ var field = GenericWithConcreteField<T>()
+}
+
+public func forceMetadata() -> Any.Type {
+ return GenericWithGenericField<Int>.self
+}
\ No newline at end of file
diff --git a/test/Inputs/clang-importer-sdk/usr/include/CoreFoundation.h b/test/Inputs/clang-importer-sdk/usr/include/CoreFoundation.h
index 508e499..51cd769 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/CoreFoundation.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/CoreFoundation.h
@@ -18,8 +18,21 @@
typedef CFTypeRef CFAliasForTypeRef;
-
+#if __LLP64__
+typedef unsigned long long CFTypeID;
+typedef unsigned long long CFOptionFlags;
+typedef unsigned long long CFHashCode;
+typedef signed long long CFIndex;
+#else
+typedef unsigned long CFTypeID;
+typedef unsigned long CFOptionFlags;
+typedef unsigned long CFHashCode;
typedef signed long CFIndex;
+#endif
+
+extern CFTypeID CFTypeID_test;
+extern CFOptionFlags CFOptionFlags_test;
+extern CFHashCode CFHashCode_test;
extern CFIndex CFIndex_test;
#define CF_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
diff --git a/test/Migrator/stdlib_rename.swift b/test/Migrator/stdlib_rename.swift
new file mode 100644
index 0000000..20397f3
--- /dev/null
+++ b/test/Migrator/stdlib_rename.swift
@@ -0,0 +1,12 @@
+// REQUIRES: objc_interop
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -emit-migrated-file-path %t/stdlib_rename.swift.result -emit-remap-file-path %t/stdlib_rename.swift.remap -o /dev/null
+// RUN: diff -u %S/stdlib_rename.swift.expected %t/stdlib_rename.swift.result
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -emit-migrated-file-path %t/stdlib_rename.swift.result -emit-remap-file-path %t/stdlib_rename.swift.remap -o /dev/null -swift-version 4.2
+// RUN: diff -u %S/stdlib_rename.swift.expected %t/stdlib_rename.swift.result
+
+func test1(_ a: [String], s: String) {
+ _ = a.index(of: s)
+}
+func test2(_ s: String, c: Character) {
+ _ = s.index(of: c)
+}
\ No newline at end of file
diff --git a/test/Migrator/stdlib_rename.swift.expected b/test/Migrator/stdlib_rename.swift.expected
new file mode 100644
index 0000000..f721bf8
--- /dev/null
+++ b/test/Migrator/stdlib_rename.swift.expected
@@ -0,0 +1,12 @@
+// REQUIRES: objc_interop
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -emit-migrated-file-path %t/stdlib_rename.swift.result -emit-remap-file-path %t/stdlib_rename.swift.remap -o /dev/null
+// RUN: diff -u %S/stdlib_rename.swift.expected %t/stdlib_rename.swift.result
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -F %S/mock-sdk -emit-migrated-file-path %t/stdlib_rename.swift.result -emit-remap-file-path %t/stdlib_rename.swift.remap -o /dev/null -swift-version 4.2
+// RUN: diff -u %S/stdlib_rename.swift.expected %t/stdlib_rename.swift.result
+
+func test1(_ a: [String], s: String) {
+ _ = a.firstIndex(of: s)
+}
+func test2(_ s: String, c: Character) {
+ _ = s.firstIndex(of: c)
+}
\ No newline at end of file
diff --git a/test/NameBinding/Inputs/HasResult.swift b/test/NameBinding/Inputs/HasResult.swift
new file mode 100644
index 0000000..6fcc1dd
--- /dev/null
+++ b/test/NameBinding/Inputs/HasResult.swift
@@ -0,0 +1,4 @@
+public enum Result<Value, Error> {
+case success(Value)
+case failure(Error)
+}
diff --git a/test/NameBinding/Inputs/MemberTypesInClasses.swift b/test/NameBinding/Inputs/MemberTypesInClasses.swift
new file mode 100644
index 0000000..1e9ed6f
--- /dev/null
+++ b/test/NameBinding/Inputs/MemberTypesInClasses.swift
@@ -0,0 +1,7 @@
+public class RootClass {
+}
+
+public class SubClass: RootClass {
+ public typealias Member = Int
+}
+
diff --git a/test/NameBinding/member_type_shadowing.swift b/test/NameBinding/member_type_shadowing.swift
new file mode 100644
index 0000000..b9231a1
--- /dev/null
+++ b/test/NameBinding/member_type_shadowing.swift
@@ -0,0 +1,15 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/MemberTypesInClasses.swift
+// RUN: %target-swift-frontend -typecheck %s -I %t -verify
+
+import MemberTypesInClasses
+
+protocol P {
+ associatedtype Member
+}
+
+extension RootClass: P {
+ typealias Member = SubClass.Member
+}
+
+
diff --git a/test/NameBinding/stdlib_shadowing.swift b/test/NameBinding/stdlib_shadowing.swift
new file mode 100644
index 0000000..ccbb824
--- /dev/null
+++ b/test/NameBinding/stdlib_shadowing.swift
@@ -0,0 +1,9 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/HasResult.swift
+// RUN: %target-swift-frontend -typecheck %s -I %t -verify
+
+import HasResult
+
+func foo() -> Result<Int, Error> {
+ return Result<Int, Error>.success(42)
+}
diff --git a/test/Parse/try.swift b/test/Parse/try.swift
index 54a2aa2..f58f4a0 100644
--- a/test/Parse/try.swift
+++ b/test/Parse/try.swift
@@ -258,3 +258,14 @@
let _: Int?? = try? producer.produceDoubleOptionalInt() // expected-error {{value of optional type 'Int???' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
let _: Int??? = try? producer.produceDoubleOptionalInt() // good
let _: String = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int???' to specified type 'String'}}
+
+// rdar://problem/46742002
+protocol Dummy : class {}
+
+class F<T> {
+ func wait() throws -> T { fatalError() }
+}
+
+func bar(_ a: F<Dummy>, _ b: F<Dummy>) {
+ _ = (try? a.wait()) === (try? b.wait())
+}
diff --git a/test/Parse/try_swift5.swift b/test/Parse/try_swift5.swift
index 6d463a0..ec05752 100644
--- a/test/Parse/try_swift5.swift
+++ b/test/Parse/try_swift5.swift
@@ -261,3 +261,14 @@
let _: Int?? = try? producer.produceDoubleOptionalInt() // good
let _: Int??? = try? producer.produceDoubleOptionalInt() // good
let _: String = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
+
+// rdar://problem/46742002
+protocol Dummy : class {}
+
+class F<T> {
+ func wait() throws -> T { fatalError() }
+}
+
+func bar(_ a: F<Dummy>, _ b: F<Dummy>) {
+ _ = (try? a.wait()) === (try? b.wait())
+}
diff --git a/test/ParseableInterface/fixed-layout-property-initializers.swift b/test/ParseableInterface/fixed-layout-property-initializers.swift
index 0b817bc..099a214 100644
--- a/test/ParseableInterface/fixed-layout-property-initializers.swift
+++ b/test/ParseableInterface/fixed-layout-property-initializers.swift
@@ -1,16 +1,16 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.swiftinterface %s
-// RUN: %FileCheck %s < %t.swiftinterface
+// RUN: %FileCheck %s --check-prefix FROMSOURCE --check-prefix CHECK < %t.swiftinterface
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t-resilient.swiftinterface -enable-resilience %s
-// RUN: %FileCheck %s < %t-resilient.swiftinterface
+// RUN: %FileCheck %s --check-prefix FROMSOURCE --check-prefix CHECK < %t-resilient.swiftinterface
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module
-// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-parseable-module-interface-path - | %FileCheck %s
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-parseable-module-interface-path - | %FileCheck %s --check-prefix FROMMODULE --check-prefix CHECK
// RUN: %target-swift-frontend -emit-module -o %t/TestResilient.swiftmodule -enable-resilience %t-resilient.swiftinterface -disable-objc-attr-requires-foundation-module
-// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-parseable-module-interface-path - | %FileCheck %s
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-parseable-module-interface-path - | %FileCheck %s --check-prefix FROMMODULE --check-prefix CHECK
// CHECK: @_fixed_layout public struct MyStruct {
@_fixed_layout
@@ -34,7 +34,8 @@
// CHECK: @_hasInitialValue public static var staticVar: [[BOOL]]
public static var staticVar: Bool = Bool(true && false)
- // CHECK: @inlinable internal init() {}
+ // FROMSOURCE: @inlinable internal init() {}
+ // FROMMODULE: @inlinable internal init(){{$}}
@inlinable init() {}
}
@@ -57,7 +58,8 @@
// CHECK: @_hasInitialValue public static var staticVar: [[BOOL]]
public static var staticVar: Bool = Bool(true && false)
- // CHECK: @inlinable internal init() {}
+ // FROMSOURCE: @inlinable internal init() {}
+ // FROMMODULE: @inlinable internal init(){{$}}
@inlinable init() {}
}
diff --git a/test/ParseableInterface/inlinable-function.swift b/test/ParseableInterface/inlinable-function.swift
index 3bb0589..f22e63d 100644
--- a/test/ParseableInterface/inlinable-function.swift
+++ b/test/ParseableInterface/inlinable-function.swift
@@ -1,15 +1,17 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule -emit-parseable-module-interface-path %t/Test.swiftinterface -module-name Test %s
-// RUN: %FileCheck %s < %t/Test.swiftinterface
-// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-parseable-module-interface-path - -module-name Test | %FileCheck %s
+// RUN: %FileCheck %s --check-prefix FROMSOURCE --check-prefix CHECK < %t/Test.swiftinterface
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-parseable-module-interface-path %t/TestFromModule.swiftinterface -module-name Test
+// RUN: %FileCheck %s --check-prefix FROMMODULE --check-prefix CHECK < %t/TestFromModule.swiftinterface
// CHECK: public struct Foo : Hashable {
public struct Foo: Hashable {
// CHECK: public var inlinableGetPublicSet: [[INT:(Swift.)?Int]] {
public var inlinableGetPublicSet: Int {
- // CHECK: @inlinable get {
- // CHECK-NEXT: return 3
- // CHECK-NEXT: }
+ // FROMSOURCE: @inlinable get {
+ // FROMMODULE: @inlinable get{{$}}
+ // FROMSOURCE-NEXT: return 3
+ // FROMSOURCE-NEXT: }
@inlinable
get {
return 3
@@ -35,11 +37,11 @@
// CHECK-NEXT: {{^}} }
}
-
// CHECK: @_transparent public var transparent: [[INT]] {
- // CHECK-NEXT: get {
- // CHECK-NEXT: return 34
- // CHECK-NEXT: }
+ // FROMMODULE-NEXT: get{{$}}
+ // FROMSOURCE-NEXT: get {
+ // FROMSOURCE-NEXT: return 34
+ // FROMSOURCE-NEXT: }
// CHECK-NEXT: }
@_transparent
public var transparent: Int {
@@ -52,17 +54,18 @@
get {
return 34
}
- // CHECK-NEXT: @_transparent set[[NEWVALUE]] {
- // CHECK-NOT: #if false
- // CHECK-NOT: print("I should not appear")
- // CHECK-NOT: #else
- // CHECK-NOT: #if false
- // CHECK-NOT: print("I also should not")
- // CHECK-NOT: #else
- // CHECK: print("I am set to \(newValue)")
- // CHECK-NOT: #endif
- // CHECK-NOT: #endif
- // CHECK-NEXT: }
+ // FROMMODULE-NEXT: @_transparent set[[NEWVALUE]]{{$}}
+ // FROMSOURCE-NEXT: @_transparent set[[NEWVALUE]] {
+ // FROMSOURCE-NOT: #if false
+ // FROMSOURCE-NOT: print("I should not appear")
+ // FROMSOURCE-NOT: #else
+ // FROMSOURCE-NOT: #if false
+ // FROMSOURCE-NOT: print("I also should not")
+ // FROMSOURCE-NOT: #else
+ // FROMSOURCE: print("I am set to \(newValue)")
+ // FROMSOURCE-NOT: #endif
+ // FROMSOURCE-NOT: #endif
+ // FROMSOURCE-NEXT: }
@_transparent
set {
#if false
@@ -80,20 +83,22 @@
// CHECK: @inlinable public var inlinableProperty: [[INT]] {
@inlinable
public var inlinableProperty: Int {
- // CHECK: get {
- // CHECK: return 32
- // CHECK: }
+ // FROMMODULE: get{{$}}
+ // FROMSOURCE: get {
+ // FROMSOURCE-NEXT: return 32
+ // FROMSOURCE-NEXT: }
get {
return 32
}
- // CHECK: set[[NEWVALUE]] {
- // CHECK-NOT: #if true
- // CHECK: print("I am set to \(newValue)")
- // CHECK-NOT: #else
- // CHECK-NOT: print("I should not appear")
- // CHECK-NOT #endif
- // CHECK: }
+ // FROMMODULE: set[[NEWVALUE]]{{$}}
+ // FROMSOURCE: set[[NEWVALUE]] {
+ // FROMSOURCE-NOT: #if true
+ // FROMSOURCE: print("I am set to \(newValue)")
+ // FROMSOURCE-NOT: #else
+ // FROMSOURCE-NOT: print("I should not appear")
+ // FROMSOURCE-NOT #endif
+ // FROMSOURCE: }
set {
#if true
print("I am set to \(newValue)")
@@ -107,16 +112,18 @@
// CHECK: @inlinable public var inlinableReadAndModify: [[INT]] {
@inlinable
public var inlinableReadAndModify: Int {
- // CHECK: _read {
- // CHECK-NEXT: yield 0
- // CHECK-NEXT: }
+ // FROMMODULE: _read{{$}}
+ // FROMSOURCE: _read {
+ // FROMSOURCE-NEXT: yield 0
+ // FROMSOURCE-NEXT: }
_read {
yield 0
}
- // CHECK: _modify {
- // CHECK-NEXT: var x = 0
- // CHECK-NEXT: yield &x
- // CHECK-NEXT: }
+ // FROMMODULE: _modify{{$}}
+ // FROMSOURCE: _modify {
+ // FROMSOURCE-NEXT: var x = 0
+ // FROMSOURCE-NEXT: yield &x
+ // FROMSOURCE-NEXT: }
_modify {
var x = 0
yield &x
@@ -126,9 +133,10 @@
// CHECK: public var inlinableReadNormalModify: [[INT]] {
public var inlinableReadNormalModify: Int {
- // CHECK: @inlinable _read {
- // CHECK-NEXT: yield 0
- // CHECK-NEXT: }
+ // FROMMODULE: @inlinable _read{{$}}
+ // FROMSOURCE: @inlinable _read {
+ // FROMSOURCE-NEXT: yield 0
+ // FROMSOURCE-NEXT: }
@inlinable _read {
yield 0
}
@@ -153,10 +161,11 @@
yield 0
}
- // CHECK: @inlinable _modify {
- // CHECK-NEXT: var x = 0
- // CHECK-NEXT: yield &x
- // CHECK-NEXT: }
+ // FROMMODULE: @inlinable _modify{{$}}
+ // FROMSOURCE: @inlinable _modify {
+ // FROMSOURCE-NEXT: var x = 0
+ // FROMSOURCE-NEXT: yield &x
+ // FROMSOURCE-NEXT: }
@inlinable _modify {
var x = 0
yield &x
@@ -176,12 +185,13 @@
// CHECK-NEXT: }
}
- // CHECK: @inlinable public func inlinableMethod() {
- // CHECK-NOT: #if NO
- // CHECK-NOT: print("Hello, world!")
- // CHECK-NOT: #endif
- // CHECK: print("Goodbye, world!")
- // CHECK-NEXT: }
+ // FROMMODULE: @inlinable public func inlinableMethod(){{$}}
+ // FROMSOURCE: @inlinable public func inlinableMethod() {
+ // FROMSOURCE-NOT: #if NO
+ // FROMSOURCE-NOT: print("Hello, world!")
+ // FROMSOURCE-NOT: #endif
+ // FROMSOURCE: print("Goodbye, world!")
+ // FROMSOURCE-NEXT: }
@inlinable
public func inlinableMethod() {
#if NO
@@ -191,9 +201,10 @@
}
- // CHECK: @_transparent [[ATTRS:(mutating public|public mutating)]] func transparentMethod() {
- // CHECK-NEXT: inlinableProperty = 4
- // CHECK-NEXT: }
+ // FROMMODULE: @_transparent [[ATTRS:(mutating public|public mutating)]] func transparentMethod(){{$}}
+ // FROMSOURCE: @_transparent [[ATTRS:(mutating public|public mutating)]] func transparentMethod() {
+ // FROMSOURCE-NEXT: inlinableProperty = 4
+ // FROMSOURCE-NEXT: }
@_transparent
mutating public func transparentMethod() {
inlinableProperty = 4
@@ -207,7 +218,8 @@
// CHECK: public subscript(i: [[INT]]) -> [[INT]] {
// CHECK-NEXT: get{{$}}
- // CHECK-NEXT: @inlinable set[[NEWVALUE]] { print("set") }
+ // FROMSOURCE-NEXT: @inlinable set[[NEWVALUE]] { print("set") }
+ // FROMMODULE-NEXT: @inlinable set[[NEWVALUE]]{{$}}
// CHECK-NEXT: }
public subscript(i: Int) -> Int {
get { return 0 }
@@ -215,7 +227,8 @@
}
// CHECK: public subscript(j: [[INT]], k: [[INT]]) -> [[INT]] {
- // CHECK-NEXT: @inlinable get { return 0 }
+ // FROMMODULE-NEXT: @inlinable get{{$}}
+ // FROMSOURCE-NEXT: @inlinable get { return 0 }
// CHECK-NEXT: set[[NEWVALUE]]{{$}}
// CHECK-NEXT: }
public subscript(j: Int, k: Int) -> Int {
@@ -224,8 +237,10 @@
}
// CHECK: @inlinable public subscript(l: [[INT]], m: [[INT]], n: [[INT]]) -> [[INT]] {
- // CHECK-NEXT: get { return 0 }
- // CHECK-NEXT: set[[NEWVALUE]] { print("set") }
+ // FROMMODULE-NEXT: get{{$}}
+ // FROMSOURCE-NEXT: get { return 0 }
+ // FROMMODULE-NEXT: set[[NEWVALUE]]{{$}}
+ // FROMSOURCE-NEXT: set[[NEWVALUE]] { print("set") }
// CHECK-NEXT: }
@inlinable
public subscript(l: Int, m: Int, n: Int) -> Int {
@@ -233,11 +248,12 @@
set { print("set") }
}
- // CHECK: public init(value: [[INT]]) {
- // CHECK-NEXT: topLevelUsableFromInline()
- // CHECK-NEXT: noAccessors = value
- // CHECK-NEXT: hasDidSet = value
- // CHECK-NEXT: }
+ // FROMMODULE: @inlinable public init(value: [[INT]]){{$}}
+ // FROMSOURCE: @inlinable public init(value: [[INT]]) {
+ // FROMSOURCE-NEXT: topLevelUsableFromInline()
+ // FROMSOURCE-NEXT: noAccessors = value
+ // FROMSOURCE-NEXT: hasDidSet = value
+ // FROMSOURCE-NEXT: }
@inlinable public init(value: Int) {
topLevelUsableFromInline()
noAccessors = value
@@ -266,9 +282,10 @@
topLevelPrivate()
}
-// CHECK: @inlinable public func topLevelInlinable() {
-// CHECK-NEXT: topLevelUsableFromInline()
-// CHECK-NEXT: }
+// FROMMODULE: @inlinable public func topLevelInlinable(){{$}}
+// FROMSOURCE: @inlinable public func topLevelInlinable() {
+// FROMSOURCE-NEXT: topLevelUsableFromInline()
+// FROMSOURCE-NEXT: }
@inlinable public func topLevelInlinable() {
topLevelUsableFromInline()
}
@@ -278,9 +295,10 @@
// CHECK: public init(){{$}}
public init() {}
- // CHECK: [[OBJC:(@objc )?]]@inlinable deinit {
- // CHECK-NEXT: print("goodbye")
- // CHECK-NEXT: }
+ // FROMMODULE: [[OBJC:(@objc )?]]@inlinable deinit{{$}}
+ // FROMSOURCE: [[OBJC:(@objc )?]]@inlinable deinit {
+ // FROMSOURCE-NEXT: print("goodbye")
+ // FROMSOURCE-NEXT: }
@inlinable deinit {
print("goodbye")
}
diff --git a/test/ParseableInterface/modifiers.swift b/test/ParseableInterface/modifiers.swift
index d63a46a..c0576b0 100644
--- a/test/ParseableInterface/modifiers.swift
+++ b/test/ParseableInterface/modifiers.swift
@@ -1,14 +1,15 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule -emit-parseable-module-interface-path %t/Test.swiftinterface -module-name Test -disable-objc-attr-requires-foundation-module -enable-objc-interop %s
-// RUN: %FileCheck %s < %t/Test.swiftinterface
-// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-parseable-module-interface-path - -module-name Test -enable-objc-interop | %FileCheck %s
+// RUN: %FileCheck %s --check-prefix FROMSOURCE --check-prefix CHECK < %t/Test.swiftinterface
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-parseable-module-interface-path - -module-name Test -enable-objc-interop | %FileCheck %s --check-prefix FROMMODULE --check-prefix CHECK
// CHECK-LABEL: final public class FinalClass {
public final class FinalClass {
// CHECK: @inlinable final public class var a: [[INT:(Swift.)?Int]] {
- // CHECK-NEXT: {{^}} get {
- // CHECK-NEXT: return 3
- // CHECK-NEXT: }
+ // FROMSOURCE-NEXT: {{^}} get {
+ // FROMSOURCE-NEXT: return 3
+ // FROMSOURCE-NEXT: }
+ // FROMMODULE-NEXT: get{{$}}
// CHECK-NEXT: }
@inlinable
public final class var a: Int {
@@ -16,9 +17,10 @@
}
// CHECK: final public class var b: [[INT]] {
- // CHECK-NEXT: {{^}} @inlinable get {
- // CHECK-NEXT: return 3
- // CHECK-NEXT: }
+ // FROMSOURCE-NEXT: {{^}} @inlinable get {
+ // FROMSOURCE-NEXT: return 3
+ // FROMSOURCE-NEXT: }
+ // FROMMODULE-NEXT: {{^}} @inlinable get{{$}}
// CHECK-NEXT: set[[NEWVALUE:(\(newValue\))?]]{{$}}
// CHECK-NEXT: }
public final class var b: Int {
@@ -32,7 +34,8 @@
// CHECK: public static var c: [[INT]] {
// CHECK-NEXT: {{^}} get
- // CHECK-NEXT: @inlinable set[[NEWVALUE]] {}
+ // FROMSOURCE-NEXT: @inlinable set[[NEWVALUE]] {}
+ // FROMMODULE-NEXT: @inlinable set[[NEWVALUE]]{{$}}
// CHECK-NEXT: }
public static var c: Int {
get {
@@ -85,7 +88,8 @@
public struct MyStruct {
// CHECK: public var e: [[INT]] {
// CHECK-NEXT: {{^}} mutating get{{$}}
- // CHECK-NEXT: {{^}} @inlinable nonmutating set[[NEWVALUE]] {}
+ // FROMSOURCE-NEXT: {{^}} @inlinable nonmutating set[[NEWVALUE]] {}
+ // FROMMODULE-NEXT: {{^}} @inlinable nonmutating set[[NEWVALUE]]{{$}}
// CHECK-NEXT: }
public var e: Int {
mutating get { return 0 }
diff --git a/test/ParseableInterface/stored-properties-client.swift b/test/ParseableInterface/stored-properties-client.swift
index a7e04fd..914815b 100644
--- a/test/ParseableInterface/stored-properties-client.swift
+++ b/test/ParseableInterface/stored-properties-client.swift
@@ -15,7 +15,7 @@
// COMMON: %[[BAGOFVARIABLES:T16StoredProperties14BagOfVariablesV]] = type <{ %TSi, %TSb, [{{(3|7)}} x i8], %TSi }>
// This type is non-@_fixed_layout, so it becomes opaque in a resilient module
-// CHECK: %[[HASSTOREDPROPERTIES:T16StoredProperties03HasaB0V]] = type <{ %TSi, %TSi, %TSb, [{{(3|7)}} x i8], %TSi, %TSb }>
+// CHECK: %[[HASSTOREDPROPERTIES:T16StoredProperties03HasaB0V]] = type <{ %TSi, %TSi, %TSb, [{{(3|7)}} x i8], %TSi, %TSb, [{{3|7}} x i8], %TSi }>
// RESILIENT: %[[HASSTOREDPROPERTIES:swift.opaque]] = type opaque
// COMMON: %[[HASSTOREDPROPERTIESFIXEDLAYOUT:T16StoredProperties03HasaB11FixedLayoutV]] = type <{ %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]] }>
diff --git a/test/ParseableInterface/stored-properties.swift b/test/ParseableInterface/stored-properties.swift
index 35e7682..774553e 100644
--- a/test/ParseableInterface/stored-properties.swift
+++ b/test/ParseableInterface/stored-properties.swift
@@ -52,6 +52,15 @@
// CHECK: private var _: [[BOOL]]
private var privateVar: Bool
+ // CHECK: @_hasStorage @_hasInitialValue public var storedWithObserversInitialValue: [[INT]] {
+ // RESILIENT: {{^}} @_hasInitialValue public var storedWithObserversInitialValue: [[INT]] {
+ // COMMON-NEXT: get
+ // COMMON-NEXT: set
+ // COMMON-NEXT: }
+ public var storedWithObserversInitialValue: Int = 0 {
+ didSet {}
+ }
+
// COMMON: public init(){{$}}
public init() {
self.simpleStoredImmutable = 0
diff --git a/test/SILGen/mangling_retroactive.swift b/test/SILGen/mangling_retroactive.swift
index ee95ccd..2c865b1 100644
--- a/test/SILGen/mangling_retroactive.swift
+++ b/test/SILGen/mangling_retroactive.swift
@@ -12,14 +12,14 @@
extension X: P { } // retroactive
extension Y: Q { } // retroactive
-// CHECK: sil hidden @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAyHCg_AiJ1QAAyHCg1_GF
+// CHECK: sil hidden @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAHPyHCg_AiJ1QAAHPyHCg1_GF
func test0(_: Z<X, Int, Y>) { }
struct Z2<T: P> {
struct Inner<V: Q> { }
}
-// CHECK: sil hidden @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg0_GF
+// CHECK: sil hidden @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAHPyHCg_AkL1QAAHPyHCg0_GF
func test1(_: Z2<X>.Inner<Y>) { }
extension X: Hashable {
@@ -38,5 +38,5 @@
struct RequiresEquatable<T: Equatable> { }
// Conditional requirement involves retroactive conformances.
-// CHECK: sil hidden @$s20mangling_retroactive5test2yyAA17RequiresEquatableVyAA1ZVy12RetroactiveB1XVSiAG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg1_GAOSQAISHAAyHC_AKSQAAyHCHCg_GF
+// CHECK: sil hidden @$s20mangling_retroactive5test2yyAA17RequiresEquatableVyAA1ZVy12RetroactiveB1XVSiAG1YVAI0F1A1PAAHPyHCg_AkL1QAAHPyHCg1_GAOSQHPAISHAAHPyHC_AKSQAAHPyHCHCg_GF
func test2(_: RequiresEquatable<Z<X, Int, Y>>) { }
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index 08fda37..2cfe911 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -614,6 +614,30 @@
return %2 : $Builtin.RawPointer
}
+sil @test_closure : $@convention(thin) (@guaranteed C) -> ()
+
+// CHECK-LABEL: sil @dead_closure_elimination
+// CHECK: bb0(%0 : $C):
+// CHECK-NEXT: cond_br
+// CHECK-NOT: strong_release
+// CHECK: bb2:
+// CHECK-NEXT: strong_release %0
+// CHECK return
+sil @dead_closure_elimination : $@convention(thin) (@owned C) -> () {
+bb0(%0 : $C):
+ %1 = function_ref @test_closure : $@convention(thin) (@guaranteed C) -> ()
+ %2 = partial_apply [callee_guaranteed] %1(%0) : $@convention(thin) (@guaranteed C) -> ()
+ cond_br undef, bb1, bb2
+bb1:
+ strong_retain %2 : $@callee_guaranteed () -> ()
+ strong_release %2 : $@callee_guaranteed () -> ()
+ br bb2
+bb2:
+ release_value %2 : $@callee_guaranteed () -> ()
+ %5 = tuple()
+ return %5 : $()
+}
+
////////////////////////////////////////////
// Load Proj To GEP Load Canonicalization //
////////////////////////////////////////////
diff --git a/test/Sema/complex_expressions.swift b/test/Sema/complex_expressions.swift
index 2fee412..788919b 100644
--- a/test/Sema/complex_expressions.swift
+++ b/test/Sema/complex_expressions.swift
@@ -1,11 +1,5 @@
// RUN: %target-typecheck-verify-swift
-// SR-139:
-// Infinite recursion parsing bitwise operators
-// Temporarily disable to get SIMD stuff working. Ideally we can reinstate this
-// with Mark's changes.
-// let x = UInt32(0x1FF)&0xFF << 24 | UInt32(0x1FF)&0xFF << 16 | UInt32(0x1FF)&0xFF << 8 | (UInt32(0x1FF)&0xFF);
-
// SR-838:
// expression test_seconds() was too complex to be solved in reasonable time
struct Nano : CustomStringConvertible {
diff --git a/test/decl/enum/enumtest.swift b/test/decl/enum/enumtest.swift
index c04ae3f..ae86aed 100644
--- a/test/decl/enum/enumtest.swift
+++ b/test/decl/enum/enumtest.swift
@@ -164,9 +164,9 @@
// Dot syntax.
_ = x2.origin.x
_ = x1.size.area()
- _ = (r : x1.size).r.area()
+ _ = (r : x1.size).r.area() // expected-error {{cannot create a single-element tuple with an element label}}
_ = x1.size.area()
- _ = (r : x1.size).r.area()
+ _ = (r : x1.size).r.area() // expected-error {{cannot create a single-element tuple with an element label}}
_ = x1.area
diff --git a/test/decl/ext/generic.swift b/test/decl/ext/generic.swift
index 1ffb543..66327d3 100644
--- a/test/decl/ext/generic.swift
+++ b/test/decl/ext/generic.swift
@@ -30,7 +30,7 @@
typealias GGG = X<Int, Double, String>
-extension GGG { } // expected-error{{constrained extension must be declared on the unspecialized generic type 'X' with constraints specified by a 'where' clause}}
+extension GGG { } // okay through a typealias
// Lvalue check when the archetypes are not the same.
struct LValueCheck<T> {
@@ -210,3 +210,16 @@
func g() { }
}
+// rdar://problem/43955962
+struct OldGeneric<T> {}
+typealias NewGeneric<T> = OldGeneric<T>
+
+extension NewGeneric {
+ static func oldMember() -> OldGeneric {
+ return OldGeneric()
+ }
+
+ static func newMember() -> NewGeneric {
+ return NewGeneric()
+ }
+}
diff --git a/test/decl/ext/typealias.swift b/test/decl/ext/typealias.swift
new file mode 100644
index 0000000..c5917a0
--- /dev/null
+++ b/test/decl/ext/typealias.swift
@@ -0,0 +1,80 @@
+// RUN: %target-typecheck-verify-swift
+
+struct Foo<T> {
+ var maybeT: T? { return nil }
+}
+
+extension Foo {
+ struct Bar<U, V> {
+ var maybeT: T? { return nil }
+ var maybeU: U? { return nil }
+ var maybeV: V? { return nil }
+
+ struct Inner {
+ var maybeT: T? { return nil }
+ var maybeU: U? { return nil }
+ var maybeV: V? { return nil }
+ }
+ }
+}
+
+typealias FooInt = Foo<Int>
+
+extension FooInt {
+ func goodT() -> Int {
+ return maybeT!
+ }
+
+ func badT() -> Float {
+ return maybeT! // expected-error{{cannot convert return expression of type 'Int' to return type 'Float'}}
+ }
+}
+
+typealias FooIntBarFloatDouble = Foo<Int>.Bar<Float, Double>
+
+extension FooIntBarFloatDouble {
+ func goodT() -> Int {
+ return maybeT!
+ }
+ func goodU() -> Float {
+ return maybeU!
+ }
+ func goodV() -> Double {
+ return maybeV!
+ }
+
+ func badT() -> Float {
+ return maybeT! // expected-error{{cannot convert return expression of type 'Int' to return type 'Float'}}
+ }
+ func badU() -> Int {
+ return maybeU! // expected-error{{cannot convert return expression of type 'Float' to return type 'Int'}}
+ }
+ func badV() -> Int {
+ return maybeV! // expected-error{{cannot convert return expression of type 'Double' to return type 'Int'}}
+ }
+}
+
+typealias FooIntBarFloatDoubleInner = Foo<Int>.Bar<Float, Double>.Inner
+
+extension FooIntBarFloatDoubleInner {
+ func goodT() -> Int {
+ return maybeT!
+ }
+ func goodU() -> Float {
+ return maybeU!
+ }
+ func goodV() -> Double {
+ return maybeV!
+ }
+
+ func badT() -> Float {
+ return maybeT! // expected-error{{cannot convert return expression of type 'Int' to return type 'Float'}}
+ }
+ func badU() -> Int {
+ return maybeU! // expected-error{{cannot convert return expression of type 'Float' to return type 'Int'}}
+ }
+ func badV() -> Int {
+ return maybeV! // expected-error{{cannot convert return expression of type 'Double' to return type 'Int'}}
+ }
+}
+
diff --git a/test/decl/nested/type_in_type.swift b/test/decl/nested/type_in_type.swift
index 978408c..6543b11 100644
--- a/test/decl/nested/type_in_type.swift
+++ b/test/decl/nested/type_in_type.swift
@@ -298,9 +298,9 @@
func takesAssocType(first: D, second: F) {}
}
-typealias OuterGenericMidGeneric<T> = OuterGeneric<T>.MidGeneric
+typealias OuterGenericMidNonGeneric<T> = OuterGeneric<T>.MidNonGeneric
-extension OuterGenericMidGeneric {
+extension OuterGenericMidNonGeneric {
}
diff --git a/test/decl/typealias/generic.swift b/test/decl/typealias/generic.swift
index 1821572..6fa96bd 100644
--- a/test/decl/typealias/generic.swift
+++ b/test/decl/typealias/generic.swift
@@ -1,6 +1,6 @@
// RUN: %target-typecheck-verify-swift
-struct MyType<TyA, TyB> {
+struct MyType<TyA, TyB> { // expected-note {{generic type 'MyType' declared here}}
var a : TyA, b : TyB
}
@@ -105,6 +105,9 @@
_ = G(a: "foo", b: 42)
_ = G<Int, String>(a: "foo", b: 42)
+// Generic typealias cannot have unbound generic type.
+typealias VeryBad1<T> = MyType // expected-error {{reference to generic type 'MyType' requires arguments in <...>}}
+typealias VeryBad2<T> = Swift.Array // expected-error {{reference to generic type 'Array' requires arguments in <...>}}
struct MyTypeWithHashable<TyA, TyB : Hashable> {
}
diff --git a/test/multifile/Inputs/external_lazy_property.swift b/test/multifile/Inputs/external_lazy_property.swift
index 80d597b..2093a96 100644
--- a/test/multifile/Inputs/external_lazy_property.swift
+++ b/test/multifile/Inputs/external_lazy_property.swift
@@ -1,3 +1,12 @@
public struct Test1 {
- lazy var property: String = "help"
+ lazy var property: String = "help"
+}
+
+public class Test2 {
+ var x = 0
+ var y = 1
+
+ lazy var property = {
+ return [self.x, self.y]
+ }()
}
diff --git a/test/multifile/lazy.swift b/test/multifile/lazy.swift
index b107ed7..9d7c478 100644
--- a/test/multifile/lazy.swift
+++ b/test/multifile/lazy.swift
@@ -1,6 +1,11 @@
// RUN: %target-swift-frontend -emit-sil -verify -primary-file %s %S/Inputs/external_lazy_property.swift
+// RUN: %target-swift-frontend -emit-sil -verify -primary-file %s -primary-file %S/Inputs/external_lazy_property.swift
// rdar://45712204
func test1(s: Test1) {
- s.property // expected-error {{cannot use mutating getter on immutable value: 's' is a 'let' constant}}
+ _ = s.property // expected-error {{cannot use mutating getter on immutable value: 's' is a 'let' constant}}
+}
+
+func test2(s: Test2) {
+ _ = s.property
}
diff --git a/test/multifile/typealias/two-modules/main.swift b/test/multifile/typealias/two-modules/main.swift
index bcab552..a48c80a 100644
--- a/test/multifile/typealias/two-modules/main.swift
+++ b/test/multifile/typealias/two-modules/main.swift
@@ -10,6 +10,7 @@
// RUN: %target-build-swift -g %S/main.swift %t/linker/library.o -I %t/linker/ -L %t/linker/ -o %t/linker/main
import library
+import enum library.Result
func testFunction<T>(withCompletion completion: (Result<T, Error>) -> Void) { }
testFunction { (result: GenericResult<Int>) in }
diff --git a/test/stdlib/ErrorBridged.swift b/test/stdlib/ErrorBridged.swift
index 2d502e4..6a90d1c 100644
--- a/test/stdlib/ErrorBridged.swift
+++ b/test/stdlib/ErrorBridged.swift
@@ -70,6 +70,8 @@
}
}
+// Gated on the availability of NSKeyedArchiver.archivedData(withRootObject:).
+@available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)
func archiveAndUnarchiveObject<T: NSCoding>(
_ object: T
) -> T?
@@ -81,11 +83,13 @@
return unarchiver.decodeObject(of: T.self, forKey: "root")
}
ErrorBridgingTests.test("NSCoding") {
- autoreleasepool {
- let orig = EnumError.ReallyBadError as NSError
- let unarchived = archiveAndUnarchiveObject(orig)!
- expectEqual(orig, unarchived)
- expectTrue(type(of: unarchived) == NSError.self)
+ if #available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *) {
+ autoreleasepool {
+ let orig = EnumError.ReallyBadError as NSError
+ let unarchived = archiveAndUnarchiveObject(orig)!
+ expectEqual(orig, unarchived)
+ expectTrue(type(of: unarchived) == NSError.self)
+ }
}
}
diff --git a/test/stdlib/Result.swift b/test/stdlib/Result.swift
new file mode 100644
index 0000000..d584f6c
--- /dev/null
+++ b/test/stdlib/Result.swift
@@ -0,0 +1,188 @@
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import Swift
+
+let ResultTests = TestSuite("Result")
+
+fileprivate enum Err: Error, Equatable {
+ case err
+ case derr
+}
+
+fileprivate let string = "string"
+
+fileprivate extension Result {
+ var success: Success? {
+ switch self {
+ case let .success(success):
+ return success
+ case .failure:
+ return nil
+ }
+ }
+
+ var failure: Failure? {
+ switch self {
+ case .success:
+ return nil
+ case let .failure(failure):
+ return failure
+ }
+ }
+}
+
+ResultTests.test("Construction") {
+ let result1: Result<String, Err> = .success(string)
+ let result2: Result<String, Err> = .failure(.err)
+ let string1: String? = {
+ switch result1 {
+ case let .success(string):
+ return string
+ case .failure:
+ expectUnreachable()
+ return nil
+ }
+ }()
+ let error: Err? = {
+ switch result2 {
+ case let .failure(failure):
+ return failure
+ case .success:
+ expectUnreachable()
+ return nil
+ }
+ }()
+
+ expectEqual(string, string1)
+ expectEqual(.err, error)
+}
+
+ResultTests.test("Throwing Initialization and Unwrapping") {
+ func notThrowing() throws -> String {
+ return string
+ }
+
+ func throwing() throws -> String {
+ throw Err.err
+ }
+
+ let result1 = Result { try throwing() }
+ let result2 = Result { try notThrowing() }
+
+ expectEqual(result1.failure as? Err, Err.err)
+ expectEqual(result2.success, string)
+
+ do {
+ _ = try result1.get()
+ } catch let error as Err {
+ expectEqual(error, Err.err)
+ } catch {
+ expectUnreachable()
+ }
+
+ do {
+ let unwrapped = try result2.get()
+ expectEqual(unwrapped, string)
+ } catch {
+ expectUnreachable()
+ }
+
+ // Test unwrapping strongly typed error.
+ let result3 = Result<String, Err>.failure(Err.err)
+ do {
+ _ = try result3.get()
+ } catch let error as Err {
+ expectEqual(error, Err.err)
+ } catch {
+ expectUnreachable()
+ }
+}
+
+ResultTests.test("Functional Transforms") {
+ func transformDouble(_ int: Int) -> Int {
+ return 2 * int
+ }
+
+ func transformTriple(_ int: Int) -> Int {
+ return 3 * int
+ }
+
+ func transformError(_ err: Err) -> Err {
+ if err == .err {
+ return .derr
+ } else {
+ return .err
+ }
+ }
+
+ func resultValueTransform(_ int: Int) -> Result<Int, Err> {
+ return .success(transformDouble(int))
+ }
+
+ func resultErrorTransform(_ err: Err) -> Result<Int, Err> {
+ return .failure(transformError(err))
+ }
+
+ let result1: Result<Int, Err> = .success(1)
+ let newResult1 = result1.map(transformDouble)
+
+ expectEqual(newResult1, .success(2))
+
+ let result2: Result<Int, Err> = .failure(.err)
+ let newResult2 = result2.mapError(transformError)
+
+ expectEqual(newResult2, .failure(.derr))
+
+ let result3: Result<Int, Err> = .success(1)
+ let newResult3 = result3.flatMap(resultValueTransform)
+
+ expectEqual(newResult3, .success(2))
+
+ let result4: Result<Int, Err> = .failure(.derr)
+ let newResult4 = result4.flatMapError(resultErrorTransform)
+
+ expectEqual(newResult4, .failure(.err))
+}
+
+ResultTests.test("Equatable") {
+ let result1: Result<Int, Err> = .success(1)
+ let result2: Result<Int, Err> = .failure(.err)
+
+ expectEqual(result1, .success(1))
+ expectNotEqual(result1, .success(2))
+ expectNotEqual(result1, .failure(.err))
+ expectNotEqual(result1, .failure(.derr))
+
+ expectNotEqual(result2, .success(1))
+ expectNotEqual(result2, .success(2))
+ expectEqual(result2, .failure(.err))
+ expectNotEqual(result2, .failure(.derr))
+
+ let confusables: [Result<Err, Err>] = [
+ .success(.err),
+ .success(.derr),
+ .failure(.err),
+ .failure(.derr)
+ ]
+
+ checkEquatable(confusables, oracle: { $0 == $1 })
+}
+
+ResultTests.test("Hashable") {
+ let result1: Result<Int, Err> = .success(1)
+ let result2: Result<Int, Err> = .success(2)
+ let result3: Result<Int, Err> = .failure(.err)
+ checkHashable([result1, result2, result3], equalityOracle: { $0 == $1 })
+
+ let confusables: [Result<Err, Err>] = [
+ .success(.err),
+ .success(.derr),
+ .failure(.err),
+ .failure(.derr)
+ ]
+ checkHashable(confusables, equalityOracle: { $0 == $1 })
+}
+
+runAllTests()
diff --git a/test/stdlib/TestData.swift b/test/stdlib/TestData.swift
index 7b3d1e7..ec8606f 100644
--- a/test/stdlib/TestData.swift
+++ b/test/stdlib/TestData.swift
@@ -805,14 +805,6 @@
object.verifier.reset()
expectTrue(data.count == object.length)
expectFalse(object.verifier.wasCopied, "Expected an invocation to copy")
-
- object.verifier.reset()
- data.append("test", count: 4)
- expectTrue(object.verifier.wasMutableCopied, "Expected an invocation to mutableCopy")
-
- let d = data as NSData
- let preservedObjectness = d is ImmutableDataVerifier
- expectTrue(preservedObjectness, "Expected ImmutableDataVerifier but got \(object_getClass(d))")
}
func test_basicMutableDataMutation() {
@@ -826,20 +818,6 @@
object.verifier.reset()
expectTrue(data.count == object.length)
expectFalse(object.verifier.wasCopied, "Expected an invocation to copy")
-
- object.verifier.reset()
- data.append("test", count: 4)
- expectTrue(object.verifier.wasMutableCopied, "Expected an invocation to mutableCopy")
- object.verifier.dump()
-
- let d = data as NSData
- let preservedObjectness = d is ImmutableDataVerifier
- expectTrue(preservedObjectness, "Expected ImmutableDataVerifier but got \(object_getClass(d))")
- }
-
- func test_roundTrip() {
- let data = returnsData()
- expectTrue(identityOfData(data))
}
func test_passing() {
@@ -966,12 +944,13 @@
}
func test_noCopyBehavior() {
- let ptr = UnsafeMutableRawPointer(bitPattern: 0x1)!
+ let ptr = UnsafeMutableRawPointer.allocate(byteCount: 17, alignment: 1)
var deallocated = false
autoreleasepool {
- let data = Data(bytesNoCopy: ptr, count: 1, deallocator: .custom({ (bytes, length) in
+ let data = Data(bytesNoCopy: ptr, count: 17, deallocator: .custom({ (bytes, length) in
deallocated = true
+ ptr.deallocate()
}))
expectFalse(deallocated)
let equal = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Bool in
@@ -980,7 +959,6 @@
expectTrue(equal)
}
-
expectTrue(deallocated)
}
@@ -1013,10 +991,6 @@
for i in 0..<d.count {
for j in i..<d.count {
let slice = d[i..<j]
- if i == 1 && j == 2 {
- print("here")
-
- }
expectEqual(slice.count, j - i, "where index range is \(i)..<\(j)")
expectEqual(slice.map { $0 }, a[i..<j].map { $0 }, "where index range is \(i)..<\(j)")
expectEqual(slice.startIndex, i, "where index range is \(i)..<\(j)")
@@ -3641,28 +3615,6 @@
expectEqual(data, Data(bytes: [4, 5, 6, 7, 0, 0]))
}
- func test_sliceEnumeration() {
- var base = DispatchData.empty
- let bytes: [UInt8] = [0, 1, 2, 3, 4]
- base.append(bytes.withUnsafeBytes { DispatchData(bytes: $0) })
- base.append(bytes.withUnsafeBytes { DispatchData(bytes: $0) })
- base.append(bytes.withUnsafeBytes { DispatchData(bytes: $0) })
- let data = ((base as AnyObject) as! Data)[3..<11]
- var regionRanges: [Range<Int>] = []
- var regionData: [Data] = []
- data.enumerateBytes { (buffer, index, _) in
- regionData.append(Data(bytes: buffer.baseAddress!, count: buffer.count))
- regionRanges.append(index..<index + buffer.count)
- }
- expectEqual(regionRanges.count, 3)
- expectEqual(3..<5, regionRanges[0])
- expectEqual(5..<10, regionRanges[1])
- expectEqual(10..<11, regionRanges[2])
- expectEqual(Data(bytes: [3, 4]), regionData[0]) //fails
- expectEqual(Data(bytes: [0, 1, 2, 3, 4]), regionData[1]) //passes
- expectEqual(Data(bytes: [0]), regionData[2]) //fails
- }
-
func test_hashEmptyData() {
let d1 = Data()
let h1 = d1.hashValue
@@ -3783,7 +3735,6 @@
DataTests.test("test_genericBuffers") { TestData().test_genericBuffers() }
DataTests.test("test_basicDataMutation") { TestData().test_basicDataMutation() }
DataTests.test("test_basicMutableDataMutation") { TestData().test_basicMutableDataMutation() }
-DataTests.test("test_roundTrip") { TestData().test_roundTrip() }
DataTests.test("test_passing") { TestData().test_passing() }
DataTests.test("test_bufferSizeCalculation") { TestData().test_bufferSizeCalculation() }
DataTests.test("test_classForCoder") { TestData().test_classForCoder() }
@@ -4056,7 +4007,6 @@
DataTests.test("test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBytes") { TestData().test_validateMutation_slice_cow_customMutableBacking_replaceSubrangeWithBytes() }
DataTests.test("test_sliceHash") { TestData().test_sliceHash() }
DataTests.test("test_slice_resize_growth") { TestData().test_slice_resize_growth() }
-DataTests.test("test_sliceEnumeration") { TestData().test_sliceEnumeration() }
DataTests.test("test_hashEmptyData") { TestData().test_hashEmptyData() }
DataTests.test("test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound() }
DataTests.test("test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
diff --git a/test/stdlib/TestUserInfo.swift b/test/stdlib/TestUserInfo.swift
index 2c2df74..272962e 100644
--- a/test/stdlib/TestUserInfo.swift
+++ b/test/stdlib/TestUserInfo.swift
@@ -130,12 +130,16 @@
func test_classForCoder() {
// confirm internal bridged impl types are not exposed to archival machinery
// we have to be circuitous here, as bridging makes it very difficult to confirm this
- let note = Notification(name: Notification.Name(rawValue: "TestSwiftNotification"), userInfo: [AnyHashable("key"):"value"])
- let archivedNote = NSKeyedArchiver.archivedData(withRootObject: note)
- let noteAsPlist = try! PropertyListSerialization.propertyList(from: archivedNote, options: [], format: nil)
- let plistAsData = try! PropertyListSerialization.data(fromPropertyList: noteAsPlist, format: .xml, options: 0)
- let xml = NSString(data: plistAsData, encoding: String.Encoding.utf8.rawValue)!
- expectEqual(xml.range(of: "_NSUserInfoDictionary").location, NSNotFound)
+ //
+ // Gated on the availability of NSKeyedArchiver.archivedData(withRootObject:).
+ if #available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *) {
+ let note = Notification(name: Notification.Name(rawValue: "TestSwiftNotification"), userInfo: [AnyHashable("key"):"value"])
+ let archivedNote = NSKeyedArchiver.archivedData(withRootObject: note)
+ let noteAsPlist = try! PropertyListSerialization.propertyList(from: archivedNote, options: [], format: nil)
+ let plistAsData = try! PropertyListSerialization.data(fromPropertyList: noteAsPlist, format: .xml, options: 0)
+ let xml = NSString(data: plistAsData, encoding: String.Encoding.utf8.rawValue)!
+ expectEqual(xml.range(of: "_NSUserInfoDictionary").location, NSNotFound)
+ }
}
func test_AnyHashableContainingNotification() {
diff --git a/test/stdlib/simd.swift.gyb b/test/stdlib/simd.swift.gyb
index afadc16..84bedf3 100644
--- a/test/stdlib/simd.swift.gyb
+++ b/test/stdlib/simd.swift.gyb
@@ -313,5 +313,10 @@
% end # for type
}
+simdTestSuite.test("debug description") {
+ expectEqual("SIMD2<Float>(1.0, 2.5)",
+ SIMD2<Float>(1.0, 2.5).debugDescription)
+}
+
runAllTests()
diff --git a/validation-test/Sema/type_checker_perf/fast/rdar21720888.swift.gyb b/validation-test/Sema/type_checker_perf/fast/rdar21720888.swift.gyb
index 89bcfbb..6d90e69 100644
--- a/validation-test/Sema/type_checker_perf/fast/rdar21720888.swift.gyb
+++ b/validation-test/Sema/type_checker_perf/fast/rdar21720888.swift.gyb
@@ -4,6 +4,6 @@
_ = [
%for i in range(0, N):
- (label: "string"),
+ (label: "string", another: 123),
%end
]
diff --git a/validation-test/Sema/type_checker_perf/slow/sr139.swift b/validation-test/Sema/type_checker_perf/slow/sr139.swift
new file mode 100644
index 0000000..f783409
--- /dev/null
+++ b/validation-test/Sema/type_checker_perf/slow/sr139.swift
@@ -0,0 +1,6 @@
+// RUN: %target-typecheck-verify-swift
+
+// SR-139:
+// Infinite recursion parsing bitwise operators
+let x = UInt32(0x1FF)&0xFF << 24 | UInt32(0x1FF)&0xFF << 16 | UInt32(0x1FF)&0xFF << 8 | (UInt32(0x1FF)&0xFF); // expected-error {{reasonable time}}
+
diff --git a/validation-test/compiler_crashers_2_fixed/0186-rdar46497155.swift b/validation-test/compiler_crashers_2_fixed/0186-rdar46497155.swift
new file mode 100644
index 0000000..ed07326
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0186-rdar46497155.swift
@@ -0,0 +1,32 @@
+// RUN: %target-typecheck-verify-swift
+
+protocol P {
+ func isEqual(_ other: P) -> Bool
+}
+
+struct A {
+ var value: P? = nil
+}
+
+struct B {
+ func foo() throws -> A {}
+}
+
+struct E {
+ func getB(_ flag: inout Bool) throws -> B {
+ return B()
+ }
+}
+
+func foo(arr: [E], other: P) -> Bool {
+ return arr.compactMap { i in
+ // expected-error@-1 {{unable to infer complex closure return type; add explicit type to disambiguate}} {{29-29=-> B? }}
+ var flag = false
+ return try? i.getB(&flag)
+ }.compactMap { u -> P? in
+ guard let a = try? u.foo() else { return nil }
+ return a.value!
+ }.contains {
+ $0.isEqual(other)
+ }
+}
diff --git a/validation-test/compiler_crashers_fixed/28815-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift b/validation-test/compiler_crashers_fixed/28815-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift
index 2941688..92e41c1 100644
--- a/validation-test/compiler_crashers_fixed/28815-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift
+++ b/validation-test/compiler_crashers_fixed/28815-formprotocolrelativetype-swift-protocoldecl-swift-genericsignaturebuilder-potent.swift
@@ -6,5 +6,8 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
+
+// XFAIL: *
+
extension CountableRange{{}{}protocol P{typealias a:A{}func 丏
protocol A:CountableRange