Merge pull request #16059 from AnthonyLatsis/unused-result-closure-warning
[DiagnosticsSema] SR-5983
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0f2f72..4c81bc6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,15 @@
Swift 4.2
---------
+* [SR-106][]
+
+ The behavior of `.description` and `.debugDescription` for floating-point
+ numbers has been changed. Previously these unconditionally printed a fixed
+ number of decimal digits (e.g. 15 and 17 for Double, respectively). They now
+ print exactly as many digits as are needed for the resulting string to
+ convert back to the original source value, and no more. For more details,
+ see the original bug report and the linked pull request.
+
* [SE-0193][]
Various function-like declarations can now be marked as `@inlinable`,
@@ -6981,6 +6990,7 @@
[SE-0198]: <https://github.com/apple/swift-evolution/blob/master/proposals/0198-playground-quicklook-api-revamp.md>
[SE-0199]: <https://github.com/apple/swift-evolution/blob/master/proposals/0199-bool-toggle.md>
+[SR-106]: <https://bugs.swift.org/browse/SR-106>
[SR-419]: <https://bugs.swift.org/browse/SR-419>
[SR-1009]: <https://bugs.swift.org/browse/SR-1009>
[SR-1446]: <https://bugs.swift.org/browse/SR-1446>
diff --git a/README.md b/README.md
index 3e44e9d..c609454 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@
For Ubuntu, you'll need the following development dependencies:
- sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev autoconf libtool systemtap-sdt-dev tzdata rsync
+ sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev systemtap-sdt-dev tzdata rsync
**Note:** LLDB currently requires at least `swig-1.3.40` but will successfully build
with version 2 shipped with Ubuntu.
diff --git a/benchmark/single-source/CSVParsing.swift b/benchmark/single-source/CSVParsing.swift
index 62eec0d..03671be 100644
--- a/benchmark/single-source/CSVParsing.swift
+++ b/benchmark/single-source/CSVParsing.swift
@@ -31,7 +31,7 @@
var result: Substring = "" // we accumulate the result
while !remainder.isEmpty {
- guard let nextQuoteIndex = remainder.index(of: "\"") else {
+ guard let nextQuoteIndex = remainder.firstIndex(of: "\"") else {
throw ParseError(message: "Expected a closing \"")
}
diff --git a/benchmark/single-source/RemoveWhere.swift b/benchmark/single-source/RemoveWhere.swift
index b995bf2..81e1287 100644
--- a/benchmark/single-source/RemoveWhere.swift
+++ b/benchmark/single-source/RemoveWhere.swift
@@ -46,7 +46,7 @@
extension RangeReplaceableCollection where Self: MutableCollection {
mutating func removeWhere_move(where match: (Element) throws -> Bool) rethrows {
- guard var i = try index(where: match) else { return }
+ guard var i = try firstIndex(where: match) else { return }
var j = index(after: i)
while j != endIndex {
@@ -62,7 +62,7 @@
}
mutating func removeWhere_swap(where match: (Element) throws -> Bool) rethrows {
- guard var i = try index(where: match) else { return }
+ guard var i = try firstIndex(where: match) else { return }
var j = index(after: i)
while j != endIndex {
diff --git a/cmake/modules/SwiftHandleGybSources.cmake b/cmake/modules/SwiftHandleGybSources.cmake
index ebf4de9..d96494c 100644
--- a/cmake/modules/SwiftHandleGybSources.cmake
+++ b/cmake/modules/SwiftHandleGybSources.cmake
@@ -111,7 +111,6 @@
"${SWIFT_SOURCE_DIR}/utils/UnicodeData/GraphemeBreakProperty.txt"
"${SWIFT_SOURCE_DIR}/utils/UnicodeData/GraphemeBreakTest.txt"
"${SWIFT_SOURCE_DIR}/utils/gyb_stdlib_support.py"
- "${SWIFT_SOURCE_DIR}/utils/gyb_stdlib_unittest_support.py"
"${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/__init__.py"
"${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/Child.py"
"${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/kinds.py"
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 750def2..e575382 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -367,7 +367,7 @@
DefaultArgumentResilienceExpansion : 1
);
- SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1,
+ SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1+1,
/// \see AbstractFunctionDecl::BodyKind
BodyKind : 3,
@@ -390,7 +390,11 @@
HasComputedNeedsNewVTableEntry : 1,
/// The ResilienceExpansion to use for default arguments.
- DefaultArgumentResilienceExpansion : 1
+ DefaultArgumentResilienceExpansion : 1,
+
+ /// Whether this member was synthesized as part of a derived
+ /// protocol conformance.
+ Synthesized : 1
);
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+2+1+1+2,
@@ -5105,6 +5109,7 @@
Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry = false;
Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion =
unsigned(ResilienceExpansion::Maximal);
+ Bits.AbstractFunctionDecl.Synthesized = false;
// Verify no bitfield truncation.
assert(Bits.AbstractFunctionDecl.NumParameterLists == NumParameterLists);
@@ -5253,6 +5258,14 @@
return Bits.AbstractFunctionDecl.NeedsNewVTableEntry;
}
+ bool isSynthesized() const {
+ return Bits.AbstractFunctionDecl.Synthesized;
+ }
+
+ void setSynthesized(bool value = true) {
+ Bits.AbstractFunctionDecl.Synthesized = value;
+ }
+
private:
void computeNeedsNewVTableEntry();
diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h
index 389984d..21fecc9 100644
--- a/include/swift/AST/DiagnosticEngine.h
+++ b/include/swift/AST/DiagnosticEngine.h
@@ -30,6 +30,7 @@
class ValueDecl;
enum class PatternKind : uint8_t;
+ enum class ReferenceOwnership : uint8_t;
enum class StaticSpellingKind : uint8_t;
enum class DescriptiveDeclKind : uint8_t;
enum DeclAttrKind : unsigned;
@@ -76,6 +77,7 @@
Type,
TypeRepr,
PatternKind,
+ ReferenceOwnership,
StaticSpellingKind,
DescriptiveDeclKind,
DeclAttribute,
@@ -103,6 +105,7 @@
Type TypeVal;
TypeRepr *TyR;
PatternKind PatternKindVal;
+ ReferenceOwnership ReferenceOwnershipVal;
StaticSpellingKind StaticSpellingKindVal;
DescriptiveDeclKind DescriptiveDeclKindVal;
const DeclAttribute *DeclAttributeVal;
@@ -162,6 +165,10 @@
DiagnosticArgument(PatternKind K)
: Kind(DiagnosticArgumentKind::PatternKind), PatternKindVal(K) {}
+ DiagnosticArgument(ReferenceOwnership RO)
+ : Kind(DiagnosticArgumentKind::ReferenceOwnership),
+ ReferenceOwnershipVal(RO) {}
+
DiagnosticArgument(StaticSpellingKind SSK)
: Kind(DiagnosticArgumentKind::StaticSpellingKind),
StaticSpellingKindVal(SSK) {}
@@ -237,6 +244,11 @@
return PatternKindVal;
}
+ ReferenceOwnership getAsReferenceOwnership() const {
+ assert(Kind == DiagnosticArgumentKind::ReferenceOwnership);
+ return ReferenceOwnershipVal;
+ }
+
StaticSpellingKind getAsStaticSpellingKind() const {
assert(Kind == DiagnosticArgumentKind::StaticSpellingKind);
return StaticSpellingKindVal;
diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def
index 1f3624d..6486e4a 100644
--- a/include/swift/AST/DiagnosticsDriver.def
+++ b/include/swift/AST/DiagnosticsDriver.def
@@ -126,6 +126,9 @@
ERROR(error_conflicting_options, none,
"conflicting options '%0' and '%1'",
(StringRef, StringRef))
+ERROR(error_option_not_supported, none,
+ "'%0' is not supported with '%1'",
+ (StringRef, StringRef))
WARNING(warn_ignore_embed_bitcode, none,
"ignoring -embed-bitcode since no object file is being generated", ())
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 897b265..9c6c449 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1960,9 +1960,8 @@
"of overridden %select{method|initializer}0 %2",
(bool, DeclName, DeclName))
ERROR(override_ownership_mismatch,none,
- "cannot override %select{strong|weak|unowned|unowned(unsafe)}0 property "
- "with %select{strong|weak|unowned|unowned(unsafe)}1 property",
- (/*ReferenceOwnership*/unsigned, /*ReferenceOwnership*/unsigned))
+ "cannot override %0 property with %1 property",
+ (ReferenceOwnership, ReferenceOwnership))
ERROR(override_dynamic_self_mismatch,none,
"cannot override a Self return type with a non-Self return type",
())
@@ -2008,10 +2007,18 @@
ERROR(override_mutable_covariant_subscript,none,
"cannot override mutable subscript of type %0 with covariant type %1",
(Type, Type))
-ERROR(decl_already_final,none,
+ERROR(static_decl_already_final,none,
"static declarations are already final", ())
ERROR(open_decl_cannot_be_final,none,
"%0 cannot be declared both 'final' and 'open'", (DescriptiveDeclKind))
+ERROR(implicitly_final_cannot_be_open,none,
+ "%select{'let' properties|members of 'final' classes|"
+ "static declarations}0 are implicitly 'final'; use 'public' instead of "
+ "'open'", (unsigned))
+WARNING(implicitly_final_cannot_be_open_swift4,none,
+ "%select{'let' properties|members of 'final' classes|"
+ "static declarations}0 are implicitly 'final'; use 'public' instead of "
+ "'open'", (unsigned))
WARNING(override_swift3_objc_inference,none,
"override of %0 %1 from extension of %2 depends on deprecated "
@@ -2739,6 +2746,15 @@
"use '%0' to reference the %1 in module %2",
(StringRef, DescriptiveDeclKind, Identifier))
+WARNING(warn_deprecated_conditional_conformance_outer_access,none,
+ "use of %0 as reference to %1 in %2 %3 will change in future versions of Swift to reference %4 in %5 %6 "
+ "which comes via a conditional conformance",
+ (DeclName, DescriptiveDeclKind, DescriptiveDeclKind, DeclName,
+ DescriptiveDeclKind, DescriptiveDeclKind, DeclName))
+NOTE(fix_deprecated_conditional_conformance_outer_access,none,
+ "use '%0' to continue to reference the %1",
+ (StringRef, DescriptiveDeclKind, Identifier))
+
ERROR(unsupported_special_decl_ref, none,
"referencing %0 as a function value is not implemented", (Identifier))
@@ -3061,10 +3077,9 @@
"add an explicit type annotation to silence this warning", ())
WARNING(unowned_assignment_immediate_deallocation,none,
- "instance will be immediately deallocated as %0 is "
- "%select{a 'strong'|a 'weak'|an 'unowned'|an 'unowned'}1 "
- "%select{variable|property}2",
- (Identifier, /*Ownership*/unsigned, /*Is Property*/unsigned))
+ "instance will be immediately deallocated because "
+ "%select{variable|property}2 %0 is %1",
+ (Identifier, ReferenceOwnership, /*Is Property*/unsigned))
NOTE(unowned_assignment_requires_strong,none,
"a strong reference is required to prevent the instance from being "
"deallocated", ())
@@ -3222,24 +3237,25 @@
// Ownership
ERROR(invalid_ownership_type,none,
- "'%select{strong|weak|unowned|unowned}0' may only be applied to "
- "class and class-bound protocol types, not %1",
- (/*ReferenceOwnership*/unsigned, Type))
+ "%0 may only be applied to class and class-bound protocol types, not %1",
+ (ReferenceOwnership, Type))
ERROR(invalid_ownership_protocol_type,none,
- "'%select{strong|weak|unowned|unowned}0' must not be applied to "
- "non-class-bound %1; consider adding a protocol conformance that has a class bound",
- (/*ReferenceOwnership*/unsigned, Type))
+ "%0 must not be applied to non-class-bound %1; "
+ "consider adding a protocol conformance that has a class bound",
+ (ReferenceOwnership, Type))
+ERROR(invalid_ownership_with_optional,none,
+ "%0 variable cannot have optional type", (ReferenceOwnership))
ERROR(invalid_weak_ownership_not_optional,none,
"'weak' variable should have optional type %0", (Type))
ERROR(invalid_weak_let,none,
"'weak' must be a mutable variable, because it may change at runtime", ())
ERROR(ownership_invalid_in_protocols,none,
- "'%select{strong|weak|unowned|unowned}0' cannot be applied to a property declaration in a protocol",
- (/*ReferenceOwnership*/unsigned))
+ "%0 cannot be applied to a property declaration in a protocol",
+ (ReferenceOwnership))
WARNING(ownership_invalid_in_protocols_compat_warning,none,
- "'%select{strong|weak|unowned|unowned}0' should not be applied to a property declaration "
+ "%0 should not be applied to a property declaration "
"in a protocol and will be disallowed in future versions",
- (/*ReferenceOwnership*/unsigned))
+ (ReferenceOwnership))
// required
ERROR(required_initializer_nonclass,none,
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index c6be668..c879733 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -2353,11 +2353,16 @@
SourceLoc DotLoc;
DeclNameLoc NameLoc;
DeclName Name;
+ ArrayRef<ValueDecl *> OuterAlternatives;
+
public:
- UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, DeclName name,
- DeclNameLoc nameloc, bool Implicit)
- : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
- NameLoc(nameloc), Name(name) {
+ UnresolvedDotExpr(
+ Expr *subexpr, SourceLoc dotloc, DeclName name, DeclNameLoc nameloc,
+ bool Implicit,
+ ArrayRef<ValueDecl *> outerAlternatives = ArrayRef<ValueDecl *>())
+ : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr),
+ DotLoc(dotloc), NameLoc(nameloc), Name(name),
+ OuterAlternatives(outerAlternatives) {
Bits.UnresolvedDotExpr.FunctionRefKind =
static_cast<unsigned>(NameLoc.isCompound() ? FunctionRefKind::Compound
: FunctionRefKind::Unapplied);
@@ -2380,6 +2385,10 @@
DeclName getName() const { return Name; }
DeclNameLoc getNameLoc() const { return NameLoc; }
+ ArrayRef<ValueDecl *> getOuterAlternatives() const {
+ return OuterAlternatives;
+ }
+
/// Retrieve the kind of function reference.
FunctionRefKind getFunctionRefKind() const {
return static_cast<FunctionRefKind>(Bits.UnresolvedDotExpr.FunctionRefKind);
diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h
index 51b6b46..96e100e 100644
--- a/include/swift/AST/NameLookup.h
+++ b/include/swift/AST/NameLookup.h
@@ -86,19 +86,37 @@
/// unqualified lookup (i.e. lookup for a plain identifier).
class UnqualifiedLookup {
public:
+ enum class Flags {
+ /// This lookup is known to not affect downstream files.
+ KnownPrivate = 0x01,
+ /// This lookup should only return types.
+ TypeLookup = 0x02,
+ /// This lookup should consider declarations within protocols to which the
+ /// context type conforms.
+ AllowProtocolMembers = 0x04,
+ /// Don't check access when doing lookup into a type.
+ IgnoreAccessControl = 0x08,
+ /// This lookup should include results from outside the innermost scope with
+ /// results.
+ IncludeOuterResults = 0x10,
+ };
+ using Options = OptionSet<Flags>;
+
/// \brief Lookup an unqualified identifier \p Name in the context.
///
/// If the current DeclContext is nested in a function body, the SourceLoc
/// is used to determine which declarations in that body are visible.
- UnqualifiedLookup(DeclName Name, DeclContext *DC,
- LazyResolver *TypeResolver,
- bool IsKnownPrivate = false,
- SourceLoc Loc = SourceLoc(),
- bool IsTypeLookup = false,
- bool AllowProtocolMembers = false,
- bool IgnoreAccessControl = false);
+ UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver,
+ SourceLoc Loc = SourceLoc(), Options options = Options());
SmallVector<LookupResultEntry, 4> Results;
+ /// \brief The index of the first result that isn't from the innermost scope
+ /// with results.
+ ///
+ /// That is, \c makeArrayRef(Results).take_front(IndexOfFirstOuterResults)
+ /// will be Results from the innermost scope that had results, and the
+ /// remaining elements of Results will be from parent scopes of this one.
+ size_t IndexOfFirstOuterResult;
/// \brief Return true if anything was found by the name lookup.
bool isSuccess() const { return !Results.empty(); }
@@ -107,6 +125,11 @@
TypeDecl *getSingleTypeResult();
};
+inline UnqualifiedLookup::Options operator|(UnqualifiedLookup::Flags flag1,
+ UnqualifiedLookup::Flags flag2) {
+ return UnqualifiedLookup::Options(flag1) | flag2;
+}
+
/// Describes the reason why a certain declaration is visible.
enum class DeclVisibilityKind {
/// Declaration is a local variable or type.
diff --git a/include/swift/AST/Ownership.h b/include/swift/AST/Ownership.h
index ac6599e..d797611 100644
--- a/include/swift/AST/Ownership.h
+++ b/include/swift/AST/Ownership.h
@@ -20,6 +20,7 @@
#define SWIFT_OWNERSHIP_H
#include "swift/Basic/InlineBitfield.h"
+#include "llvm/Support/raw_ostream.h"
#include <stdint.h>
namespace swift {
@@ -46,6 +47,9 @@
enum : unsigned { NumReferenceOwnershipBits =
countBitsUsed(static_cast<unsigned>(ReferenceOwnership::Last_Kind)) };
+/// Diagnostic printing of \c StaticSpellingKind.
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceOwnership RO);
+
/// Different kinds of value ownership supported by Swift.
enum class ValueOwnership : uint8_t {
/// \brief the context-dependent default ownership (sometimes shared,
diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h
index a8eccf4..4b7a77d 100644
--- a/include/swift/AST/Stmt.h
+++ b/include/swift/AST/Stmt.h
@@ -1023,7 +1023,7 @@
SourceLoc Loc;
Identifier TargetName; // Named target statement, if specified in the source.
SourceLoc TargetLoc;
- LabeledStmt *Target; // Target stmt, wired up by Sema.
+ LabeledStmt *Target = nullptr; // Target stmt, wired up by Sema.
public:
BreakStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
Optional<bool> implicit = None)
@@ -1058,7 +1058,7 @@
SourceLoc Loc;
Identifier TargetName; // Named target statement, if specified in the source.
SourceLoc TargetLoc;
- LabeledStmt *Target;
+ LabeledStmt *Target = nullptr;
public:
ContinueStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
diff --git a/include/swift/AST/TypeMatcher.h b/include/swift/AST/TypeMatcher.h
index 34cedc0..8f092c5 100644
--- a/include/swift/AST/TypeMatcher.h
+++ b/include/swift/AST/TypeMatcher.h
@@ -141,43 +141,25 @@
return mismatch(firstTuple.getPointer(), secondType, sugaredFirstType);
}
- template<typename FirstReferenceStorageType>
- bool handleReferenceStorageType(
- CanTypeWrapper<FirstReferenceStorageType> firstStorage,
- Type secondType, Type sugaredFirstType) {
- if (auto secondStorage = secondType->getAs<FirstReferenceStorageType>()) {
- return this->visit(
- firstStorage.getReferentType(),
- secondStorage->getReferentType(),
- sugaredFirstType->getAs<FirstReferenceStorageType>()
- ->getReferentType());
+ bool visitReferenceStorageType(CanReferenceStorageType firstStorage,
+ Type secondType, Type sugaredFirstType) {
+ auto _secondStorage = secondType->getCanonicalType();
+ if (firstStorage->getKind() == _secondStorage->getKind()) {
+ auto secondStorage = cast<ReferenceStorageType>(_secondStorage);
+ return this->visit(firstStorage.getReferentType(),
+ secondStorage->getReferentType(),
+ sugaredFirstType->castTo<ReferenceStorageType>()
+ ->getReferentType());
}
return mismatch(firstStorage.getPointer(), secondType, sugaredFirstType);
}
- bool visitUnownedStorageType(CanUnownedStorageType firstStorage,
- Type secondType, Type sugaredFirstType) {
- return handleReferenceStorageType(firstStorage, secondType,
- sugaredFirstType);
- }
-
- bool visitUnmanagedStorageType(CanUnmanagedStorageType firstStorage,
- Type secondType, Type sugaredFirstType) {
- return handleReferenceStorageType(firstStorage, secondType,
- sugaredFirstType);
- }
-
- bool visitWeakStorageType(CanWeakStorageType firstStorage,
- Type secondType, Type sugaredFirstType) {
- return handleReferenceStorageType(firstStorage, secondType,
- sugaredFirstType);
- }
-
- template<typename FirstNominalType>
- bool handleNominalType(CanTypeWrapper<FirstNominalType> firstNominal,
- Type secondType, Type sugaredFirstType) {
- if (auto secondNominal = secondType->getAs<FirstNominalType>()) {
+ bool visitNominalType(CanNominalType firstNominal,
+ Type secondType, Type sugaredFirstType) {
+ auto _secondNominal = secondType->getCanonicalType();
+ if (firstNominal->getKind() == _secondNominal->getKind()) {
+ auto secondNominal = cast<NominalType>(_secondNominal);
if (firstNominal->getDecl() != secondNominal->getDecl())
return mismatch(firstNominal.getPointer(), secondNominal,
sugaredFirstType);
@@ -185,7 +167,7 @@
if (firstNominal.getParent())
return this->visit(firstNominal.getParent(),
secondNominal->getParent(),
- sugaredFirstType->castTo<FirstNominalType>()
+ sugaredFirstType->castTo<NominalType>()
->getParent());
return true;
@@ -194,52 +176,20 @@
return mismatch(firstNominal.getPointer(), secondType, sugaredFirstType);
}
- bool visitEnumType(CanEnumType firstEnum, Type secondType,
- Type sugaredFirstType) {
- return handleNominalType(firstEnum, secondType, sugaredFirstType);
- }
-
- bool visitStructType(CanStructType firstStruct, Type secondType,
- Type sugaredFirstType) {
- return handleNominalType(firstStruct, secondType, sugaredFirstType);
- }
-
- bool visitClassType(CanClassType firstClass, Type secondType,
- Type sugaredFirstType) {
- return handleNominalType(firstClass, secondType, sugaredFirstType);
- }
-
- bool visitProtocolType(CanProtocolType firstProtocol, Type secondType,
- Type sugaredFirstType) {
- return handleNominalType(firstProtocol, secondType, sugaredFirstType);
- }
-
- template<typename FirstMetatypeType>
- bool handleAnyMetatypeType(CanTypeWrapper<FirstMetatypeType> firstMeta,
- Type secondType, Type sugaredFirstType) {
- if (auto secondMeta = secondType->getAs<FirstMetatypeType>()) {
- if (firstMeta->getKind() != secondMeta->getKind())
- return mismatch(firstMeta.getPointer(), secondMeta, sugaredFirstType);
-
+ bool visitAnyMetatypeType(CanAnyMetatypeType firstMeta,
+ Type secondType, Type sugaredFirstType) {
+ auto _secondMeta = secondType->getCanonicalType();
+ if (firstMeta->getKind() == _secondMeta->getKind()) {
+ auto secondMeta = cast<AnyMetatypeType>(_secondMeta);
return this->visit(firstMeta.getInstanceType(),
secondMeta->getInstanceType(),
- sugaredFirstType->castTo<FirstMetatypeType>()
+ sugaredFirstType->castTo<AnyMetatypeType>()
->getInstanceType());
}
return mismatch(firstMeta.getPointer(), secondType, sugaredFirstType);
}
- bool visitMetatypeType(CanMetatypeType firstMeta, Type secondType,
- Type sugaredFirstType) {
- return handleAnyMetatypeType(firstMeta, secondType, sugaredFirstType);
- }
-
- bool visitExistentialMetatypeType(CanExistentialMetatypeType firstMeta,
- Type secondType, Type sugaredFirstType) {
- return handleAnyMetatypeType(firstMeta, secondType, sugaredFirstType);
- }
-
TRIVIAL_CASE(ModuleType)
TRIVIAL_CASE(DynamicSelfType)
TRIVIAL_CASE(ArchetypeType)
@@ -332,15 +282,15 @@
return mismatch(firstUBGT.getPointer(), secondType, sugaredFirstType);
}
- template<typename FirstBoundGenericType>
- bool handleBoundGenericType(CanTypeWrapper<FirstBoundGenericType> firstBGT,
- Type secondType, Type sugaredFirstType) {
- if (auto secondBGT = secondType->getAs<FirstBoundGenericType>()) {
+ bool visitBoundGenericType(CanBoundGenericType firstBGT,
+ Type secondType, Type sugaredFirstType) {
+ auto _secondBGT = secondType->getCanonicalType();
+ if (firstBGT->getKind() == _secondBGT->getKind()) {
+ auto secondBGT = cast<BoundGenericType>(_secondBGT);
if (firstBGT->getDecl() != secondBGT->getDecl())
return mismatch(firstBGT.getPointer(), secondBGT, sugaredFirstType);
- auto sugaredFirstBGT
- = sugaredFirstType->castTo<FirstBoundGenericType>();
+ auto sugaredFirstBGT = sugaredFirstType->castTo<BoundGenericType>();
if (firstBGT->getParent() &&
!this->visit(firstBGT.getParent(), secondBGT->getParent(),
sugaredFirstBGT->getParent()))
@@ -360,21 +310,6 @@
return mismatch(firstBGT.getPointer(), secondType, sugaredFirstType);
}
- bool visitBoundGenericClassType(CanBoundGenericClassType firstBGT,
- Type secondType, Type sugaredFirstType) {
- return handleBoundGenericType(firstBGT, secondType, sugaredFirstType);
- }
-
- bool visitBoundGenericEnumType(CanBoundGenericEnumType firstBGT,
- Type secondType, Type sugaredFirstType) {
- return handleBoundGenericType(firstBGT, secondType, sugaredFirstType);
- }
-
- bool visitBoundGenericStructType(CanBoundGenericStructType firstBGT,
- Type secondType, Type sugaredFirstType) {
- return handleBoundGenericType(firstBGT, secondType, sugaredFirstType);
- }
-
TRIVIAL_CASE(TypeVariableType)
#undef TRIVIAL_CASE
diff --git a/include/swift/AST/Witness.h b/include/swift/AST/Witness.h
index 02b4a1d..8736cce 100644
--- a/include/swift/AST/Witness.h
+++ b/include/swift/AST/Witness.h
@@ -150,9 +150,6 @@
/// Determines whether there is a witness at all.
explicit operator bool() const { return !storage.isNull(); }
- /// Determine whether this witness requires any substitutions.
- bool requiresSubstitution() const { return storage.is<StoredWitness *>(); }
-
/// Retrieve the substitutions required to use this witness from the
/// synthetic environment.
///
@@ -164,15 +161,17 @@
/// Retrieve the synthetic generic environment.
GenericEnvironment *getSyntheticEnvironment() const {
- assert(requiresSubstitution() && "No substitutions required for witness");
- return storage.get<StoredWitness *>()->syntheticEnvironment;
+ if (auto *storedWitness = storage.dyn_cast<StoredWitness *>())
+ return storedWitness->syntheticEnvironment;
+ return nullptr;
}
/// Retrieve the substitution map that maps the interface types of the
/// requirement to the interface types of the synthetic environment.
SubstitutionList getRequirementToSyntheticSubs() const {
- assert(requiresSubstitution() && "No substitutions required for witness");
- return storage.get<StoredWitness *>()->reqToSyntheticEnvSubs;
+ if (auto *storedWitness = storage.dyn_cast<StoredWitness *>())
+ return storedWitness->reqToSyntheticEnvSubs;
+ return {};
}
LLVM_ATTRIBUTE_DEPRECATED(
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index c4673e4..83a7971 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -466,6 +466,14 @@
/// This should always round-trip perfectly with demangleSymbolAsNode.
std::string mangleNode(const NodePointer &root);
+using SymbolicResolver = llvm::function_ref<Demangle::NodePointer (const void *)>;
+
+/// \brief Remangle a demangled parse tree, using a callback to resolve
+/// symbolic references.
+///
+/// This should always round-trip perfectly with demangleSymbolAsNode.
+std::string mangleNode(const NodePointer &root, SymbolicResolver resolver);
+
/// Remangle in the old mangling scheme.
///
/// This is only used for objc-runtime names and should be removed as soon as
diff --git a/include/swift/IDE/APIDigesterData.h b/include/swift/IDE/APIDigesterData.h
index ec6c3ea..abacb15 100644
--- a/include/swift/IDE/APIDigesterData.h
+++ b/include/swift/IDE/APIDigesterData.h
@@ -334,6 +334,21 @@
}
};
+struct NameCorrectionInfo {
+ StringRef OriginalName;
+ StringRef CorrectedName;
+ StringRef ModuleName;
+ NameCorrectionInfo(StringRef OriginalName, StringRef CorrectedName,
+ StringRef ModuleName): OriginalName(OriginalName),
+ CorrectedName(CorrectedName), ModuleName(ModuleName) {}
+ bool operator<(NameCorrectionInfo Other) const {
+ if (ModuleName != Other.ModuleName)
+ return ModuleName.compare(Other.ModuleName) < 0;
+ else
+ return OriginalName.compare(Other.OriginalName) < 0;
+ }
+};
+
/// APIDiffItem store is the interface that migrator should communicates with;
/// Given a key, usually the usr of the system entity under migration, the store
/// should return a slice of related changes in the same format of
@@ -343,6 +358,7 @@
struct Implementation;
Implementation &Impl;
static void serialize(llvm::raw_ostream &os, ArrayRef<APIDiffItem*> Items);
+ static void serialize(llvm::raw_ostream &os, ArrayRef<NameCorrectionInfo> Items);
APIDiffItemStore(const APIDiffItemStore& that) = delete;
APIDiffItemStore();
~APIDiffItemStore();
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index 20efd72..906e3c1 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -81,7 +81,12 @@
NODE_ANNOTATION_CHANGE_KIND(OptionalArrayMemberUpdate)
NODE_ANNOTATION_CHANGE_KIND(SimpleStringRepresentableUpdate)
NODE_ANNOTATION_CHANGE_KIND(SimpleOptionalStringRepresentableUpdate)
-
+NODE_ANNOTATION_CHANGE_KIND(RevertDictionaryKeyUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertOptionalDictionaryKeyUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertArrayMemberUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertOptionalArrayMemberUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertSimpleStringRepresentableUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertSimpleOptionalStringRepresentableUpdate)
DECL_ATTR(deprecated)
DECL_ATTR(fixedLayout)
diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h
index a6a36bc..792eb85 100644
--- a/include/swift/Runtime/Debug.h
+++ b/include/swift/Runtime/Debug.h
@@ -46,19 +46,19 @@
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
-static void CRSetCrashLogMessage(const char *message) {
+static inline void CRSetCrashLogMessage(const char *message) {
gCRAnnotations.message = reinterpret_cast<uint64_t>(message);
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
-static const char *CRGetCrashLogMessage() {
+static inline const char *CRGetCrashLogMessage() {
return reinterpret_cast<const char *>(gCRAnnotations.message);
}
#else
LLVM_ATTRIBUTE_ALWAYS_INLINE
-static void CRSetCrashLogMessage(const char *) {}
+static inline void CRSetCrashLogMessage(const char *) {}
#endif
diff --git a/include/swift/Runtime/Exclusivity.h b/include/swift/Runtime/Exclusivity.h
index aa75a46..d3a4ffc 100644
--- a/include/swift/Runtime/Exclusivity.h
+++ b/include/swift/Runtime/Exclusivity.h
@@ -58,6 +58,19 @@
SWIFT_RUNTIME_EXPORT
bool _swift_disableExclusivityChecking;
+#ifndef NDEBUG
+
+/// Dump all accesses currently tracked by the runtime.
+///
+/// This is a debug routine that is intended to be used from the debugger and is
+/// compiled out when asserts are disabled. The intention is that it allows one
+/// to dump the access state to easily see if/when exclusivity violations will
+/// happen. This eases debugging.
+SWIFT_RUNTIME_EXPORT
+void swift_dumpTrackedAccesses();
+
+#endif
+
} // end namespace swift
#endif
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 3e9df39..f55c5f8 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -827,7 +827,7 @@
ATTRS(NoUnwind))
// MetadataResponse swift_checkMetadataState(MetadataRequest request,
-// cosnt Metadata *type);
+// const Metadata *type);
FUNCTION(CheckMetadataState, swift_checkMetadataState, SwiftCC,
RETURNS(TypeMetadataResponseTy),
ARGS(SizeTy, TypeMetadataPtrTy),
diff --git a/include/swift/SIL/SILVTableVisitor.h b/include/swift/SIL/SILVTableVisitor.h
index abf4f24..9549cfa 100644
--- a/include/swift/SIL/SILVTableVisitor.h
+++ b/include/swift/SIL/SILVTableVisitor.h
@@ -18,11 +18,55 @@
#ifndef SWIFT_SIL_SILVTABLEVISITOR_H
#define SWIFT_SIL_SILVTABLEVISITOR_H
+#include <string>
+
#include "swift/AST/Decl.h"
#include "swift/AST/Types.h"
+#include "swift/AST/ASTMangler.h"
namespace swift {
+// Utility class for deterministically ordering vtable entries for
+// synthesized methods.
+struct SortedFuncList {
+ using Entry = std::pair<std::string, AbstractFunctionDecl *>;
+ SmallVector<Entry, 2> elts;
+ bool sorted = false;
+
+ void add(AbstractFunctionDecl *afd) {
+ Mangle::ASTMangler mangler;
+ std::string mangledName;
+ if (auto *cd = dyn_cast<ConstructorDecl>(afd))
+ mangledName = mangler.mangleConstructorEntity(cd, 0, 0);
+ else
+ mangledName = mangler.mangleEntity(afd, 0);
+
+ elts.push_back(std::make_pair(mangledName, afd));
+ }
+
+ bool empty() { return elts.empty(); }
+
+ void sort() {
+ assert(!sorted);
+ sorted = true;
+ std::sort(elts.begin(),
+ elts.end(),
+ [](const Entry &lhs, const Entry &rhs) -> bool {
+ return lhs.first < rhs.first;
+ });
+ }
+
+ decltype(elts)::const_iterator begin() const {
+ assert(sorted);
+ return elts.begin();
+ }
+
+ decltype(elts)::const_iterator end() const {
+ assert(sorted);
+ return elts.end();
+ }
+};
+
/// A CRTP class for visiting virtually-dispatched methods of a class.
///
/// You must override these two methods in your subclass:
@@ -76,19 +120,47 @@
}
}
+ void maybeAddMember(Decl *member) {
+ if (auto *fd = dyn_cast<FuncDecl>(member))
+ maybeAddMethod(fd);
+ else if (auto *cd = dyn_cast<ConstructorDecl>(member))
+ maybeAddConstructor(cd);
+ else if (auto *placeholder = dyn_cast<MissingMemberDecl>(member))
+ asDerived().addPlaceholder(placeholder);
+ }
+
protected:
void addVTableEntries(ClassDecl *theClass) {
// Imported classes do not have a vtable.
if (!theClass->hasKnownSwiftImplementation())
return;
+ // Note that while vtable order is not ABI, we still want it to be
+ // consistent between translation units.
+ //
+ // So, sort synthesized members by their mangled name, since they
+ // are added lazily during type checking, with the remaining ones
+ // forced at the end.
+ SortedFuncList synthesizedMembers;
+
for (auto member : theClass->getMembers()) {
- if (auto *fd = dyn_cast<FuncDecl>(member))
- maybeAddMethod(fd);
- else if (auto *cd = dyn_cast<ConstructorDecl>(member))
- maybeAddConstructor(cd);
- else if (auto *placeholder = dyn_cast<MissingMemberDecl>(member))
- asDerived().addPlaceholder(placeholder);
+ if (auto *afd = dyn_cast<AbstractFunctionDecl>(member)) {
+ if (afd->isSynthesized()) {
+ synthesizedMembers.add(afd);
+ continue;
+ }
+ }
+
+ maybeAddMember(member);
+ }
+
+ if (synthesizedMembers.empty())
+ return;
+
+ synthesizedMembers.sort();
+
+ for (const auto &pair : synthesizedMembers) {
+ maybeAddMember(pair.second);
}
}
};
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 15e3dc3..d35b753 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 408; // Last change: begin_access [nontracking]
+const uint16_t VERSION_MINOR = 409; // Last change: standalone requirement subs
using DeclIDField = BCFixed<31>;
diff --git a/include/swift/Strings.h b/include/swift/Strings.h
index 4d02d9d..38a687a 100644
--- a/include/swift/Strings.h
+++ b/include/swift/Strings.h
@@ -13,6 +13,9 @@
#ifndef SWIFT_STRINGS_H
#define SWIFT_STRINGS_H
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
namespace swift {
/// The extension for serialized modules.
@@ -89,6 +92,10 @@
constexpr static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
/// The name of the Builtin type for Word
constexpr static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
+
+constexpr static StringLiteral OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY =
+ "optimize.sil.preserve_exclusivity";
+
} // end namespace swift
#endif // SWIFT_STRINGS_H
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d3c0a97..ea83a0c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1430,8 +1430,9 @@
static void recordKnownProtocol(ModuleDecl *Stdlib, StringRef Name,
KnownProtocolKind Kind) {
Identifier ID = Stdlib->getASTContext().getIdentifier(Name);
- UnqualifiedLookup Lookup(ID, Stdlib, nullptr, /*IsKnownPrivate=*/true,
- SourceLoc(), /*IsTypeLookup=*/true);
+ UnqualifiedLookup Lookup(ID, Stdlib, nullptr, SourceLoc(),
+ UnqualifiedLookup::Flags::KnownPrivate |
+ UnqualifiedLookup::Flags::TypeLookup);
if (auto Proto
= dyn_cast_or_null<ProtocolDecl>(Lookup.getSingleTypeResult()))
Proto->setKnownProtocolKind(Kind);
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 1e49ce1..735a631 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2115,11 +2115,17 @@
void verifyChecked(ValueDecl *VD) {
if (VD->hasAccess()) {
- if (VD->getFormalAccess() == AccessLevel::Open &&
- !isa<ClassDecl>(VD) && !VD->isPotentiallyOverridable()) {
- Out << "decl cannot be 'open'\n";
- VD->dump(Out);
- abort();
+ if (VD->getFormalAccess() == AccessLevel::Open) {
+ if (!isa<ClassDecl>(VD) && !VD->isPotentiallyOverridable()) {
+ Out << "decl cannot be 'open'\n";
+ VD->dump(Out);
+ abort();
+ }
+ if (VD->isFinal()) {
+ Out << "decl cannot be both 'open' and 'final'\n";
+ VD->dump(Out);
+ abort();
+ }
}
} else {
if (!VD->getDeclContext()->isLocalContext() &&
@@ -2516,13 +2522,18 @@
// Check the witness substitutions.
const auto &witness = normal->getWitness(req, nullptr);
- if (witness.requiresSubstitution()) {
- GenericEnv.push_back({witness.getSyntheticEnvironment()});
- for (const auto &sub : witness.getSubstitutions()) {
- verifyChecked(sub.getReplacement());
- }
+ if (auto *genericEnv = witness.getSyntheticEnvironment())
+ GenericEnv.push_back({genericEnv});
+
+ for (const auto &sub : witness.getRequirementToSyntheticSubs())
+ verifyChecked(sub.getReplacement());
+
+ for (const auto &sub : witness.getSubstitutions())
+ verifyChecked(sub.getReplacement());
+
+ if (auto *genericEnv = witness.getSyntheticEnvironment()) {
assert(GenericEnv.back().storage.dyn_cast<GenericEnvironment *>()
- == witness.getSyntheticEnvironment());
+ == genericEnv);
GenericEnv.pop_back();
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ca75410..39b08df 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -296,6 +296,17 @@
llvm_unreachable("bad StaticSpellingKind");
}
+llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
+ ReferenceOwnership RO) {
+ switch (RO) {
+ case ReferenceOwnership::Strong: return OS << "'strong'";
+ case ReferenceOwnership::Weak: return OS << "'weak'";
+ case ReferenceOwnership::Unowned: return OS << "'unowned'";
+ case ReferenceOwnership::Unmanaged: return OS << "'unowned(unsafe)'";
+ }
+ llvm_unreachable("bad ReferenceOwnership kind");
+}
+
DeclContext *Decl::getInnermostDeclContext() const {
if (auto func = dyn_cast<AbstractFunctionDecl>(this))
return const_cast<AbstractFunctionDecl*>(func);
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index 95cd868..d0456a7 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -472,6 +472,19 @@
assert(Modifier.empty() && "Improper modifier for PatternKind argument");
Out << Arg.getAsPatternKind();
break;
+
+ case DiagnosticArgumentKind::ReferenceOwnership:
+ if (Modifier == "select") {
+ formatSelectionArgument(ModifierArguments, Args,
+ unsigned(Arg.getAsReferenceOwnership()),
+ FormatOpts, Out);
+ } else {
+ assert(Modifier.empty() &&
+ "Improper modifier for ReferenceOwnership argument");
+ Out << Arg.getAsReferenceOwnership();
+ }
+ break;
+
case DiagnosticArgumentKind::StaticSpellingKind:
if (Modifier == "select") {
formatSelectionArgument(ModifierArguments, Args,
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index 2643f71..f93caad 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -453,24 +453,42 @@
}
UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
- LazyResolver *TypeResolver,
- bool IsKnownNonCascading,
- SourceLoc Loc, bool IsTypeLookup,
- bool AllowProtocolMembers,
- bool IgnoreAccessControl) {
+ LazyResolver *TypeResolver, SourceLoc Loc,
+ Options options)
+ : IndexOfFirstOuterResult(0)
+{
ModuleDecl &M = *DC->getParentModule();
ASTContext &Ctx = M.getASTContext();
const SourceManager &SM = Ctx.SourceMgr;
DebuggerClient *DebugClient = M.getDebugClient();
- NamedDeclConsumer Consumer(Name, Results, IsTypeLookup);
+ auto isOriginallyTypeLookup = options.contains(Flags::TypeLookup);
+ NamedDeclConsumer Consumer(Name, Results, isOriginallyTypeLookup);
+
+ NLOptions baseNLOptions = NL_UnqualifiedDefault;
+ if (options.contains(Flags::AllowProtocolMembers))
+ baseNLOptions |= NL_ProtocolMembers;
+ if (isOriginallyTypeLookup)
+ baseNLOptions |= NL_OnlyTypes;
+ if (options.contains(Flags::IgnoreAccessControl))
+ baseNLOptions |= NL_IgnoreAccessControl;
Optional<bool> isCascadingUse;
- if (IsKnownNonCascading)
+ if (options.contains(Flags::KnownPrivate))
isCascadingUse = false;
SmallVector<LookupResultEntry, 4> UnavailableInnerResults;
+ auto shouldReturnBasedOnResults = [&](bool noMoreOuterResults = false) {
+ if (Results.empty())
+ return false;
+
+ if (IndexOfFirstOuterResult == 0)
+ IndexOfFirstOuterResult = Results.size();
+
+ return !options.contains(Flags::IncludeOuterResults) || noMoreOuterResults;
+ };
+
if (Loc.isValid() &&
DC->getParentSourceFile()->Kind != SourceFileKind::REPL &&
Ctx.LangOpts.EnableASTScopeLookup) {
@@ -506,7 +524,7 @@
}
// If we found anything, we're done.
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
// When we are in the body of a method, get the 'self' declaration.
@@ -575,22 +593,17 @@
if (lookupType->hasError()) continue;
+ NLOptions options = baseNLOptions;
// Perform lookup into the type.
- NLOptions options = NL_UnqualifiedDefault;
if (isCascadingUse.getValue())
options |= NL_KnownCascadingDependency;
else
options |= NL_KnownNonCascadingDependency;
- if (AllowProtocolMembers)
- options |= NL_ProtocolMembers;
- if (IsTypeLookup)
- options |= NL_OnlyTypes;
- if (IgnoreAccessControl)
- options |= NL_IgnoreAccessControl;
-
SmallVector<ValueDecl *, 4> lookup;
dc->lookupQualified(lookupType, Name, options, TypeResolver, lookup);
+
+ auto startIndex = Results.size();
for (auto result : lookup) {
auto *baseDC = dc;
if (!isa<TypeDecl>(result) && selfDC) baseDC = selfDC;
@@ -607,15 +620,17 @@
.isUnavailableInSwiftVersion(effectiveVersion);
};
- // If all of the results we found are unavailable, keep looking.
- if (std::all_of(Results.begin(), Results.end(),
- unavailableLookupResult)) {
- UnavailableInnerResults.append(Results.begin(), Results.end());
- Results.clear();
+ // If all of the results we just found are unavailable, keep looking.
+ auto begin = Results.begin() + startIndex;
+ if (std::all_of(begin, Results.end(), unavailableLookupResult)) {
+ UnavailableInnerResults.append(begin, Results.end());
+ Results.erase(begin, Results.end());
} else {
if (DebugClient)
filterForDiscriminator(Results, DebugClient);
- return;
+
+ if (shouldReturnBasedOnResults())
+ return;
}
}
@@ -652,7 +667,7 @@
if (auto *selfParam = PBI->getImplicitSelfDecl()) {
Consumer.foundDecl(selfParam,
DeclVisibilityKind::FunctionParameter);
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
DC = DC->getParent();
@@ -698,11 +713,11 @@
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.visit(AFD->getBody());
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
for (auto *PL : AFD->getParameterLists())
localVal.checkParameterList(PL);
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
}
if (!isCascadingUse.hasValue() || isCascadingUse.getValue())
@@ -741,10 +756,10 @@
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.visit(CE->getBody());
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
localVal.checkParameterList(CE->getParameters());
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
}
}
@@ -781,27 +796,21 @@
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.checkGenericParams(GenericParams);
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
}
if (BaseDC && !ExtendedType->hasError()) {
- NLOptions options = NL_UnqualifiedDefault;
+ NLOptions options = baseNLOptions;
if (isCascadingUse.getValue())
options |= NL_KnownCascadingDependency;
else
options |= NL_KnownNonCascadingDependency;
- if (AllowProtocolMembers)
- options |= NL_ProtocolMembers;
- if (IsTypeLookup)
- options |= NL_OnlyTypes;
- if (IgnoreAccessControl)
- options |= NL_IgnoreAccessControl;
-
SmallVector<ValueDecl *, 4> Lookup;
DC->lookupQualified(ExtendedType, Name, options, TypeResolver, Lookup);
bool FoundAny = false;
+ auto startIndex = Results.size();
for (auto Result : Lookup) {
// In Swift 3 mode, unqualified lookup skips static methods when
// performing lookup from instance context.
@@ -846,15 +855,16 @@
};
// If all of the results we found are unavailable, keep looking.
- if (std::all_of(Results.begin(), Results.end(),
- unavailableLookupResult)) {
- UnavailableInnerResults.append(Results.begin(), Results.end());
- Results.clear();
- FoundAny = false;
+ auto begin = Results.begin() + startIndex;
+ if (std::all_of(begin, Results.end(), unavailableLookupResult)) {
+ UnavailableInnerResults.append(begin, Results.end());
+ Results.erase(begin, Results.end());
} else {
if (DebugClient)
filterForDiscriminator(Results, DebugClient);
- return;
+
+ if (shouldReturnBasedOnResults())
+ return;
}
}
}
@@ -873,7 +883,7 @@
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.checkGenericParams(dcGenericParams);
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
if (!isa<ExtensionDecl>(DC))
@@ -896,16 +906,16 @@
// local types.
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.checkSourceFile(*SF);
- if (!Results.empty())
+ if (shouldReturnBasedOnResults())
return;
}
}
}
// TODO: Does the debugger client care about compound names?
- if (Name.isSimpleName()
- && DebugClient && DebugClient->lookupOverrides(Name.getBaseName(), DC,
- Loc, IsTypeLookup, Results))
+ if (Name.isSimpleName() && DebugClient &&
+ DebugClient->lookupOverrides(Name.getBaseName(), DC, Loc,
+ isOriginallyTypeLookup, Results))
return;
recordLookupOfTopLevelName(DC, Name, isCascadingUse.getValue());
@@ -917,8 +927,8 @@
using namespace namelookup;
SmallVector<ValueDecl *, 8> CurModuleResults;
- auto resolutionKind =
- IsTypeLookup ? ResolutionKind::TypesOnly : ResolutionKind::Overloadable;
+ auto resolutionKind = isOriginallyTypeLookup ? ResolutionKind::TypesOnly
+ : ResolutionKind::Overloadable;
lookupInModule(&M, {}, Name, CurModuleResults, NLKind::UnqualifiedLookup,
resolutionKind, TypeResolver, DC, extraImports);
@@ -930,20 +940,19 @@
// Now add any names the DebugClient knows about to the lookup.
if (Name.isSimpleName() && DebugClient)
- DebugClient->lookupAdditions(Name.getBaseName(), DC, Loc, IsTypeLookup,
- Results);
+ DebugClient->lookupAdditions(Name.getBaseName(), DC, Loc,
+ isOriginallyTypeLookup, Results);
// If we've found something, we're done.
- if (!Results.empty())
+ if (shouldReturnBasedOnResults(/*noMoreOuterResults=*/true))
return;
// If we still haven't found anything, but we do have some
// declarations that are "unavailable in the current Swift", drop
// those in.
- if (!UnavailableInnerResults.empty()) {
- Results = std::move(UnavailableInnerResults);
+ Results = std::move(UnavailableInnerResults);
+ if (shouldReturnBasedOnResults(/*noMoreOuterResults=*/true))
return;
- }
if (!Name.isSimpleName())
return;
@@ -951,7 +960,8 @@
// Look for a module with the given name.
if (Name.isSimpleName(M.getName())) {
Results.push_back(LookupResultEntry(&M));
- return;
+ if (shouldReturnBasedOnResults(/*noMoreOuterResults=*/true))
+ return;
}
ModuleDecl *desiredModule = Ctx.getLoadedModule(Name.getBaseIdentifier());
@@ -966,6 +976,8 @@
return true;
});
}
+ // Make sure we've recorded the inner-result-boundary.
+ (void)shouldReturnBasedOnResults(/*noMoreOuterResults=*/true);
}
TypeDecl* UnqualifiedLookup::getSingleTypeResult() {
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 3325322..e2afc66 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -41,8 +41,13 @@
Witness::Witness(ValueDecl *decl, SubstitutionList substitutions,
GenericEnvironment *syntheticEnv,
SubstitutionList reqToSynthesizedEnvSubs) {
- auto &ctx = decl->getASTContext();
+ if (!syntheticEnv && substitutions.empty() &&
+ reqToSynthesizedEnvSubs.empty()) {
+ storage = decl;
+ return;
+ }
+ auto &ctx = decl->getASTContext();
auto declRef = ConcreteDeclRef(ctx, decl, substitutions);
auto storedMem = ctx.Allocate(sizeof(StoredWitness), alignof(StoredWitness));
auto stored = new (storedMem)
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 08e2cbe..063f5f4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -3412,7 +3412,7 @@
genericMemberType->getExtInfo());
}
- auto type = memberType.subst(subs);
+ auto type = memberType.subst(subs, SubstFlags::UseErrorType);
if (isa<AbstractFunctionDecl>(baseDecl)) {
type = type->replaceSelfParameterType(this);
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 1913152..de67729 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -487,6 +487,7 @@
auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
{ paramRef }, { Identifier() });
reinterpreted->setType(enumTy);
+ reinterpreted->setThrows(false);
auto assign = new (C) AssignExpr(selfRef, SourceLoc(), reinterpreted,
/*implicit*/ true);
@@ -573,6 +574,7 @@
auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
{ selfRef }, { Identifier() });
reinterpreted->setType(rawTy);
+ reinterpreted->setThrows(false);
auto ret = new (C) ReturnStmt(SourceLoc(), reinterpreted);
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
@@ -911,6 +913,7 @@
auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
{ selfRef },
{ Identifier() });
+ reinterpreted->setThrows(false);
auto ret = new (C) ReturnStmt(SourceLoc(), reinterpreted);
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
/*implicit*/ true);
@@ -2639,6 +2642,7 @@
AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
structDecl->computeType();
structDecl->setCheckedInheritanceClause();
+ structDecl->setAddedImplicitInitializers();
auto options = getDefaultMakeStructRawValuedOptions();
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
@@ -2689,6 +2693,7 @@
errorWrapper = new (C) StructDecl(loc, name, loc, None, nullptr, dc);
errorWrapper->computeType();
errorWrapper->setValidationStarted();
+ errorWrapper->setAddedImplicitInitializers();
errorWrapper->setAccess(AccessLevel::Public);
errorWrapper->getAttrs().add(
new (Impl.SwiftContext) FixedLayoutAttr(/*IsImplicit*/true));
@@ -3124,6 +3129,7 @@
Impl.importSourceLoc(decl->getLocation()),
None, nullptr, dc);
result->computeType();
+ result->setAddedImplicitInitializers();
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
// FIXME: Figure out what to do with superclasses in C++. One possible
@@ -5300,6 +5306,7 @@
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
structDecl->computeType();
structDecl->setCheckedInheritanceClause();
+ structDecl->setAddedImplicitInitializers();
// Import the type of the underlying storage
auto storedUnderlyingType = Impl.importTypeIgnoreIUO(
@@ -5578,6 +5585,7 @@
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
structDecl->computeType();
structDecl->setCheckedInheritanceClause();
+ structDecl->setAddedImplicitInitializers();
makeStructRawValued(Impl, structDecl, underlyingType,
{KnownProtocolKind::OptionSet});
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 28b771e..7b825e1 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -152,6 +152,9 @@
// nested generics. This factory owns them.
NodeFactory Factory;
+ // A callback for resolving symbolic references.
+ SymbolicResolver Resolver;
+
StringRef getBufferStr() const { return Buffer.getStringRef(); }
void resetBuffer(size_t toPos) { Buffer.resetSize(toPos); }
@@ -284,7 +287,8 @@
#include "swift/Demangling/DemangleNodes.def"
public:
- Remangler(DemanglerPrinter &Buffer) : Buffer(Buffer) {}
+ Remangler(DemanglerPrinter &Buffer,
+ SymbolicResolver Resolver) : Buffer(Buffer), Resolver(Resolver) {}
void mangle(Node *node) {
switch (node->getKind()) {
@@ -1994,18 +1998,25 @@
}
void Remangler::mangleSymbolicReference(Node *node) {
- unreachable("should not try to mangle a symbolic reference; "
- "resolve it to a non-symbolic demangling tree instead");
+ return mangle(Resolver((const void *)node->getIndex()));
}
} // anonymous namespace
/// The top-level interface to the remangler.
std::string Demangle::mangleNode(const NodePointer &node) {
+ return mangleNode(node, [](const void *) -> NodePointer {
+ unreachable("should not try to mangle a symbolic reference; "
+ "resolve it to a non-symbolic demangling tree instead");
+ });
+}
+
+std::string
+Demangle::mangleNode(const NodePointer &node, SymbolicResolver resolver) {
if (!node) return "";
DemanglerPrinter printer;
- Remangler(printer).mangle(node);
+ Remangler(printer, resolver).mangle(node);
return std::move(printer).str();
}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 4ca40e1..c22cfbf 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -119,88 +119,133 @@
return Args;
}
-static void validateArgs(DiagnosticEngine &diags, const ArgList &Args) {
- if (Args.hasArgNoClaim(options::OPT_import_underlying_module) &&
- Args.hasArgNoClaim(options::OPT_import_objc_header)) {
+static void validateBridgingHeaderArgs(DiagnosticEngine &diags,
+ const ArgList &args) {
+ if (args.hasArgNoClaim(options::OPT_import_underlying_module) &&
+ args.hasArgNoClaim(options::OPT_import_objc_header)) {
diags.diagnose({}, diag::error_framework_bridging_header);
}
+}
+
+static void validateDeploymentTarget(DiagnosticEngine &diags,
+ const ArgList &args) {
+ const Arg *A = args.getLastArg(options::OPT_target);
+ if (!A)
+ return;
// Check minimum supported OS versions.
- if (const Arg *A = Args.getLastArg(options::OPT_target)) {
- llvm::Triple triple(llvm::Triple::normalize(A->getValue()));
- if (triple.isMacOSX()) {
- if (triple.isMacOSXVersionLT(10, 9))
+ llvm::Triple triple(llvm::Triple::normalize(A->getValue()));
+ if (triple.isMacOSX()) {
+ if (triple.isMacOSXVersionLT(10, 9))
+ diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
+ "OS X 10.9");
+ } else if (triple.isiOS()) {
+ if (triple.isTvOS()) {
+ if (triple.isOSVersionLT(9, 0)) {
diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
- "OS X 10.9");
- } else if (triple.isiOS()) {
- if (triple.isTvOS()) {
- if (triple.isOSVersionLT(9, 0)) {
- diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
- "tvOS 9.0");
- return;
- }
- }
- if (triple.isOSVersionLT(7))
- diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
- "iOS 7");
- if (triple.isArch32Bit() && !triple.isOSVersionLT(11)) {
- diags.diagnose(SourceLoc(), diag::error_ios_maximum_deployment_32,
- triple.getOSMajorVersion());
- }
- } else if (triple.isWatchOS()) {
- if (triple.isOSVersionLT(2, 0)) {
- diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
- "watchOS 2.0");
- return;
+ "tvOS 9.0");
+ return;
}
}
+ if (triple.isOSVersionLT(7))
+ diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
+ "iOS 7");
+ if (triple.isArch32Bit() && !triple.isOSVersionLT(11)) {
+ diags.diagnose(SourceLoc(), diag::error_ios_maximum_deployment_32,
+ triple.getOSMajorVersion());
+ }
+ } else if (triple.isWatchOS()) {
+ if (triple.isOSVersionLT(2, 0)) {
+ diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
+ "watchOS 2.0");
+ return;
+ }
}
+}
- // Check for conflicting warning control flags
- if (Args.hasArg(options::OPT_suppress_warnings) &&
- Args.hasArg(options::OPT_warnings_as_errors)) {
+static void validateWarningControlArgs(DiagnosticEngine &diags,
+ const ArgList &args) {
+ if (args.hasArg(options::OPT_suppress_warnings) &&
+ args.hasArg(options::OPT_warnings_as_errors)) {
diags.diagnose(SourceLoc(), diag::error_conflicting_options,
"-warnings-as-errors", "-suppress-warnings");
}
+}
- // Check for conflicting profiling flags
- const Arg *ProfileGenerate = Args.getLastArg(options::OPT_profile_generate);
- const Arg *ProfileUse = Args.getLastArg(options::OPT_profile_use);
- if (ProfileGenerate && ProfileUse)
+static void validateProfilingArgs(DiagnosticEngine &diags,
+ const ArgList &args) {
+ const Arg *ProfileGenerate = args.getLastArg(options::OPT_profile_generate);
+ const Arg *ProfileUse = args.getLastArg(options::OPT_profile_use);
+ if (ProfileGenerate && ProfileUse) {
diags.diagnose(SourceLoc(), diag::error_conflicting_options,
"-profile-generate", "-profile-use");
-
- // Check if the profdata is missing
- if (ProfileUse && !llvm::sys::fs::exists(ProfileUse->getValue()))
- diags.diagnose(SourceLoc(), diag::error_profile_missing,
- ProfileUse->getValue());
-
- // Check for missing debug option when verifying debug info.
- if (Args.hasArg(options::OPT_verify_debug_info)) {
- bool hasDebugOption = true;
- Arg *Arg = Args.getLastArg(swift::options::OPT_g_Group);
- if (!Arg || Arg->getOption().matches(swift::options::OPT_gnone))
- hasDebugOption = false;
- if (!hasDebugOption)
- diags.diagnose(SourceLoc(),
- diag::verify_debug_info_requires_debug_option);
}
- for (const Arg *A : Args.filtered(options::OPT_D)) {
+ // Check if the profdata is missing
+ if (ProfileUse && !llvm::sys::fs::exists(ProfileUse->getValue())) {
+ diags.diagnose(SourceLoc(), diag::error_profile_missing,
+ ProfileUse->getValue());
+ }
+}
+
+static void validateDebugInfoArgs(DiagnosticEngine &diags,
+ const ArgList &args) {
+ // Check for missing debug option when verifying debug info.
+ if (args.hasArg(options::OPT_verify_debug_info)) {
+ Arg *debugOpt = args.getLastArg(swift::options::OPT_g_Group);
+ if (!debugOpt || debugOpt->getOption().matches(swift::options::OPT_gnone)) {
+ diags.diagnose(SourceLoc(),
+ diag::verify_debug_info_requires_debug_option);
+ }
+ }
+}
+
+static void validateCompilationConditionArgs(DiagnosticEngine &diags,
+ const ArgList &args) {
+ for (const Arg *A : args.filtered(options::OPT_D)) {
StringRef name = A->getValue();
- if (name.find('=') != StringRef::npos)
+ if (name.find('=') != StringRef::npos) {
diags.diagnose(SourceLoc(),
diag::cannot_assign_value_to_conditional_compilation_flag,
name);
- else if (name.startswith("-D"))
+ } else if (name.startswith("-D")) {
diags.diagnose(SourceLoc(), diag::redundant_prefix_compilation_flag,
name);
- else if (!Lexer::isIdentifier(name))
+ } else if (!Lexer::isIdentifier(name)) {
diags.diagnose(SourceLoc(), diag::invalid_conditional_compilation_flag,
name);
+ }
}
}
+static void validateAutolinkingArgs(DiagnosticEngine &diags,
+ const ArgList &args) {
+ auto *forceLoadArg = args.getLastArg(options::OPT_autolink_force_load);
+ if (!forceLoadArg)
+ return;
+ auto *incrementalArg = args.getLastArg(options::OPT_incremental);
+ if (!incrementalArg)
+ return;
+
+ // Note: -incremental can itself be overridden by other arguments later
+ // on, but since -autolink-force-load is a rare and not-really-recommended
+ // option it's not worth modeling that complexity here (or moving the
+ // check somewhere else).
+ diags.diagnose(SourceLoc(), diag::error_option_not_supported,
+ forceLoadArg->getSpelling(), incrementalArg->getSpelling());
+}
+
+/// Perform miscellaneous early validation of arguments.
+static void validateArgs(DiagnosticEngine &diags, const ArgList &args) {
+ validateBridgingHeaderArgs(diags, args);
+ validateDeploymentTarget(diags, args);
+ validateWarningControlArgs(diags, args);
+ validateProfilingArgs(diags, args);
+ validateDebugInfoArgs(diags, args);
+ validateCompilationConditionArgs(diags, args);
+ validateAutolinkingArgs(diags, args);
+}
+
std::unique_ptr<ToolChain>
Driver::buildToolChain(const llvm::opt::InputArgList &ArgList) {
diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp
index 2727671..f8e663e 100644
--- a/lib/Driver/FrontendUtil.cpp
+++ b/lib/Driver/FrontendUtil.cpp
@@ -34,6 +34,11 @@
// frontend command.
Args.push_back("-force-single-frontend-invocation");
+ // Explictly disable batch mode to avoid a spurious warning when combining
+ // -enable-batch-mode with -force-single-frontend-invocation. This is an
+ // implementation detail.
+ Args.push_back("-disable-batch-mode");
+
// Avoid using filelists
std::string neverThreshold =
std::to_string(Compilation::NEVER_USE_FILELIST);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index ccf92e8..8af50c8 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -312,7 +312,7 @@
Opts.EnableNonFrozenEnumExhaustivityDiagnostics =
Args.hasFlag(OPT_enable_nonfrozen_enum_exhaustivity_diagnostics,
OPT_disable_nonfrozen_enum_exhaustivity_diagnostics,
- Opts.EnableNonFrozenEnumExhaustivityDiagnostics);
+ Opts.isSwiftVersionAtLeast(5));
if (Arg *A = Args.getLastArg(OPT_Rpass_EQ))
Opts.OptimizationRemarkPassedPattern =
diff --git a/lib/IDE/APIDigesterData.cpp b/lib/IDE/APIDigesterData.cpp
index d998fd3..2714fdf 100644
--- a/lib/IDE/APIDigesterData.cpp
+++ b/lib/IDE/APIDigesterData.cpp
@@ -444,6 +444,25 @@
return const_cast<APIDiffItem *&>(seq[index]);
}
};
+
+template<>
+struct ObjectTraits<NameCorrectionInfo> {
+ static void mapping(Output &out, NameCorrectionInfo &value) {
+ out.mapRequired(getKeyContent(DiffItemKeyKind::KK_OldPrintedName),value.OriginalName);
+ out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NewPrintedName), value.CorrectedName);
+ out.mapRequired(getKeyContent(DiffItemKeyKind::KK_ModuleName), value.ModuleName);
+ }
+};
+template<>
+struct ArrayTraits<ArrayRef<NameCorrectionInfo>> {
+ static size_t size(Output &out, ArrayRef<NameCorrectionInfo> &seq) {
+ return seq.size();
+ }
+ static NameCorrectionInfo &element(Output &, ArrayRef<NameCorrectionInfo> &seq,
+ size_t index) {
+ return const_cast<NameCorrectionInfo&>(seq[index]);
+ }
+};
} // namespace json
} // namespace swift
@@ -453,6 +472,12 @@
yout << Items;
}
+void swift::ide::api::APIDiffItemStore::
+serialize(llvm::raw_ostream &os, ArrayRef<NameCorrectionInfo> Items) {
+ json::Output yout(os);
+ yout << Items;
+}
+
struct swift::ide::api::APIDiffItemStore::Implementation {
private:
llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 2> AllBuffer;
diff --git a/lib/IDE/TypeReconstruction.cpp b/lib/IDE/TypeReconstruction.cpp
index 0256f66..48b651d 100644
--- a/lib/IDE/TypeReconstruction.cpp
+++ b/lib/IDE/TypeReconstruction.cpp
@@ -596,7 +596,7 @@
// FIXME: Need a more complete/robust lookup mechanism that can handle
// declarations in sub-stmts, etc.
UnqualifiedLookup lookup(name, FD, ast->getLazyResolver(),
- /*IsKnownPrivate=*/false, FD->getEndLoc());
+ FD->getEndLoc());
if (!lookup.isSuccess()) {
result._error = "no decl found in function";
} else {
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 47b3c78..59eefc9 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2310,11 +2310,19 @@
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
- if (f->getInlineStrategy() == NoInline) {
+ switch (f->getInlineStrategy()) {
+ case NoInline:
attrs = attrs.addAttribute(signature.getType()->getContext(),
llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoInline);
+ break;
+ case AlwaysInline:
+ // FIXME: We do not currently transfer AlwaysInline since doing so results
+ // in test failures, which must be investigated first.
+ case InlineDefault:
+ break;
}
+
if (isReadOnlyFunction(f)) {
attrs = attrs.addAttribute(signature.getType()->getContext(),
llvm::AttributeList::FunctionIndex,
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index df147e2..353bfe3 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -365,8 +365,8 @@
}
void addExtendedContext() {
- auto string = getTypeRef(IGM,
- E->getSelfInterfaceType()->getCanonicalType());
+ auto string = IGM.getTypeRef(
+ E->getSelfInterfaceType()->getCanonicalType());
B.addRelativeAddress(string);
}
@@ -3841,7 +3841,7 @@
auto flags = GenericRequirementFlags(abiKind, false, false);
auto typeName =
- getTypeRef(IGM, requirement.getSecondType()->getCanonicalType());
+ IGM.getTypeRef(requirement.getSecondType()->getCanonicalType());
addGenericRequirement(IGM, B, metadata, sig, flags,
requirement.getFirstType(),
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index bb61f72..9e08613 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -164,6 +164,12 @@
}
};
+llvm::Constant *IRGenModule::getTypeRef(CanType type) {
+ IRGenMangler Mangler;
+ auto SymbolicName = Mangler.mangleTypeForReflection(*this, type);
+ return getAddrOfStringForTypeRef(SymbolicName);
+}
+
class ReflectionMetadataBuilder {
protected:
IRGenModule &IGM;
@@ -203,46 +209,23 @@
/// Add a 32-bit relative offset to a mangled typeref string
/// in the typeref reflection section.
- void addTypeRef(ModuleDecl *ModuleContext, CanType type,
- CanGenericSignature Context = {}) {
- assert(type);
-
- // Generic parameters should be written in terms of interface types
- // for the purposes of reflection metadata
- assert(!type->hasArchetype() && "Forgot to map typeref out of context");
-
- // TODO: As a compatibility hack, mangle single-field boxes with the legacy
- // mangling in reflection metadata.
- bool isSingleFieldOfBox = false;
- auto boxTy = dyn_cast<SILBoxType>(type);
- if (boxTy && boxTy->getLayout()->getFields().size() == 1) {
- GenericContextScope scope(IGM, Context);
- type = boxTy->getFieldLoweredType(IGM.getSILModule(), 0);
- isSingleFieldOfBox = true;
- }
- IRGenMangler mangler;
- auto MangledStr = mangler.mangleTypeForReflection(IGM, type,
- ModuleContext,
- isSingleFieldOfBox);
- auto mangledName = IGM.getAddrOfStringForTypeRef(MangledStr);
- B.addRelativeAddress(mangledName);
+ void addTypeRef(CanType type) {
+ B.addRelativeAddress(IGM.getTypeRef(type));
}
/// Add a 32-bit relative offset to a mangled nominal type string
/// in the typeref reflection section.
void addNominalRef(const NominalTypeDecl *nominal) {
- IRGenMangler mangler;
- SymbolicMangling mangledStr;
if (auto proto = dyn_cast<ProtocolDecl>(nominal)) {
+ IRGenMangler mangler;
+ SymbolicMangling mangledStr;
mangledStr.String = mangler.mangleBareProtocol(proto);
+ auto mangledName = IGM.getAddrOfStringForTypeRef(mangledStr);
+ B.addRelativeAddress(mangledName);
} else {
CanType type = nominal->getDeclaredType()->getCanonicalType();
- mangledStr =
- mangler.mangleTypeForReflection(IGM, type, nominal->getModuleContext(),
- /*isSingleFieldOfBox=*/false);
+ B.addRelativeAddress(IGM.getTypeRef(type));
}
- auto mangledName = IGM.getAddrOfStringForTypeRef(mangledStr);
- B.addRelativeAddress(mangledName);
}
llvm::GlobalVariable *emit(Optional<LinkEntity> entity,
@@ -296,9 +279,7 @@
PrettyStackTraceDecl DebugStack("emitting associated type metadata",
Nominal);
- auto *M = IGM.getSILModule().getSwiftModule();
-
- addTypeRef(M, Nominal->getDeclaredType()->getCanonicalType());
+ addTypeRef(Nominal->getDeclaredType()->getCanonicalType());
addNominalRef(Conformance->getProtocol());
B.addInt32(AssociatedTypes.size());
@@ -308,7 +289,7 @@
auto NameGlobal = IGM.getAddrOfFieldName(AssocTy.first);
B.addRelativeAddress(NameGlobal);
addBuiltinTypeRefs(AssocTy.second);
- addTypeRef(M, AssocTy.second);
+ addTypeRef(AssocTy.second);
}
}
@@ -342,7 +323,7 @@
if (!type) {
B.addInt32(0);
} else {
- addTypeRef(value->getModuleContext(), type);
+ addTypeRef(type);
addBuiltinTypeRefs(type);
}
@@ -448,8 +429,7 @@
auto *CD = dyn_cast<ClassDecl>(NTD);
if (CD && CD->getSuperclass()) {
- addTypeRef(NTD->getModuleContext(),
- CD->getSuperclass()->getCanonicalType());
+ addTypeRef(CD->getSuperclass()->getCanonicalType());
} else {
B.addInt32(0);
}
@@ -511,7 +491,7 @@
}
void layout() override {
- addTypeRef(module, type);
+ addTypeRef(type);
B.addInt32(ti->getFixedSize().getValue());
B.addInt32(ti->getFixedAlignment().getValue());
@@ -561,7 +541,7 @@
B.addInt32(0); // Number of sources
B.addInt32(0); // Number of generic bindings
- addTypeRef(IGM.getSILModule().getSwiftModule(), BoxedType);
+ addTypeRef(BoxedType);
addBuiltinTypeRefs(BoxedType);
}
@@ -754,8 +734,7 @@
// Now add typerefs of all of the captures.
for (auto CaptureType : CaptureTypes) {
- addTypeRef(IGM.getSILModule().getSwiftModule(), CaptureType,
- OrigCalleeType->getGenericSignature());
+ addTypeRef(CaptureType);
addBuiltinTypeRefs(CaptureType);
}
@@ -765,7 +744,7 @@
auto GenericParam = GenericAndSource.first->getCanonicalType();
auto Source = GenericAndSource.second;
- addTypeRef(nullptr, GenericParam);
+ addTypeRef(GenericParam);
addMetadataSource(Source);
}
}
diff --git a/lib/IRGen/IRGenMangler.cpp b/lib/IRGen/IRGenMangler.cpp
index d9fcc0c..40e7679 100644
--- a/lib/IRGen/IRGenMangler.cpp
+++ b/lib/IRGen/IRGenMangler.cpp
@@ -81,10 +81,8 @@
SymbolicMangling
IRGenMangler::mangleTypeForReflection(IRGenModule &IGM,
- Type Ty,
- ModuleDecl *Module,
- bool isSingleFieldOfBox) {
- Mod = Module;
+ Type Ty) {
+ Mod = IGM.getSwiftModule();
OptimizeProtocolNames = false;
llvm::SaveAndRestore<std::function<bool (const DeclContext *)>>
@@ -109,8 +107,6 @@
SymbolicReferences.clear();
appendType(Ty);
- if (isSingleFieldOfBox)
- appendOperator("Xb");
return {finalize(), std::move(SymbolicReferences)};
}
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index a0b25a4..9d342e1 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -354,9 +354,7 @@
}
SymbolicMangling mangleTypeForReflection(IRGenModule &IGM,
- Type Ty,
- ModuleDecl *Module,
- bool isSingleFieldOfBox);
+ Type Ty);
std::string mangleTypeForLLVMTypeName(CanType Ty);
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 833df22..e2bc7b8 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -970,6 +970,7 @@
/// reflection metadata.
llvm::SetVector<const StructDecl *> ImportedStructs;
+ llvm::Constant *getTypeRef(CanType type);
llvm::Constant *getAddrOfStringForTypeRef(StringRef mangling);
llvm::Constant *getAddrOfStringForTypeRef(const SymbolicMangling &mangling);
llvm::Constant *getAddrOfFieldName(StringRef Name);
diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp
index aa993fc..158fabb 100644
--- a/lib/IRGen/MetadataRequest.cpp
+++ b/lib/IRGen/MetadataRequest.cpp
@@ -297,18 +297,6 @@
return addr;
}
-// FIXME: willBeRelativelyAddressed is only needed to work around an ld64 bug
-// resolving relative references to coalesceable symbols.
-// It should be removed when fixed. rdar://problem/22674524
-llvm::Constant *irgen::getTypeRef(IRGenModule &IGM, CanType type) {
- IRGenMangler Mangler;
- auto SymbolicName = Mangler.mangleTypeForReflection(IGM, type,
- IGM.getSwiftModule(),
- /*single-field box*/ false);
-
- return IGM.getAddrOfStringForTypeRef(SymbolicName);
-}
-
llvm::Value *irgen::emitObjCMetadataRefForMetadata(IRGenFunction &IGF,
llvm::Value *classPtr) {
assert(IGF.IGM.Context.LangOpts.EnableObjCInterop);
diff --git a/lib/IRGen/MetadataRequest.h b/lib/IRGen/MetadataRequest.h
index 86ad7a3..ec1beba 100644
--- a/lib/IRGen/MetadataRequest.h
+++ b/lib/IRGen/MetadataRequest.h
@@ -503,8 +503,6 @@
llvm::Value *uniqueForeignTypeMetadataRef(IRGenFunction &IGF,
llvm::Value *candidate);
-llvm::Constant *getTypeRef(IRGenModule &IGM, CanType type);
-
using LazyCacheEmitter =
llvm::function_ref<MetadataResponse(IRGenFunction &IGF, Explosion ¶ms)>;
diff --git a/lib/Migrator/TypeOfMigratorPass.cpp b/lib/Migrator/TypeOfMigratorPass.cpp
index 3697b9c..965f5b3 100644
--- a/lib/Migrator/TypeOfMigratorPass.cpp
+++ b/lib/Migrator/TypeOfMigratorPass.cpp
@@ -44,7 +44,6 @@
{ SF->getASTContext().getIdentifier("type") },
ContextStack.empty() ? SF->getModuleScopeContext() : ContextStack.back(),
/*TypeResolver=*/SF->getASTContext().getLazyResolver(),
- /*IsKnownPrivate=*/false,
DTE->getLoc()
};
auto isShadowing = [&]() -> bool {
diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp
index b0f3685..91557c4 100644
--- a/lib/SIL/SILProfiler.cpp
+++ b/lib/SIL/SILProfiler.cpp
@@ -93,11 +93,8 @@
assert(hasASTBeenTypeChecked(N) && "Cannot use this AST for profiling");
if (auto *D = N.dyn_cast<Decl *>()) {
- // Any mapped function may be profiled. There's an exception for
- // constructors because all of the constructors for a type share a single
- // profiler.
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D))
- return !isa<ConstructorDecl>(AFD);
+ return true;
if (isa<TopLevelCodeDecl>(D))
return true;
@@ -798,7 +795,7 @@
return visitFunctionDecl(*this, AFD, [&] {
CounterExpr &funcCounter = assignCounter(AFD->getBody());
- if (isa<ConstructorDecl>(AFD))
+ if (ParentNominalType && isa<ConstructorDecl>(AFD))
addToCounter(ParentNominalType, funcCounter);
});
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
@@ -995,16 +992,6 @@
return {};
}
-static void walkTopLevelNodeForProfiling(ASTNode Root, ASTWalker &Walker) {
- Root.walk(Walker);
-
- // Visit extensions when walking through a nominal type.
- auto *NTD = dyn_cast_or_null<NominalTypeDecl>(Root.dyn_cast<Decl *>());
- if (NTD)
- for (ExtensionDecl *ED : NTD->getExtensions())
- ED->walk(Walker);
-}
-
void SILProfiler::assignRegionCounters() {
const auto &SM = M.getASTContext().SourceMgr;
@@ -1040,7 +1027,7 @@
CurrentFuncName, getEquivalentPGOLinkage(CurrentFuncLinkage),
CurrentFileName);
- walkTopLevelNodeForProfiling(Root, Mapper);
+ Root.walk(Mapper);
NumRegionCounters = Mapper.NextCounter;
// TODO: Mapper needs to calculate a function hash as it goes.
@@ -1048,7 +1035,7 @@
if (EmitCoverageMapping) {
CoverageMapping Coverage(SM);
- walkTopLevelNodeForProfiling(Root, Coverage);
+ Root.walk(Coverage);
CovMap =
Coverage.emitSourceRegions(M, CurrentFuncName, PGOFuncName, PGOFuncHash,
RegionCounterMap, CurrentFileName);
@@ -1066,7 +1053,7 @@
}
PGOMapping pgoMapper(RegionLoadedCounterMap, LoadedCounts,
RegionCondToParentMap);
- walkTopLevelNodeForProfiling(Root, pgoMapper);
+ Root.walk(pgoMapper);
}
}
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 0ac3d43..ee30072 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -2000,8 +2000,12 @@
SILType caseTy =
UI->getOperand()->getType().getEnumElementType(UI->getElement(),
F.getModule());
- requireSameType(caseTy, UI->getType(),
- "InitEnumDataAddrInst result does not match type of enum case");
+
+ if (UI->getModule().getStage() != SILStage::Lowered) {
+ requireSameType(
+ caseTy, UI->getType(),
+ "InitEnumDataAddrInst result does not match type of enum case");
+ }
}
void checkUncheckedEnumDataInst(UncheckedEnumDataInst *UI) {
@@ -2019,8 +2023,11 @@
SILType caseTy =
UI->getOperand()->getType().getEnumElementType(UI->getElement(),
F.getModule());
- require(caseTy == UI->getType(),
- "UncheckedEnumData result does not match type of enum case");
+
+ if (UI->getModule().getStage() != SILStage::Lowered) {
+ require(caseTy == UI->getType(),
+ "UncheckedEnumData result does not match type of enum case");
+ }
}
void checkUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *UI) {
@@ -2038,8 +2045,11 @@
SILType caseTy =
UI->getOperand()->getType().getEnumElementType(UI->getElement(),
F.getModule());
- require(caseTy == UI->getType(),
- "UncheckedTakeEnumDataAddrInst result does not match type of enum case");
+
+ if (UI->getModule().getStage() != SILStage::Lowered) {
+ require(caseTy == UI->getType(), "UncheckedTakeEnumDataAddrInst result "
+ "does not match type of enum case");
+ }
}
void checkInjectEnumAddrInst(InjectEnumAddrInst *IUAI) {
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index ff77f9c..7dbc069 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -489,13 +489,22 @@
}
SILProfiler *
-SILGenModule::getOrCreateProfilerForConstructors(NominalTypeDecl *decl) {
- assert(decl && "No nominal type for constructor lookup");
-
+SILGenModule::getOrCreateProfilerForConstructors(DeclContext *ctx,
+ ConstructorDecl *cd) {
const auto &Opts = M.getOptions();
if (!Opts.GenerateProfile && Opts.UseProfile.empty())
return nullptr;
+ // Profile nominal types and extensions separately, as they may live in
+ // distinct files. For extensions, just pass in the constructor, because
+ // there are no stored property initializers to visit.
+ Decl *decl = nullptr;
+ if (ctx->isExtensionContext())
+ decl = cd;
+ else
+ decl = ctx->getAsNominalTypeOrNominalTypeExtensionContext();
+ assert(decl && "No decl available for profiling in this context");
+
SILProfiler *&profiler = constructorProfilers[decl];
if (!profiler)
profiler = SILProfiler::create(M, ForDefinition, decl);
@@ -755,7 +764,7 @@
bool ForCoverageMapping = doesASTRequireProfiling(M, decl);
- if (auto *clsDecl = declCtx->getAsClassOrClassExtensionContext()) {
+ if (declCtx->getAsClassOrClassExtensionContext()) {
// Class constructors have separate entry points for allocation and
// initialization.
emitOrDelayFunction(
@@ -772,11 +781,12 @@
SILDeclRef initConstant(decl, SILDeclRef::Kind::Initializer);
emitOrDelayFunction(
*this, initConstant,
- [this, initConstant, decl, clsDecl](SILFunction *initF) {
+ [this, initConstant, decl, declCtx](SILFunction *initF) {
preEmitFunction(initConstant, decl, initF, decl);
PrettyStackTraceSILFunction X("silgen constructor initializer",
initF);
- initF->setProfiler(getOrCreateProfilerForConstructors(clsDecl));
+ initF->setProfiler(
+ getOrCreateProfilerForConstructors(declCtx, decl));
SILGenFunction(*this, *initF).emitClassConstructorInitializer(decl);
postEmitFunction(initConstant, initF);
},
@@ -784,12 +794,11 @@
}
} else {
// Struct and enum constructors do everything in a single function.
- auto *nomDecl = declCtx->getAsNominalTypeOrNominalTypeExtensionContext();
emitOrDelayFunction(
- *this, constant, [this, constant, decl, nomDecl](SILFunction *f) {
+ *this, constant, [this, constant, decl, declCtx](SILFunction *f) {
preEmitFunction(constant, decl, f, decl);
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
- f->setProfiler(getOrCreateProfilerForConstructors(nomDecl));
+ f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl));
SILGenFunction(*this, *f).emitValueConstructor(decl);
postEmitFunction(constant, f);
});
@@ -997,10 +1006,8 @@
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
// Inherit a profiler instance from the constructor.
- auto *nominalDecl =
- var->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
- if (nominalDecl)
- f->setProfiler(getOrCreateProfilerForConstructors(nominalDecl));
+ f->setProfiler(
+ getOrCreateProfilerForConstructors(var->getDeclContext(), nullptr));
SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
postEmitFunction(constant, f);
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index 66ae0b9..8b39f6f 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -96,9 +96,10 @@
/// The most recent conformance...
NormalProtocolConformance *lastEmittedConformance = nullptr;
- /// Profiler instances for constructors, grouped by associated nominal type.
+ /// Profiler instances for constructors, grouped by associated decl.
/// Each profiler is shared by all member initializers for a nominal type.
- llvm::DenseMap<NominalTypeDecl *, SILProfiler *> constructorProfilers;
+ /// Constructors within extensions are profiled separately.
+ llvm::DenseMap<Decl *, SILProfiler *> constructorProfilers;
SILFunction *emitTopLevelFunction(SILLocation Loc);
@@ -440,9 +441,12 @@
/// Emit a property descriptor for the given storage decl if it needs one.
void tryEmitPropertyDescriptor(AbstractStorageDecl *decl);
- /// Get or create the profiler instance for a nominal type's constructors.
- SILProfiler *getOrCreateProfilerForConstructors(NominalTypeDecl *decl);
-
+ /// Get or create the shared profiler instance for a type's constructors.
+ /// This takes care to create separate profilers for extensions, which may
+ /// reside in a different file than the one where the base type is defined.
+ SILProfiler *getOrCreateProfilerForConstructors(DeclContext *ctx,
+ ConstructorDecl *cd);
+
private:
/// Emit the deallocator for a class that uses the objc allocator.
void emitObjCAllocatorDestructor(ClassDecl *cd, DestructorDecl *dd);
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index c9dfcd2..aa72932 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -574,10 +574,11 @@
SILType valueBufferTy =
SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
- SILValue buffer = SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
- valueBufferTy.getAddressType(),
- /*strict*/ true,
- /*invariant*/ false);
+ SILValue buffer =
+ SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
+ valueBufferTy.getAddressType(),
+ /*strict*/ true,
+ /*invariant*/ false);
SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
SILAccessEnforcement::Dynamic,
/*noNestedConflict*/ false);
@@ -586,11 +587,10 @@
}
/// Specialized emitter for Builtin.performInstantaneousReadAccess
-static ManagedValue emitBuiltinPerformInstantaneousReadAccess(SILGenFunction &SGF,
- SILLocation loc,
- SubstitutionList substitutions,
- ArrayRef<ManagedValue> args,
- SGFContext C) {
+static ManagedValue emitBuiltinPerformInstantaneousReadAccess(
+ SILGenFunction &SGF, SILLocation loc, SubstitutionList substitutions,
+ ArrayRef<ManagedValue> args, SGFContext C) {
+
assert(substitutions.size() == 1 &&
"Builtin.performInstantaneousReadAccess should have one substitution");
assert(args.size() == 2 &&
@@ -603,13 +603,21 @@
/*strict*/ true,
/*invariant*/ false);
- // Begin and then immediately end a read access. No nested conflict is
- // possible because there are no instructions between the begin and the
- // end of the access.
- SILValue access = SGF.B.createBeginAccess(loc, addr, SILAccessKind::Read,
- SILAccessEnforcement::Dynamic,
- /*noNestedConflict*/ true);
- SGF.B.createEndAccess(loc, access, /*aborted*/ false);
+ SILType valueBufferTy =
+ SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
+ SILValue unusedBuffer = SGF.emitTemporaryAllocation(loc, valueBufferTy);
+
+ // Begin an "unscoped" read access. No nested conflict is possible because
+ // the compiler should generate the actual read for the KeyPath expression
+ // immediately after the call to this builtin, which forms the address of
+ // that real access. When noNestedConflict=true, no EndUnpairedAccess should
+ // be emitted.
+ //
+ // Unpaired access is necessary because a BeginAccess/EndAccess pair with no
+ // use will be trivially optimized away.
+ SGF.B.createBeginUnpairedAccess(loc, addr, unusedBuffer, SILAccessKind::Read,
+ SILAccessEnforcement::Dynamic,
+ /*noNestedConflict*/ true);
return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index b6bc09a..60e1797 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -19,12 +19,19 @@
/// test cases through the pipeline and exercising SIL verification before all
/// passes support access markers.
///
+/// This must only run before inlining _semantic calls. If we inline and drop
+/// the @_semantics("optimize.sil.preserve_exclusivity") attribute, the inlined
+/// markers will be eliminated, but the noninlined markers will not. This would
+/// result in inconsistent begin/end_unpaired_access resulting in unpredictable,
+/// potentially catastrophic runtime behavior.
+///
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "access-marker-elim"
#include "swift/Basic/Range.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/Strings.h"
#include "llvm/Support/CommandLine.h"
using namespace swift;
@@ -167,6 +174,12 @@
void run() override {
auto &M = *getModule();
for (auto &F : M) {
+ if (F.hasSemanticsAttr(OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY)) {
+ DEBUG(llvm::dbgs() << "Skipping " << F.getName() << ". Found "
+ << OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY << " tag!\n");
+ continue;
+ }
+
bool removedAny = AccessMarkerElimination(&F).stripMarkers();
// Only invalidate analyses if we removed some markers.
diff --git a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
index ee9f4c3..da15951 100644
--- a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
+++ b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
@@ -20,12 +20,14 @@
///
//===----------------------------------------------------------------------===//
-#include "swift/SILOptimizer/PassManager/Passes.h"
+#define DEBUG_TYPE "sil-cleanup"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/Strings.h"
using namespace swift;
@@ -68,10 +70,12 @@
class IRGenPrepare : public SILFunctionTransform {
void run() override {
- bool shouldInvalidate = cleanFunction(*getFunction());
- if (!shouldInvalidate)
- return;
- invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
+ SILFunction *F = getFunction();
+
+ bool shouldInvalidate = cleanFunction(*F);
+
+ if (shouldInvalidate)
+ invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
}
};
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 4da4ffa..44bb95c 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -2820,6 +2820,22 @@
}
auto selected = *selectedElt;
+ if (!selected.choice.getBaseType()) {
+ // This is one of the "outer alternatives", meaning the innermost
+ // methods didn't work out.
+ //
+ // The only way to get here is via an UnresolvedDotExpr with outer
+ // alternatives.
+ auto UDE = cast<UnresolvedDotExpr>(expr);
+ cs.diagnoseDeprecatedConditionalConformanceOuterAccess(
+ UDE, selected.choice.getDecl());
+
+ return buildDeclRef(selected.choice, nameLoc, selected.openedFullType,
+ memberLocator, implicit,
+ selected.choice.getFunctionRefKind(),
+ AccessSemantics::Ordinary);
+ }
+
switch (selected.choice.getKind()) {
case OverloadChoiceKind::DeclViaBridge: {
base = cs.coerceToRValue(base);
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 2165e22..6ad37ae 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -1333,7 +1333,7 @@
static DeclName
findCorrectEnumCaseName(Type Ty, TypoCorrectionResults &corrections,
DeclName memberName) {
- if (!memberName.isSimpleName())
+ if (memberName.isSpecial() || !memberName.isSimpleName())
return DeclName();
if (!Ty->is<EnumType>() &&
!Ty->is<BoundGenericEnumType>())
@@ -1630,7 +1630,7 @@
// This happens, for example, with ambiguous OverloadedDeclRefExprs. We should
// just implement visitOverloadedDeclRefExprs and nuke this.
-
+
// If we couldn't resolve an argument, then produce a generic "ambiguity"
// diagnostic.
diagnose(anchor->getLoc(), diag::ambiguous_member_overload_set,
@@ -3549,6 +3549,58 @@
TE->isImplicit(), TT));
}
+static DeclName getBaseName(DeclContext *context) {
+ if (auto generic = context->getAsNominalTypeOrNominalTypeExtensionContext()) {
+ return generic->getName();
+ } else if (context->isModuleScopeContext())
+ return context->getParentModule()->getName();
+ else
+ llvm_unreachable("Unsupported base");
+};
+
+static void emitFixItForExplicitlyQualifiedReference(
+ TypeChecker &tc, UnresolvedDotExpr *UDE,
+ decltype(diag::fix_unqualified_access_top_level) diag, DeclName baseName,
+ DescriptiveDeclKind kind) {
+ auto name = baseName.getBaseIdentifier();
+ SmallString<32> namePlusDot = name.str();
+ namePlusDot.push_back('.');
+
+ tc.diagnose(UDE->getLoc(), diag, namePlusDot, kind, name)
+ .fixItInsert(UDE->getStartLoc(), namePlusDot);
+}
+
+void ConstraintSystem::diagnoseDeprecatedConditionalConformanceOuterAccess(
+ UnresolvedDotExpr *UDE, ValueDecl *choice) {
+ auto result = TC.lookupUnqualified(DC, UDE->getName(), UDE->getLoc());
+ assert(result && "names can't just disappear");
+ // These should all come from the same place.
+ auto exampleInner = result.front();
+ auto innerChoice = exampleInner.getValueDecl();
+ auto innerDC = exampleInner.getDeclContext()->getInnermostTypeContext();
+ auto innerParentDecl =
+ innerDC->getAsNominalTypeOrNominalTypeExtensionContext();
+ auto innerBaseName = getBaseName(innerDC);
+
+ auto choiceKind = choice->getDescriptiveKind();
+ auto choiceDC = choice->getDeclContext();
+ auto choiceBaseName = getBaseName(choiceDC);
+ auto choiceParentDecl = choiceDC->getAsDeclOrDeclExtensionContext();
+ auto choiceParentKind = choiceParentDecl
+ ? choiceParentDecl->getDescriptiveKind()
+ : DescriptiveDeclKind::Module;
+
+ TC.diagnose(UDE->getLoc(),
+ diag::warn_deprecated_conditional_conformance_outer_access,
+ UDE->getName(), choiceKind, choiceParentKind, choiceBaseName,
+ innerChoice->getDescriptiveKind(),
+ innerParentDecl->getDescriptiveKind(), innerBaseName);
+
+ emitFixItForExplicitlyQualifiedReference(
+ TC, UDE, diag::fix_deprecated_conditional_conformance_outer_access,
+ choiceBaseName, choiceKind);
+}
+
static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
CalleeCandidateInfo &CCI,
ArrayRef<Identifier> argLabels,
@@ -3655,16 +3707,6 @@
return kind;
};
- auto getBaseName = [](DeclContext *context) -> DeclName {
- if (auto generic =
- context->getAsNominalTypeOrNominalTypeExtensionContext()) {
- return generic->getName();
- } else if (context->isModuleScopeContext())
- return context->getParentModule()->getName();
- else
- llvm_unreachable("Unsupported base");
- };
-
auto diagnoseShadowing = [&](ValueDecl *base,
ArrayRef<OverloadChoice> candidates) -> bool {
CalleeCandidateInfo calleeInfo(base ? base->getInterfaceType() : nullptr,
@@ -3712,13 +3754,8 @@
if (baseKind == DescriptiveDeclKind::Module)
topLevelDiag = diag::fix_unqualified_access_top_level_multi;
- auto name = baseName.getBaseIdentifier();
- SmallString<32> namePlusDot = name.str();
- namePlusDot.push_back('.');
-
- TC.diagnose(UDE->getLoc(), topLevelDiag, namePlusDot,
- choice->getDescriptiveKind(), name)
- .fixItInsert(UDE->getStartLoc(), namePlusDot);
+ emitFixItForExplicitlyQualifiedReference(TC, UDE, topLevelDiag, baseName,
+ choice->getDescriptiveKind());
for (auto &candidate : calleeInfo.candidates) {
if (auto decl = candidate.getDecl())
@@ -6857,7 +6894,7 @@
// If we have more than one result, filter out unavailable or
// obviously unusable candidates.
if (lookup.size() > 1) {
- lookup.filter([&](LookupResultEntry result) -> bool {
+ lookup.filter([&](LookupResultEntry result, bool isOuter) -> bool {
// Drop unavailable candidates.
if (result.getValueDecl()->getAttrs().isUnavailable(TC.Context))
return false;
@@ -7525,18 +7562,23 @@
// If this is a tuple, then the index needs to be valid.
if (auto tuple = baseObjTy->getAs<TupleType>()) {
- StringRef nameStr = memberName.getBaseIdentifier().str();
- int fieldIdx = -1;
- // Resolve a number reference into the tuple type.
- unsigned Value = 0;
- if (!nameStr.getAsInteger(10, Value) && Value < tuple->getNumElements()) {
- fieldIdx = Value;
- } else {
- fieldIdx = tuple->getNamedElementId(memberName.getBaseIdentifier());
- }
+ auto baseName = memberName.getBaseName();
- if (fieldIdx != -1)
- return false; // Lookup is valid.
+ if (!baseName.isSpecial()) {
+ StringRef nameStr = baseName.userFacingName();
+
+ int fieldIdx = -1;
+ // Resolve a number reference into the tuple type.
+ unsigned Value = 0;
+ if (!nameStr.getAsInteger(10, Value) && Value < tuple->getNumElements()) {
+ fieldIdx = Value;
+ } else {
+ fieldIdx = tuple->getNamedElementId(memberName.getBaseIdentifier());
+ }
+
+ if (fieldIdx != -1)
+ return false; // Lookup is valid.
+ }
diagnose(BaseLoc, diag::could_not_find_tuple_member, baseObjTy, memberName)
.highlight(memberRange);
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index a9c8a0c..339018b 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -978,7 +978,8 @@
/// \brief Add constraints for a reference to a named member of the given
/// base type, and return the type of such a reference.
Type addMemberRefConstraints(Expr *expr, Expr *base, DeclName name,
- FunctionRefKind functionRefKind) {
+ FunctionRefKind functionRefKind,
+ ArrayRef<ValueDecl *> outerAlternatives) {
// The base must have a member of the given name, such that accessing
// that member through the base returns a value convertible to the type
// of this expression.
@@ -986,8 +987,13 @@
auto tv = CS.createTypeVariable(
CS.getConstraintLocator(expr, ConstraintLocator::Member),
TVO_CanBindToLValue);
- CS.addValueMemberConstraint(baseTy, name, tv, CurDC, functionRefKind,
- CS.getConstraintLocator(expr, ConstraintLocator::Member));
+ SmallVector<OverloadChoice, 4> outerChoices;
+ for (auto decl : outerAlternatives) {
+ outerChoices.push_back(OverloadChoice(Type(), decl, functionRefKind));
+ }
+ CS.addValueMemberConstraint(
+ baseTy, name, tv, CurDC, functionRefKind, outerChoices,
+ CS.getConstraintLocator(expr, ConstraintLocator::Member));
return tv;
}
@@ -1116,6 +1122,7 @@
} else {
CS.addValueMemberConstraint(baseTy, DeclBaseName::createSubscript(),
fnTy, CurDC, FunctionRefKind::DoubleApply,
+ /*outerAlternatives=*/{},
memberLocator);
}
@@ -1496,9 +1503,12 @@
TVO_PrefersSubtypeBinding);
auto resultTy = CS.createTypeVariable(CS.getConstraintLocator(expr));
auto methodTy = FunctionType::get(argsTy, resultTy);
- CS.addValueMemberConstraint(baseTy, expr->getName(),
- methodTy, CurDC, expr->getFunctionRefKind(),
- CS.getConstraintLocator(expr, ConstraintLocator::ConstructorMember));
+ CS.addValueMemberConstraint(
+ baseTy, expr->getName(), methodTy, CurDC,
+ expr->getFunctionRefKind(),
+ /*outerAlternatives=*/{},
+ CS.getConstraintLocator(expr,
+ ConstraintLocator::ConstructorMember));
// The result of the expression is the partial application of the
// constructor to the subexpression.
@@ -1506,7 +1516,8 @@
}
return addMemberRefConstraints(expr, expr->getBase(), expr->getName(),
- expr->getFunctionRefKind());
+ expr->getFunctionRefKind(),
+ expr->getOuterAlternatives());
}
Type visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) {
@@ -1911,7 +1922,8 @@
Identifier name
= context.getIdentifier(llvm::utostr(expr->getFieldNumber()));
return addMemberRefConstraints(expr, expr->getBase(), name,
- FunctionRefKind::Unapplied);
+ FunctionRefKind::Unapplied,
+ /*outerAlternatives=*/{});
}
/// Give each parameter in a ClosureExpr a fresh type variable if parameter
@@ -2862,6 +2874,7 @@
memberTy,
CurDC,
refKind,
+ /*outerAlternatives=*/{},
memberLocator);
base = memberTy;
break;
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 1693c50..0a06bcfd 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -2555,6 +2555,7 @@
DeclBaseName::createConstructor(),
FunctionType::get(tv, resultType),
useDC, functionRefKind,
+ /*outerAlternatives=*/{},
getConstraintLocator(
fnLocator,
ConstraintLocator::ConstructorMember));
@@ -3443,14 +3444,11 @@
return result;
}
-ConstraintSystem::SolutionKind
-ConstraintSystem::simplifyMemberConstraint(ConstraintKind kind,
- Type baseTy, DeclName member,
- Type memberTy,
- DeclContext *useDC,
- FunctionRefKind functionRefKind,
- TypeMatchOptions flags,
- ConstraintLocatorBuilder locatorB) {
+ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
+ ConstraintKind kind, Type baseTy, DeclName member, Type memberTy,
+ DeclContext *useDC, FunctionRefKind functionRefKind,
+ ArrayRef<OverloadChoice> outerAlternatives, TypeMatchOptions flags,
+ ConstraintLocatorBuilder locatorB) {
// Resolve the base type, if we can. If we can't resolve the base type,
// then we can't solve this constraint.
// FIXME: simplifyType() call here could be getFixedTypeRecursive?
@@ -3467,8 +3465,8 @@
// If requested, generate a constraint.
if (flags.contains(TMF_GenerateConstraints)) {
addUnsolvedConstraint(
- Constraint::createMember(*this, kind, baseTy, memberTy, member, useDC,
- functionRefKind, locator));
+ Constraint::createMemberOrOuterDisjunction(*this, kind, baseTy, memberTy, member, useDC,
+ functionRefKind, outerAlternatives, locator));
return SolutionKind::Solved;
}
@@ -3485,8 +3483,8 @@
// If we found viable candidates, then we're done!
if (!result.ViableCandidates.empty()) {
addOverloadSet(memberTy, result.ViableCandidates, useDC, locator,
- result.getFavoredChoice());
-
+ result.getFavoredChoice(), outerAlternatives);
+
return SolutionKind::Solved;
}
@@ -3522,7 +3520,8 @@
// Look through one level of optional.
addValueMemberConstraint(baseObjTy->getOptionalObjectType(),
- member, memberTy, useDC, functionRefKind, locator);
+ member, memberTy, useDC, functionRefKind,
+ outerAlternatives, locator);
return SolutionKind::Solved;
}
return SolutionKind::Error;
@@ -5202,6 +5201,7 @@
constraint.getSecondType(),
constraint.getMemberUseDC(),
constraint.getFunctionRefKind(),
+ /*outerAlternatives=*/{},
TMF_GenerateConstraints,
constraint.getLocator());
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index adfdfd3..68a7545 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -642,6 +642,25 @@
locator, typeVars);
}
+Constraint *Constraint::createMemberOrOuterDisjunction(
+ ConstraintSystem &cs, ConstraintKind kind, Type first, Type second,
+ DeclName member, DeclContext *useDC, FunctionRefKind functionRefKind,
+ ArrayRef<OverloadChoice> outerAlternatives, ConstraintLocator *locator) {
+ auto memberConstraint = createMember(cs, kind, first, second, member,
+ useDC, functionRefKind, locator);
+
+ if (outerAlternatives.empty())
+ return memberConstraint;
+
+ SmallVector<Constraint *, 4> constraints;
+ constraints.push_back(memberConstraint);
+ memberConstraint->setFavored();
+ for (auto choice : outerAlternatives) {
+ constraints.push_back(
+ Constraint::createBindOverload(cs, first, choice, useDC, locator));
+ }
+ return Constraint::createDisjunction(cs, constraints, locator, ForgetChoice);
+}
Constraint *Constraint::createMember(ConstraintSystem &cs, ConstraintKind kind,
Type first, Type second, DeclName member,
diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h
index 29f8269..ca09d09 100644
--- a/lib/Sema/Constraint.h
+++ b/lib/Sema/Constraint.h
@@ -435,6 +435,13 @@
Type First, Type Second, Type Third,
ConstraintLocator *locator);
+ /// Create a new member constraint, or a disjunction of that with the outer
+ /// alternatives.
+ static Constraint *createMemberOrOuterDisjunction(
+ ConstraintSystem &cs, ConstraintKind kind, Type first, Type second,
+ DeclName member, DeclContext *useDC, FunctionRefKind functionRefKind,
+ ArrayRef<OverloadChoice> outerAlternatives, ConstraintLocator *locator);
+
/// Create a new member constraint.
static Constraint *createMember(ConstraintSystem &cs, ConstraintKind kind,
Type first, Type second, DeclName member,
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 8e9a29b..efee4f3 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -295,12 +295,13 @@
// If there's anything to remove, filter it out now.
if (anyRemovals) {
- result->filter([&](LookupResultEntry entry) -> bool {
+ result->filter([&](LookupResultEntry entry, bool isOuter) -> bool {
auto *decl = entry.getValueDecl();
// Remove invalid declarations so the constraint solver doesn't need to
// cope with them.
- if (decl->isInvalid()) return false;
+ if (decl->isInvalid())
+ return false;
return known[getDynamicResultSignature(decl)] == decl;
});
@@ -1471,11 +1472,12 @@
ArrayRef<OverloadChoice> choices,
DeclContext *useDC,
ConstraintLocator *locator,
- OverloadChoice *favoredChoice) {
+ OverloadChoice *favoredChoice,
+ ArrayRef<OverloadChoice> outerAlternatives) {
assert(!choices.empty() && "Empty overload set");
// If there is a single choice, add the bind overload directly.
- if (choices.size() == 1) {
+ if (choices.size() == 1 && outerAlternatives.empty()) {
addBindOverloadConstraint(boundType, choices.front(), locator, useDC);
return;
}
@@ -1511,7 +1513,26 @@
useDC, locator));
}
- addDisjunctionConstraint(overloads, locator, ForgetChoice, favoredChoice);
+ auto innerDisjunction = Constraint::createDisjunction(*this, overloads,
+ locator, ForgetChoice);
+ if (outerAlternatives.empty()) {
+ if (favoredChoice)
+ innerDisjunction->setFavored();
+
+ addUnsolvedConstraint(innerDisjunction);
+ return;
+ }
+
+ SmallVector<Constraint *, 4> outerConstraints;
+ outerConstraints.push_back(innerDisjunction);
+ innerDisjunction->setFavored();
+ for (auto choice : outerAlternatives) {
+ outerConstraints.push_back(Constraint::createBindOverload(
+ *this, boundType, choice,
+ useDC, locator));
+ }
+
+ addDisjunctionConstraint(outerConstraints, locator, ForgetChoice, favoredChoice);
}
/// If we're resolving an overload set with a decl that has special type
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 2d524d5..2e1b31b 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -1748,6 +1748,13 @@
/// emits an error message.
void diagnoseFailureForExpr(Expr *expr);
+ /// \brief Give the deprecation warning for referring to a global function
+ /// when there's a method from a conditional conformance in a smaller/closer
+ /// scope.
+ void
+ diagnoseDeprecatedConditionalConformanceOuterAccess(UnresolvedDotExpr *UDE,
+ ValueDecl *choice);
+
/// \brief Add a constraint to the constraint system.
void addConstraint(ConstraintKind kind, Type first, Type second,
ConstraintLocatorBuilder locator,
@@ -1784,14 +1791,15 @@
void addValueMemberConstraint(Type baseTy, DeclName name, Type memberTy,
DeclContext *useDC,
FunctionRefKind functionRefKind,
+ ArrayRef<OverloadChoice> outerAlternatives,
ConstraintLocatorBuilder locator) {
assert(baseTy);
assert(memberTy);
assert(name);
assert(useDC);
- switch (simplifyMemberConstraint(ConstraintKind::ValueMember, baseTy, name,
- memberTy, useDC, functionRefKind,
- TMF_GenerateConstraints, locator)) {
+ switch (simplifyMemberConstraint(
+ ConstraintKind::ValueMember, baseTy, name, memberTy, useDC,
+ functionRefKind, outerAlternatives, TMF_GenerateConstraints, locator)) {
case SolutionKind::Unsolved:
llvm_unreachable("Unsolved result when generating constraints!");
@@ -1800,10 +1808,9 @@
case SolutionKind::Error:
if (shouldAddNewFailingConstraint()) {
- addNewFailingConstraint(
- Constraint::createMember(*this, ConstraintKind::ValueMember, baseTy,
- memberTy, name, useDC, functionRefKind,
- getConstraintLocator(locator)));
+ addNewFailingConstraint(Constraint::createMemberOrOuterDisjunction(
+ *this, ConstraintKind::ValueMember, baseTy, memberTy, name, useDC,
+ functionRefKind, outerAlternatives, getConstraintLocator(locator)));
}
break;
}
@@ -1822,6 +1829,7 @@
switch (simplifyMemberConstraint(ConstraintKind::UnresolvedValueMember,
baseTy, name, memberTy,
useDC, functionRefKind,
+ /*outerAlternatives=*/{},
TMF_GenerateConstraints, locator)) {
case SolutionKind::Unsolved:
llvm_unreachable("Unsolved result when generating constraints!");
@@ -2190,7 +2198,8 @@
/// sets.
void addOverloadSet(Type boundType, ArrayRef<OverloadChoice> choices,
DeclContext *useDC, ConstraintLocator *locator,
- OverloadChoice *favored = nullptr);
+ OverloadChoice *favored = nullptr,
+ ArrayRef<OverloadChoice> outerAlternatives = {});
/// \brief Retrieve the allocator used by this constraint system.
llvm::BumpPtrAllocator &getAllocator() { return Allocator; }
@@ -2561,14 +2570,12 @@
ConstraintLocatorBuilder locator);
/// \brief Attempt to simplify the given member constraint.
- SolutionKind simplifyMemberConstraint(ConstraintKind kind,
- Type baseType, DeclName member,
- Type memberType, DeclContext *useDC,
- FunctionRefKind functionRefKind,
- TypeMatchOptions flags,
- ConstraintLocatorBuilder locator);
+ SolutionKind simplifyMemberConstraint(
+ ConstraintKind kind, Type baseType, DeclName member, Type memberType,
+ DeclContext *useDC, FunctionRefKind functionRefKind,
+ ArrayRef<OverloadChoice> outerAlternatives, TypeMatchOptions flags,
+ ConstraintLocatorBuilder locator);
-
/// \brief Attempt to simplify the optional object constraint.
SolutionKind simplifyOptionalObjectConstraint(
Type first, Type second,
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index 55b329b..ac77bbc 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -750,13 +750,14 @@
TypeLoc::withoutLoc(returnType),
target);
encodeDecl->setImplicit();
+ encodeDecl->setSynthesized();
encodeDecl->setBodySynthesizer(deriveBodyEncodable_encode);
// This method should be marked as 'override' for classes inheriting Encodable
// conformance from a parent class.
auto *classDecl = dyn_cast<ClassDecl>(target);
if (classDecl && superclassIsEncodable(classDecl)) {
- auto *attr = new (C) SimpleDeclAttr<DAK_Override>(/*IsImplicit=*/true);
+ auto *attr = new (C) OverrideAttr(/*IsImplicit=*/true);
encodeDecl->getAttrs().add(attr);
}
@@ -1084,11 +1085,12 @@
SourceLoc(), selfDecl, paramList,
/*GenericParams=*/nullptr, target);
initDecl->setImplicit();
+ initDecl->setSynthesized();
initDecl->setBodySynthesizer(deriveBodyDecodable_init);
// This constructor should be marked as `required` for non-final classes.
if (isa<ClassDecl>(target) && !target->getAttrs().hasAttribute<FinalAttr>()) {
- auto *reqAttr = new (C) SimpleDeclAttr<DAK_Required>(/*IsImplicit=*/true);
+ auto *reqAttr = new (C) RequiredAttr(/*IsImplicit=*/true);
initDecl->getAttrs().add(reqAttr);
}
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index dfdb730..4bc0d96 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -145,6 +145,17 @@
addGetterToReadOnlyDerivedProperty(tc, propDecl, rawType);
getterDecl->setBodySynthesizer(&deriveBodyRawRepresentable_raw);
+ // If the containing module is not resilient, make sure clients can get at
+ // the raw value without function call overhead.
+ if (parentDC->getParentModule()->getResilienceStrategy() !=
+ ResilienceStrategy::Resilient) {
+ AccessScope access =
+ enumDecl->getFormalAccessScope(nullptr,
+ /*treatUsableFromInlineAsPublic*/true);
+ if (access.isPublic())
+ getterDecl->getAttrs().add(new (C) InlinableAttr(/*implicit*/false));
+ }
+
auto dc = cast<IterableDeclContext>(parentDecl);
dc->addMember(getterDecl);
dc->addMember(propDecl);
@@ -343,6 +354,17 @@
initDecl->copyFormalAccessFrom(enumDecl, /*sourceIsParentContext*/true);
initDecl->setValidationStarted();
+ // If the containing module is not resilient, make sure clients can construct
+ // an instance without function call overhead.
+ if (parentDC->getParentModule()->getResilienceStrategy() !=
+ ResilienceStrategy::Resilient) {
+ AccessScope access =
+ enumDecl->getFormalAccessScope(nullptr,
+ /*treatUsableFromInlineAsPublic*/true);
+ if (access.isPublic())
+ initDecl->getAttrs().add(new (C) InlinableAttr(/*implicit*/false));
+ }
+
tc.Context.addSynthesizedDecl(initDecl);
cast<IterableDeclContext>(parentDecl)->addMember(initDecl);
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index a8bcf50..b13c12c 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -873,7 +873,8 @@
DeclContext *topLevelContext = DC->getModuleScopeContext();
UnqualifiedLookup lookup(VD->getBaseName(), topLevelContext, &TC,
- /*knownPrivate*/true);
+ /*Loc=*/SourceLoc(),
+ UnqualifiedLookup::Flags::KnownPrivate);
// Group results by module. Pick an arbitrary result from each module.
llvm::SmallDenseMap<const ModuleDecl*,const ValueDecl*,4> resultsByModule;
@@ -2128,8 +2129,7 @@
storageKind = SK_Property;
TC.diagnose(diagLoc, diag::unowned_assignment_immediate_deallocation,
- varDecl->getName(),
- (unsigned) ownershipAttr->get(), (unsigned) storageKind)
+ varDecl->getName(), ownershipAttr->get(), unsigned(storageKind))
.highlight(diagRange);
TC.diagnose(diagLoc, diag::unowned_assignment_requires_strong)
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index e651a99..43e4bc2 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -991,11 +991,11 @@
// If none of the ones we find are acceptable, then reject one.
auto oneCandidate = candidates.front();
- candidates.filter([&](LookupResultEntry entry)->bool {
+ candidates.filter([&](LookupResultEntry entry, bool isOuter) -> bool {
auto cand = cast<SubscriptDecl>(entry.getValueDecl());
return isAcceptableDynamicMemberLookupSubscript(cand, decl, TC);
});
-
+
if (candidates.empty()) {
TC.diagnose(oneCandidate.getValueDecl()->getLoc(),
diag::type_invalid_dml, type);
@@ -1984,7 +1984,10 @@
// On internal declarations, @inlinable implies @usableFromInline.
if (VD->getAttrs().hasAttribute<InlinableAttr>()) {
- diagnoseAndRemoveAttr(attr, diag::inlinable_implies_usable_from_inline);
+ if (attr->isImplicit())
+ attr->setInvalid();
+ else
+ diagnoseAndRemoveAttr(attr, diag::inlinable_implies_usable_from_inline);
return;
}
}
@@ -2143,7 +2146,9 @@
auto ownershipKind = attr->get();
// A weak variable must have type R? or R! for some ownership-capable type R.
- Type underlyingType = type;
+ auto underlyingType = type->getOptionalObjectType();
+ auto isOptional = bool(underlyingType);
+ auto allowOptional = false;
switch (ownershipKind) {
case ReferenceOwnership::Strong:
llvm_unreachable("Cannot specify 'strong' in an ownership attribute");
@@ -2151,24 +2156,35 @@
case ReferenceOwnership::Unmanaged:
break;
case ReferenceOwnership::Weak:
+ allowOptional = true;
if (var->isLet()) {
diagnose(var->getStartLoc(), diag::invalid_weak_let);
attr->setInvalid();
}
- if (Type objType = type->getOptionalObjectType()) {
- underlyingType = objType;
- } else {
- // @IBOutlet must be optional, but not necessarily weak. Let it diagnose.
- if (!var->getAttrs().hasAttribute<IBOutletAttr>()) {
- diagnose(var->getStartLoc(), diag::invalid_weak_ownership_not_optional,
- OptionalType::get(type));
- }
- attr->setInvalid();
+ if (isOptional)
+ break;
+
+ // @IBOutlet must be optional, but not necessarily weak. Let it diagnose.
+ if (!var->getAttrs().hasAttribute<IBOutletAttr>()) {
+ diagnose(var->getStartLoc(), diag::invalid_weak_ownership_not_optional,
+ OptionalType::get(type));
}
+ attr->setInvalid();
break;
}
+
+ if (!allowOptional && isOptional) {
+ diagnose(var->getStartLoc(), diag::invalid_ownership_with_optional,
+ ownershipKind)
+ .fixItReplace(attr->getRange(), "weak");
+ attr->setInvalid();
+ }
+
+ if (!underlyingType)
+ underlyingType = type;
+
if (!underlyingType->allowsOwnership()) {
auto D = diag::invalid_ownership_type;
@@ -2178,23 +2194,19 @@
D = diag::invalid_ownership_protocol_type;
}
- diagnose(var->getStartLoc(), D, (unsigned) ownershipKind, underlyingType);
+ diagnose(var->getStartLoc(), D, ownershipKind, underlyingType);
attr->setInvalid();
- } else if (isa<ProtocolDecl>(var->getDeclContext()) &&
- !cast<ProtocolDecl>(var->getDeclContext())->isObjC()) {
+ }
+
+ auto PDC = dyn_cast<ProtocolDecl>((var->getDeclContext()));
+ if (PDC && !PDC->isObjC()) {
// Ownership does not make sense in protocols, except for "weak" on
// properties of Objective-C protocols.
- if (Context.isSwiftVersionAtLeast(5))
- diagnose(attr->getLocation(),
- diag::ownership_invalid_in_protocols,
- (unsigned) ownershipKind)
- .fixItRemove(attr->getRange());
- else
- diagnose(attr->getLocation(),
- diag::ownership_invalid_in_protocols_compat_warning,
- (unsigned) ownershipKind)
- .fixItRemove(attr->getRange());
-
+ auto D = Context.isSwiftVersionAtLeast(5)
+ ? diag::ownership_invalid_in_protocols
+ : diag::ownership_invalid_in_protocols_compat_warning;
+ diagnose(attr->getLocation(), D, ownershipKind)
+ .fixItRemove(attr->getRange());
attr->setInvalid();
}
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 7b3ae4f..d43aedb 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -397,6 +397,56 @@
}
}
+static bool findNonMembers(TypeChecker &TC,
+ ArrayRef<LookupResultEntry> lookupResults,
+ DeclRefKind refKind, bool breakOnMember,
+ SmallVectorImpl<ValueDecl *> &ResultValues,
+ llvm::function_ref<bool(ValueDecl *)> isValid) {
+ bool AllDeclRefs = true;
+ for (auto Result : lookupResults) {
+ // If we find a member, then all of the results aren't non-members.
+ bool IsMember =
+ (Result.getBaseDecl() && !isa<ModuleDecl>(Result.getBaseDecl()));
+ if (IsMember) {
+ AllDeclRefs = false;
+ if (breakOnMember)
+ break;
+ continue;
+ }
+
+ ValueDecl *D = Result.getValueDecl();
+ if (!D->hasInterfaceType())
+ TC.validateDecl(D);
+
+ // FIXME: Circularity hack.
+ if (!D->hasInterfaceType()) {
+ AllDeclRefs = false;
+ continue;
+ }
+
+ if (!isValid(D))
+ return false;
+
+ if (matchesDeclRefKind(D, refKind))
+ ResultValues.push_back(D);
+ }
+
+ return AllDeclRefs;
+}
+
+/// Whether we should be looking at the outer results for a function called \c
+/// name.
+///
+/// This is very restrictive because it's a source compatibility issue (see the
+/// if (AllConditionalConformances) { (void)findNonMembers(...); } below).
+static bool shouldConsiderOuterResultsFor(DeclName name) {
+ const StringRef specialNames[] = {"min", "max"};
+ for (auto specialName : specialNames)
+ if (name.isSimpleName(specialName))
+ return true;
+
+ return false;
+}
/// Bind an UnresolvedDeclRefExpr by performing name lookup and
/// returning the resultant expression. Context is the DeclContext used
@@ -411,6 +461,9 @@
NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
if (isa<AbstractFunctionDecl>(DC))
lookupOptions |= NameLookupFlags::KnownPrivate;
+ if (shouldConsiderOuterResultsFor(Name))
+ lookupOptions |= NameLookupFlags::IncludeOuterResults;
+
auto Lookup = lookupUnqualified(DC, Name, Loc, lookupOptions);
if (!Lookup) {
@@ -526,40 +579,27 @@
UDRE->isImplicit());
}
- bool AllDeclRefs = true;
SmallVector<ValueDecl*, 4> ResultValues;
- for (auto Result : Lookup) {
- // If we find a member, then all of the results aren't non-members.
- bool IsMember = (Result.getBaseDecl() &&
- !isa<ModuleDecl>(Result.getBaseDecl()));
- if (IsMember) {
- AllDeclRefs = false;
- break;
- }
+ Expr *error = nullptr;
+ bool AllDeclRefs = findNonMembers(
+ *this, Lookup.innerResults(), UDRE->getRefKind(), /*breakOnMember=*/true,
+ ResultValues, [&](ValueDecl *D) {
+ // FIXME: The source-location checks won't make sense once
+ // EnableASTScopeLookup is the default.
+ if (Loc.isValid() && D->getLoc().isValid() &&
+ D->getDeclContext()->isLocalContext() &&
+ D->getDeclContext() == DC &&
+ Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc())) {
+ diagnose(Loc, diag::use_local_before_declaration, Name);
+ diagnose(D, diag::decl_declared_here, Name);
+ error = new (Context) ErrorExpr(UDRE->getSourceRange());
+ return false;
+ }
+ return true;
+ });
+ if (error)
+ return error;
- ValueDecl *D = Result.getValueDecl();
- if (!D->hasInterfaceType()) validateDecl(D);
-
- // FIXME: Circularity hack.
- if (!D->hasInterfaceType()) {
- AllDeclRefs = false;
- continue;
- }
-
- // FIXME: The source-location checks won't make sense once
- // EnableASTScopeLookup is the default.
- if (Loc.isValid() && D->getLoc().isValid() &&
- D->getDeclContext()->isLocalContext() &&
- D->getDeclContext() == DC &&
- Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc())) {
- diagnose(Loc, diag::use_local_before_declaration, Name);
- diagnose(D, diag::decl_declared_here, Name);
- return new (Context) ErrorExpr(UDRE->getSourceRange());
- }
- if (matchesDeclRefKind(D, UDRE->getRefKind()))
- ResultValues.push_back(D);
- }
-
if (AllDeclRefs) {
// Diagnose uses of operators that found no matching candidates.
if (ResultValues.empty()) {
@@ -599,20 +639,43 @@
ResultValues.clear();
bool AllMemberRefs = true;
+ bool AllConditionalConformances = true;
ValueDecl *Base = nullptr;
DeclContext *BaseDC = nullptr;
for (auto Result : Lookup) {
+ auto ThisBase = Result.getBaseDecl();
+
// Track the base for member declarations.
- if (Result.getBaseDecl() &&
- !isa<ModuleDecl>(Result.getBaseDecl())) {
- ResultValues.push_back(Result.getValueDecl());
- if (Base && Result.getBaseDecl() != Base) {
+ if (ThisBase && !isa<ModuleDecl>(ThisBase)) {
+ auto Value = Result.getValueDecl();
+ ResultValues.push_back(Value);
+ if (Base && ThisBase != Base) {
AllMemberRefs = false;
break;
}
- Base = Result.getBaseDecl();
+ Base = ThisBase;
BaseDC = Result.getDeclContext();
+
+ // Check if this result is derived through a conditional conformance,
+ // meaning it comes from a protocol (or extension) where there's a
+ // conditional conformance for the type with the method in question
+ // (NB. that type may not be the type associated with DC, for tested types
+ // with static methods).
+ if (auto Proto = Value->getDeclContext()
+ ->getAsProtocolOrProtocolExtensionContext()) {
+ auto contextSelfType =
+ BaseDC->getInnermostTypeContext()->getDeclaredInterfaceType();
+ auto conformance = conformsToProtocol(
+ contextSelfType, Proto, DC,
+ ConformanceCheckFlags::InExpression |
+ ConformanceCheckFlags::SkipConditionalRequirements);
+
+ if (!conformance || conformance->getConditionalRequirements().empty()) {
+ AllConditionalConformances = false;
+ }
+ }
+
continue;
}
@@ -633,13 +696,29 @@
BaseExpr = new (Context) DeclRefExpr(Base, UDRE->getNameLoc(),
/*Implicit=*/true);
}
-
-
+
+ // We *might* include any non-members that we found in outer contexts in
+ // some special cases, for backwards compatibility: first, we have to be
+ // looking for one of the special names
+ // ('shouldConsiderOuterResultsFor(Name)'), and second, all of the inner
+ // results need to come from conditional conformances. The second condition
+ // is how the problem here was encountered: a type ('Range') was made to
+ // conditionally conform to a new protocol ('Sequence'), which introduced
+ // some extra methods ('min' and 'max') that shadowed global functions that
+ // people regularly called within extensions to that type (usually adding
+ // 'clamp').
+ llvm::SmallVector<ValueDecl *, 4> outerAlternatives;
+ if (AllConditionalConformances) {
+ (void)findNonMembers(*this, Lookup.outerResults(), UDRE->getRefKind(),
+ /*breakOnMember=*/false, outerAlternatives,
+ /*isValid=*/[&](ValueDecl *) { return true; });
+ }
+
// Otherwise, form an UnresolvedDotExpr and sema will resolve it based on
// type information.
- return new (Context) UnresolvedDotExpr(BaseExpr, SourceLoc(), Name,
- UDRE->getNameLoc(),
- UDRE->isImplicit());
+ return new (Context) UnresolvedDotExpr(
+ BaseExpr, SourceLoc(), Name, UDRE->getNameLoc(), UDRE->isImplicit(),
+ Context.AllocateCopy(outerAlternatives));
}
// FIXME: If we reach this point, the program we're being handed is likely
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 3d3aae9..12771d5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1213,6 +1213,7 @@
void swift::makeFinal(ASTContext &ctx, ValueDecl *D) {
if (D && !D->isFinal()) {
+ assert(isa<ClassDecl>(D) || D->isPotentiallyOverridable());
D->getAttrs().add(new (ctx) FinalAttr(/*IsImplicit=*/true));
}
}
@@ -1223,6 +1224,57 @@
}
}
+namespace {
+// The raw values of this enum must be kept in sync with
+// diag::implicitly_final_cannot_be_open.
+enum class ImplicitlyFinalReason : unsigned {
+ /// A property was declared with 'let'.
+ Let,
+ /// The containing class is final.
+ FinalClass,
+ /// A member was declared as 'static'.
+ Static
+};
+}
+
+static void inferFinalAndDiagnoseIfNeeded(TypeChecker &TC, ValueDecl *D,
+ StaticSpellingKind staticSpelling) {
+ auto cls = D->getDeclContext()->getAsClassOrClassExtensionContext();
+ if (!cls)
+ return;
+
+ // Are there any reasons to infer 'final'? Prefer 'static' over the class
+ // being final for the purposes of diagnostics.
+ Optional<ImplicitlyFinalReason> reason;
+ if (staticSpelling == StaticSpellingKind::KeywordStatic) {
+ reason = ImplicitlyFinalReason::Static;
+
+ if (auto finalAttr = D->getAttrs().getAttribute<FinalAttr>()) {
+ auto finalRange = finalAttr->getRange();
+ if (finalRange.isValid()) {
+ TC.diagnose(finalRange.Start, diag::static_decl_already_final)
+ .fixItRemove(finalRange);
+ }
+ }
+ } else if (cls->isFinal()) {
+ reason = ImplicitlyFinalReason::FinalClass;
+ }
+
+ if (!reason)
+ return;
+
+ if (D->getFormalAccess() == AccessLevel::Open) {
+ auto diagID = diag::implicitly_final_cannot_be_open;
+ if (!TC.Context.isSwiftVersionAtLeast(5))
+ diagID = diag::implicitly_final_cannot_be_open_swift4;
+ auto inFlightDiag = TC.diagnose(D, diagID,
+ static_cast<unsigned>(reason.getValue()));
+ fixItAccess(inFlightDiag, D, AccessLevel::Public);
+ }
+
+ makeFinal(TC.Context, D);
+}
+
/// Configure the implicit 'self' parameter of a function, setting its type,
/// pattern, etc.
///
@@ -1498,14 +1550,26 @@
// decl. A setter attribute can also override this.
AbstractStorageDecl *storage = accessor->getStorage();
if (storage->hasAccess()) {
- if (accessor->getAccessorKind() == AccessorKind::IsSetter ||
- accessor->getAccessorKind() == AccessorKind::IsMutableAddressor ||
- accessor->getAccessorKind() == AccessorKind::IsMaterializeForSet)
- accessor->setAccess(storage->getSetterFormalAccess());
- else
+ switch (accessor->getAccessorKind()) {
+ case AccessorKind::IsGetter:
+ case AccessorKind::IsAddressor:
accessor->setAccess(storage->getFormalAccess());
+ break;
+ case AccessorKind::IsSetter:
+ case AccessorKind::IsMutableAddressor:
+ case AccessorKind::IsMaterializeForSet:
+ accessor->setAccess(storage->getSetterFormalAccess());
+ break;
+ case AccessorKind::IsWillSet:
+ case AccessorKind::IsDidSet:
+ // These are only needed to synthesize the setter.
+ accessor->setAccess(AccessLevel::Private);
+ break;
+ }
} else {
computeAccessLevel(storage);
+ assert(accessor->hasAccess() &&
+ "if the accessor isn't just the getter/setter this isn't enough");
}
}
@@ -2571,36 +2635,14 @@
if (D->isFinal() && !isNSManaged)
return;
- // Variables declared with 'let' cannot be 'dynamic'.
- if (auto VD = dyn_cast<VarDecl>(D)) {
- auto staticSpelling = VD->getParentPatternBinding()->getStaticSpelling();
-
- // The presence of 'static' blocks the inference of 'dynamic'.
- if (staticSpelling == StaticSpellingKind::KeywordStatic)
- return;
-
- if (VD->isLet() && !isNSManaged)
- return;
- }
-
// Accessors should not infer 'dynamic' on their own; they can get it from
// their storage decls.
- if (auto FD = dyn_cast<FuncDecl>(D)) {
- if (isa<AccessorDecl>(FD))
- return;
+ if (isa<AccessorDecl>(D))
+ return;
- auto staticSpelling = FD->getStaticSpelling();
-
- // The presence of 'static' bocks the inference of 'dynamic'.
- if (staticSpelling == StaticSpellingKind::KeywordStatic)
- return;
- }
-
- // The presence of 'final' on a class prevents 'dynamic'.
+ // Only classes can use 'dynamic'.
auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
- if (!classDecl) return;
- if (!isNSManaged && classDecl->isFinal() &&
- !classDecl->requiresStoredPropertyInits())
+ if (!classDecl)
return;
// Add the 'dynamic' attribute.
@@ -4331,6 +4373,7 @@
TC.validateDecl(ED);
TC.DeclsToFinalize.remove(ED);
+ ED->setHasValidatedLayout();
{
// Check for circular inheritance of the raw type.
@@ -4364,6 +4407,7 @@
TC.validateDecl(SD);
TC.DeclsToFinalize.remove(SD);
+ SD->setHasValidatedLayout();
TC.addImplicitConstructors(SD);
@@ -4489,6 +4533,7 @@
TC.validateDecl(CD);
TC.requestSuperclassLayout(CD);
TC.DeclsToFinalize.remove(CD);
+ CD->setHasValidatedLayout();
{
// Check for circular inheritance.
@@ -5289,6 +5334,7 @@
// Check whether the types are identical.
auto parentDeclTy = owningTy->adjustSuperclassMemberDeclType(
parentDecl, decl, parentDecl->getInterfaceType());
+ if (parentDeclTy->hasError()) continue;
parentDeclTy = parentDeclTy->getUnlabeledType(TC.Context);
if (method) {
// For methods, strip off the 'Self' type.
@@ -5442,8 +5488,7 @@
parentOwnership = ReferenceOwnership::Strong;
if (parentOwnership != ownershipAttr->get()) {
TC.diagnose(decl, diag::override_ownership_mismatch,
- (unsigned)parentOwnership,
- (unsigned)ownershipAttr->get());
+ parentOwnership, ownershipAttr->get());
TC.diagnose(matchDecl, diag::overridden_here);
}
}
@@ -6869,7 +6914,7 @@
}
if (!isa<ClassDecl>(nominal))
- DeclsToFinalize.insert(nominal);
+ requestNominalLayout(nominal);
break;
}
@@ -7043,33 +7088,28 @@
}
}
- // Infer 'dynamic' before touching accessors.
- inferDynamic(Context, VD);
-
// If this variable is a class member, mark it final if the
// class is final, or if it was declared with 'let'.
- if (auto cls = dyn_cast<ClassDecl>(nominalDecl)) {
- if (cls->isFinal() || VD->isLet()) {
- if (!VD->isFinal()) {
- makeFinal(Context, VD);
- }
- }
- if (VD->isStatic()) {
- auto staticSpelling =
- VD->getParentPatternBinding()->getStaticSpelling();
- if (staticSpelling == StaticSpellingKind::KeywordStatic) {
- auto finalAttr = VD->getAttrs().getAttribute<FinalAttr>();
- if (finalAttr) {
- auto finalRange = finalAttr->getRange();
- if (finalRange.isValid())
- diagnose(finalRange.Start, diag::decl_already_final)
- .highlight(finalRange)
- .fixItRemove(finalRange);
- }
- makeFinal(Context, VD);
- }
+ auto staticSpelling =
+ VD->getParentPatternBinding()->getStaticSpelling();
+ inferFinalAndDiagnoseIfNeeded(*this, VD, staticSpelling);
+
+ if (VD->isLet() && isa<ClassDecl>(nominalDecl)) {
+ makeFinal(Context, VD);
+
+ if (VD->getFormalAccess() == AccessLevel::Open) {
+ auto diagID = diag::implicitly_final_cannot_be_open;
+ if (!Context.isSwiftVersionAtLeast(5))
+ diagID = diag::implicitly_final_cannot_be_open_swift4;
+ auto inFlightDiag =
+ diagnose(D, diagID,
+ static_cast<unsigned>(ImplicitlyFinalReason::Let));
+ fixItAccess(inFlightDiag, D, AccessLevel::Public);
}
}
+
+ // Infer 'dynamic' after 'final' but before touching accessors.
+ inferDynamic(Context, VD);
}
// Perform accessor-related validation.
@@ -7367,6 +7407,9 @@
errorConvention)))
isObjC = None;
markAsObjC(*this, FD, isObjC, errorConvention);
+
+ inferFinalAndDiagnoseIfNeeded(*this, FD, FD->getStaticSpelling());
+ inferDynamic(Context, FD);
}
// If the function is exported to C, it must be representable in (Obj-)C.
@@ -7381,28 +7424,6 @@
}
}
- inferDynamic(Context, FD);
-
- // If this is a class member, mark it final if the class is final.
- if (auto cls = FD->getDeclContext()->getAsClassOrClassExtensionContext()) {
- if (cls->isFinal() && !FD->isFinal()) {
- makeFinal(Context, FD);
- }
- // static func declarations in classes are synonyms
- // for `class final func` declarations.
- if (FD->getStaticSpelling() == StaticSpellingKind::KeywordStatic) {
- auto finalAttr = FD->getAttrs().getAttribute<FinalAttr>();
- if (finalAttr) {
- auto finalRange = finalAttr->getRange();
- if (finalRange.isValid())
- diagnose(finalRange.Start, diag::decl_already_final)
- .highlight(finalRange)
- .fixItRemove(finalRange);
- }
- makeFinal(Context, FD);
- }
- }
-
checkDeclAttributes(FD);
break;
@@ -7715,13 +7736,9 @@
}
// Member subscripts need some special validation logic.
- if (auto nominalDecl = dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
+ if (dc->isTypeContext()) {
// If this is a class member, mark it final if the class is final.
- if (auto cls = dyn_cast<ClassDecl>(nominalDecl)) {
- if (cls->isFinal() && !SD->isFinal()) {
- makeFinal(Context, SD);
- }
- }
+ inferFinalAndDiagnoseIfNeeded(*this, SD, StaticSpellingKind::None);
// A subscript is ObjC-compatible if it's explicitly @objc, or a
// member of an ObjC-compatible class or protocol.
@@ -7975,11 +7992,6 @@
assert(!nominal->hasClangNode());
assert(isa<SourceFile>(nominal->getModuleScopeContext()));
- Optional<bool> lazyVarsAlreadyHaveImplementation;
-
- if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
- TC.requestSuperclassLayout(classDecl);
-
for (auto *D : nominal->getMembers()) {
auto VD = dyn_cast<ValueDecl>(D);
if (!VD)
@@ -7991,40 +8003,44 @@
TC.validateDecl(VD);
// The only thing left to do is synthesize storage for lazy variables.
- // We only have to do that if it's a type from another file, though.
- // In NDEBUG builds, bail out as soon as we can.
-#ifdef NDEBUG
- if (lazyVarsAlreadyHaveImplementation.hasValue() &&
- lazyVarsAlreadyHaveImplementation.getValue())
- continue;
-#endif
auto *prop = dyn_cast<VarDecl>(D);
if (!prop)
continue;
if (prop->getAttrs().hasAttribute<LazyAttr>() && !prop->isStatic()
&& prop->getGetter()) {
- bool hasImplementation = prop->getGetter()->hasBody();
-
- if (lazyVarsAlreadyHaveImplementation.hasValue()) {
- assert(lazyVarsAlreadyHaveImplementation.getValue() ==
- hasImplementation &&
- "only some lazy vars already have implementations");
- } else {
- lazyVarsAlreadyHaveImplementation = hasImplementation;
- }
-
- if (!hasImplementation)
- TC.completeLazyVarImplementation(prop);
+ assert(!prop->getGetter()->hasBody());
+ TC.completeLazyVarImplementation(prop);
}
}
- // FIXME: We need to add implicit initializers and dtors when a decl is
- // touched, because it affects vtable layout. If you're not defining the
- // class, you shouldn't have to know what the vtable layout is.
if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
+ // We need to add implicit initializers and dtors because it
+ // affects vtable layout.
TC.addImplicitConstructors(CD);
CD->addImplicitDestructor();
+
+ // We need the superclass vtable layout as well.
+ TC.requestSuperclassLayout(CD);
+
+ auto useConformance = [&](ProtocolDecl *protocol) {
+ if (auto ref = TC.conformsToProtocol(
+ CD->getDeclaredInterfaceType(), protocol, CD,
+ ConformanceCheckFlags::SkipConditionalRequirements,
+ SourceLoc())) {
+ if (ref->getConcrete()->getDeclContext() == CD)
+ TC.markConformanceUsed(*ref, CD);
+ }
+ };
+
+ // If the class is Encodable or Decodable, force those
+ // conformances to ensure that the init(from:) and
+ // encode(to:) members appear in the vtable.
+ //
+ // FIXME: Generalize this to other protocols for which
+ // we can derive conformances.
+ useConformance(TC.Context.getProtocol(KnownProtocolKind::Decodable));
+ useConformance(TC.Context.getProtocol(KnownProtocolKind::Encodable));
}
// validateDeclForNameLookup will not trigger an immediate full
@@ -8575,6 +8591,27 @@
}
}
+void TypeChecker::maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl) {
+ // Some heuristics to skip emitting a diagnostic if the class is already
+ // irreperably busted.
+ if (classDecl->isInvalid() ||
+ classDecl->inheritsSuperclassInitializers(nullptr))
+ return;
+
+ auto *superclassDecl = classDecl->getSuperclassDecl();
+ if (superclassDecl &&
+ superclassDecl->hasMissingDesignatedInitializers())
+ return;
+
+ for (auto member : classDecl->lookupDirect(DeclBaseName::createConstructor())) {
+ auto ctor = dyn_cast<ConstructorDecl>(member);
+ if (ctor && ctor->isDesignatedInit())
+ return;
+ }
+
+ diagnoseClassWithoutInitializers(*this, classDecl);
+}
+
/// Diagnose a missing required initializer.
static void diagnoseMissingRequiredInitializer(
TypeChecker &TC,
@@ -8697,16 +8734,13 @@
// Bail out if we're validating one of our constructors already; we'll
// revisit the issue later.
if (isa<ClassDecl>(decl)) {
- bool alreadyValidatingCtor = false;
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
validateDecl(ctor);
if (!ctor->hasValidSignature())
- alreadyValidatingCtor = true;
+ return;
}
}
- if (alreadyValidatingCtor)
- return;
}
decl->setAddedImplicitInitializers();
@@ -8716,37 +8750,8 @@
bool FoundMemberwiseInitializedProperty = false;
bool SuppressDefaultInitializer = false;
bool SuppressMemberwiseInitializer = false;
- bool FoundSynthesizedInit = false;
bool FoundDesignatedInit = false;
- // Before we look for constructors, we need to make sure that all synthesized
- // initializers are properly synthesized.
- //
- // NOTE: Lookups of synthesized initializers MUST come after
- // decl->setAddedImplicitInitializers() in case synthesis requires
- // protocol conformance checking, which might be recursive here.
- // FIXME: Disable this code and prevent _any_ implicit constructors from doing
- // this. Investigate why this hasn't worked otherwise.
- DeclName synthesizedInitializers[1] = {
- // init(from:) is synthesized by derived conformance to Decodable.
- DeclName(Context, DeclBaseName::createConstructor(), Context.Id_from)
- };
-
- auto initializerIsSynthesized = [=](ConstructorDecl *initializer) {
- if (!initializer->isImplicit())
- return false;
-
- for (auto &name : synthesizedInitializers)
- if (initializer->getFullName() == name)
- return true;
-
- return false;
- };
-
- for (auto &name : synthesizedInitializers) {
- synthesizeMemberForLookup(decl, name);
- }
-
SmallPtrSet<CanType, 4> initializerParamTypes;
llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;
if (decl->hasClangNode() && isa<ClassDecl>(decl)) {
@@ -8768,13 +8773,10 @@
} else {
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
- // Synthesized initializers others than the default initializer should
- // not prevent default initializer synthesis.
- if (initializerIsSynthesized(ctor)) {
- FoundSynthesizedInit = true;
- } else if (ctor->isDesignatedInit()) {
+ // Initializers that were synthesized to fulfill derived conformances
+ // should not prevent default initializer synthesis.
+ if (ctor->isDesignatedInit() && !ctor->isSynthesized())
FoundDesignatedInit = true;
- }
if (isa<StructDecl>(decl))
continue;
@@ -8846,8 +8848,10 @@
}
if (auto structDecl = dyn_cast<StructDecl>(decl)) {
- if (!FoundDesignatedInit && !SuppressMemberwiseInitializer
- && !structDecl->hasUnreferenceableStorage()) {
+ assert(!structDecl->hasUnreferenceableStorage() &&
+ "User-defined structs cannot have unreferenceable storage");
+
+ if (!FoundDesignatedInit && !SuppressMemberwiseInitializer) {
// For a struct with memberwise initialized properties, we add a
// memberwise init.
if (FoundMemberwiseInitializedProperty) {
@@ -8869,13 +8873,13 @@
// FIXME: Currently skipping generic classes.
auto classDecl = cast<ClassDecl>(decl);
if (classDecl->hasSuperclass()) {
- bool canInheritInitializers = !FoundDesignatedInit;
+ bool canInheritInitializers = (!SuppressDefaultInitializer &&
+ !FoundDesignatedInit);
// We can't define these overrides if we have any uninitialized
// stored properties.
- if (SuppressDefaultInitializer && !FoundDesignatedInit
- && !FoundSynthesizedInit && !classDecl->hasClangNode()) {
- diagnoseClassWithoutInitializers(*this, classDecl);
+ if (SuppressDefaultInitializer && !FoundDesignatedInit &&
+ !classDecl->hasClangNode()) {
return;
}
@@ -8976,12 +8980,8 @@
// constructor.
// ... unless there are uninitialized stored properties.
- if (SuppressDefaultInitializer) {
- if (!FoundSynthesizedInit)
- diagnoseClassWithoutInitializers(*this, classDecl);
-
+ if (SuppressDefaultInitializer)
return;
- }
defineDefaultConstructor(decl);
}
@@ -8992,14 +8992,9 @@
auto baseName = member.getBaseName();
// Checks whether the target conforms to the given protocol. If the
- // conformance is incomplete, check the conformance to force synthesis, if
- // possible.
+ // conformance is incomplete, force the conformance.
//
- // Swallows diagnostics if conformance checking is already in progress (so we
- // don't display diagnostics twice).
- //
- // Returns whether the target conforms to the protocol and the conformance is
- // complete.
+ // Returns whether the target conforms to the protocol.
auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
auto targetType = target->getDeclaredInterfaceType();
if (auto ref = conformsToProtocol(
@@ -9008,26 +9003,12 @@
ConformanceCheckFlags::SkipConditionalRequirements),
SourceLoc())) {
if (auto *conformance = ref->getConcrete()->getRootNormalConformance()) {
- if (conformance->isIncomplete()) {
- // Check conformance, forcing synthesis.
- //
- // If synthesizing conformance fails, this will produce diagnostics.
- // If conformance checking was already in progress elsewhere, though,
- // this could produce diagnostics twice.
- //
- // To prevent this duplication, we swallow the diagnostics if the
- // state of the conformance is not Incomplete.
- DiagnosticTransaction transaction(Context.Diags);
- auto shouldSwallowDiagnostics =
- conformance->getState() != ProtocolConformanceState::Incomplete;
-
+ if (conformance->getState() == ProtocolConformanceState::Incomplete) {
checkConformance(conformance);
- if (shouldSwallowDiagnostics)
- transaction.abort();
-
- return conformance->isComplete();
}
}
+
+ return true;
}
return false;
@@ -9049,13 +9030,6 @@
auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
if (!evaluateTargetConformanceTo(decodableProto))
(void)evaluateTargetConformanceTo(encodableProto);
- } else if (baseName.getIdentifier() == Context.Id_allCases ||
- baseName.getIdentifier() == Context.Id_AllCases) {
- // If the target should conform to the CaseIterable protocol, check the
- // conformance here to attempt synthesis.
- auto *caseIterableProto
- = Context.getProtocol(KnownProtocolKind::CaseIterable);
- (void)evaluateTargetConformanceTo(caseIterableProto);
}
} else {
auto argumentNames = member.getArgumentNames();
@@ -9084,32 +9058,6 @@
}
}
-void TypeChecker::addImplicitStructConformances(StructDecl *SD) {
- // Type-check the protocol conformances of the struct decl to instantiate its
- // derived conformances.
- checkConformancesInContext(SD, SD);
-}
-
-void TypeChecker::addImplicitEnumConformances(EnumDecl *ED) {
- // Type-check the raw values of the enum.
- for (auto elt : ED->getAllElements()) {
- assert(elt->hasRawValueExpr());
- if (elt->getTypeCheckedRawValueExpr()) continue;
- Expr *typeChecked = elt->getRawValueExpr();
- Type rawTy = ED->mapTypeIntoContext(ED->getRawType());
- auto resultTy = typeCheckExpression(
- typeChecked, ED, TypeLoc::withoutLoc(rawTy), CTP_EnumCaseRawValue);
- assert(resultTy);
- (void)resultTy;
- elt->setTypeCheckedRawValueExpr(typeChecked);
- checkEnumElementErrorHandling(elt);
- }
-
- // Type-check the protocol conformances of the enum decl to instantiate its
- // derived conformances.
- checkConformancesInContext(ED, ED);
-}
-
void TypeChecker::defineDefaultConstructor(NominalTypeDecl *decl) {
PrettyStackTraceDecl stackTrace("defining default constructor for",
decl);
diff --git a/lib/Sema/TypeCheckExprObjC.cpp b/lib/Sema/TypeCheckExprObjC.cpp
index db91929..cb7f3c8 100644
--- a/lib/Sema/TypeCheckExprObjC.cpp
+++ b/lib/Sema/TypeCheckExprObjC.cpp
@@ -277,7 +277,7 @@
// If we have more than one result, filter out unavailable or
// obviously unusable candidates.
if (lookup.size() > 1) {
- lookup.filter([&](LookupResultEntry result) -> bool {
+ lookup.filter([&](LookupResultEntry result, bool isOuter) -> bool {
// Drop unavailable candidates.
if (result.getValueDecl()->getAttrs().isUnavailable(Context))
return false;
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index a084f88..f680463 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -26,10 +26,23 @@
using namespace swift;
-void LookupResult::filter(const std::function<bool(LookupResultEntry)> &pred) {
+void LookupResult::filter(
+ const std::function<bool(LookupResultEntry, bool)> &pred) {
+ size_t index = 0;
+ size_t originalFirstOuter = IndexOfFirstOuterResult;
Results.erase(std::remove_if(Results.begin(), Results.end(),
[&](LookupResultEntry result) -> bool {
- return !pred(result);
+ auto isInner = index < originalFirstOuter;
+ index++;
+ if (pred(result, !isInner))
+ return false;
+
+ // Need to remove this, which means, if it is
+ // an inner result, the outer results need to
+ // shift down.
+ if (isInner)
+ IndexOfFirstOuterResult--;
+ return true;
}),
Results.end());
}
@@ -46,6 +59,8 @@
/// The vector of found declarations.
SmallVector<ValueDecl *, 4> FoundDecls;
+ /// The vector of found declarations.
+ SmallVector<ValueDecl *, 4> FoundOuterDecls;
/// The set of known declarations.
llvm::SmallDenseMap<std::pair<ValueDecl *, DeclContext *>, bool, 4> Known;
@@ -76,25 +91,35 @@
// Remove any overridden declarations from the found-declarations set.
removeOverriddenDecls(FoundDecls);
+ removeOverriddenDecls(FoundOuterDecls);
// Remove any shadowed declarations from the found-declarations set.
removeShadowedDecls(FoundDecls, DC->getParentModule(), &TC);
+ removeShadowedDecls(FoundOuterDecls, DC->getParentModule(), &TC);
// Filter out those results that have been removed from the
// found-declarations set.
- unsigned foundIdx = 0, foundSize = FoundDecls.size();
- Result.filter([&](LookupResultEntry result) -> bool {
- // If the current result matches the remaining found declaration,
- // keep it and move to the next found declaration.
- if (foundIdx < foundSize &&
- result.getValueDecl() == FoundDecls[foundIdx]) {
- ++foundIdx;
- return true;
- }
+ unsigned foundIdx = 0, foundSize = FoundDecls.size(),
+ foundOuterSize = FoundOuterDecls.size();
+ Result.filter([&](LookupResultEntry result, bool isOuter) -> bool {
+ unsigned idx = foundIdx;
+ unsigned limit = foundSize;
+ ArrayRef<ValueDecl *> decls = FoundDecls;
+ if (isOuter) {
+ idx = foundIdx - foundSize;
+ limit = foundOuterSize;
+ decls = FoundOuterDecls;
+ }
+ // If the current result matches the remaining found declaration,
+ // keep it and move to the next found declaration.
+ if (idx < limit && result.getValueDecl() == decls[idx]) {
+ ++foundIdx;
+ return true;
+ }
- // Otherwise, this result should be filtered out.
- return false;
- });
+ // Otherwise, this result should be filtered out.
+ return false;
+ });
}
/// Add a new result.
@@ -106,7 +131,11 @@
///
/// \param foundInType The type through which we found the
/// declaration.
- void add(ValueDecl *found, DeclContext *baseDC, Type foundInType) {
+ ///
+ /// \param isOuter Whether this is an outer result (i.e. a result that isn't
+ /// from the innermost scope with results)
+ void add(ValueDecl *found, DeclContext *baseDC, Type foundInType,
+ bool isOuter) {
ConformanceCheckOptions conformanceOptions;
if (Options.contains(NameLookupFlags::KnownPrivate))
conformanceOptions |= ConformanceCheckFlags::InExpression;
@@ -116,8 +145,11 @@
auto addResult = [&](ValueDecl *result) {
if (Known.insert({{result, baseDC}, false}).second) {
- Result.add(LookupResultEntry(baseDC, result));
- FoundDecls.push_back(result);
+ Result.add(LookupResultEntry(baseDC, result), isOuter);
+ if (isOuter)
+ FoundOuterDecls.push_back(result);
+ else
+ FoundDecls.push_back(result);
}
};
@@ -212,21 +244,32 @@
};
} // end anonymous namespace
+static UnqualifiedLookup::Options
+convertToUnqualifiedLookupOptions(NameLookupOptions options) {
+ UnqualifiedLookup::Options newOptions;
+ if (options.contains(NameLookupFlags::KnownPrivate))
+ newOptions |= UnqualifiedLookup::Flags::KnownPrivate;
+ if (options.contains(NameLookupFlags::ProtocolMembers))
+ newOptions |= UnqualifiedLookup::Flags::AllowProtocolMembers;
+ if (options.contains(NameLookupFlags::IgnoreAccessControl))
+ newOptions |= UnqualifiedLookup::Flags::IgnoreAccessControl;
+ if (options.contains(NameLookupFlags::IncludeOuterResults))
+ newOptions |= UnqualifiedLookup::Flags::IncludeOuterResults;
+
+ return newOptions;
+}
+
LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
SourceLoc loc,
NameLookupOptions options) {
- UnqualifiedLookup lookup(
- name, dc, this,
- options.contains(NameLookupFlags::KnownPrivate),
- loc,
- /*IsTypeLookup=*/false,
- options.contains(NameLookupFlags::ProtocolMembers),
- options.contains(NameLookupFlags::IgnoreAccessControl));
+ UnqualifiedLookup lookup(name, dc, this, loc,
+ convertToUnqualifiedLookupOptions(options));
LookupResult result;
LookupResultBuilder builder(*this, result, dc, options,
/*memberLookup*/false);
- for (const auto &found : lookup.Results) {
+ for (auto idx : indices(lookup.Results)) {
+ const auto &found = lookup.Results[idx];
// Determine which type we looked through to find this result.
Type foundInType;
@@ -240,7 +283,8 @@
assert(foundInType && "bogus base declaration?");
}
- builder.add(found.getValueDecl(), found.getDeclContext(), foundInType);
+ builder.add(found.getValueDecl(), found.getDeclContext(), foundInType,
+ /*isOuter=*/idx >= lookup.IndexOfFirstOuterResult);
}
return result;
}
@@ -249,19 +293,17 @@
TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclName name,
SourceLoc loc,
NameLookupOptions options) {
+ auto ulOptions = convertToUnqualifiedLookupOptions(options) |
+ UnqualifiedLookup::Flags::TypeLookup;
{
// Try lookup without ProtocolMembers first.
UnqualifiedLookup lookup(
- name, dc, this,
- options.contains(NameLookupFlags::KnownPrivate),
- loc,
- /*IsTypeLookup=*/true,
- /*AllowProtocolMembers=*/false,
- options.contains(NameLookupFlags::IgnoreAccessControl));
+ name, dc, this, loc,
+ ulOptions - UnqualifiedLookup::Flags::AllowProtocolMembers);
if (!lookup.Results.empty() ||
!options.contains(NameLookupFlags::ProtocolMembers)) {
- return LookupResult(lookup.Results);
+ return LookupResult(lookup.Results, lookup.IndexOfFirstOuterResult);
}
}
@@ -272,14 +314,10 @@
// is called too early, we start resolving extensions -- even those
// which do provide not conformances.
UnqualifiedLookup lookup(
- name, dc, this,
- options.contains(NameLookupFlags::KnownPrivate),
- loc,
- /*IsTypeLookup=*/true,
- /*AllowProtocolMembers=*/true,
- options.contains(NameLookupFlags::IgnoreAccessControl));
+ name, dc, this, loc,
+ ulOptions | UnqualifiedLookup::Flags::AllowProtocolMembers);
- return LookupResult(lookup.Results);
+ return LookupResult(lookup.Results, lookup.IndexOfFirstOuterResult);
}
}
@@ -310,7 +348,7 @@
dc->lookupQualified(type, name, subOptions, this, lookupResults);
for (auto found : lookupResults)
- builder.add(found, nullptr, type);
+ builder.add(found, nullptr, type, /*isOuter=*/false);
return result;
}
@@ -621,7 +659,7 @@
void
TypoCorrectionResults::addAllCandidatesToLookup(LookupResult &lookup) const {
for (auto candidate : Candidates)
- lookup.add(LookupResultEntry(candidate));
+ lookup.add(LookupResultEntry(candidate), /*isOuter=*/false);
}
static Decl *findExplicitParentForImplicitDecl(ValueDecl *decl) {
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index c18ec50..73e85b1 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1495,15 +1495,21 @@
return conformance;
}
// And... even if it isn't conditional, we still don't currently support
- // @objc protocols in extensions.
+ // @objc protocols in extensions of Swift generic classes, because there's
+ // no stable Objective-C class object to install the protocol conformance
+ // category onto.
if (isa<ExtensionDecl>(DC)) {
if (auto genericT = T->getGenericAncestor()) {
- auto isSubclass = !genericT->isEqual(T);
- auto genericTIsGeneric = (bool)genericT->getAnyGeneric()->getGenericParams();
- TC.diagnose(ComplainLoc, diag::objc_protocol_in_generic_extension, T,
- ProtoType, isSubclass, genericTIsGeneric);
- conformance->setInvalid();
- return conformance;
+ if (!cast<ClassDecl>(genericT->getAnyNominal())
+ ->usesObjCGenericsModel()) {
+ auto isSubclass = !genericT->isEqual(T);
+ auto genericTIsGeneric = (bool)genericT->getAnyGeneric()
+ ->getGenericParams();
+ TC.diagnose(ComplainLoc, diag::objc_protocol_in_generic_extension, T,
+ ProtoType, isSubclass, genericTIsGeneric);
+ conformance->setInvalid();
+ return conformance;
+ }
}
}
}
@@ -4024,6 +4030,7 @@
llvm::SetVector<ValueDecl *> globalMissingWitnesses;
ConformanceChecker checker(*this, conformance, globalMissingWitnesses);
checker.ensureRequirementsAreSatisfied(/*failUnsubstituted=*/true);
+ checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
}
/// Determine the score when trying to match two identifiers together.
@@ -4931,6 +4938,7 @@
checker.resolveTypeWitnesses();
else
checker.resolveSingleTypeWitness(assocType);
+ checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
}
void TypeChecker::resolveWitness(const NormalProtocolConformance *conformance,
@@ -4941,6 +4949,7 @@
const_cast<NormalProtocolConformance*>(conformance),
MissingWitnesses);
checker.resolveSingleWitness(requirement);
+ checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
}
ValueDecl *TypeChecker::deriveProtocolRequirement(DeclContext *DC,
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index d2a448d..439f842 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -1381,10 +1381,8 @@
// playgrounds.
return;
}
- if (!TC.Context.isSwiftVersionAtLeast(5)) {
- // Downgrade missing '@unknown' to a warning in Swift 4 and below.
- mainDiagType = diag::non_exhaustive_switch_warn;
- }
+ // Missing '@unknown' is just a warning.
+ mainDiagType = diag::non_exhaustive_switch_warn;
break;
}
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 7978707..9151ffb 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -65,18 +65,6 @@
Context.setLazyResolver(nullptr);
}
-void TypeChecker::handleExternalDecl(Decl *decl) {
- if (auto SD = dyn_cast<StructDecl>(decl)) {
- addImplicitStructConformances(SD);
- }
- if (auto CD = dyn_cast<ClassDecl>(decl)) {
- CD->addImplicitDestructor();
- }
- if (auto ED = dyn_cast<EnumDecl>(decl)) {
- addImplicitEnumConformances(ED);
- }
-}
-
ProtocolDecl *TypeChecker::getProtocol(SourceLoc loc, KnownProtocolKind kind) {
auto protocol = Context.getProtocol(kind);
if (!protocol && loc.isValid()) {
@@ -450,6 +438,10 @@
else {
auto *ntd = cast<NominalTypeDecl>(decl);
TC.checkConformancesInContext(ntd, ntd);
+
+ // Finally, we can check classes for missing initializers.
+ if (auto *classDecl = dyn_cast<ClassDecl>(ntd))
+ TC.maybeDiagnoseClassWithoutInitializers(classDecl);
}
}
TC.ConformanceContexts.clear();
@@ -475,10 +467,8 @@
TC.checkFunctionErrorHandling(AFD);
continue;
}
- if (isa<NominalTypeDecl>(decl)) {
- TC.handleExternalDecl(decl);
+ if (isa<NominalTypeDecl>(decl))
continue;
- }
if (isa<VarDecl>(decl))
continue;
llvm_unreachable("Unhandled external definition kind");
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 86e2aaf..a1a7169 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -86,35 +86,57 @@
private:
/// The set of results found.
SmallVector<LookupResultEntry, 4> Results;
+ size_t IndexOfFirstOuterResult = 0;
public:
LookupResult() {}
- explicit
- LookupResult(const SmallVectorImpl<LookupResultEntry> &Results)
- : Results(Results.begin(), Results.end()) {}
+ explicit LookupResult(const SmallVectorImpl<LookupResultEntry> &Results,
+ size_t indexOfFirstOuterResult)
+ : Results(Results.begin(), Results.end()),
+ IndexOfFirstOuterResult(indexOfFirstOuterResult) {}
using iterator = SmallVectorImpl<LookupResultEntry>::iterator;
iterator begin() { return Results.begin(); }
- iterator end() { return Results.end(); }
- unsigned size() const { return Results.size(); }
- bool empty() const { return Results.empty(); }
+ iterator end() {
+ return Results.begin() + IndexOfFirstOuterResult;
+ }
+ unsigned size() const { return innerResults().size(); }
+ bool empty() const { return innerResults().empty(); }
+
+ ArrayRef<LookupResultEntry> innerResults() const {
+ return llvm::makeArrayRef(Results).take_front(IndexOfFirstOuterResult);
+ }
+
+ ArrayRef<LookupResultEntry> outerResults() const {
+ return llvm::makeArrayRef(Results).drop_front(IndexOfFirstOuterResult);
+ }
const LookupResultEntry& operator[](unsigned index) const {
return Results[index];
}
- LookupResultEntry front() const { return Results.front(); }
- LookupResultEntry back() const { return Results.back(); }
+ LookupResultEntry front() const { return innerResults().front(); }
+ LookupResultEntry back() const { return innerResults().back(); }
/// Add a result to the set of results.
- void add(LookupResultEntry result) { Results.push_back(result); }
+ void add(LookupResultEntry result, bool isOuter) {
+ Results.push_back(result);
+ if (!isOuter) {
+ IndexOfFirstOuterResult++;
+ assert(IndexOfFirstOuterResult == Results.size() &&
+ "found an outer result before an inner one");
+ } else {
+ assert(IndexOfFirstOuterResult > 0 &&
+ "found outer results without an inner one");
+ }
+ }
void clear() { Results.clear(); }
/// Determine whether the result set is nonempty.
explicit operator bool() const {
- return !Results.empty();
+ return !empty();
}
TypeDecl *getSingleTypeResult() const {
@@ -125,7 +147,8 @@
}
/// Filter out any results that aren't accepted by the given predicate.
- void filter(const std::function<bool(LookupResultEntry)> &pred);
+ void
+ filter(const std::function<bool(LookupResultEntry, /*isOuter*/ bool)> &pred);
};
/// The result of name lookup for types.
@@ -260,6 +283,9 @@
/// Whether to ignore access control for this lookup, allowing inaccessible
/// results to be returned.
IgnoreAccessControl = 0x10,
+ /// Whether to include results from outside the innermost scope that has a
+ /// result.
+ IncludeOuterResults = 0x20,
};
/// A set of options that control name lookup.
@@ -1535,18 +1561,14 @@
/// Retrieve the set of inherited protocols for this protocol type.
llvm::TinyPtrVector<ProtocolDecl *> getDirectConformsTo(ProtocolDecl *proto);
+ /// Diagnose if the class has no designated initializers.
+ void maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl);
+
+ ///
/// \brief Add any implicitly-defined constructors required for the given
/// struct or class.
void addImplicitConstructors(NominalTypeDecl *typeDecl);
- /// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an
- /// imported NS_OPTIONS struct.
- void addImplicitStructConformances(StructDecl *ED);
-
- /// \brief Add the RawRepresentable, Equatable, and Hashable methods to an
- /// enum with a raw type.
- void addImplicitEnumConformances(EnumDecl *ED);
-
/// Synthesize the member with the given name on the target if applicable,
/// i.e. if the member is synthesizable and has not yet been added to the
/// target.
@@ -2269,12 +2291,6 @@
/// we're parsing the standard library.
ModuleDecl *getStdlibModule(const DeclContext *dc);
- /// \name AST Mutation Listener Implementation
- /// @{
- void handleExternalDecl(Decl *decl);
-
- /// @}
-
/// \name Lazy resolution.
///
/// Routines that perform lazy resolution as required for AST operations.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 896131a..755e38e 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -5309,13 +5309,13 @@
if (auto syntheticSig = getGenericSignature(*rawIDIter++)) {
// Create the synthetic environment.
syntheticEnv = syntheticSig->createGenericEnvironment();
+ }
- // Requirement -> synthetic substitutions.
- if (unsigned numReqSubstitutions = *rawIDIter++) {
- while (numReqSubstitutions--) {
- auto sub = maybeReadSubstitution(DeclTypeCursor, nullptr);
- reqToSyntheticSubs.push_back(*sub);
- }
+ // Requirement -> synthetic substitutions.
+ if (unsigned numReqSubstitutions = *rawIDIter++) {
+ while (numReqSubstitutions--) {
+ auto sub = maybeReadSubstitution(DeclTypeCursor, nullptr);
+ reqToSyntheticSubs.push_back(*sub);
}
}
@@ -5334,13 +5334,6 @@
continue;
}
- // Handle simple witnesses.
- if (witnessSubstitutions.empty() && !syntheticSig && !syntheticEnv &&
- reqToSyntheticSubs.empty()) {
- trySetWitness(Witness(witness));
- continue;
- }
-
// Set the witness.
trySetWitness(Witness(witness, witnessSubstitutions,
syntheticEnv, reqToSyntheticSubs));
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 0219e97..ad76558 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1530,19 +1530,17 @@
// If there is no witness, we're done.
if (!witness.getDecl()) return;
- if (auto genericEnv = witness.requiresSubstitution()
- ? witness.getSyntheticEnvironment()
- : nullptr) {
+ if (auto *genericEnv = witness.getSyntheticEnvironment()) {
// Generic signature.
auto *genericSig = genericEnv->getGenericSignature();
data.push_back(addGenericSignatureRef(genericSig));
-
- auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
- data.push_back(reqToSyntheticSubs.size());
} else {
data.push_back(/*null generic signature*/0);
}
+ auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
+
+ data.push_back(reqToSyntheticSubs.size());
data.push_back(witness.getSubstitutions().size());
});
@@ -1568,19 +1566,14 @@
// Bail out early for simple witnesses.
if (!witness.getDecl()) return;
- if (witness.requiresSubstitution()) {
- // Write requirement-to-synthetic substitutions.
- writeSubstitutions(witness.getRequirementToSyntheticSubs(),
- DeclTypeAbbrCodes,
- nullptr);
- }
+ // Write requirement-to-synthetic substitutions.
+ writeSubstitutions(witness.getRequirementToSyntheticSubs(),
+ DeclTypeAbbrCodes, nullptr);
// Write the witness substitutions.
writeSubstitutions(witness.getSubstitutions(),
DeclTypeAbbrCodes,
- witness.requiresSubstitution()
- ? witness.getSyntheticEnvironment()
- : nullptr);
+ witness.getSyntheticEnvironment());
});
}
diff --git a/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt b/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt
index 2776ce4..39e44da 100644
--- a/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt
+++ b/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt
@@ -7,15 +7,15 @@
# filename.
StdlibCollectionUnittest.swift
- CheckCollectionInstance.swift.gyb
- CheckCollectionType.swift.gyb
- CheckMutableCollectionType.swift.gyb
+ CheckCollectionInstance.swift
+ CheckCollectionType.swift
+ CheckMutableCollectionType.swift
CheckRangeReplaceableCollectionType.swift
CheckRangeReplaceableSliceType.swift
- CheckSequenceInstance.swift.gyb
+ CheckSequenceInstance.swift
CheckSequenceType.swift
- LoggingWrappers.swift.gyb
- MinimalCollections.swift.gyb
+ LoggingWrappers.swift
+ MinimalCollections.swift
RangeSelection.swift
../../public/core/WriteBackMutableSlice.swift
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift
new file mode 100644
index 0000000..b6c2876
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift
@@ -0,0 +1,1917 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import StdlibUnittest
+
+public struct CollectionMisuseResiliencyChecks {
+ public enum FailureKind {
+ case none
+ case trap
+ }
+
+ public var creatingOutOfBoundsIndicesBehavior: FailureKind = .trap
+ public var subscriptOnOutOfBoundsIndicesBehavior: FailureKind = .trap
+ public var subscriptRangeOnOutOfBoundsRangesBehavior: FailureKind = .trap
+
+ public static var all: CollectionMisuseResiliencyChecks {
+ return CollectionMisuseResiliencyChecks()
+ }
+
+ public static var none: CollectionMisuseResiliencyChecks {
+ return CollectionMisuseResiliencyChecks(
+ creatingOutOfBoundsIndicesBehavior: .none,
+ subscriptOnOutOfBoundsIndicesBehavior: .none,
+ subscriptRangeOnOutOfBoundsRangesBehavior: .none)
+ }
+}
+
+
+/// Test that the elements of `instances` satisfy
+/// the semantic
+/// requirements of `Collection`, using `equalityOracle` to
+/// generate equality expectations from pairs of positions in
+/// `instances`.
+///
+/// - Precondition: `endIndex` is reachable from all
+/// elements of `instances`.
+public func checkIncrementable<Instances, BaseCollection>(
+ _ instances: Instances,
+ of baseCollection: BaseCollection,
+ equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ endIndex: Instances.Element,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances : Collection,
+ BaseCollection : Collection,
+ Instances.Element == BaseCollection.Index {
+
+ checkEquatable(instances, oracle: equalityOracle, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ for i in instances {
+ if i != endIndex {
+ let next = baseCollection.index(after: i)
+ // index(after:) gets us a new index value
+ expectNotEqual(i, next, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ // Which is the same as if we apply formIndex(after:)
+ var j = i
+ baseCollection.formIndex(after: &j)
+ expectEqual(j, next, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+}
+
+/// Test that the elements of `instances` satisfy
+/// some of the semantic
+/// requirements of `BidirectionalCollection`, using `equalityOracle` to
+/// generate equality expectations from pairs of positions in
+/// `instances`.
+///
+/// - Precondition: all
+/// elements of `instances` are reachable from `startIndex`.
+public func checkDecrementable<Instances, BaseCollection>(
+ _ instances: Instances,
+ of baseCollection: BaseCollection,
+ equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ startIndex: Instances.Element,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances : Collection,
+ BaseCollection : BidirectionalCollection,
+ Instances.Element == BaseCollection.Index {
+
+ checkEquatable(instances, oracle: equalityOracle, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ for i in instances {
+ if i != startIndex {
+ let next = baseCollection.index(before: i)
+ // index(before:) gets us a new index value
+ expectNotEqual(i, next, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ // Which is the same as if we apply formIndex(before:)
+ var j = i
+ baseCollection.formIndex(before: &j)
+ expectEqual(j, next, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+}
+
+internal func _checkIncrementalAdvance<Instances, BaseCollection>(
+ _ instances: Instances,
+ of baseCollection : BaseCollection,
+ equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ limit: Instances.Element,
+ sign: Int, // 1 or -1
+ next: (Instances.Element) -> Instances.Element,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances : Collection,
+ BaseCollection : Collection,
+ Instances.Element == BaseCollection.Index {
+ for i in instances {
+ let d: Int = sign > 0 ?
+ baseCollection.distance(from: i, to: limit) :
+ -baseCollection.distance(from: limit, to: i)
+
+ var offset: Int = 0
+ for _ in 0...Int64(d * sign) {
+ let j = baseCollection.index(i, offsetBy: offset)
+ let k = baseCollection.index(i, offsetBy: offset + sign, limitedBy: limit) ?? limit
+ let jAtLimit = offset == d
+ if jAtLimit {
+ expectEqual(limit, j, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ expectEqual(jAtLimit ? j : next(j), k, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ offset += sign
+ }
+ }
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// index for `Collection`, using `equalityOracle` to generate equality
+/// expectations from pairs of positions in `instances`.
+///
+/// - Precondition: `endIndex` is reachable from all elements of
+/// `instances`
+public func checkForwardIndex<Instances, BaseCollection>(
+ _ instances: Instances,
+ of baseCollection: BaseCollection,
+ equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ endIndex: Instances.Element,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances : Collection,
+ BaseCollection : Collection,
+ Instances.Element == BaseCollection.Index {
+
+ checkIncrementable(instances, of: baseCollection,
+ equalityOracle: equalityOracle, endIndex: endIndex, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ _checkIncrementalAdvance(instances, of: baseCollection,
+ equalityOracle: equalityOracle, limit: endIndex,
+ sign: 1, next: { baseCollection.index(after: $0) }, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// index for `BidirectionalCollection`, using `equalityOracle` to generate
+/// equality expectations from pairs of positions in `instances`.
+///
+/// - Precondition:
+/// - all elements of `instances` are reachable from `startIndex`.
+/// - `endIndex` is reachable from all elements of `instances`.
+public func checkBidirectionalIndex<Instances, BaseCollection>(
+ _ instances: Instances,
+ of baseCollection: BaseCollection,
+ equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ startIndex: Instances.Element,
+ endIndex: Instances.Element,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances: Collection,
+ BaseCollection : BidirectionalCollection,
+ Instances.Element == BaseCollection.Index {
+
+ checkForwardIndex(instances, of: baseCollection,
+ equalityOracle: equalityOracle, endIndex: endIndex)
+
+ checkDecrementable(instances, of: baseCollection,
+ equalityOracle: equalityOracle, startIndex: startIndex, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ _checkIncrementalAdvance(instances, of: baseCollection,
+ equalityOracle: equalityOracle, limit: startIndex,
+ sign: -1, next: { baseCollection.index(before: $0) }, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// index for `RandomAccessCollection`, using `advanceOracle` and
+/// 'distanceOracle' to generate expectations about the results of
+/// `advanced(by:)` and `distance(to:)` from pairs of positions in `instances`
+/// and `distances`.
+///
+/// - Precondition:
+/// - all elements of `instances` are reachable from `startIndex`.
+/// - `endIndex` is reachable from all elements of `instances`.
+public func checkRandomAccessIndex<Instances, Distances, BaseCollection>(
+ _ instances: Instances, distances: Distances,
+ of baseCollection: BaseCollection,
+ distanceOracle:
+ (Instances.Index, Instances.Index) -> Distances.Element,
+ advanceOracle:
+ (Instances.Index, Distances.Index) -> Instances.Element,
+ startIndex: Instances.Iterator.Element,
+ endIndex: Instances.Iterator.Element,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances : Collection,
+ Distances : Collection,
+ BaseCollection : RandomAccessCollection,
+ Instances.Element == BaseCollection.Index,
+ Distances.Element == Int {
+
+ checkBidirectionalIndex(instances, of: baseCollection,
+ equalityOracle: { distanceOracle($0, $1) == 0 },
+ startIndex: startIndex, endIndex: endIndex, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ checkAdvancesAndDistances(
+ instances, distances: distances,
+ of: baseCollection,
+ distanceOracle: distanceOracle,
+ advanceOracle: advanceOracle, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
+
+// Copies what checkStrideable is doing, but instead of calling
+// advanced(by:) and distance(to:) on an Strideable's,
+// calls corresponding methods on a base collection.
+public func checkAdvancesAndDistances<Instances, Distances, BaseCollection>(
+ _ instances: Instances, distances: Distances,
+ of baseCollection: BaseCollection,
+ distanceOracle:
+ (Instances.Index, Instances.Index) -> Distances.Element,
+ advanceOracle:
+ (Instances.Index, Distances.Index) -> Instances.Element,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ Instances : Collection,
+ Distances : Collection,
+ BaseCollection : Collection,
+ Instances.Element == BaseCollection.Index,
+ Distances.Element == Int {
+
+ checkComparable(
+ instances,
+ oracle: {
+ let d = distanceOracle($1, $0);
+ return d < 0 ? .lt : d == 0 ? .eq : .gt
+ },
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ for i in instances.indices {
+ let x = instances[i]
+ expectEqual(x, baseCollection.index(x, offsetBy: 0))
+
+ for j in distances.indices {
+ let y = distances[j]
+ expectEqual(advanceOracle(i, j), baseCollection.index(x, offsetBy: y))
+ }
+
+ for j in instances.indices {
+ let y = instances[j]
+ expectEqual(distanceOracle(i, j), baseCollection.distance(from: x, to: y))
+ }
+ }
+}
+
+// Generate two overloads: one for Array (which will get
+// picked up when the caller passes a literal), and another that
+// accepts any appropriate Collection type.
+
+// Top-level check for Collection instances. Alias for checkForwardCollection.
+// Checks all slices: O(n^2).
+public func checkCollection<Expected: Collection, C : Collection>(
+ _ expected: Expected,
+ _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+ checkForwardCollection(expected, collection, message(),
+ stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+}
+
+
+// Calls checkForwardCollection with default `sameValue`.
+public func checkForwardCollection<
+ Expected: Collection, C : Collection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ C.Element == Expected.Element,
+ Expected.Element : Equatable {
+
+ checkForwardCollection(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all Collection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkForwardCollection<
+ Expected: Collection, C : Collection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+ C.Element == Expected.Element {
+
+ checkOneLevelOfForwardCollection(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+ // Avoid validation of all possible (n^2) slices on large collection.
+ // Test cases should call checkOneLevelOfForwardCollection instead.
+ expectLT(expected.count, 30)
+
+ _checkSliceableWithForwardIndex(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkForwardCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `Collection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfForwardCollection<
+ Expected: Collection, C : Collection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+ // A `Collection` is a multi-pass `Sequence`.
+ for _ in 0..<3 {
+ checkSequence(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+ }
+
+ //===------------------------------------------------------------------===//
+ // Check Index semantics
+ //===------------------------------------------------------------------===//
+
+ let succ = { collection.index(after: $0) }
+ // Advances up to 1 positions without passing endIndex. Don't use
+ // advanced(by: n) to do this because it's under test here.
+ let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+ // advances up to 5 positions without passing endIndex. Picking a
+ // small constant to avoid complexity explosion on large input
+ // collections.
+ let next5 = { next(next(next(next(next($0))))) }
+
+ let partWay0 = next5(collection.startIndex)
+ let partWay1 = next5(partWay0)
+
+
+ let instances = _allIndices(into: collection,
+ in: collection.startIndex..<partWay0)
+ checkForwardIndex(instances, of: collection,
+ equalityOracle: { $0 == $1 }, endIndex: partWay1, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+ let expectedArray = Array(expected)
+
+ // Check `count`.
+ expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ //===------------------------------------------------------------------===//
+ // Check Iteration behavior.
+ //===------------------------------------------------------------------===//
+
+ for _ in 0..<3 {
+ do {
+ let startIndex = collection.startIndex
+ let endIndex = collection.endIndex
+
+ for _ in collection.indices {
+ expectEqual(
+ startIndex, collection.startIndex,
+ "Iteration should not change startIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqual(
+ endIndex, collection.endIndex,
+ "Iteration should not change endIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+
+ var allIndices = Array(collection.indices)
+
+ if expectedArray.count >= 2 {
+ for i in 0..<allIndices.count-1 {
+ let successor1 = succ(allIndices[i])
+ var successor2 = allIndices[i]
+ successor2 = succ(successor2)
+ var successor3 = allIndices[i]
+ successor3 = succ(successor3)
+ for s in [ successor1, successor2, successor3 ] {
+ expectEqual(allIndices[i + 1], s, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i + 1], collection[s], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+
+
+ } // end of `if expectedArray.count >= 2`
+
+ do {
+ var allIndices2: [C.Index] = []
+ for i in collection.indices {
+ allIndices2.append(i)
+ }
+
+ expectEqualSequence(
+ allIndices, allIndices2, "iteration should not invalidate indices",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqualSequence(
+ expectedArray, allIndices.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ expectEqualSequence(
+ expectedArray, allIndices2.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ } // end of `for _ in 0..<3`
+
+ // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkForwardCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithForwardIndex<
+Expected: Collection, S : Collection
+>(
+ _ expected: Expected, _ sliceable: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+ S.Element == Expected.Element {
+
+ let expectedArray = Array(expected)
+
+ let succ = { sliceable.index(after: $0) }
+
+ var start = sliceable.startIndex
+ for startNumericIndex in 0...expectedArray.count {
+ var end = start
+ for endNumericIndex in startNumericIndex...expectedArray.count {
+ let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+ let slice = sliceable[start..<end]
+ // For every possible slice, verify that the slice's bounds are identical
+ // to the indices used to form the slice.
+ expectEqual(start, slice.startIndex)
+ expectEqual(end, slice.endIndex)
+
+ checkOneLevelOfForwardCollection(expectedSlice, slice, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ if end != sliceable.endIndex {
+ end = succ(end)
+ }
+ }
+ if start != sliceable.endIndex {
+ start = succ(start)
+ }
+ }
+}
+
+
+// Calls checkBidirectionalCollection with default `sameValue`.
+public func checkBidirectionalCollection<
+ Expected: Collection, C : BidirectionalCollection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ C.Element == Expected.Element,
+ Expected.Element : Equatable {
+
+ checkBidirectionalCollection(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all BidirectionalCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkBidirectionalCollection<
+ Expected: Collection, C : BidirectionalCollection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+ C.Element == Expected.Element {
+
+ checkOneLevelOfBidirectionalCollection(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+ // Avoid validation of all possible (n^2) slices on large collection.
+ // Test cases should call checkOneLevelOfBidirectionalCollection instead.
+ expectLT(expected.count, 30)
+
+ _checkSliceableWithBidirectionalIndex(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkBidirectionalCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `BidirectionalCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfBidirectionalCollection<
+ Expected: Collection, C : BidirectionalCollection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+ // A `Collection` is a multi-pass `Sequence`.
+ for _ in 0..<3 {
+ checkSequence(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+ }
+
+ //===------------------------------------------------------------------===//
+ // Check Index semantics
+ //===------------------------------------------------------------------===//
+
+ let succ = { collection.index(after: $0) }
+ let pred = { collection.index(before: $0) }
+ // Advances up to 1 positions without passing endIndex. Don't use
+ // advanced(by: n) to do this because it's under test here.
+ let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+ // advances up to 5 positions without passing endIndex. Picking a
+ // small constant to avoid complexity explosion on large input
+ // collections.
+ let next5 = { next(next(next(next(next($0))))) }
+
+ let partWay0 = next5(collection.startIndex)
+ let partWay1 = next5(partWay0)
+
+
+ let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+ checkBidirectionalIndex(instances, of: collection,
+ equalityOracle: { $0 == $1 },
+ startIndex: collection.startIndex,
+ endIndex: next5(partWay1), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+ let expectedArray = Array(expected)
+
+ // Check `count`.
+ expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ //===------------------------------------------------------------------===//
+ // Check Iteration behavior.
+ //===------------------------------------------------------------------===//
+
+ for _ in 0..<3 {
+ do {
+ let startIndex = collection.startIndex
+ let endIndex = collection.endIndex
+
+ for _ in collection.indices {
+ expectEqual(
+ startIndex, collection.startIndex,
+ "Iteration should not change startIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqual(
+ endIndex, collection.endIndex,
+ "Iteration should not change endIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+
+ var allIndices = Array(collection.indices)
+
+ if expectedArray.count >= 2 {
+ for i in 0..<allIndices.count-1 {
+ let successor1 = succ(allIndices[i])
+ var successor2 = allIndices[i]
+ successor2 = succ(successor2)
+ var successor3 = allIndices[i]
+ successor3 = succ(successor3)
+ for s in [ successor1, successor2, successor3 ] {
+ expectEqual(allIndices[i + 1], s, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i + 1], collection[s], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+
+
+ for i in 1..<allIndices.count {
+ let predecessor1 = pred(allIndices[i])
+ var predecessor2 = allIndices[i]
+ predecessor2 = pred(predecessor2)
+ var predecessor3 = allIndices[i]
+ predecessor3 = pred(predecessor3)
+ for p in [ predecessor1, predecessor2, predecessor3 ] {
+ expectEqual(allIndices[i - 1], p, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i - 1], collection[p], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+ for i in 1..<allIndices.count {
+ let index = succ(pred(allIndices[i]))
+ expectEqual(allIndices[i], index, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i], collection[index], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+
+
+ } // end of `if expectedArray.count >= 2`
+
+ do {
+ var allIndices2: [C.Index] = []
+ for i in collection.indices {
+ allIndices2.append(i)
+ }
+
+ expectEqualSequence(
+ allIndices, allIndices2, "iteration should not invalidate indices",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqualSequence(
+ expectedArray, allIndices.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ expectEqualSequence(
+ expectedArray, allIndices2.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ } // end of `for _ in 0..<3`
+
+ // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkBidirectionalCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithBidirectionalIndex<
+Expected: Collection, S : BidirectionalCollection
+>(
+ _ expected: Expected, _ sliceable: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+ S.Element == Expected.Element {
+
+ let expectedArray = Array(expected)
+
+ let succ = { sliceable.index(after: $0) }
+ let pred = { sliceable.index(before: $0) }
+
+ var start = sliceable.startIndex
+ for startNumericIndex in 0...expectedArray.count {
+ if start != sliceable.endIndex {
+ start = succ(start)
+ start = pred(start)
+ start = succ(start)
+ start = pred(start)
+ }
+ var end = start
+ for endNumericIndex in startNumericIndex...expectedArray.count {
+ if end != sliceable.endIndex {
+ end = succ(end)
+ end = pred(end)
+ end = succ(end)
+ end = pred(end)
+ }
+ let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+ let slice = sliceable[start..<end]
+ // For every possible slice, verify that the slice's bounds are identical
+ // to the indices used to form the slice.
+ expectEqual(start, slice.startIndex)
+ expectEqual(end, slice.endIndex)
+
+ checkOneLevelOfBidirectionalCollection(expectedSlice, slice, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ if end != sliceable.endIndex {
+ end = succ(end)
+ }
+ }
+ if start != sliceable.endIndex {
+ start = succ(start)
+ }
+ }
+}
+
+
+// Calls checkRandomAccessCollection with default `sameValue`.
+public func checkRandomAccessCollection<
+ Expected: Collection, C : RandomAccessCollection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ C.Element == Expected.Element,
+ Expected.Element : Equatable {
+
+ checkRandomAccessCollection(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all RandomAccessCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkRandomAccessCollection<
+ Expected: Collection, C : RandomAccessCollection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+ C.Element == Expected.Element {
+
+ checkOneLevelOfRandomAccessCollection(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+ // Avoid validation of all possible (n^2) slices on large collection.
+ // Test cases should call checkOneLevelOfRandomAccessCollection instead.
+ expectLT(expected.count, 30)
+
+ _checkSliceableWithRandomAccessIndex(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkRandomAccessCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `RandomAccessCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfRandomAccessCollection<
+ Expected: Collection, C : RandomAccessCollection
+>(
+ _ expected: Expected, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+ // A `Collection` is a multi-pass `Sequence`.
+ for _ in 0..<3 {
+ checkSequence(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+ }
+
+ //===------------------------------------------------------------------===//
+ // Check Index semantics
+ //===------------------------------------------------------------------===//
+
+ let succ = { collection.index(after: $0) }
+ let pred = { collection.index(before: $0) }
+ // Advances up to 1 positions without passing endIndex. Don't use
+ // advanced(by: n) to do this because it's under test here.
+ let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+ // advances up to 5 positions without passing endIndex. Picking a
+ // small constant to avoid complexity explosion on large input
+ // collections.
+ let next5 = { next(next(next(next(next($0))))) }
+
+ let partWay0 = next5(collection.startIndex)
+ let partWay1 = next5(partWay0)
+
+ typealias Distance = Int
+
+ let count: Distance = collection.count
+ let offset0 = min(5, count)
+ let offset1 = min(10, count)
+ let offset2 = min(15, count)
+
+ let distanceCandidates: [Distance] = [
+ -11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
+
+ let distances = distanceCandidates.filter { (x: Distance) -> Bool in
+ x + offset0 >= 0 && x + offset1 <= count
+ }
+
+ func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
+ return collection.index(i, offsetBy: n)
+ }
+
+ let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+
+ checkRandomAccessIndex(
+ instances,
+ distances: distances,
+ of: collection,
+ distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
+ advanceOracle: { x, y in nextN(distances[y], instances[x]) },
+ startIndex: collection.startIndex,
+ endIndex: next5(partWay1), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+ let expectedArray = Array(expected)
+
+ // Check `count`.
+ expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ //===------------------------------------------------------------------===//
+ // Check Iteration behavior.
+ //===------------------------------------------------------------------===//
+
+ for _ in 0..<3 {
+ do {
+ let startIndex = collection.startIndex
+ let endIndex = collection.endIndex
+
+ for _ in collection.indices {
+ expectEqual(
+ startIndex, collection.startIndex,
+ "Iteration should not change startIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqual(
+ endIndex, collection.endIndex,
+ "Iteration should not change endIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+
+ var allIndices = Array(collection.indices)
+
+ if expectedArray.count >= 2 {
+ for i in 0..<allIndices.count-1 {
+ let successor1 = succ(allIndices[i])
+ var successor2 = allIndices[i]
+ successor2 = succ(successor2)
+ var successor3 = allIndices[i]
+ successor3 = succ(successor3)
+ for s in [ successor1, successor2, successor3 ] {
+ expectEqual(allIndices[i + 1], s, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i + 1], collection[s], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+
+
+ } // end of `if expectedArray.count >= 2`
+
+ do {
+ var allIndices2: [C.Index] = []
+ for i in collection.indices {
+ allIndices2.append(i)
+ }
+
+ expectEqualSequence(
+ allIndices, allIndices2, "iteration should not invalidate indices",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqualSequence(
+ expectedArray, allIndices.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ expectEqualSequence(
+ expectedArray, allIndices2.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ } // end of `for _ in 0..<3`
+
+ // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkRandomAccessCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithRandomAccessIndex<
+Expected: Collection, S : RandomAccessCollection
+>(
+ _ expected: Expected, _ sliceable: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+ S.Element == Expected.Element {
+
+ let expectedArray = Array(expected)
+
+ let succ = { sliceable.index(after: $0) }
+ let pred = { sliceable.index(before: $0) }
+
+ var start = sliceable.startIndex
+ for startNumericIndex in 0...expectedArray.count {
+ if start != sliceable.endIndex {
+ start = succ(start)
+ start = pred(start)
+ start = succ(start)
+ start = pred(start)
+ }
+ var end = start
+ for endNumericIndex in startNumericIndex...expectedArray.count {
+ if end != sliceable.endIndex {
+ end = succ(end)
+ end = pred(end)
+ end = succ(end)
+ end = pred(end)
+ }
+ let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+ let slice = sliceable[start..<end]
+ // For every possible slice, verify that the slice's bounds are identical
+ // to the indices used to form the slice.
+ expectEqual(start, slice.startIndex)
+ expectEqual(end, slice.endIndex)
+
+ checkOneLevelOfRandomAccessCollection(expectedSlice, slice, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ if end != sliceable.endIndex {
+ end = succ(end)
+ }
+ }
+ if start != sliceable.endIndex {
+ start = succ(start)
+ }
+ }
+}
+
+
+
+// Top-level check for Collection instances. Alias for checkForwardCollection.
+// Checks all slices: O(n^2).
+public func checkCollection<Element, C : Collection>(
+ _ expected: Array<Element>,
+ _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+ checkForwardCollection(expected, collection, message(),
+ stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+}
+
+
+// Calls checkForwardCollection with default `sameValue`.
+public func checkForwardCollection<
+ Element, C : Collection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ C.Element == Element,
+ Element : Equatable {
+
+ checkForwardCollection(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all Collection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkForwardCollection<
+ Element, C : Collection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where
+ C.Element == Element {
+
+ checkOneLevelOfForwardCollection(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+ // Avoid validation of all possible (n^2) slices on large collection.
+ // Test cases should call checkOneLevelOfForwardCollection instead.
+ expectLT(expected.count, 30)
+
+ _checkSliceableWithForwardIndex(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkForwardCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `Collection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfForwardCollection<
+ Element, C : Collection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+ // A `Collection` is a multi-pass `Sequence`.
+ for _ in 0..<3 {
+ checkSequence(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+ }
+
+ //===------------------------------------------------------------------===//
+ // Check Index semantics
+ //===------------------------------------------------------------------===//
+
+ let succ = { collection.index(after: $0) }
+ // Advances up to 1 positions without passing endIndex. Don't use
+ // advanced(by: n) to do this because it's under test here.
+ let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+ // advances up to 5 positions without passing endIndex. Picking a
+ // small constant to avoid complexity explosion on large input
+ // collections.
+ let next5 = { next(next(next(next(next($0))))) }
+
+ let partWay0 = next5(collection.startIndex)
+ let partWay1 = next5(partWay0)
+
+
+ let instances = _allIndices(into: collection,
+ in: collection.startIndex..<partWay0)
+ checkForwardIndex(instances, of: collection,
+ equalityOracle: { $0 == $1 }, endIndex: partWay1, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+ let expectedArray = Array(expected)
+
+ // Check `count`.
+ expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ //===------------------------------------------------------------------===//
+ // Check Iteration behavior.
+ //===------------------------------------------------------------------===//
+
+ for _ in 0..<3 {
+ do {
+ let startIndex = collection.startIndex
+ let endIndex = collection.endIndex
+
+ for _ in collection.indices {
+ expectEqual(
+ startIndex, collection.startIndex,
+ "Iteration should not change startIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqual(
+ endIndex, collection.endIndex,
+ "Iteration should not change endIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+
+ var allIndices = Array(collection.indices)
+
+ if expectedArray.count >= 2 {
+ for i in 0..<allIndices.count-1 {
+ let successor1 = succ(allIndices[i])
+ var successor2 = allIndices[i]
+ successor2 = succ(successor2)
+ var successor3 = allIndices[i]
+ successor3 = succ(successor3)
+ for s in [ successor1, successor2, successor3 ] {
+ expectEqual(allIndices[i + 1], s, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i + 1], collection[s], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+
+
+ } // end of `if expectedArray.count >= 2`
+
+ do {
+ var allIndices2: [C.Index] = []
+ for i in collection.indices {
+ allIndices2.append(i)
+ }
+
+ expectEqualSequence(
+ allIndices, allIndices2, "iteration should not invalidate indices",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqualSequence(
+ expectedArray, allIndices.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ expectEqualSequence(
+ expectedArray, allIndices2.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ } // end of `for _ in 0..<3`
+
+ // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkForwardCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithForwardIndex<
+Element, S : Collection
+>(
+ _ expected: Array<Element>, _ sliceable: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where
+ S.Element == Element {
+
+ let expectedArray = Array(expected)
+
+ let succ = { sliceable.index(after: $0) }
+
+ var start = sliceable.startIndex
+ for startNumericIndex in 0...expectedArray.count {
+ var end = start
+ for endNumericIndex in startNumericIndex...expectedArray.count {
+ let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+ let slice = sliceable[start..<end]
+ // For every possible slice, verify that the slice's bounds are identical
+ // to the indices used to form the slice.
+ expectEqual(start, slice.startIndex)
+ expectEqual(end, slice.endIndex)
+
+ checkOneLevelOfForwardCollection(expectedSlice, slice, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ if end != sliceable.endIndex {
+ end = succ(end)
+ }
+ }
+ if start != sliceable.endIndex {
+ start = succ(start)
+ }
+ }
+}
+
+
+// Calls checkBidirectionalCollection with default `sameValue`.
+public func checkBidirectionalCollection<
+ Element, C : BidirectionalCollection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ C.Element == Element,
+ Element : Equatable {
+
+ checkBidirectionalCollection(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all BidirectionalCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkBidirectionalCollection<
+ Element, C : BidirectionalCollection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where
+ C.Element == Element {
+
+ checkOneLevelOfBidirectionalCollection(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+ // Avoid validation of all possible (n^2) slices on large collection.
+ // Test cases should call checkOneLevelOfBidirectionalCollection instead.
+ expectLT(expected.count, 30)
+
+ _checkSliceableWithBidirectionalIndex(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkBidirectionalCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `BidirectionalCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfBidirectionalCollection<
+ Element, C : BidirectionalCollection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+ // A `Collection` is a multi-pass `Sequence`.
+ for _ in 0..<3 {
+ checkSequence(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+ }
+
+ //===------------------------------------------------------------------===//
+ // Check Index semantics
+ //===------------------------------------------------------------------===//
+
+ let succ = { collection.index(after: $0) }
+ let pred = { collection.index(before: $0) }
+ // Advances up to 1 positions without passing endIndex. Don't use
+ // advanced(by: n) to do this because it's under test here.
+ let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+ // advances up to 5 positions without passing endIndex. Picking a
+ // small constant to avoid complexity explosion on large input
+ // collections.
+ let next5 = { next(next(next(next(next($0))))) }
+
+ let partWay0 = next5(collection.startIndex)
+ let partWay1 = next5(partWay0)
+
+
+ let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+ checkBidirectionalIndex(instances, of: collection,
+ equalityOracle: { $0 == $1 },
+ startIndex: collection.startIndex,
+ endIndex: next5(partWay1), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+ let expectedArray = Array(expected)
+
+ // Check `count`.
+ expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ //===------------------------------------------------------------------===//
+ // Check Iteration behavior.
+ //===------------------------------------------------------------------===//
+
+ for _ in 0..<3 {
+ do {
+ let startIndex = collection.startIndex
+ let endIndex = collection.endIndex
+
+ for _ in collection.indices {
+ expectEqual(
+ startIndex, collection.startIndex,
+ "Iteration should not change startIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqual(
+ endIndex, collection.endIndex,
+ "Iteration should not change endIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+
+ var allIndices = Array(collection.indices)
+
+ if expectedArray.count >= 2 {
+ for i in 0..<allIndices.count-1 {
+ let successor1 = succ(allIndices[i])
+ var successor2 = allIndices[i]
+ successor2 = succ(successor2)
+ var successor3 = allIndices[i]
+ successor3 = succ(successor3)
+ for s in [ successor1, successor2, successor3 ] {
+ expectEqual(allIndices[i + 1], s, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i + 1], collection[s], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+
+
+ for i in 1..<allIndices.count {
+ let predecessor1 = pred(allIndices[i])
+ var predecessor2 = allIndices[i]
+ predecessor2 = pred(predecessor2)
+ var predecessor3 = allIndices[i]
+ predecessor3 = pred(predecessor3)
+ for p in [ predecessor1, predecessor2, predecessor3 ] {
+ expectEqual(allIndices[i - 1], p, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i - 1], collection[p], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+ for i in 1..<allIndices.count {
+ let index = succ(pred(allIndices[i]))
+ expectEqual(allIndices[i], index, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i], collection[index], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+
+
+ } // end of `if expectedArray.count >= 2`
+
+ do {
+ var allIndices2: [C.Index] = []
+ for i in collection.indices {
+ allIndices2.append(i)
+ }
+
+ expectEqualSequence(
+ allIndices, allIndices2, "iteration should not invalidate indices",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqualSequence(
+ expectedArray, allIndices.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ expectEqualSequence(
+ expectedArray, allIndices2.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ } // end of `for _ in 0..<3`
+
+ // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkBidirectionalCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithBidirectionalIndex<
+Element, S : BidirectionalCollection
+>(
+ _ expected: Array<Element>, _ sliceable: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where
+ S.Element == Element {
+
+ let expectedArray = Array(expected)
+
+ let succ = { sliceable.index(after: $0) }
+ let pred = { sliceable.index(before: $0) }
+
+ var start = sliceable.startIndex
+ for startNumericIndex in 0...expectedArray.count {
+ if start != sliceable.endIndex {
+ start = succ(start)
+ start = pred(start)
+ start = succ(start)
+ start = pred(start)
+ }
+ var end = start
+ for endNumericIndex in startNumericIndex...expectedArray.count {
+ if end != sliceable.endIndex {
+ end = succ(end)
+ end = pred(end)
+ end = succ(end)
+ end = pred(end)
+ }
+ let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+ let slice = sliceable[start..<end]
+ // For every possible slice, verify that the slice's bounds are identical
+ // to the indices used to form the slice.
+ expectEqual(start, slice.startIndex)
+ expectEqual(end, slice.endIndex)
+
+ checkOneLevelOfBidirectionalCollection(expectedSlice, slice, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ if end != sliceable.endIndex {
+ end = succ(end)
+ }
+ }
+ if start != sliceable.endIndex {
+ start = succ(start)
+ }
+ }
+}
+
+
+// Calls checkRandomAccessCollection with default `sameValue`.
+public func checkRandomAccessCollection<
+ Element, C : RandomAccessCollection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ C.Element == Element,
+ Element : Equatable {
+
+ checkRandomAccessCollection(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all RandomAccessCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkRandomAccessCollection<
+ Element, C : RandomAccessCollection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where
+ C.Element == Element {
+
+ checkOneLevelOfRandomAccessCollection(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+ // Avoid validation of all possible (n^2) slices on large collection.
+ // Test cases should call checkOneLevelOfRandomAccessCollection instead.
+ expectLT(expected.count, 30)
+
+ _checkSliceableWithRandomAccessIndex(expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkRandomAccessCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `RandomAccessCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfRandomAccessCollection<
+ Element, C : RandomAccessCollection
+>(
+ _ expected: Array<Element>, _ collection: C,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+ // A `Collection` is a multi-pass `Sequence`.
+ for _ in 0..<3 {
+ checkSequence(
+ expected, collection, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+ }
+
+ //===------------------------------------------------------------------===//
+ // Check Index semantics
+ //===------------------------------------------------------------------===//
+
+ let succ = { collection.index(after: $0) }
+ let pred = { collection.index(before: $0) }
+ // Advances up to 1 positions without passing endIndex. Don't use
+ // advanced(by: n) to do this because it's under test here.
+ let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+ // advances up to 5 positions without passing endIndex. Picking a
+ // small constant to avoid complexity explosion on large input
+ // collections.
+ let next5 = { next(next(next(next(next($0))))) }
+
+ let partWay0 = next5(collection.startIndex)
+ let partWay1 = next5(partWay0)
+
+ typealias Distance = Int
+
+ let count: Distance = collection.count
+ let offset0 = min(5, count)
+ let offset1 = min(10, count)
+ let offset2 = min(15, count)
+
+ let distanceCandidates: [Distance] = [
+ -11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
+
+ let distances = distanceCandidates.filter { (x: Distance) -> Bool in
+ x + offset0 >= 0 && x + offset1 <= count
+ }
+
+ func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
+ return collection.index(i, offsetBy: n)
+ }
+
+ let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+
+ checkRandomAccessIndex(
+ instances,
+ distances: distances,
+ of: collection,
+ distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
+ advanceOracle: { x, y in nextN(distances[y], instances[x]) },
+ startIndex: collection.startIndex,
+ endIndex: next5(partWay1), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+ let expectedArray = Array(expected)
+
+ // Check `count`.
+ expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ //===------------------------------------------------------------------===//
+ // Check Iteration behavior.
+ //===------------------------------------------------------------------===//
+
+ for _ in 0..<3 {
+ do {
+ let startIndex = collection.startIndex
+ let endIndex = collection.endIndex
+
+ for _ in collection.indices {
+ expectEqual(
+ startIndex, collection.startIndex,
+ "Iteration should not change startIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqual(
+ endIndex, collection.endIndex,
+ "Iteration should not change endIndex",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ }
+
+ var allIndices = Array(collection.indices)
+
+ if expectedArray.count >= 2 {
+ for i in 0..<allIndices.count-1 {
+ let successor1 = succ(allIndices[i])
+ var successor2 = allIndices[i]
+ successor2 = succ(successor2)
+ var successor3 = allIndices[i]
+ successor3 = succ(successor3)
+ for s in [ successor1, successor2, successor3 ] {
+ expectEqual(allIndices[i + 1], s, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqualTest(
+ expectedArray[i + 1], collection[s], message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ }
+
+
+ } // end of `if expectedArray.count >= 2`
+
+ do {
+ var allIndices2: [C.Index] = []
+ for i in collection.indices {
+ allIndices2.append(i)
+ }
+
+ expectEqualSequence(
+ allIndices, allIndices2, "iteration should not invalidate indices",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ expectEqualSequence(
+ expectedArray, allIndices.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ expectEqualSequence(
+ expectedArray, allIndices2.map { collection[$0] },
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+ } // end of `for _ in 0..<3`
+
+ // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkRandomAccessCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithRandomAccessIndex<
+Element, S : RandomAccessCollection
+>(
+ _ expected: Array<Element>, _ sliceable: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where
+ S.Element == Element {
+
+ let expectedArray = Array(expected)
+
+ let succ = { sliceable.index(after: $0) }
+ let pred = { sliceable.index(before: $0) }
+
+ var start = sliceable.startIndex
+ for startNumericIndex in 0...expectedArray.count {
+ if start != sliceable.endIndex {
+ start = succ(start)
+ start = pred(start)
+ start = succ(start)
+ start = pred(start)
+ }
+ var end = start
+ for endNumericIndex in startNumericIndex...expectedArray.count {
+ if end != sliceable.endIndex {
+ end = succ(end)
+ end = pred(end)
+ end = succ(end)
+ end = pred(end)
+ }
+ let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+ let slice = sliceable[start..<end]
+ // For every possible slice, verify that the slice's bounds are identical
+ // to the indices used to form the slice.
+ expectEqual(start, slice.startIndex)
+ expectEqual(end, slice.endIndex)
+
+ checkOneLevelOfRandomAccessCollection(expectedSlice, slice, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ if end != sliceable.endIndex {
+ end = succ(end)
+ }
+ }
+ if start != sliceable.endIndex {
+ start = succ(start)
+ }
+ }
+}
+
+
+
+// Check RangeReplaceableCollection using a factory.
+//
+// Note: This does not invoke other collection tests.
+public func checkRangeReplaceable<C, N>(
+ _ makeCollection: @escaping () -> C,
+ _ makeNewValues: (Int) -> N
+) where
+ C : RangeReplaceableCollection,
+ N : Collection,
+ C.Element : Equatable,
+ C.Element == N.Element {
+
+ typealias A = C
+
+ // First make an independent copy of the array that we can use for
+ // comparison later.
+ let source = Array<A.Element>(makeCollection())
+
+ for (ix, i) in source.indices.enumerated() {
+ for (jx_, j) in (i..<source.endIndex).enumerated() {
+ let jx = jx_ + ix
+
+ let oldCount = jx - ix
+ for newCount in 0..<(2 * oldCount) {
+ let newValues = makeNewValues(newCount)
+
+ func reportFailure(_ a: inout A, _ message: String) {
+ print("\(message) when replacing indices \(ix)...\(jx)")
+ print(" in \(Array(source)) with \(Array(newValues))")
+ print(" yielding \(Array(a))")
+ print("====================================")
+ expectTrue(false)
+ }
+
+ var a = makeCollection()
+
+ a.replaceSubrange(nthIndex(a, ix)..<nthIndex(a, jx), with: newValues)
+ let growth = newCount - oldCount
+
+ let expectedCount = source.count + growth
+ let actualCount = numericCast(a.count) as Int
+ if actualCount != expectedCount {
+ reportFailure(
+ &a, "\(actualCount) != expected count \(expectedCount)")
+ }
+
+ for (kx, k) in a.indices.enumerated() {
+ let expectedValue = kx < ix ? nth(source, kx)
+ : kx < jx + growth ? nth(newValues, kx - ix)
+ : nth(source, kx - growth)
+
+ if a[k] != expectedValue {
+ reportFailure(
+ &a,
+ // FIXME: why do we need to break this string into two parts?
+ "a[\(kx)] = "
+ + "\(a[k]) != expected value \(expectedValue)")
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
deleted file mode 100644
index 008c400..0000000
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
+++ /dev/null
@@ -1,620 +0,0 @@
-//===--- CheckCollectionInstance.swift.gyb --------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-from gyb_stdlib_support import TRAVERSALS, collectionForTraversal
-}%
-
-import StdlibUnittest
-
-public struct CollectionMisuseResiliencyChecks {
- public enum FailureKind {
- case none
- case trap
- }
-
- public var creatingOutOfBoundsIndicesBehavior: FailureKind = .trap
- public var subscriptOnOutOfBoundsIndicesBehavior: FailureKind = .trap
- public var subscriptRangeOnOutOfBoundsRangesBehavior: FailureKind = .trap
-
- public static var all: CollectionMisuseResiliencyChecks {
- return CollectionMisuseResiliencyChecks()
- }
-
- public static var none: CollectionMisuseResiliencyChecks {
- return CollectionMisuseResiliencyChecks(
- creatingOutOfBoundsIndicesBehavior: .none,
- subscriptOnOutOfBoundsIndicesBehavior: .none,
- subscriptRangeOnOutOfBoundsRangesBehavior: .none)
- }
-}
-
-% for inc, protocol, direction, end in (
-% ('inc', 'Collection', 'after', 'end'),
-% ('dec', 'BidirectionalCollection', 'before', 'start')):
-
-/// Test that the elements of `instances` satisfy
-/// ${'some of ' if inc == 'dec' else ''}the semantic
-/// requirements of `${protocol}`, using `equalityOracle` to
-/// generate equality expectations from pairs of positions in
-/// `instances`.
-///
-/// - Precondition: ${'''`endIndex` is reachable from all
-/// elements of `instances`.''' if inc == 'inc' else '''all
-/// elements of `instances` are reachable from `startIndex`.'''}
-public func check${inc.capitalize()}rementable<Instances, BaseCollection>(
- _ instances: Instances,
- of baseCollection: BaseCollection,
- equalityOracle: (Instances.Index, Instances.Index) -> Bool,
- ${end}Index: Instances.Element, ${TRACE}
-) where
- Instances : Collection,
- BaseCollection : ${protocol},
- Instances.Element == BaseCollection.Index {
-
- checkEquatable(instances, oracle: equalityOracle, ${trace})
- for i in instances {
- if i != ${end}Index {
- let next = baseCollection.index(${direction}: i)
- // index(${direction}:) gets us a new index value
- expectNotEqual(i, next, ${trace})
-
- // Which is the same as if we apply formIndex(${direction}:)
- var j = i
- baseCollection.formIndex(${direction}: &j)
- expectEqual(j, next, ${trace})
- }
- }
-}
-%end
-
-internal func _checkIncrementalAdvance<Instances, BaseCollection>(
- _ instances: Instances,
- of baseCollection : BaseCollection,
- equalityOracle: (Instances.Index, Instances.Index) -> Bool,
- limit: Instances.Element,
- sign: Int, // 1 or -1
- next: (Instances.Element) -> Instances.Element,
- ${TRACE}
-) where
- Instances : Collection,
- BaseCollection : Collection,
- Instances.Element == BaseCollection.Index {
- for i in instances {
- let d: Int = sign > 0 ?
- baseCollection.distance(from: i, to: limit) :
- -baseCollection.distance(from: limit, to: i)
-
- var offset: Int = 0
- for _ in 0...Int64(d * sign) {
- let j = baseCollection.index(i, offsetBy: offset)
- let k = baseCollection.index(i, offsetBy: offset + sign, limitedBy: limit) ?? limit
- let jAtLimit = offset == d
- if jAtLimit {
- expectEqual(limit, j, ${trace})
- }
- expectEqual(jAtLimit ? j : next(j), k, ${trace})
- offset += sign
- }
- }
-}
-
-/// Test that the elements of `instances` satisfy the semantic requirements of
-/// index for `Collection`, using `equalityOracle` to generate equality
-/// expectations from pairs of positions in `instances`.
-///
-/// - Precondition: `endIndex` is reachable from all elements of
-/// `instances`
-public func checkForwardIndex<Instances, BaseCollection>(
- _ instances: Instances,
- of baseCollection: BaseCollection,
- equalityOracle: (Instances.Index, Instances.Index) -> Bool,
- endIndex: Instances.Element, ${TRACE}
-) where
- Instances : Collection,
- BaseCollection : Collection,
- Instances.Element == BaseCollection.Index {
-
- checkIncrementable(instances, of: baseCollection,
- equalityOracle: equalityOracle, endIndex: endIndex, ${trace})
-
- _checkIncrementalAdvance(instances, of: baseCollection,
- equalityOracle: equalityOracle, limit: endIndex,
- sign: 1, next: { baseCollection.index(after: $0) }, ${trace})
-}
-
-/// Test that the elements of `instances` satisfy the semantic requirements of
-/// index for `BidirectionalCollection`, using `equalityOracle` to generate
-/// equality expectations from pairs of positions in `instances`.
-///
-/// - Precondition:
-/// - all elements of `instances` are reachable from `startIndex`.
-/// - `endIndex` is reachable from all elements of `instances`.
-public func checkBidirectionalIndex<Instances, BaseCollection>(
- _ instances: Instances,
- of baseCollection: BaseCollection,
- equalityOracle: (Instances.Index, Instances.Index) -> Bool,
- startIndex: Instances.Element,
- endIndex: Instances.Element,
- ${TRACE}
-) where
- Instances: Collection,
- BaseCollection : BidirectionalCollection,
- Instances.Element == BaseCollection.Index {
-
- checkForwardIndex(instances, of: baseCollection,
- equalityOracle: equalityOracle, endIndex: endIndex)
-
- checkDecrementable(instances, of: baseCollection,
- equalityOracle: equalityOracle, startIndex: startIndex, ${trace})
-
- _checkIncrementalAdvance(instances, of: baseCollection,
- equalityOracle: equalityOracle, limit: startIndex,
- sign: -1, next: { baseCollection.index(before: $0) }, ${trace})
-}
-
-/// Test that the elements of `instances` satisfy the semantic requirements of
-/// index for `RandomAccessCollection`, using `advanceOracle` and
-/// 'distanceOracle' to generate expectations about the results of
-/// `advanced(by:)` and `distance(to:)` from pairs of positions in `instances`
-/// and `distances`.
-///
-/// - Precondition:
-/// - all elements of `instances` are reachable from `startIndex`.
-/// - `endIndex` is reachable from all elements of `instances`.
-public func checkRandomAccessIndex<Instances, Distances, BaseCollection>(
- _ instances: Instances, distances: Distances,
- of baseCollection: BaseCollection,
- distanceOracle:
- (Instances.Index, Instances.Index) -> Distances.Element,
- advanceOracle:
- (Instances.Index, Distances.Index) -> Instances.Element,
- startIndex: Instances.Iterator.Element,
- endIndex: Instances.Iterator.Element,
- ${TRACE}
-) where
- Instances : Collection,
- Distances : Collection,
- BaseCollection : RandomAccessCollection,
- Instances.Element == BaseCollection.Index,
- Distances.Element == Int {
-
- checkBidirectionalIndex(instances, of: baseCollection,
- equalityOracle: { distanceOracle($0, $1) == 0 },
- startIndex: startIndex, endIndex: endIndex, ${trace})
-
- checkAdvancesAndDistances(
- instances, distances: distances,
- of: baseCollection,
- distanceOracle: distanceOracle,
- advanceOracle: advanceOracle, ${trace})
-}
-
-// Copies what checkStrideable is doing, but instead of calling
-// advanced(by:) and distance(to:) on an Strideable's,
-// calls corresponding methods on a base collection.
-public func checkAdvancesAndDistances<Instances, Distances, BaseCollection>(
- _ instances: Instances, distances: Distances,
- of baseCollection: BaseCollection,
- distanceOracle:
- (Instances.Index, Instances.Index) -> Distances.Element,
- advanceOracle:
- (Instances.Index, Distances.Index) -> Instances.Element,
- ${TRACE}
-) where
- Instances : Collection,
- Distances : Collection,
- BaseCollection : Collection,
- Instances.Element == BaseCollection.Index,
- Distances.Element == Int {
-
- checkComparable(
- instances,
- oracle: {
- let d = distanceOracle($1, $0);
- return d < 0 ? .lt : d == 0 ? .eq : .gt
- },
- ${trace})
-
- for i in instances.indices {
- let x = instances[i]
- expectEqual(x, baseCollection.index(x, offsetBy: 0))
-
- for j in distances.indices {
- let y = distances[j]
- expectEqual(advanceOracle(i, j), baseCollection.index(x, offsetBy: y))
- }
-
- for j in instances.indices {
- let y = instances[j]
- expectEqual(distanceOracle(i, j), baseCollection.distance(from: x, to: y))
- }
- }
-}
-
-// Generate two overloads: one for Array (which will get
-// picked up when the caller passes a literal), and another that
-// accepts any appropriate Collection type.
-% for genericParam, Element, Expected in [
-% ('Expected: Collection', 'Expected.Element', 'Expected'),
-% ('Element' , 'Element' , 'Array<Element>')]:
-
-// Top-level check for Collection instances. Alias for checkForwardCollection.
-// Checks all slices: O(n^2).
-public func checkCollection<${genericParam}, C : Collection>(
- _ expected: ${Expected},
- _ collection: C,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- sameValue: (${Element}, ${Element}) -> Bool
-) where C.Element == ${Element} {
-
- checkForwardCollection(expected, collection, message(),
- stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
- resiliencyChecks: resiliencyChecks,
- sameValue: sameValue)
-}
-
-% for Traversal in TRAVERSALS:
-% TraversalCollection = collectionForTraversal(Traversal)
-
-// Calls check${Traversal}Collection with default `sameValue`.
-public func check${Traversal}Collection<
- ${genericParam}, C : ${TraversalCollection}
->(
- _ expected: ${Expected}, _ collection: C,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all
-) where
- C.Element == ${Element},
- ${Element} : Equatable {
-
- check${Traversal}Collection(
- expected, collection, ${trace},
- resiliencyChecks: resiliencyChecks) { $0 == $1 }
-}
-
-// Top-Level check for all ${TraversalCollection} semantics on a single
-// instance. This constrains SubSequence associated types in order to check
-// slice semantics.
-// Checks all slices: O(n^2).
-public func check${Traversal}Collection<
- ${genericParam}, C : ${TraversalCollection}
->(
- _ expected: ${Expected}, _ collection: C,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- sameValue: (${Element}, ${Element}) -> Bool
-) where
- C.Element == ${Element} {
-
- checkOneLevelOf${Traversal}Collection(expected, collection, ${trace},
- resiliencyChecks: resiliencyChecks, sameValue: sameValue)
-
- // Avoid validation of all possible (n^2) slices on large collection.
- // Test cases should call checkOneLevelOf${Traversal}Collection instead.
- expectLT(expected.count, 30)
-
- _checkSliceableWith${Traversal}Index(expected, collection, ${trace},
- resiliencyChecks: resiliencyChecks, sameValue: sameValue)
-}
-
-// Helper for check${Traversal}Collection. Check that instance of `C`,
-// `collection`, upholds the semantics of `${TraversalCollection}`,
-// non-recursively. This does not check subsequences. It may be called for each
-// subsequence without combinatorial explosion. Also, since recursive protocol
-// constraints are not supported, our second level of checks cannot depend on the
-// associated type properties of SubSequence.
-//
-// Checks all slices: O(n^2).
-public func checkOneLevelOf${Traversal}Collection<
- ${genericParam}, C : ${TraversalCollection}
->(
- _ expected: ${Expected}, _ collection: C,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- sameValue: (${Element}, ${Element}) -> Bool
-) where C.Element == ${Element} {
-
- // A `Collection` is a multi-pass `Sequence`.
- for _ in 0..<3 {
- checkSequence(
- expected, collection, ${trace},
- resiliencyChecks: resiliencyChecks, sameValue: sameValue)
- }
-
- //===------------------------------------------------------------------===//
- // Check Index semantics
- //===------------------------------------------------------------------===//
-
- let succ = { collection.index(after: $0) }
-% if Traversal != 'Forward':
- let pred = { collection.index(before: $0) }
-% end
- // Advances up to 1 positions without passing endIndex. Don't use
- // advanced(by: n) to do this because it's under test here.
- let next = { $0 == collection.endIndex ? $0 : succ($0) }
-
- // advances up to 5 positions without passing endIndex. Picking a
- // small constant to avoid complexity explosion on large input
- // collections.
- let next5 = { next(next(next(next(next($0))))) }
-
- let partWay0 = next5(collection.startIndex)
- let partWay1 = next5(partWay0)
-
-% if Traversal == 'Forward':
-
- let instances = _allIndices(into: collection,
- in: collection.startIndex..<partWay0)
- checkForwardIndex(instances, of: collection,
- equalityOracle: { $0 == $1 }, endIndex: partWay1, ${trace})
-
-% elif Traversal == 'Bidirectional':
-
- let instances = _allIndices(into: collection, in: partWay0..<partWay1)
- checkBidirectionalIndex(instances, of: collection,
- equalityOracle: { $0 == $1 },
- startIndex: collection.startIndex,
- endIndex: next5(partWay1), ${trace})
-
-% else:
-% assert(Traversal == 'RandomAccess')
- typealias Distance = Int
-
- let count: Distance = collection.count
- let offset0 = min(5, count)
- let offset1 = min(10, count)
- let offset2 = min(15, count)
-
- let distanceCandidates: [Distance] = [
- -11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
-
- let distances = distanceCandidates.filter { (x: Distance) -> Bool in
- x + offset0 >= 0 && x + offset1 <= count
- }
-
- func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
- return collection.index(i, offsetBy: n)
- }
-
- let instances = _allIndices(into: collection, in: partWay0..<partWay1)
-
- checkRandomAccessIndex(
- instances,
- distances: distances,
- of: collection,
- distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
- advanceOracle: { x, y in nextN(distances[y], instances[x]) },
- startIndex: collection.startIndex,
- endIndex: next5(partWay1), ${trace})
-
-% end
-
- let expectedArray = Array(expected)
-
- // Check `count`.
- expectEqual(Int64(expectedArray.count), Int64(collection.count), ${trace})
-
- //===------------------------------------------------------------------===//
- // Check Iteration behavior.
- //===------------------------------------------------------------------===//
-
- for _ in 0..<3 {
- do {
- let startIndex = collection.startIndex
- let endIndex = collection.endIndex
-
- for _ in collection.indices {
- expectEqual(
- startIndex, collection.startIndex,
- "Iteration should not change startIndex",
- stackTrace: ${stackTrace})
-
- expectEqual(
- endIndex, collection.endIndex,
- "Iteration should not change endIndex",
- stackTrace: ${stackTrace})
- }
- }
-
- var allIndices = Array(collection.indices)
-
- if expectedArray.count >= 2 {
- for i in 0..<allIndices.count-1 {
- let successor1 = succ(allIndices[i])
- var successor2 = allIndices[i]
- successor2 = succ(successor2)
- var successor3 = allIndices[i]
- successor3 = succ(successor3)
- for s in [ successor1, successor2, successor3 ] {
- expectEqual(allIndices[i + 1], s, ${trace})
- expectEqualTest(
- expectedArray[i + 1], collection[s], ${trace}, sameValue: sameValue)
- }
- }
-
-% if Traversal == "Bidirectional":
-
- for i in 1..<allIndices.count {
- let predecessor1 = pred(allIndices[i])
- var predecessor2 = allIndices[i]
- predecessor2 = pred(predecessor2)
- var predecessor3 = allIndices[i]
- predecessor3 = pred(predecessor3)
- for p in [ predecessor1, predecessor2, predecessor3 ] {
- expectEqual(allIndices[i - 1], p, ${trace})
- expectEqualTest(
- expectedArray[i - 1], collection[p], ${trace}, sameValue: sameValue)
- }
- }
- for i in 1..<allIndices.count {
- let index = succ(pred(allIndices[i]))
- expectEqual(allIndices[i], index, ${trace})
- expectEqualTest(
- expectedArray[i], collection[index], ${trace}, sameValue: sameValue)
- }
-
-% end # Traversal == "Bidirectional"
-
- } // end of `if expectedArray.count >= 2`
-
- do {
- var allIndices2: [C.Index] = []
- for i in collection.indices {
- allIndices2.append(i)
- }
-
- expectEqualSequence(
- allIndices, allIndices2, "iteration should not invalidate indices",
- stackTrace: ${stackTrace})
-
- expectEqualSequence(
- expectedArray, allIndices.map { collection[$0] },
- stackTrace: ${stackTrace}, sameValue: sameValue)
- expectEqualSequence(
- expectedArray, allIndices2.map { collection[$0] },
- stackTrace: ${stackTrace}, sameValue: sameValue)
- }
- } // end of `for _ in 0..<3`
-
- // FIXME: more checks for bidirectional and random access collections.
-}
-
-// Helper for check${Traversal}Collection to check Slices.
-//
-// Checks all slices: O(n^2).
-internal func _checkSliceableWith${Traversal}Index<
-${genericParam}, S : ${TraversalCollection}
->(
- _ expected: ${Expected}, _ sliceable: S, ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- sameValue: (${Element}, ${Element}) -> Bool
-) where
- S.Element == ${Element} {
-
- let expectedArray = Array(expected)
-
- let succ = { sliceable.index(after: $0) }
-% if Traversal != "Forward":
- let pred = { sliceable.index(before: $0) }
-% end
-
- var start = sliceable.startIndex
- for startNumericIndex in 0...expectedArray.count {
-% if Traversal != "Forward":
- if start != sliceable.endIndex {
- start = succ(start)
- start = pred(start)
- start = succ(start)
- start = pred(start)
- }
-% end
- var end = start
- for endNumericIndex in startNumericIndex...expectedArray.count {
-% if Traversal != "Forward":
- if end != sliceable.endIndex {
- end = succ(end)
- end = pred(end)
- end = succ(end)
- end = pred(end)
- }
-% end
- let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
- let slice = sliceable[start..<end]
- // For every possible slice, verify that the slice's bounds are identical
- // to the indices used to form the slice.
- expectEqual(start, slice.startIndex)
- expectEqual(end, slice.endIndex)
-
- checkOneLevelOf${Traversal}Collection(expectedSlice, slice, ${trace},
- resiliencyChecks: resiliencyChecks,
- sameValue: sameValue)
-
- if end != sliceable.endIndex {
- end = succ(end)
- }
- }
- if start != sliceable.endIndex {
- start = succ(start)
- }
- }
-}
-
-% end # Traversal
-
-% end # genericParam, Elements, Expected
-
-// Check RangeReplaceableCollection using a factory.
-//
-// Note: This does not invoke other collection tests.
-public func checkRangeReplaceable<C, N>(
- _ makeCollection: @escaping () -> C,
- _ makeNewValues: (Int) -> N
-) where
- C : RangeReplaceableCollection,
- N : Collection,
- C.Element : Equatable,
- C.Element == N.Element {
-
- typealias A = C
-
- // First make an independent copy of the array that we can use for
- // comparison later.
- let source = Array<A.Element>(makeCollection())
-
- for (ix, i) in source.indices.enumerated() {
- for (jx_, j) in (i..<source.endIndex).enumerated() {
- let jx = jx_ + ix
-
- let oldCount = jx - ix
- for newCount in 0..<(2 * oldCount) {
- let newValues = makeNewValues(newCount)
-
- func reportFailure(_ a: inout A, _ message: String) {
- print("\(message) when replacing indices \(ix)...\(jx)")
- print(" in \(Array(source)) with \(Array(newValues))")
- print(" yielding \(Array(a))")
- print("====================================")
- expectTrue(false)
- }
-
- var a = makeCollection()
-
- a.replaceSubrange(nthIndex(a, ix)..<nthIndex(a, jx), with: newValues)
- let growth = newCount - oldCount
-
- let expectedCount = source.count + growth
- let actualCount = numericCast(a.count) as Int
- if actualCount != expectedCount {
- reportFailure(
- &a, "\(actualCount) != expected count \(expectedCount)")
- }
-
- for (kx, k) in a.indices.enumerated() {
- let expectedValue = kx < ix ? nth(source, kx)
- : kx < jx + growth ? nth(newValues, kx - ix)
- : nth(source, kx - growth)
-
- if a[k] != expectedValue {
- reportFailure(
- &a,
- // FIXME: why do we need to break this string into two parts?
- "a[\(kx)] = "
- + "\(a[k]) != expected value \(expectedValue)")
- }
- }
- }
- }
- }
-}
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift
similarity index 69%
rename from stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
rename to stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift
index a15353c..ddd179f 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift
@@ -468,49 +468,36 @@
}
}
-%{
- from gyb_stdlib_support import collectionForTraversal
- def testConstraints(protocol):
- return '''
- C : %(protocol)s,
- CollectionWithEquatableElement : %(protocol)s,
- CollectionWithEquatableElement.Iterator.Element : Equatable
- ''' % locals()
-
- testParams = '''
- _ testNamePrefix: String = "",
- makeCollection: @escaping ([C.Iterator.Element]) -> C,
- wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
- extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
-
- makeCollectionOfEquatable: @escaping (
- [CollectionWithEquatableElement.Iterator.Element]
- ) -> CollectionWithEquatableElement,
-
- wrapValueIntoEquatable: @escaping (
- MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
-
- extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
-
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- outOfBoundsIndexOffset: Int = 1,
- outOfBoundsSubscriptOffset: Int = 1,
- collectionIsBidirectional: Bool
- '''
-
- import re
- forwardTestArgs = ',\n '.join(
- [ x.group(1) + ': ' + x.group(1)
- for x in re.finditer(r'([a-zA-Z0-9_]+):', testParams) ]
- ).replace('testNamePrefix: ', '\n ')
-}%
extension TestSuite {
public func addCollectionTests<
C, CollectionWithEquatableElement
>(
- ${testParams} = false
+
+ _ testNamePrefix: String = "",
+ makeCollection: @escaping ([C.Iterator.Element]) -> C,
+ wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+ extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+ makeCollectionOfEquatable: @escaping (
+ [CollectionWithEquatableElement.Iterator.Element]
+ ) -> CollectionWithEquatableElement,
+
+ wrapValueIntoEquatable: @escaping (
+ MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+ extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ outOfBoundsIndexOffset: Int = 1,
+ outOfBoundsSubscriptOffset: Int = 1,
+ collectionIsBidirectional: Bool
+ = false
) where
- ${testConstraints('Collection')} {
+
+ C : Collection,
+ CollectionWithEquatableElement : Collection,
+ CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
var testNamePrefix = testNamePrefix
@@ -827,13 +814,13 @@
}
//===------------------------------------------------------------------===//
- // index(of:)/index(where:)
+ // firstIndex(of:)/firstIndex(where:)
//===------------------------------------------------------------------===//
- self.test("\(testNamePrefix).index(of:)/semantics") {
+ self.test("\(testNamePrefix).firstIndex(of:)/semantics") {
for test in findTests {
let c = makeWrappedCollectionWithEquatableElement(test.sequence)
- var result = c.index(of: wrapValueIntoEquatable(test.element))
+ var result = c.firstIndex(of: wrapValueIntoEquatable(test.element))
expectType(
Optional<CollectionWithEquatableElement.Index>.self,
&result)
@@ -847,12 +834,12 @@
}
}
- self.test("\(testNamePrefix).index(where:)/semantics") {
+ self.test("\(testNamePrefix).firstIndex(where:)/semantics") {
for test in findTests {
let closureLifetimeTracker = LifetimeTracked(0)
expectEqual(1, LifetimeTracked.instances)
let c = makeWrappedCollectionWithEquatableElement(test.sequence)
- let result = c.index {
+ let result = c.firstIndex {
(candidate) in
_blackHole(closureLifetimeTracker)
return
@@ -1166,15 +1153,49 @@
}
//===------------------------------------------------------------------===//
- self.addCommonTests(${forwardTestArgs})
+ self.addCommonTests(
+ testNamePrefix,
+ makeCollection: makeCollection,
+ wrapValue: wrapValue,
+ extractValue: extractValue,
+ makeCollectionOfEquatable: makeCollectionOfEquatable,
+ wrapValueIntoEquatable: wrapValueIntoEquatable,
+ extractValueFromEquatable: extractValueFromEquatable,
+ resiliencyChecks: resiliencyChecks,
+ outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+ outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+ collectionIsBidirectional: collectionIsBidirectional)
} // addCollectionTests
public func addBidirectionalCollectionTests<
C, CollectionWithEquatableElement
>(
- ${testParams} = true
+
+ _ testNamePrefix: String = "",
+ makeCollection: @escaping ([C.Iterator.Element]) -> C,
+ wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+ extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+ makeCollectionOfEquatable: @escaping (
+ [CollectionWithEquatableElement.Iterator.Element]
+ ) -> CollectionWithEquatableElement,
+
+ wrapValueIntoEquatable: @escaping (
+ MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+ extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ outOfBoundsIndexOffset: Int = 1,
+ outOfBoundsSubscriptOffset: Int = 1,
+ collectionIsBidirectional: Bool
+ = true
) where
- ${testConstraints('BidirectionalCollection')} {
+
+ C : BidirectionalCollection,
+ CollectionWithEquatableElement : BidirectionalCollection,
+ CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
var testNamePrefix = testNamePrefix
@@ -1184,7 +1205,18 @@
return
}
- addCollectionTests(${forwardTestArgs})
+ addCollectionTests(
+ testNamePrefix,
+ makeCollection: makeCollection,
+ wrapValue: wrapValue,
+ extractValue: extractValue,
+ makeCollectionOfEquatable: makeCollectionOfEquatable,
+ wrapValueIntoEquatable: wrapValueIntoEquatable,
+ extractValueFromEquatable: extractValueFromEquatable,
+ resiliencyChecks: resiliencyChecks,
+ outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+ outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+ collectionIsBidirectional: collectionIsBidirectional)
func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
return makeCollection(elements.map(wrapValue))
@@ -1484,15 +1516,49 @@
//===------------------------------------------------------------------===//
- self.addCommonTests(${forwardTestArgs})
+ self.addCommonTests(
+ testNamePrefix,
+ makeCollection: makeCollection,
+ wrapValue: wrapValue,
+ extractValue: extractValue,
+ makeCollectionOfEquatable: makeCollectionOfEquatable,
+ wrapValueIntoEquatable: wrapValueIntoEquatable,
+ extractValueFromEquatable: extractValueFromEquatable,
+ resiliencyChecks: resiliencyChecks,
+ outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+ outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+ collectionIsBidirectional: collectionIsBidirectional)
} // addBidirectionalCollectionTests
public func addRandomAccessCollectionTests<
C, CollectionWithEquatableElement
>(
- ${testParams} = true
+
+ _ testNamePrefix: String = "",
+ makeCollection: @escaping ([C.Iterator.Element]) -> C,
+ wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+ extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+ makeCollectionOfEquatable: @escaping (
+ [CollectionWithEquatableElement.Iterator.Element]
+ ) -> CollectionWithEquatableElement,
+
+ wrapValueIntoEquatable: @escaping (
+ MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+ extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ outOfBoundsIndexOffset: Int = 1,
+ outOfBoundsSubscriptOffset: Int = 1,
+ collectionIsBidirectional: Bool
+ = true
) where
- ${testConstraints('RandomAccessCollection')} {
+
+ C : RandomAccessCollection,
+ CollectionWithEquatableElement : RandomAccessCollection,
+ CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
var testNamePrefix = testNamePrefix
@@ -1502,7 +1568,18 @@
return
}
- addBidirectionalCollectionTests(${forwardTestArgs})
+ addBidirectionalCollectionTests(
+ testNamePrefix,
+ makeCollection: makeCollection,
+ wrapValue: wrapValue,
+ extractValue: extractValue,
+ makeCollectionOfEquatable: makeCollectionOfEquatable,
+ wrapValueIntoEquatable: wrapValueIntoEquatable,
+ extractValueFromEquatable: extractValueFromEquatable,
+ resiliencyChecks: resiliencyChecks,
+ outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+ outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+ collectionIsBidirectional: collectionIsBidirectional)
testNamePrefix += String(describing: C.Type.self)
@@ -1539,16 +1616,49 @@
}
//===------------------------------------------------------------------===//
- self.addCommonTests(${forwardTestArgs})
+ self.addCommonTests(
+ testNamePrefix,
+ makeCollection: makeCollection,
+ wrapValue: wrapValue,
+ extractValue: extractValue,
+ makeCollectionOfEquatable: makeCollectionOfEquatable,
+ wrapValueIntoEquatable: wrapValueIntoEquatable,
+ extractValueFromEquatable: extractValueFromEquatable,
+ resiliencyChecks: resiliencyChecks,
+ outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+ outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+ collectionIsBidirectional: collectionIsBidirectional)
} // addRandomAccessCollectionTests
-% for Traversal in ['Forward', 'Bidirectional', 'RandomAccess']:
func addCommonTests<
C, CollectionWithEquatableElement
>(
- ${testParams}
+
+ _ testNamePrefix: String = "",
+ makeCollection: @escaping ([C.Iterator.Element]) -> C,
+ wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+ extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+ makeCollectionOfEquatable: @escaping (
+ [CollectionWithEquatableElement.Iterator.Element]
+ ) -> CollectionWithEquatableElement,
+
+ wrapValueIntoEquatable: @escaping (
+ MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+ extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ outOfBoundsIndexOffset: Int = 1,
+ outOfBoundsSubscriptOffset: Int = 1,
+ collectionIsBidirectional: Bool
+
) where
- ${testConstraints(collectionForTraversal(Traversal))} {
+
+ C : Collection,
+ CollectionWithEquatableElement : Collection,
+ CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
if !checksAdded.insert(
"\(testNamePrefix).\(C.self).\(#function)"
@@ -1560,8 +1670,7 @@
return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
}
-% for function_name in ['index', 'formIndex']:
- self.test("\(testNamePrefix).${function_name}(after:)/semantics") {
+ self.test("\(testNamePrefix).index(after:)/semantics") {
for test in indexAfterTests {
let c = toCollection(test.start..<test.end)
var currentIndex = c.startIndex
@@ -1569,16 +1678,24 @@
repeat {
expectEqual(counter, extractValue(c[currentIndex]).value,
stackTrace: SourceLocStack().with(test.loc))
-% if function_name is 'index':
currentIndex = c.index(after: currentIndex)
-% else:
- c.formIndex(after: ¤tIndex)
-% end
counter += 1
} while counter < test.end
}
}
-% end
+ self.test("\(testNamePrefix).formIndex(after:)/semantics") {
+ for test in indexAfterTests {
+ let c = toCollection(test.start..<test.end)
+ var currentIndex = c.startIndex
+ var counter = test.start
+ repeat {
+ expectEqual(counter, extractValue(c[currentIndex]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ c.formIndex(after: ¤tIndex)
+ counter += 1
+ } while counter < test.end
+ }
+ }
self.test("\(testNamePrefix)/distance(from:to:)/semantics")
.forEach(in: distanceFromToTests) {
@@ -1637,31 +1754,36 @@
stackTrace: SourceLocStack().with(test.loc))
}
-% for function_name in ['index', 'formIndex']:
- self.test("\(testNamePrefix)/${function_name}(_:offsetBy: -n)/semantics")
+ self.test("\(testNamePrefix)/index(_:offsetBy: -n)/semantics")
.forEach(
in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
) {
test in
let c = toCollection(0..<20)
-% if function_name is 'index':
let start = c.nthIndex(test.startOffset)
-% else:
- var new = c.nthIndex(test.startOffset)
-% end
if test.expectedOffset! < 0 || !collectionIsBidirectional {
expectCrashLater()
}
-% if function_name is 'index':
let new = c.index(start, offsetBy: numericCast(test.distance))
-% else:
- c.formIndex(&new, offsetBy: numericCast(test.distance))
-% end
expectEqual(test.expectedOffset!, extractValue(c[new]).value,
stackTrace: SourceLocStack().with(test.loc))
}
-% end
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ var new = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! < 0 || !collectionIsBidirectional {
+ expectCrashLater()
+ }
+ c.formIndex(&new, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
self.test("\(testNamePrefix)/index(_:offsetBy: n, limitedBy:)/semantics") {
for test in indexOffsetByTests.filter(
@@ -1757,5 +1879,502 @@
}
}
-% end
+ func addCommonTests<
+ C, CollectionWithEquatableElement
+ >(
+
+ _ testNamePrefix: String = "",
+ makeCollection: @escaping ([C.Iterator.Element]) -> C,
+ wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+ extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+ makeCollectionOfEquatable: @escaping (
+ [CollectionWithEquatableElement.Iterator.Element]
+ ) -> CollectionWithEquatableElement,
+
+ wrapValueIntoEquatable: @escaping (
+ MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+ extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ outOfBoundsIndexOffset: Int = 1,
+ outOfBoundsSubscriptOffset: Int = 1,
+ collectionIsBidirectional: Bool
+
+ ) where
+
+ C : BidirectionalCollection,
+ CollectionWithEquatableElement : BidirectionalCollection,
+ CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
+
+ if !checksAdded.insert(
+ "\(testNamePrefix).\(C.self).\(#function)"
+ ).inserted {
+ return
+ }
+
+ func toCollection(_ r: Range<Int>) -> C {
+ return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
+ }
+
+ self.test("\(testNamePrefix).index(after:)/semantics") {
+ for test in indexAfterTests {
+ let c = toCollection(test.start..<test.end)
+ var currentIndex = c.startIndex
+ var counter = test.start
+ repeat {
+ expectEqual(counter, extractValue(c[currentIndex]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ currentIndex = c.index(after: currentIndex)
+ counter += 1
+ } while counter < test.end
+ }
+ }
+ self.test("\(testNamePrefix).formIndex(after:)/semantics") {
+ for test in indexAfterTests {
+ let c = toCollection(test.start..<test.end)
+ var currentIndex = c.startIndex
+ var counter = test.start
+ repeat {
+ expectEqual(counter, extractValue(c[currentIndex]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ c.formIndex(after: ¤tIndex)
+ counter += 1
+ } while counter < test.end
+ }
+ }
+
+ self.test("\(testNamePrefix)/distance(from:to:)/semantics")
+ .forEach(in: distanceFromToTests) {
+ test in
+ let c = toCollection(0..<20)
+ let backwards = (test.startOffset > test.endOffset)
+ if backwards && !collectionIsBidirectional {
+ expectCrashLater()
+ }
+
+ let d = c.distance(
+ from: c.nthIndex(test.startOffset), to: c.nthIndex(test.endOffset))
+ expectEqual(
+ numericCast(test.expectedDistance),
+ d, stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+ ) {
+ test in
+ let max = 10
+ let c = toCollection(0..<max)
+
+ if test.expectedOffset! >= max {
+ expectCrashLater()
+ }
+ let new = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance))
+
+ // Since the `nthIndex(offset:)` method performs the same operation
+ // (i.e. advances `c.startIndex` by `test.distance`, it would be
+ // silly to compare index values. Luckily the underlying collection
+ // contains exactly index offsets.
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+ ) {
+ test in
+ let max = 10
+ let c = toCollection(0..<max)
+
+ var new = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! >= max {
+ expectCrashLater()
+ }
+ c.formIndex(&new, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: -n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ let start = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! < 0 || !collectionIsBidirectional {
+ expectCrashLater()
+ }
+ let new = c.index(start, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ var new = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! < 0 || !collectionIsBidirectional {
+ expectCrashLater()
+ }
+ c.formIndex(&new, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: n, limitedBy:)/semantics") {
+ for test in indexOffsetByTests.filter(
+ {$0.limit != nil && $0.distance >= 0}
+ ) {
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ let new = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new!,
+ stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ expectNil(new)
+ }
+ }
+ }
+
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: n, limitedBy:)/semantics") {
+ for test in indexOffsetByTests.filter(
+ {$0.limit != nil && $0.distance >= 0}
+ ) {
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ var new = c.nthIndex(test.startOffset)
+ let exact = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new,
+ stackTrace: SourceLocStack().with(test.loc))
+ expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ // Clamped to the limit
+ expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+ expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+ }
+ }
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: -n, limitedBy:)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ if collectionIsBidirectional {
+ let new = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new!,
+ stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ expectNil(new)
+ }
+ } else {
+ expectCrashLater()
+ _ = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ }
+ }
+
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n, limitedBy:)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ var new = c.nthIndex(test.startOffset)
+ if collectionIsBidirectional {
+ let exact = c.formIndex(
+ &new,
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new,
+ stackTrace: SourceLocStack().with(test.loc))
+ expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+ expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+ }
+ } else {
+ expectCrashLater()
+ _ = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+ }
+ }
+
+ }
+ func addCommonTests<
+ C, CollectionWithEquatableElement
+ >(
+
+ _ testNamePrefix: String = "",
+ makeCollection: @escaping ([C.Iterator.Element]) -> C,
+ wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+ extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+ makeCollectionOfEquatable: @escaping (
+ [CollectionWithEquatableElement.Iterator.Element]
+ ) -> CollectionWithEquatableElement,
+
+ wrapValueIntoEquatable: @escaping (
+ MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+ extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ outOfBoundsIndexOffset: Int = 1,
+ outOfBoundsSubscriptOffset: Int = 1,
+ collectionIsBidirectional: Bool
+
+ ) where
+
+ C : RandomAccessCollection,
+ CollectionWithEquatableElement : RandomAccessCollection,
+ CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
+
+ if !checksAdded.insert(
+ "\(testNamePrefix).\(C.self).\(#function)"
+ ).inserted {
+ return
+ }
+
+ func toCollection(_ r: Range<Int>) -> C {
+ return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
+ }
+
+ self.test("\(testNamePrefix).index(after:)/semantics") {
+ for test in indexAfterTests {
+ let c = toCollection(test.start..<test.end)
+ var currentIndex = c.startIndex
+ var counter = test.start
+ repeat {
+ expectEqual(counter, extractValue(c[currentIndex]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ currentIndex = c.index(after: currentIndex)
+ counter += 1
+ } while counter < test.end
+ }
+ }
+ self.test("\(testNamePrefix).formIndex(after:)/semantics") {
+ for test in indexAfterTests {
+ let c = toCollection(test.start..<test.end)
+ var currentIndex = c.startIndex
+ var counter = test.start
+ repeat {
+ expectEqual(counter, extractValue(c[currentIndex]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ c.formIndex(after: ¤tIndex)
+ counter += 1
+ } while counter < test.end
+ }
+ }
+
+ self.test("\(testNamePrefix)/distance(from:to:)/semantics")
+ .forEach(in: distanceFromToTests) {
+ test in
+ let c = toCollection(0..<20)
+ let backwards = (test.startOffset > test.endOffset)
+ if backwards && !collectionIsBidirectional {
+ expectCrashLater()
+ }
+
+ let d = c.distance(
+ from: c.nthIndex(test.startOffset), to: c.nthIndex(test.endOffset))
+ expectEqual(
+ numericCast(test.expectedDistance),
+ d, stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+ ) {
+ test in
+ let max = 10
+ let c = toCollection(0..<max)
+
+ if test.expectedOffset! >= max {
+ expectCrashLater()
+ }
+ let new = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance))
+
+ // Since the `nthIndex(offset:)` method performs the same operation
+ // (i.e. advances `c.startIndex` by `test.distance`, it would be
+ // silly to compare index values. Luckily the underlying collection
+ // contains exactly index offsets.
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+ ) {
+ test in
+ let max = 10
+ let c = toCollection(0..<max)
+
+ var new = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! >= max {
+ expectCrashLater()
+ }
+ c.formIndex(&new, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: -n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ let start = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! < 0 || !collectionIsBidirectional {
+ expectCrashLater()
+ }
+ let new = c.index(start, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ var new = c.nthIndex(test.startOffset)
+
+ if test.expectedOffset! < 0 || !collectionIsBidirectional {
+ expectCrashLater()
+ }
+ c.formIndex(&new, offsetBy: numericCast(test.distance))
+ expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+ stackTrace: SourceLocStack().with(test.loc))
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: n, limitedBy:)/semantics") {
+ for test in indexOffsetByTests.filter(
+ {$0.limit != nil && $0.distance >= 0}
+ ) {
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ let new = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new!,
+ stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ expectNil(new)
+ }
+ }
+ }
+
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: n, limitedBy:)/semantics") {
+ for test in indexOffsetByTests.filter(
+ {$0.limit != nil && $0.distance >= 0}
+ ) {
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ var new = c.nthIndex(test.startOffset)
+ let exact = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new,
+ stackTrace: SourceLocStack().with(test.loc))
+ expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ // Clamped to the limit
+ expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+ expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+ }
+ }
+ }
+
+ self.test("\(testNamePrefix)/index(_:offsetBy: -n, limitedBy:)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ if collectionIsBidirectional {
+ let new = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new!,
+ stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ expectNil(new)
+ }
+ } else {
+ expectCrashLater()
+ _ = c.index(
+ c.nthIndex(test.startOffset),
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ }
+ }
+
+ self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n, limitedBy:)/semantics")
+ .forEach(
+ in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+ ) {
+ test in
+ let c = toCollection(0..<20)
+ let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+ var new = c.nthIndex(test.startOffset)
+ if collectionIsBidirectional {
+ let exact = c.formIndex(
+ &new,
+ offsetBy: numericCast(test.distance),
+ limitedBy: limit)
+ if let expectedOffset = test.expectedOffset {
+ expectEqual(c.nthIndex(expectedOffset), new,
+ stackTrace: SourceLocStack().with(test.loc))
+ expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+ } else {
+ expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+ expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+ }
+ } else {
+ expectCrashLater()
+ _ = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+ }
+ }
+
+ }
}
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift
similarity index 86%
rename from stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
rename to stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift
index b5560d9..2c2bd70 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift
@@ -446,7 +446,8 @@
var c = makeWrappedCollection(test.collection)
var result = c._withUnsafeMutableBufferPointerIfSupported {
(bufferPointer) -> OpaqueValue<Array<OpaqueValue<Int>>> in
- return OpaqueValue(bufferPointer.map(extractValue))
+ let value = OpaqueValue(bufferPointer.map(extractValue))
+ return value
}
expectType(Optional<OpaqueValue<Array<OpaqueValue<Int>>>>.self, &result)
if withUnsafeMutableBufferPointerIsSupported {
@@ -492,7 +493,7 @@
expectEqualSequence(
elements.map { $0.value },
c.map { extract($0).value })
-
+
// If `sorted` throws then result will be empty else
// returned result must be sorted.
if thrown {
@@ -511,33 +512,18 @@
}
}
-% for predicate in [False, True]:
-
-self.test("\(testNamePrefix).sorted/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/${'Predicate' if predicate else 'WhereElementIsComparable'}") {
+self.test("\(testNamePrefix).sorted/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/WhereElementIsComparable") {
let sequence = [ 5, 4, 3, 2, 1 ]
-% if predicate:
- let elements: [OpaqueValue<Int>] =
- zip(sequence, 0..<sequence.count).map {
- OpaqueValue($0, identity: $1)
- }
- let c = makeWrappedCollection(elements)
-% else:
let elements: [MinimalComparableValue] =
zip(sequence, 0..<sequence.count).map {
MinimalComparableValue($0, identity: $1)
}
let c = makeWrappedCollectionWithComparableElement(elements)
-% end
var lc = LoggingMutableCollection(wrapping: c)
-% if predicate:
- let result = lc.sorted { extractValue($0).value < extractValue($1).value }
- let extractedResult = result.map(extractValue)
-% else:
let result = lc.sorted()
let extractedResult = result.map(extractValueFromComparable)
-% end
// This sort operation is not in-place.
// The collection is copied into an array before sorting.
@@ -550,26 +536,12 @@
expectEqualSequence([ 1, 2, 3, 4, 5 ], extractedResult.map { $0.value })
}
-func checkSort_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+func checkSort_WhereElementIsComparable(
sequence: [Int],
equalImpl: @escaping ((Int, Int) -> Bool),
lessImpl: @escaping ((Int, Int) -> Bool),
verifyOrder: Bool
) {
-% if predicate:
- let extract = extractValue
- let elements: [OpaqueValue<Int>] =
- zip(sequence, 0..<sequence.count).map {
- OpaqueValue($0, identity: $1)
- }
- let c = makeWrappedCollection(elements)
- let closureLifetimeTracker = LifetimeTracked(0)
- let result = c.sorted {
- (lhs, rhs) in
- _blackHole(closureLifetimeTracker)
- return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
- }
-% else:
MinimalComparableValue.equalImpl.value = equalImpl
MinimalComparableValue.lessImpl.value = lessImpl
@@ -580,7 +552,6 @@
}
let c = makeWrappedCollectionWithComparableElement(elements)
let result = c.sorted()
-% end
// Check that the original collection is unchanged.
expectEqualSequence(
@@ -606,10 +577,10 @@
}
}
-self.test("\(testNamePrefix).sorted/${'Predicate' if predicate else 'WhereElementIsComparable'}") {
+self.test("\(testNamePrefix).sorted/WhereElementIsComparable") {
for test in partitionExhaustiveTests {
forAllPermutations(test.sequence) { (sequence) in
- checkSort_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+ checkSort_WhereElementIsComparable(
sequence: sequence,
equalImpl: { $0 == $1 },
lessImpl: { $0 < $1 },
@@ -618,11 +589,11 @@
}
}
-self.test("\(testNamePrefix).sorted/${'Predicate' if predicate else 'WhereElementIsComparable'}/InvalidOrderings") {
+self.test("\(testNamePrefix).sorted/WhereElementIsComparable/InvalidOrderings") {
withInvalidOrderings { (comparisonPredicate: @escaping (Int, Int) -> Bool) in
for i in 0..<7 {
forAllPermutations(i) { (sequence) in
- checkSort_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+ checkSort_WhereElementIsComparable(
sequence: sequence,
equalImpl: {
!comparisonPredicate($0, $1) &&
@@ -659,7 +630,127 @@
}
}
-% end
+
+self.test("\(testNamePrefix).sorted/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/Predicate") {
+ let sequence = [ 5, 4, 3, 2, 1 ]
+ let elements: [OpaqueValue<Int>] =
+ zip(sequence, 0..<sequence.count).map {
+ OpaqueValue($0, identity: $1)
+ }
+ let c = makeWrappedCollection(elements)
+
+ var lc = LoggingMutableCollection(wrapping: c)
+
+ let result = lc.sorted { extractValue($0).value < extractValue($1).value }
+ let extractedResult = result.map(extractValue)
+
+ // This sort operation is not in-place.
+ // The collection is copied into an array before sorting.
+ expectEqual(
+ 0, lc.log._withUnsafeMutableBufferPointerIfSupported[type(of: lc)])
+ expectEqual(
+ 0,
+ lc.log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[type(of: lc)])
+
+ expectEqualSequence([ 1, 2, 3, 4, 5 ], extractedResult.map { $0.value })
+}
+
+func checkSort_Predicate(
+ sequence: [Int],
+ equalImpl: @escaping ((Int, Int) -> Bool),
+ lessImpl: @escaping ((Int, Int) -> Bool),
+ verifyOrder: Bool
+) {
+ let extract = extractValue
+ let elements: [OpaqueValue<Int>] =
+ zip(sequence, 0..<sequence.count).map {
+ OpaqueValue($0, identity: $1)
+ }
+ let c = makeWrappedCollection(elements)
+ let closureLifetimeTracker = LifetimeTracked(0)
+ let result = c.sorted {
+ (lhs, rhs) in
+ _blackHole(closureLifetimeTracker)
+ return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
+ }
+
+ // Check that the original collection is unchanged.
+ expectEqualSequence(
+ elements.map { $0.value },
+ c.map { extract($0).value })
+
+ let extractedResult = result.map(extract)
+
+ // Check that we didn't lose any elements.
+ expectEqualsUnordered(
+ 0..<sequence.count,
+ extractedResult.map { $0.identity })
+
+ // Check that the elements are sorted.
+ if verifyOrder {
+ for i in extractedResult.indices {
+ if i != extractedResult.index(before: extractedResult.endIndex) {
+ let first = extractedResult[i].value
+ let second = extractedResult[extractedResult.index(after: i)].value
+ expectFalse(lessImpl(second, first))
+ }
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sorted/Predicate") {
+ for test in partitionExhaustiveTests {
+ forAllPermutations(test.sequence) { (sequence) in
+ checkSort_Predicate(
+ sequence: sequence,
+ equalImpl: { $0 == $1 },
+ lessImpl: { $0 < $1 },
+ verifyOrder: true)
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sorted/Predicate/InvalidOrderings") {
+ withInvalidOrderings { (comparisonPredicate: @escaping (Int, Int) -> Bool) in
+ for i in 0..<7 {
+ forAllPermutations(i) { (sequence) in
+ checkSort_Predicate(
+ sequence: sequence,
+ equalImpl: {
+ !comparisonPredicate($0, $1) &&
+ !comparisonPredicate($1, $0)
+ },
+ lessImpl: comparisonPredicate,
+ verifyOrder: false)
+ }
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sorted/ThrowingPredicate") {
+ for test in partitionExhaustiveTests {
+ forAllPermutations(test.sequence) { (sequence) in
+ for i in 0..<sequence.count {
+ checkSortedPredicateThrow(
+ sequence: sequence,
+ lessImpl: { $0 < $1 },
+ throwIndex: i)
+ }
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sorted/ThrowingPredicateWithLargeNumberElements") {
+ for sequence in largeElementSortTests {
+ for i in 0..<sequence.count {
+ checkSortedPredicateThrow(
+ sequence: sequence,
+ lessImpl: { $0 < $1 },
+ throwIndex: i)
+ }
+ }
+}
+
//===----------------------------------------------------------------------===//
// partition(by:)
@@ -993,36 +1084,20 @@
return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
}
} catch {}
-
+
//Check no element should lost and added
expectEqualsUnordered(
sequence,
c.map { extract($0).value })
}
-% for predicate in [False, True]:
-func checkSortInPlace_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+func checkSortInPlace_WhereElementIsComparable(
sequence: [Int],
equalImpl: @escaping ((Int, Int) -> Bool),
lessImpl: @escaping ((Int, Int) -> Bool),
verifyOrder: Bool
) {
-% if predicate:
- let extract = extractValue
- let elements: [OpaqueValue<Int>] =
- zip(sequence, 0..<sequence.count).map {
- OpaqueValue($0, identity: $1)
- }
-
- var c = makeWrappedCollection(elements)
- let closureLifetimeTracker = LifetimeTracked(0)
- c.sort {
- (lhs, rhs) in
- _blackHole(closureLifetimeTracker)
- return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
- }
-% else:
MinimalComparableValue.equalImpl.value = equalImpl
MinimalComparableValue.lessImpl.value = lessImpl
@@ -1034,7 +1109,6 @@
var c = makeWrappedCollectionWithComparableElement(elements)
c.sort()
-% end
let extractedResult = c.map(extract)
@@ -1055,10 +1129,10 @@
}
}
-self.test("\(testNamePrefix).sort/${'Predicate' if predicate else 'WhereElementIsEquatable'}") {
+self.test("\(testNamePrefix).sort/WhereElementIsEquatable") {
for test in partitionExhaustiveTests {
forAllPermutations(test.sequence) { (sequence) in
- checkSortInPlace_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+ checkSortInPlace_WhereElementIsComparable(
sequence: sequence,
equalImpl: { $0 == $1 },
lessImpl: { $0 < $1 },
@@ -1067,11 +1141,11 @@
}
}
-self.test("\(testNamePrefix).sort/${'Predicate' if predicate else 'WhereElementIsEquatable'}/InvalidOrderings") {
+self.test("\(testNamePrefix).sort/WhereElementIsEquatable/InvalidOrderings") {
withInvalidOrderings { (comparisonPredicate : @escaping (Int, Int) -> Bool) in
for i in 0..<7 {
forAllPermutations(i) { (sequence) in
- checkSortInPlace_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+ checkSortInPlace_WhereElementIsComparable(
sequence: sequence,
equalImpl: {
!comparisonPredicate($0, $1) &&
@@ -1107,8 +1181,99 @@
}
}
}
-
-% end
+
+
+func checkSortInPlace_Predicate(
+ sequence: [Int],
+ equalImpl: @escaping ((Int, Int) -> Bool),
+ lessImpl: @escaping ((Int, Int) -> Bool),
+ verifyOrder: Bool
+) {
+ let extract = extractValue
+ let elements: [OpaqueValue<Int>] =
+ zip(sequence, 0..<sequence.count).map {
+ OpaqueValue($0, identity: $1)
+ }
+
+ var c = makeWrappedCollection(elements)
+ let closureLifetimeTracker = LifetimeTracked(0)
+ c.sort {
+ (lhs, rhs) in
+ _blackHole(closureLifetimeTracker)
+ return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
+ }
+
+ let extractedResult = c.map(extract)
+
+ // Check that we didn't lose any elements.
+ expectEqualsUnordered(
+ 0..<sequence.count,
+ extractedResult.map { $0.identity })
+
+ // Check that the elements are sorted.
+ if verifyOrder {
+ for i in extractedResult.indices {
+ if i != extractedResult.index(before: extractedResult.endIndex) {
+ let first = extractedResult[i].value
+ let second = extractedResult[extractedResult.index(after: i)].value
+ expectFalse(lessImpl(second, first))
+ }
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sort/Predicate") {
+ for test in partitionExhaustiveTests {
+ forAllPermutations(test.sequence) { (sequence) in
+ checkSortInPlace_Predicate(
+ sequence: sequence,
+ equalImpl: { $0 == $1 },
+ lessImpl: { $0 < $1 },
+ verifyOrder: true)
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sort/Predicate/InvalidOrderings") {
+ withInvalidOrderings { (comparisonPredicate : @escaping (Int, Int) -> Bool) in
+ for i in 0..<7 {
+ forAllPermutations(i) { (sequence) in
+ checkSortInPlace_Predicate(
+ sequence: sequence,
+ equalImpl: {
+ !comparisonPredicate($0, $1) &&
+ !comparisonPredicate($1, $0)
+ },
+ lessImpl: comparisonPredicate,
+ verifyOrder: false)
+ }
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sort/ThrowingPredicate") {
+ for test in partitionExhaustiveTests {
+ forAllPermutations(test.sequence) { (sequence) in
+ for i in 0..<sequence.count {
+ checkSortPredicateThrow(
+ sequence: sequence,
+ lessImpl: { $0 < $1 },
+ throwIndex: i)
+ }
+ }
+ }
+}
+
+self.test("\(testNamePrefix).sort/ThrowingPredicateWithLargeNumberElements") {
+ for sequence in largeElementSortTests {
+ for i in 0..<sequence.count {
+ checkSortPredicateThrow(
+ sequence: sequence,
+ lessImpl: { $0 < $1 },
+ throwIndex: i)
+ }
+ }
+}
//===----------------------------------------------------------------------===//
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift b/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift
new file mode 100644
index 0000000..94ba6cf
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift
@@ -0,0 +1,257 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+
+import StdlibUnittest
+
+// Generate two overloads: one for Array (which will get
+// picked up when the caller passes a literal), and another that
+// accepts any appropriate Collection type.
+
+public func checkIterator<
+ Expected: Collection, I : IteratorProtocol
+>(
+ _ expected: Expected,
+ _ iterator: I,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
+) where I.Element == Expected.Iterator.Element {
+ // Copying a `IteratorProtocol` is allowed.
+ var mutableGen = iterator
+ var actual: [Expected.Iterator.Element] = []
+ while let e = mutableGen.next() {
+ actual.append(e)
+ }
+ expectEqualSequence(
+ expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+
+ // Having returned `.None` once, a `IteratorProtocol` should not generate
+ // more elements.
+ for _ in 0..<10 {
+ expectNil(mutableGen.next(), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+}
+
+public func checkIterator<
+ Expected: Collection, I : IteratorProtocol
+>(
+ _ expected: Expected,
+ _ iterator: I,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where I.Element == Expected.Iterator.Element, Expected.Iterator.Element : Equatable {
+ checkIterator(
+ expected, iterator, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+ resiliencyChecks: resiliencyChecks
+ ) { $0 == $1 }
+}
+
+public func checkSequence<
+ Expected: Collection, S : Sequence
+>(
+ _ expected: Expected,
+ _ sequence: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
+) where S.Iterator.Element == Expected.Iterator.Element {
+ let expectedCount: Int = numericCast(expected.count)
+ checkIterator(
+ expected, sequence.makeIterator(), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ expectGE(
+ expectedCount, sequence.underestimatedCount, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ // Test `_copyContents(initializing:)` if we can do so without destroying the
+ // sequence.
+ _ = sequence._preprocessingPass { () -> Void in
+ var count = 0
+ for _ in sequence { count += 1 }
+ let ptr = UnsafeMutablePointer<S.Iterator.Element>.allocate(capacity: count)
+ let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
+ var (remainders,writtenUpTo) = sequence._copyContents(initializing: buf)
+ expectTrue(remainders.next() == nil,
+ "_copyContents returned unwritten elements")
+ expectTrue(writtenUpTo == buf.endIndex,
+ "_copyContents failed to use entire buffer")
+ expectEqualSequence(expected, buf, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ ptr.deinitialize(count: count)
+ ptr.deallocate()
+ }
+
+ // Test `_copyToContiguousArray()` if we can do so
+ // without destroying the sequence.
+ _ = sequence._preprocessingPass { () -> Void in
+ let copy = sequence._copyToContiguousArray()
+ expectEqualSequence(expected, copy, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+}
+
+public func checkSequence<
+ Expected: Collection, S : Sequence
+>(
+ _ expected: Expected,
+ _ sequence: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ S.Iterator.Element == Expected.Iterator.Element,
+ S.Iterator.Element : Equatable {
+
+ checkSequence(
+ expected, sequence, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+ resiliencyChecks: resiliencyChecks
+ ) { $0 == $1 }
+}
+
+public func checkIterator<
+ Element, I : IteratorProtocol
+>(
+ _ expected: Array<Element>,
+ _ iterator: I,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where I.Element == Element {
+ // Copying a `IteratorProtocol` is allowed.
+ var mutableGen = iterator
+ var actual: [Element] = []
+ while let e = mutableGen.next() {
+ actual.append(e)
+ }
+ expectEqualSequence(
+ expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+
+ // Having returned `.None` once, a `IteratorProtocol` should not generate
+ // more elements.
+ for _ in 0..<10 {
+ expectNil(mutableGen.next(), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+}
+
+public func checkIterator<
+ Element, I : IteratorProtocol
+>(
+ _ expected: Array<Element>,
+ _ iterator: I,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where I.Element == Element, Element : Equatable {
+ checkIterator(
+ expected, iterator, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+ resiliencyChecks: resiliencyChecks
+ ) { $0 == $1 }
+}
+
+public func checkSequence<
+ Element, S : Sequence
+>(
+ _ expected: Array<Element>,
+ _ sequence: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+ sameValue: (Element, Element) -> Bool
+) where S.Iterator.Element == Element {
+ let expectedCount: Int = numericCast(expected.count)
+ checkIterator(
+ expected, sequence.makeIterator(), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ resiliencyChecks: resiliencyChecks,
+ sameValue: sameValue)
+
+ expectGE(
+ expectedCount, sequence.underestimatedCount, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ // Test `_copyContents(initializing:)` if we can do so without destroying the
+ // sequence.
+ _ = sequence._preprocessingPass { () -> Void in
+ var count = 0
+ for _ in sequence { count += 1 }
+ let ptr = UnsafeMutablePointer<S.Iterator.Element>.allocate(capacity: count)
+ let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
+ var (remainders,writtenUpTo) = sequence._copyContents(initializing: buf)
+ expectTrue(remainders.next() == nil,
+ "_copyContents returned unwritten elements")
+ expectTrue(writtenUpTo == buf.endIndex,
+ "_copyContents failed to use entire buffer")
+ expectEqualSequence(expected, buf, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ ptr.deinitialize(count: count)
+ ptr.deallocate()
+ }
+
+ // Test `_copyToContiguousArray()` if we can do so
+ // without destroying the sequence.
+ _ = sequence._preprocessingPass { () -> Void in
+ let copy = sequence._copyToContiguousArray()
+ expectEqualSequence(expected, copy, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+ }
+}
+
+public func checkSequence<
+ Element, S : Sequence
+>(
+ _ expected: Array<Element>,
+ _ sequence: S,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
+ resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+ S.Iterator.Element == Element,
+ S.Iterator.Element : Equatable {
+
+ checkSequence(
+ expected, sequence, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+ resiliencyChecks: resiliencyChecks
+ ) { $0 == $1 }
+}
+
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift.gyb
deleted file mode 100644
index 40fad27..0000000
--- a/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift.gyb
+++ /dev/null
@@ -1,126 +0,0 @@
-//===--- CheckSequenceInstance.swift.gyb ----------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
-import StdlibUnittest
-
-// Generate two overloads: one for Array (which will get
-// picked up when the caller passes a literal), and another that
-// accepts any appropriate Collection type.
-% for genericParam, Element, Expected in zip(
-% ('Expected: Collection', 'Element'),
-% ('Expected.Iterator.Element', 'Element'),
-% ('Expected', 'Array<Element>')):
-
-public func checkIterator<
- ${genericParam}, I : IteratorProtocol
->(
- _ expected: ${Expected},
- _ iterator: I,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- sameValue: (${Element}, ${Element}) -> Bool
-) where I.Element == ${Element} {
- // Copying a `IteratorProtocol` is allowed.
- var mutableGen = iterator
- var actual: [${Element}] = []
- while let e = mutableGen.next() {
- actual.append(e)
- }
- expectEqualSequence(
- expected, actual, ${trace}, sameValue: sameValue)
-
- // Having returned `.None` once, a `IteratorProtocol` should not generate
- // more elements.
- for _ in 0..<10 {
- expectNil(mutableGen.next(), ${trace})
- }
-}
-
-public func checkIterator<
- ${genericParam}, I : IteratorProtocol
->(
- _ expected: ${Expected},
- _ iterator: I,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all
-) where I.Element == ${Element}, ${Element} : Equatable {
- checkIterator(
- expected, iterator, ${trace}, showFrame: false,
- resiliencyChecks: resiliencyChecks
- ) { $0 == $1 }
-}
-
-public func checkSequence<
- ${genericParam}, S : Sequence
->(
- _ expected: ${Expected},
- _ sequence: S,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
- sameValue: (${Element}, ${Element}) -> Bool
-) where S.Iterator.Element == ${Element} {
- let expectedCount: Int = numericCast(expected.count)
- checkIterator(
- expected, sequence.makeIterator(), ${trace},
- resiliencyChecks: resiliencyChecks,
- sameValue: sameValue)
-
- expectGE(
- expectedCount, sequence.underestimatedCount, ${trace})
-
- // Test `_copyContents(initializing:)` if we can do so without destroying the
- // sequence.
- _ = sequence._preprocessingPass { () -> Void in
- var count = 0
- for _ in sequence { count += 1 }
- let ptr = UnsafeMutablePointer<S.Iterator.Element>.allocate(capacity: count)
- let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
- var (remainders,writtenUpTo) = sequence._copyContents(initializing: buf)
- expectTrue(remainders.next() == nil,
- "_copyContents returned unwritten elements")
- expectTrue(writtenUpTo == buf.endIndex,
- "_copyContents failed to use entire buffer")
- expectEqualSequence(expected, buf, ${trace}, sameValue: sameValue)
- ptr.deinitialize(count: count)
- ptr.deallocate()
- }
-
- // Test `_copyToContiguousArray()` if we can do so
- // without destroying the sequence.
- _ = sequence._preprocessingPass { () -> Void in
- let copy = sequence._copyToContiguousArray()
- expectEqualSequence(expected, copy, ${trace}, sameValue: sameValue)
- }
-}
-
-public func checkSequence<
- ${genericParam}, S : Sequence
->(
- _ expected: ${Expected},
- _ sequence: S,
- ${TRACE},
- resiliencyChecks: CollectionMisuseResiliencyChecks = .all
-) where
- S.Iterator.Element == ${Element},
- S.Iterator.Element : Equatable {
-
- checkSequence(
- expected, sequence, ${trace}, showFrame: false,
- resiliencyChecks: resiliencyChecks
- ) { $0 == $1 }
-}
-
-% end
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
index e1551c4..4b6f922 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
@@ -1935,17 +1935,17 @@
}
//===----------------------------------------------------------------------===//
-// first()
+// first(where:)
//===----------------------------------------------------------------------===//
-self.test("\(testNamePrefix).first/semantics") {
+self.test("\(testNamePrefix).first(where:)/semantics") {
for test in findTests {
let s = makeWrappedSequenceWithEquatableElement(test.sequence)
let closureLifetimeTracker = LifetimeTracked(0)
- let found = s.first {
+ let found = s.first(where: {
_blackHole(closureLifetimeTracker)
return $0 == wrapValueIntoEquatable(test.element)
- }
+ })
expectEqual(
test.expected == nil ? nil : wrapValueIntoEquatable(test.element),
found,
diff --git a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift
new file mode 100644
index 0000000..0dad559
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift
@@ -0,0 +1,3169 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import StdlibUnittest
+
+public protocol Wrapper {
+ associatedtype Base
+ init(wrapping base: Base)
+ var base: Base { get set }
+}
+
+public protocol LoggingType : Wrapper {
+ associatedtype Log : AnyObject
+}
+
+extension LoggingType {
+ public var log: Log.Type {
+ return Log.self
+ }
+
+ public var selfType: Any.Type {
+ return type(of: self)
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Iterator
+//===----------------------------------------------------------------------===//
+
+public class IteratorLog {
+ public static func dispatchTester<I>(
+ _ iterator: I
+ ) -> LoggingIterator<LoggingIterator<I>> {
+ return LoggingIterator(wrapping: LoggingIterator(wrapping: iterator))
+ }
+ public static var next = TypeIndexed(0)
+}
+
+public struct LoggingIterator<Base : IteratorProtocol>
+ : IteratorProtocol, LoggingType {
+
+ public typealias Log = IteratorLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public mutating func next() -> Base.Element? {
+ Log.next[selfType] += 1
+ return base.next()
+ }
+
+ public var base: Base
+}
+
+//===----------------------------------------------------------------------===//
+// Sequence and Collection logs
+//===----------------------------------------------------------------------===//
+
+public class SequenceLog {
+ public static func dispatchTester<S>(
+ _ s: S
+ ) -> LoggingSequence<LoggingSequence<S>> {
+ return LoggingSequence(wrapping: LoggingSequence(wrapping: s))
+ }
+ public static var makeIterator = TypeIndexed(0)
+ public static var underestimatedCount = TypeIndexed(0)
+ public static var map = TypeIndexed(0)
+ public static var filter = TypeIndexed(0)
+ public static var forEach = TypeIndexed(0)
+ public static var dropFirst = TypeIndexed(0)
+ public static var dropLast = TypeIndexed(0)
+ public static var dropWhile = TypeIndexed(0)
+ public static var prefixWhile = TypeIndexed(0)
+ public static var prefixMaxLength = TypeIndexed(0)
+ public static var suffixMaxLength = TypeIndexed(0)
+ public static var split = TypeIndexed(0)
+ public static var _customContainsEquatableElement = TypeIndexed(0)
+ public static var _preprocessingPass = TypeIndexed(0)
+ public static var _copyToContiguousArray = TypeIndexed(0)
+ public static var _copyContents = TypeIndexed(0)
+}
+
+public class CollectionLog : SequenceLog {
+ public class func dispatchTester<C>(
+ _ c: C
+ ) -> LoggingCollection<LoggingCollection<C>> {
+ return LoggingCollection(wrapping: LoggingCollection(wrapping: c))
+ }
+ public static var startIndex = TypeIndexed(0)
+ public static var endIndex = TypeIndexed(0)
+ public static var subscriptIndex = TypeIndexed(0)
+ public static var subscriptRange = TypeIndexed(0)
+ public static var _failEarlyRangeCheckIndex = TypeIndexed(0)
+ public static var _failEarlyRangeCheckRange = TypeIndexed(0)
+ public static var successor = TypeIndexed(0)
+ public static var formSuccessor = TypeIndexed(0)
+ public static var indices = TypeIndexed(0)
+ public static var prefixUpTo = TypeIndexed(0)
+ public static var prefixThrough = TypeIndexed(0)
+ public static var suffixFrom = TypeIndexed(0)
+ public static var isEmpty = TypeIndexed(0)
+ public static var count = TypeIndexed(0)
+ public static var _customIndexOfEquatableElement = TypeIndexed(0)
+ public static var first = TypeIndexed(0)
+ public static var advance = TypeIndexed(0)
+ public static var advanceLimit = TypeIndexed(0)
+ public static var distance = TypeIndexed(0)
+}
+
+public class BidirectionalCollectionLog : SequenceLog {
+ public class func dispatchTester<C>(
+ _ c: C
+ ) -> LoggingBidirectionalCollection<LoggingBidirectionalCollection<C>> {
+ return LoggingBidirectionalCollection(
+ wrapping: LoggingBidirectionalCollection(wrapping: c))
+ }
+ public static var predecessor = TypeIndexed(0)
+ public static var formPredecessor = TypeIndexed(0)
+ public static var last = TypeIndexed(0)
+}
+
+public class MutableCollectionLog : CollectionLog {
+ public class func dispatchTester<C>(
+ _ c: C
+ ) -> LoggingMutableCollection<LoggingMutableCollection<C>> {
+ return LoggingMutableCollection(
+ wrapping: LoggingMutableCollection(wrapping: c))
+ }
+ public static var subscriptIndexSet = TypeIndexed(0)
+ public static var subscriptRangeSet = TypeIndexed(0)
+ public static var partitionBy = TypeIndexed(0)
+ public static var _withUnsafeMutableBufferPointerIfSupported = TypeIndexed(0)
+ public static var _withUnsafeMutableBufferPointerIfSupportedNonNilReturns =
+ TypeIndexed(0)
+}
+
+/// Data container to keep track of how many times each `Base` type calls methods
+/// of `RangeReplaceableCollection`.
+///
+/// Each static variable is a mapping of Type -> Number of calls.
+public class RangeReplaceableCollectionLog : CollectionLog {
+ public static var init_ = TypeIndexed(0)
+ public static var initRepeating = TypeIndexed(0)
+ public static var initWithSequence = TypeIndexed(0)
+
+ public static var _customRemoveLast = TypeIndexed(0)
+ public static var _customRemoveLastN = TypeIndexed(0)
+ public static var append = TypeIndexed(0)
+ public static var appendContentsOf = TypeIndexed(0)
+ public static var insert = TypeIndexed(0)
+ public static var insertContentsOf = TypeIndexed(0)
+ public static var removeAll = TypeIndexed(0)
+ public static var removeAt = TypeIndexed(0)
+ public static var removeFirst = TypeIndexed(0)
+ public static var removeFirstN = TypeIndexed(0)
+ public static var removeSubrange = TypeIndexed(0)
+ public static var replaceSubrange = TypeIndexed(0)
+ public static var reserveCapacity = TypeIndexed(0)
+
+ public class func dispatchTester<C>(
+ _ rrc: C
+ ) -> LoggingRangeReplaceableCollection<LoggingRangeReplaceableCollection<C>> {
+ return LoggingRangeReplaceableCollection(
+ wrapping: LoggingRangeReplaceableCollection(wrapping: rrc)
+ )
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Sequence and Collection that count method calls
+//===----------------------------------------------------------------------===//
+
+/// Interposes between `Sequence` method calls to increment each method's
+/// counter.
+public struct LoggingSequence<
+ Base : Sequence
+> : Sequence, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = SequenceLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+
+
+}
+/// Interposes between `Collection` method calls to increment each method's
+/// counter.
+public struct LoggingCollection<
+ Base : Collection & Collection
+> : Collection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = CollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+
+}
+/// Interposes between `Collection` method calls to increment each method's
+/// counter.
+public struct LoggingBidirectionalCollection<
+ Base : Collection & BidirectionalCollection
+> : BidirectionalCollection, Collection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = CollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+
+ public func index(before i: Index) -> Index {
+ BidirectionalCollectionLog.predecessor[selfType] += 1
+ return base.index(before: i)
+ }
+
+ public func formIndex(before i: inout Index) {
+ BidirectionalCollectionLog.formPredecessor[selfType] += 1
+ base.formIndex(before: &i)
+ }
+
+ public var last: Iterator.Element? {
+ BidirectionalCollectionLog.last[selfType] += 1
+ return base.last
+ }
+}
+/// Interposes between `Collection` method calls to increment each method's
+/// counter.
+public struct LoggingRandomAccessCollection<
+ Base : Collection & RandomAccessCollection
+> : RandomAccessCollection, Collection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = CollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+
+ public func index(before i: Index) -> Index {
+ BidirectionalCollectionLog.predecessor[selfType] += 1
+ return base.index(before: i)
+ }
+
+ public func formIndex(before i: inout Index) {
+ BidirectionalCollectionLog.formPredecessor[selfType] += 1
+ base.formIndex(before: &i)
+ }
+
+ public var last: Iterator.Element? {
+ BidirectionalCollectionLog.last[selfType] += 1
+ return base.last
+ }
+}
+/// Interposes between `MutableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingMutableCollection<
+ Base : MutableCollection & Collection
+> : Collection, MutableCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = MutableCollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ set {
+ Log.subscriptIndexSet[selfType] += 1
+ base[position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ set {
+ Log.subscriptRangeSet[selfType] += 1
+ base[bounds] = newValue
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+ public mutating func partition(
+ by belongsInSecondPartition: (Iterator.Element) throws -> Bool
+ ) rethrows -> Index {
+ Log.partitionBy[selfType] += 1
+ return try base.partition(by: belongsInSecondPartition)
+ }
+
+ public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+ _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+ ) rethrows -> R? {
+ Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+ let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+ if result != nil {
+ Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+ }
+ return result
+ }
+
+}
+/// Interposes between `MutableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingMutableBidirectionalCollection<
+ Base : MutableCollection & BidirectionalCollection
+> : BidirectionalCollection, MutableCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = MutableCollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ set {
+ Log.subscriptIndexSet[selfType] += 1
+ base[position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ set {
+ Log.subscriptRangeSet[selfType] += 1
+ base[bounds] = newValue
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+ public mutating func partition(
+ by belongsInSecondPartition: (Iterator.Element) throws -> Bool
+ ) rethrows -> Index {
+ Log.partitionBy[selfType] += 1
+ return try base.partition(by: belongsInSecondPartition)
+ }
+
+ public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+ _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+ ) rethrows -> R? {
+ Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+ let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+ if result != nil {
+ Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+ }
+ return result
+ }
+
+ public func index(before i: Index) -> Index {
+ BidirectionalCollectionLog.predecessor[selfType] += 1
+ return base.index(before: i)
+ }
+
+ public func formIndex(before i: inout Index) {
+ BidirectionalCollectionLog.formPredecessor[selfType] += 1
+ base.formIndex(before: &i)
+ }
+
+ public var last: Iterator.Element? {
+ BidirectionalCollectionLog.last[selfType] += 1
+ return base.last
+ }
+}
+/// Interposes between `MutableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingMutableRandomAccessCollection<
+ Base : MutableCollection & RandomAccessCollection
+> : RandomAccessCollection, MutableCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = MutableCollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ set {
+ Log.subscriptIndexSet[selfType] += 1
+ base[position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ set {
+ Log.subscriptRangeSet[selfType] += 1
+ base[bounds] = newValue
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+ public mutating func partition(
+ by belongsInSecondPartition: (Iterator.Element) throws -> Bool
+ ) rethrows -> Index {
+ Log.partitionBy[selfType] += 1
+ return try base.partition(by: belongsInSecondPartition)
+ }
+
+ public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+ _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+ ) rethrows -> R? {
+ Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+ let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+ if result != nil {
+ Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+ }
+ return result
+ }
+
+ public func index(before i: Index) -> Index {
+ BidirectionalCollectionLog.predecessor[selfType] += 1
+ return base.index(before: i)
+ }
+
+ public func formIndex(before i: inout Index) {
+ BidirectionalCollectionLog.formPredecessor[selfType] += 1
+ base.formIndex(before: &i)
+ }
+
+ public var last: Iterator.Element? {
+ BidirectionalCollectionLog.last[selfType] += 1
+ return base.last
+ }
+}
+/// Interposes between `RangeReplaceableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingRangeReplaceableCollection<
+ Base : RangeReplaceableCollection & Collection
+> : Collection, RangeReplaceableCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = RangeReplaceableCollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+
+ public init() {
+ self.base = Base()
+ Log.init_[selfType] += 1
+ }
+
+ public init(repeating repeatedValue: Iterator.Element, count: Int) {
+ self.base = Base(repeating: repeatedValue, count: count)
+ Log.initRepeating[selfType] += 1
+ }
+
+ public init<S : Sequence>(_ elements: S)
+ where S.Iterator.Element == Iterator.Element {
+ self.base = Base(elements)
+ Log.initWithSequence[selfType] += 1
+ }
+
+ public mutating func _customRemoveLast() -> Base.Iterator.Element? {
+ Log._customRemoveLast[selfType] += 1
+ return base._customRemoveLast()
+ }
+
+ public mutating func _customRemoveLast(_ n: Int) -> Bool {
+ Log._customRemoveLastN[selfType] += 1
+ return base._customRemoveLast(n)
+ }
+
+ public mutating func append(_ newElement: Base.Iterator.Element) {
+ Log.append[selfType] += 1
+ base.append(newElement)
+ }
+
+ public mutating func append<S : Sequence>(
+ contentsOf newElements: S
+ ) where S.Iterator.Element == Base.Iterator.Element {
+ Log.appendContentsOf[selfType] += 1
+ base.append(contentsOf: newElements)
+ }
+
+ public mutating func insert(
+ _ newElement: Base.Iterator.Element, at i: Index
+ ) {
+ Log.insert[selfType] += 1
+ base.insert(newElement, at: i)
+ }
+
+ public mutating func insert<C : Collection>(
+ contentsOf newElements: C, at i: Index
+ ) where C.Iterator.Element == Base.Iterator.Element {
+ Log.insertContentsOf[selfType] += 1
+ base.insert(contentsOf: newElements, at: i)
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+ Log.removeAll[selfType] += 1
+ base.removeAll(keepingCapacity: keepCapacity)
+ }
+
+ @discardableResult
+ public mutating func remove(at index: Index) -> Base.Iterator.Element {
+ Log.removeAt[selfType] += 1
+ return base.remove(at: index)
+ }
+
+ @discardableResult
+ public mutating func removeFirst() -> Base.Iterator.Element {
+ Log.removeFirst[selfType] += 1
+ return base.removeFirst()
+ }
+
+ public mutating func removeFirst(_ n: Int) {
+ Log.removeFirstN[selfType] += 1
+ base.removeFirst(n)
+ }
+
+ public mutating func removeSubrange(_ bounds: Range<Index>) {
+ Log.removeSubrange[selfType] += 1
+ base.removeSubrange(bounds)
+ }
+
+ public mutating func replaceSubrange<C : Collection>(
+ _ bounds: Range<Index>, with newElements: C
+ ) where C.Iterator.Element == Base.Iterator.Element {
+ Log.replaceSubrange[selfType] += 1
+ base.replaceSubrange(bounds, with: newElements)
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ Log.reserveCapacity[selfType] += 1
+ base.reserveCapacity(n)
+ }
+}
+/// Interposes between `RangeReplaceableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingRangeReplaceableBidirectionalCollection<
+ Base : RangeReplaceableCollection & BidirectionalCollection
+> : BidirectionalCollection, RangeReplaceableCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = RangeReplaceableCollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+
+ public init() {
+ self.base = Base()
+ Log.init_[selfType] += 1
+ }
+
+ public init(repeating repeatedValue: Iterator.Element, count: Int) {
+ self.base = Base(repeating: repeatedValue, count: count)
+ Log.initRepeating[selfType] += 1
+ }
+
+ public init<S : Sequence>(_ elements: S)
+ where S.Iterator.Element == Iterator.Element {
+ self.base = Base(elements)
+ Log.initWithSequence[selfType] += 1
+ }
+
+ public mutating func _customRemoveLast() -> Base.Iterator.Element? {
+ Log._customRemoveLast[selfType] += 1
+ return base._customRemoveLast()
+ }
+
+ public mutating func _customRemoveLast(_ n: Int) -> Bool {
+ Log._customRemoveLastN[selfType] += 1
+ return base._customRemoveLast(n)
+ }
+
+ public mutating func append(_ newElement: Base.Iterator.Element) {
+ Log.append[selfType] += 1
+ base.append(newElement)
+ }
+
+ public mutating func append<S : Sequence>(
+ contentsOf newElements: S
+ ) where S.Iterator.Element == Base.Iterator.Element {
+ Log.appendContentsOf[selfType] += 1
+ base.append(contentsOf: newElements)
+ }
+
+ public mutating func insert(
+ _ newElement: Base.Iterator.Element, at i: Index
+ ) {
+ Log.insert[selfType] += 1
+ base.insert(newElement, at: i)
+ }
+
+ public mutating func insert<C : Collection>(
+ contentsOf newElements: C, at i: Index
+ ) where C.Iterator.Element == Base.Iterator.Element {
+ Log.insertContentsOf[selfType] += 1
+ base.insert(contentsOf: newElements, at: i)
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+ Log.removeAll[selfType] += 1
+ base.removeAll(keepingCapacity: keepCapacity)
+ }
+
+ @discardableResult
+ public mutating func remove(at index: Index) -> Base.Iterator.Element {
+ Log.removeAt[selfType] += 1
+ return base.remove(at: index)
+ }
+
+ @discardableResult
+ public mutating func removeFirst() -> Base.Iterator.Element {
+ Log.removeFirst[selfType] += 1
+ return base.removeFirst()
+ }
+
+ public mutating func removeFirst(_ n: Int) {
+ Log.removeFirstN[selfType] += 1
+ base.removeFirst(n)
+ }
+
+ public mutating func removeSubrange(_ bounds: Range<Index>) {
+ Log.removeSubrange[selfType] += 1
+ base.removeSubrange(bounds)
+ }
+
+ public mutating func replaceSubrange<C : Collection>(
+ _ bounds: Range<Index>, with newElements: C
+ ) where C.Iterator.Element == Base.Iterator.Element {
+ Log.replaceSubrange[selfType] += 1
+ base.replaceSubrange(bounds, with: newElements)
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ Log.reserveCapacity[selfType] += 1
+ base.reserveCapacity(n)
+ }
+ public func index(before i: Index) -> Index {
+ BidirectionalCollectionLog.predecessor[selfType] += 1
+ return base.index(before: i)
+ }
+
+ public func formIndex(before i: inout Index) {
+ BidirectionalCollectionLog.formPredecessor[selfType] += 1
+ base.formIndex(before: &i)
+ }
+
+ public var last: Iterator.Element? {
+ BidirectionalCollectionLog.last[selfType] += 1
+ return base.last
+ }
+}
+/// Interposes between `RangeReplaceableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingRangeReplaceableRandomAccessCollection<
+ Base : RangeReplaceableCollection & RandomAccessCollection
+> : RandomAccessCollection, RangeReplaceableCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = RangeReplaceableCollectionLog
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public typealias Iterator = LoggingIterator<Base.Iterator>
+
+ public func makeIterator() -> Iterator {
+ Log.makeIterator[selfType] += 1
+ return LoggingIterator(wrapping: base.makeIterator())
+ }
+
+ public var underestimatedCount: Int {
+ Log.underestimatedCount[selfType] += 1
+ return base.underestimatedCount
+ }
+
+ public func map<T>(
+ _ transform: (Base.Iterator.Element) throws -> T
+ ) rethrows -> [T] {
+ Log.map[selfType] += 1
+ return try base.map(transform)
+ }
+
+ public func filter(
+ _ isIncluded: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [Base.Iterator.Element] {
+ Log.filter[selfType] += 1
+ return try base.filter(isIncluded)
+ }
+
+ public func forEach(
+ _ body: (Base.Iterator.Element) throws -> Void
+ ) rethrows {
+ Log.forEach[selfType] += 1
+ try base.forEach(body)
+ }
+
+ public typealias SubSequence = Base.SubSequence
+
+ public func dropFirst(_ n: Int) -> SubSequence {
+ Log.dropFirst[selfType] += 1
+ return base.dropFirst(n)
+ }
+
+ public func dropLast(_ n: Int) -> SubSequence {
+ Log.dropLast[selfType] += 1
+ return base.dropLast(n)
+ }
+
+ public func drop(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.dropWhile[selfType] += 1
+ return try base.drop(while: predicate)
+ }
+
+ public func prefix(_ maxLength: Int) -> SubSequence {
+ Log.prefixMaxLength[selfType] += 1
+ return base.prefix(maxLength)
+ }
+
+ public func prefix(
+ while predicate: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> SubSequence {
+ Log.prefixWhile[selfType] += 1
+ return try base.prefix(while: predicate)
+ }
+
+ public func suffix(_ maxLength: Int) -> SubSequence {
+ Log.suffixMaxLength[selfType] += 1
+ return base.suffix(maxLength)
+ }
+
+ public func split(
+ maxSplits: Int = Int.max,
+ omittingEmptySubsequences: Bool = true,
+ whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+ ) rethrows -> [SubSequence] {
+ Log.split[selfType] += 1
+ return try base.split(
+ maxSplits: maxSplits,
+ omittingEmptySubsequences: omittingEmptySubsequences,
+ whereSeparator: isSeparator)
+ }
+
+ public func _customContainsEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Bool? {
+ Log._customContainsEquatableElement[selfType] += 1
+ return base._customContainsEquatableElement(element)
+ }
+
+ /// If `self` is multi-pass (i.e., a `Collection`), invoke
+ /// `preprocess` on `self` and return its result. Otherwise, return
+ /// `nil`.
+ public func _preprocessingPass<R>(
+ _ preprocess: () throws -> R
+ ) rethrows -> R? {
+ Log._preprocessingPass[selfType] += 1
+ return try base._preprocessingPass(preprocess)
+ }
+
+ /// Create a native array buffer containing the elements of `self`,
+ /// in the same order.
+ public func _copyToContiguousArray()
+ -> ContiguousArray<Base.Iterator.Element> {
+ Log._copyToContiguousArray[selfType] += 1
+ return base._copyToContiguousArray()
+ }
+
+ /// Copy a Sequence into an array.
+ public func _copyContents(
+ initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+ ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+ Log._copyContents[selfType] += 1
+ let (it,idx) = base._copyContents(initializing: buffer)
+ return (Iterator(wrapping: it),idx)
+ }
+
+ public typealias Index = Base.Index
+
+ public var startIndex: Index {
+ Log.startIndex[selfType] += 1
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ Log.endIndex[selfType] += 1
+ return base.endIndex
+ }
+
+ public subscript(position: Index) -> Base.Iterator.Element {
+ get {
+ Log.subscriptIndex[selfType] += 1
+ return base[position]
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ Log.subscriptRange[selfType] += 1
+ return base[bounds]
+ }
+ }
+
+ public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckIndex[selfType] += 1
+ base._failEarlyRangeCheck(index, bounds: bounds)
+ }
+
+ public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+ Log._failEarlyRangeCheckRange[selfType] += 1
+ base._failEarlyRangeCheck(range, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ Log.successor[selfType] += 1
+ return base.index(after: i)
+ }
+
+ public func formIndex(after i: inout Index) {
+ Log.formSuccessor[selfType] += 1
+ base.formIndex(after: &i)
+ }
+
+ public typealias Indices = Base.Indices
+
+ public var indices: Indices {
+ Log.indices[selfType] += 1
+ return base.indices
+ }
+
+ public func prefix(upTo end: Index) -> SubSequence {
+ Log.prefixUpTo[selfType] += 1
+ return base.prefix(upTo: end)
+ }
+
+ public func prefix(through position: Index) -> SubSequence {
+ Log.prefixThrough[selfType] += 1
+ return base.prefix(through: position)
+ }
+
+ public func suffix(from start: Index) -> SubSequence {
+ Log.suffixFrom[selfType] += 1
+ return base.suffix(from: start)
+ }
+
+ public var isEmpty: Bool {
+ Log.isEmpty[selfType] += 1
+ return base.isEmpty
+ }
+
+ public var count: Int {
+ Log.count[selfType] += 1
+ return base.count
+ }
+
+ public func _customIndexOfEquatableElement(
+ _ element: Base.Iterator.Element
+ ) -> Index?? {
+ Log._customIndexOfEquatableElement[selfType] += 1
+ return base._customIndexOfEquatableElement(element)
+ }
+
+ public var first: Base.Iterator.Element? {
+ Log.first[selfType] += 1
+ return base.first
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ Log.advance[selfType] += 1
+ return base.index(i, offsetBy: n)
+ }
+
+ public func index(
+ _ i: Index, offsetBy n: Int, limitedBy limit: Index
+ ) -> Index? {
+ Log.advanceLimit[selfType] += 1
+ return base.index(i, offsetBy: n, limitedBy: limit)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ Log.distance[selfType] += 1
+ return base.distance(from: start, to: end)
+ }
+
+
+ public init() {
+ self.base = Base()
+ Log.init_[selfType] += 1
+ }
+
+ public init(repeating repeatedValue: Iterator.Element, count: Int) {
+ self.base = Base(repeating: repeatedValue, count: count)
+ Log.initRepeating[selfType] += 1
+ }
+
+ public init<S : Sequence>(_ elements: S)
+ where S.Iterator.Element == Iterator.Element {
+ self.base = Base(elements)
+ Log.initWithSequence[selfType] += 1
+ }
+
+ public mutating func _customRemoveLast() -> Base.Iterator.Element? {
+ Log._customRemoveLast[selfType] += 1
+ return base._customRemoveLast()
+ }
+
+ public mutating func _customRemoveLast(_ n: Int) -> Bool {
+ Log._customRemoveLastN[selfType] += 1
+ return base._customRemoveLast(n)
+ }
+
+ public mutating func append(_ newElement: Base.Iterator.Element) {
+ Log.append[selfType] += 1
+ base.append(newElement)
+ }
+
+ public mutating func append<S : Sequence>(
+ contentsOf newElements: S
+ ) where S.Iterator.Element == Base.Iterator.Element {
+ Log.appendContentsOf[selfType] += 1
+ base.append(contentsOf: newElements)
+ }
+
+ public mutating func insert(
+ _ newElement: Base.Iterator.Element, at i: Index
+ ) {
+ Log.insert[selfType] += 1
+ base.insert(newElement, at: i)
+ }
+
+ public mutating func insert<C : Collection>(
+ contentsOf newElements: C, at i: Index
+ ) where C.Iterator.Element == Base.Iterator.Element {
+ Log.insertContentsOf[selfType] += 1
+ base.insert(contentsOf: newElements, at: i)
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+ Log.removeAll[selfType] += 1
+ base.removeAll(keepingCapacity: keepCapacity)
+ }
+
+ @discardableResult
+ public mutating func remove(at index: Index) -> Base.Iterator.Element {
+ Log.removeAt[selfType] += 1
+ return base.remove(at: index)
+ }
+
+ @discardableResult
+ public mutating func removeFirst() -> Base.Iterator.Element {
+ Log.removeFirst[selfType] += 1
+ return base.removeFirst()
+ }
+
+ public mutating func removeFirst(_ n: Int) {
+ Log.removeFirstN[selfType] += 1
+ base.removeFirst(n)
+ }
+
+ public mutating func removeSubrange(_ bounds: Range<Index>) {
+ Log.removeSubrange[selfType] += 1
+ base.removeSubrange(bounds)
+ }
+
+ public mutating func replaceSubrange<C : Collection>(
+ _ bounds: Range<Index>, with newElements: C
+ ) where C.Iterator.Element == Base.Iterator.Element {
+ Log.replaceSubrange[selfType] += 1
+ base.replaceSubrange(bounds, with: newElements)
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ Log.reserveCapacity[selfType] += 1
+ base.reserveCapacity(n)
+ }
+ public func index(before i: Index) -> Index {
+ BidirectionalCollectionLog.predecessor[selfType] += 1
+ return base.index(before: i)
+ }
+
+ public func formIndex(before i: inout Index) {
+ BidirectionalCollectionLog.formPredecessor[selfType] += 1
+ base.formIndex(before: &i)
+ }
+
+ public var last: Iterator.Element? {
+ BidirectionalCollectionLog.last[selfType] += 1
+ return base.last
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Collections that count calls to `_withUnsafeMutableBufferPointerIfSupported`
+//===----------------------------------------------------------------------===//
+
+/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
+/// to increment a counter. Calls to this method from within dispatched methods
+/// are uncounted by the standard logging collection wrapper.
+public struct BufferAccessLoggingMutableCollection<
+ Base : MutableCollection & Collection
+> : MutableCollection, Collection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = MutableCollectionLog
+
+ public typealias SubSequence = Base.SubSequence
+ public typealias Iterator = Base.Iterator
+ public typealias Element = Base.Element
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public func makeIterator() -> Iterator {
+ return base.makeIterator()
+ }
+
+ public typealias Index = Base.Index
+ public typealias Indices = Base.Indices
+
+ public var startIndex: Index {
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ return base.endIndex
+ }
+
+ public var indices: Indices {
+ return base.indices
+ }
+
+ public subscript(position: Index) -> Element {
+ get {
+ return base[position]
+ }
+ set {
+ base[position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ return base[bounds]
+ }
+ set {
+ base[bounds] = newValue
+ }
+ }
+
+ public func index(after i: Index) -> Index {
+ return base.index(after: i)
+ }
+
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+ _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+ ) rethrows -> R? {
+ Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+ let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+ if result != nil {
+ Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+ }
+ return result
+ }
+}
+/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
+/// to increment a counter. Calls to this method from within dispatched methods
+/// are uncounted by the standard logging collection wrapper.
+public struct BufferAccessLoggingMutableBidirectionalCollection<
+ Base : MutableCollection & BidirectionalCollection
+> : MutableCollection, BidirectionalCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = MutableCollectionLog
+
+ public typealias SubSequence = Base.SubSequence
+ public typealias Iterator = Base.Iterator
+ public typealias Element = Base.Element
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public func makeIterator() -> Iterator {
+ return base.makeIterator()
+ }
+
+ public typealias Index = Base.Index
+ public typealias Indices = Base.Indices
+
+ public var startIndex: Index {
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ return base.endIndex
+ }
+
+ public var indices: Indices {
+ return base.indices
+ }
+
+ public subscript(position: Index) -> Element {
+ get {
+ return base[position]
+ }
+ set {
+ base[position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ return base[bounds]
+ }
+ set {
+ base[bounds] = newValue
+ }
+ }
+
+ public func index(after i: Index) -> Index {
+ return base.index(after: i)
+ }
+
+ public func index(before i: Index) -> Index {
+ return base.index(before: i)
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+ _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+ ) rethrows -> R? {
+ Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+ let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+ if result != nil {
+ Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+ }
+ return result
+ }
+}
+/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
+/// to increment a counter. Calls to this method from within dispatched methods
+/// are uncounted by the standard logging collection wrapper.
+public struct BufferAccessLoggingMutableRandomAccessCollection<
+ Base : MutableCollection & RandomAccessCollection
+> : MutableCollection, RandomAccessCollection, LoggingType {
+
+ public var base: Base
+
+ public typealias Log = MutableCollectionLog
+
+ public typealias SubSequence = Base.SubSequence
+ public typealias Iterator = Base.Iterator
+ public typealias Element = Base.Element
+
+ public init(wrapping base: Base) {
+ self.base = base
+ }
+
+ public func makeIterator() -> Iterator {
+ return base.makeIterator()
+ }
+
+ public typealias Index = Base.Index
+ public typealias Indices = Base.Indices
+
+ public var startIndex: Index {
+ return base.startIndex
+ }
+
+ public var endIndex: Index {
+ return base.endIndex
+ }
+
+ public var indices: Indices {
+ return base.indices
+ }
+
+ public subscript(position: Index) -> Element {
+ get {
+ return base[position]
+ }
+ set {
+ base[position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<Index>) -> SubSequence {
+ get {
+ return base[bounds]
+ }
+ set {
+ base[bounds] = newValue
+ }
+ }
+
+ public func index(after i: Index) -> Index {
+ return base.index(after: i)
+ }
+
+ public func index(before i: Index) -> Index {
+ return base.index(before: i)
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+ public func distance(from start: Index, to end: Index) -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+ _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+ ) rethrows -> R? {
+ Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+ let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+ if result != nil {
+ Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+ }
+ return result
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Custom assertions
+//===----------------------------------------------------------------------===//
+
+public func expectCustomizable<T : LoggingType>(
+ _: T, _ counters: TypeIndexed<Int>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ T.Base : LoggingType,
+ T.Log == T.Base.Log {
+ let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
+ expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
+ expectEqual(
+ counters[T.self], counters[T.Base.self], message(), stackTrace: newTrace)
+}
+
+public func expectNotCustomizable<T : LoggingType>(
+ _: T, _ counters: TypeIndexed<Int>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where
+ T.Base : LoggingType,
+ T.Log == T.Base.Log {
+ let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
+ expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
+ expectEqual(0, counters[T.Base.self], message(), stackTrace: newTrace)
+}
diff --git a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
deleted file mode 100644
index 1cac3f9..0000000
--- a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
+++ /dev/null
@@ -1,700 +0,0 @@
-//===--- LoggingWrappers.swift.gyb ----------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_support import TRAVERSALS, collectionForTraversal
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
-import StdlibUnittest
-
-public protocol Wrapper {
- associatedtype Base
- init(wrapping base: Base)
- var base: Base { get set }
-}
-
-public protocol LoggingType : Wrapper {
- associatedtype Log : AnyObject
-}
-
-extension LoggingType {
- public var log: Log.Type {
- return Log.self
- }
-
- public var selfType: Any.Type {
- return type(of: self)
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Iterator
-//===----------------------------------------------------------------------===//
-
-public class IteratorLog {
- public static func dispatchTester<I>(
- _ iterator: I
- ) -> LoggingIterator<LoggingIterator<I>> {
- return LoggingIterator(wrapping: LoggingIterator(wrapping: iterator))
- }
- public static var next = TypeIndexed(0)
-}
-
-public struct LoggingIterator<Base : IteratorProtocol>
- : IteratorProtocol, LoggingType {
-
- public typealias Log = IteratorLog
-
- public init(wrapping base: Base) {
- self.base = base
- }
-
- public mutating func next() -> Base.Element? {
- Log.next[selfType] += 1
- return base.next()
- }
-
- public var base: Base
-}
-
-//===----------------------------------------------------------------------===//
-// Sequence and Collection logs
-//===----------------------------------------------------------------------===//
-
-public class SequenceLog {
- public static func dispatchTester<S>(
- _ s: S
- ) -> LoggingSequence<LoggingSequence<S>> {
- return LoggingSequence(wrapping: LoggingSequence(wrapping: s))
- }
- public static var makeIterator = TypeIndexed(0)
- public static var underestimatedCount = TypeIndexed(0)
- public static var map = TypeIndexed(0)
- public static var filter = TypeIndexed(0)
- public static var forEach = TypeIndexed(0)
- public static var dropFirst = TypeIndexed(0)
- public static var dropLast = TypeIndexed(0)
- public static var dropWhile = TypeIndexed(0)
- public static var prefixWhile = TypeIndexed(0)
- public static var prefixMaxLength = TypeIndexed(0)
- public static var suffixMaxLength = TypeIndexed(0)
- public static var split = TypeIndexed(0)
- public static var _customContainsEquatableElement = TypeIndexed(0)
- public static var _preprocessingPass = TypeIndexed(0)
- public static var _copyToContiguousArray = TypeIndexed(0)
- public static var _copyContents = TypeIndexed(0)
-}
-
-public class CollectionLog : SequenceLog {
- public class func dispatchTester<C>(
- _ c: C
- ) -> LoggingCollection<LoggingCollection<C>> {
- return LoggingCollection(wrapping: LoggingCollection(wrapping: c))
- }
- public static var startIndex = TypeIndexed(0)
- public static var endIndex = TypeIndexed(0)
- public static var subscriptIndex = TypeIndexed(0)
- public static var subscriptRange = TypeIndexed(0)
- public static var _failEarlyRangeCheckIndex = TypeIndexed(0)
- public static var _failEarlyRangeCheckRange = TypeIndexed(0)
- public static var successor = TypeIndexed(0)
- public static var formSuccessor = TypeIndexed(0)
- public static var indices = TypeIndexed(0)
- public static var prefixUpTo = TypeIndexed(0)
- public static var prefixThrough = TypeIndexed(0)
- public static var suffixFrom = TypeIndexed(0)
- public static var isEmpty = TypeIndexed(0)
- public static var count = TypeIndexed(0)
- public static var _customIndexOfEquatableElement = TypeIndexed(0)
- public static var first = TypeIndexed(0)
- public static var advance = TypeIndexed(0)
- public static var advanceLimit = TypeIndexed(0)
- public static var distance = TypeIndexed(0)
-}
-
-public class BidirectionalCollectionLog : SequenceLog {
- public class func dispatchTester<C>(
- _ c: C
- ) -> LoggingBidirectionalCollection<LoggingBidirectionalCollection<C>> {
- return LoggingBidirectionalCollection(
- wrapping: LoggingBidirectionalCollection(wrapping: c))
- }
- public static var predecessor = TypeIndexed(0)
- public static var formPredecessor = TypeIndexed(0)
- public static var last = TypeIndexed(0)
-}
-
-public class MutableCollectionLog : CollectionLog {
- public class func dispatchTester<C>(
- _ c: C
- ) -> LoggingMutableCollection<LoggingMutableCollection<C>> {
- return LoggingMutableCollection(
- wrapping: LoggingMutableCollection(wrapping: c))
- }
- public static var subscriptIndexSet = TypeIndexed(0)
- public static var subscriptRangeSet = TypeIndexed(0)
- public static var partitionBy = TypeIndexed(0)
- public static var _withUnsafeMutableBufferPointerIfSupported = TypeIndexed(0)
- public static var _withUnsafeMutableBufferPointerIfSupportedNonNilReturns =
- TypeIndexed(0)
-}
-
-/// Data container to keep track of how many times each `Base` type calls methods
-/// of `RangeReplaceableCollection`.
-///
-/// Each static variable is a mapping of Type -> Number of calls.
-public class RangeReplaceableCollectionLog : CollectionLog {
- public static var init_ = TypeIndexed(0)
- public static var initRepeating = TypeIndexed(0)
- public static var initWithSequence = TypeIndexed(0)
-
- public static var _customRemoveLast = TypeIndexed(0)
- public static var _customRemoveLastN = TypeIndexed(0)
- public static var append = TypeIndexed(0)
- public static var appendContentsOf = TypeIndexed(0)
- public static var insert = TypeIndexed(0)
- public static var insertContentsOf = TypeIndexed(0)
- public static var removeAll = TypeIndexed(0)
- public static var removeAt = TypeIndexed(0)
- public static var removeFirst = TypeIndexed(0)
- public static var removeFirstN = TypeIndexed(0)
- public static var removeSubrange = TypeIndexed(0)
- public static var replaceSubrange = TypeIndexed(0)
- public static var reserveCapacity = TypeIndexed(0)
-
- public class func dispatchTester<C>(
- _ rrc: C
- ) -> LoggingRangeReplaceableCollection<LoggingRangeReplaceableCollection<C>> {
- return LoggingRangeReplaceableCollection(
- wrapping: LoggingRangeReplaceableCollection(wrapping: rrc)
- )
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Sequence and Collection that count method calls
-//===----------------------------------------------------------------------===//
-
-% for Kind in ['Sequence', 'Collection', 'MutableCollection', 'RangeReplaceableCollection']:
-% for Traversal in [''] if Kind == 'Sequence' else TRAVERSALS:
-% if Kind == 'Sequence':
-% Self = 'LoggingSequence'
-% else:
-% Self = 'Logging' + Kind.replace('Collection', collectionForTraversal(Traversal))
-% end
-% if Kind == 'Sequence':
-% Constraints = Kind
-% Protocols = Kind
-% else:
-% Constraints = Kind + ' & ' + collectionForTraversal(Traversal)
-% Protocols = ', '.join(set([Kind, collectionForTraversal(Traversal)]))
-% end
-/// Interposes between `${Kind}` method calls to increment each method's
-/// counter.
-public struct ${Self}<
- Base : ${Constraints}
-> : ${Protocols}, LoggingType {
-
- public var base: Base
-
- public typealias Log = ${Kind}Log
-
- public init(wrapping base: Base) {
- self.base = base
- }
-
- public typealias Iterator = LoggingIterator<Base.Iterator>
-
- public func makeIterator() -> Iterator {
- Log.makeIterator[selfType] += 1
- return LoggingIterator(wrapping: base.makeIterator())
- }
-
- public var underestimatedCount: Int {
- Log.underestimatedCount[selfType] += 1
- return base.underestimatedCount
- }
-
- public func map<T>(
- _ transform: (Base.Iterator.Element) throws -> T
- ) rethrows -> [T] {
- Log.map[selfType] += 1
- return try base.map(transform)
- }
-
- public func filter(
- _ isIncluded: (Base.Iterator.Element) throws -> Bool
- ) rethrows -> [Base.Iterator.Element] {
- Log.filter[selfType] += 1
- return try base.filter(isIncluded)
- }
-
- public func forEach(
- _ body: (Base.Iterator.Element) throws -> Void
- ) rethrows {
- Log.forEach[selfType] += 1
- try base.forEach(body)
- }
-
- public typealias SubSequence = Base.SubSequence
-
- public func dropFirst(_ n: Int) -> SubSequence {
- Log.dropFirst[selfType] += 1
- return base.dropFirst(n)
- }
-
- public func dropLast(_ n: Int) -> SubSequence {
- Log.dropLast[selfType] += 1
- return base.dropLast(n)
- }
-
- public func drop(
- while predicate: (Base.Iterator.Element) throws -> Bool
- ) rethrows -> SubSequence {
- Log.dropWhile[selfType] += 1
- return try base.drop(while: predicate)
- }
-
- public func prefix(_ maxLength: Int) -> SubSequence {
- Log.prefixMaxLength[selfType] += 1
- return base.prefix(maxLength)
- }
-
- public func prefix(
- while predicate: (Base.Iterator.Element) throws -> Bool
- ) rethrows -> SubSequence {
- Log.prefixWhile[selfType] += 1
- return try base.prefix(while: predicate)
- }
-
- public func suffix(_ maxLength: Int) -> SubSequence {
- Log.suffixMaxLength[selfType] += 1
- return base.suffix(maxLength)
- }
-
- public func split(
- maxSplits: Int = Int.max,
- omittingEmptySubsequences: Bool = true,
- whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
- ) rethrows -> [SubSequence] {
- Log.split[selfType] += 1
- return try base.split(
- maxSplits: maxSplits,
- omittingEmptySubsequences: omittingEmptySubsequences,
- whereSeparator: isSeparator)
- }
-
- public func _customContainsEquatableElement(
- _ element: Base.Iterator.Element
- ) -> Bool? {
- Log._customContainsEquatableElement[selfType] += 1
- return base._customContainsEquatableElement(element)
- }
-
- /// If `self` is multi-pass (i.e., a `Collection`), invoke
- /// `preprocess` on `self` and return its result. Otherwise, return
- /// `nil`.
- public func _preprocessingPass<R>(
- _ preprocess: () throws -> R
- ) rethrows -> R? {
- Log._preprocessingPass[selfType] += 1
- return try base._preprocessingPass(preprocess)
- }
-
- /// Create a native array buffer containing the elements of `self`,
- /// in the same order.
- public func _copyToContiguousArray()
- -> ContiguousArray<Base.Iterator.Element> {
- Log._copyToContiguousArray[selfType] += 1
- return base._copyToContiguousArray()
- }
-
- /// Copy a Sequence into an array.
- public func _copyContents(
- initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
- ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
- Log._copyContents[selfType] += 1
- let (it,idx) = base._copyContents(initializing: buffer)
- return (Iterator(wrapping: it),idx)
- }
-
-% if Kind in ['Collection', 'MutableCollection', 'RangeReplaceableCollection']:
- public typealias Index = Base.Index
-
- public var startIndex: Index {
- Log.startIndex[selfType] += 1
- return base.startIndex
- }
-
- public var endIndex: Index {
- Log.endIndex[selfType] += 1
- return base.endIndex
- }
-
- public subscript(position: Index) -> Base.Iterator.Element {
- get {
- Log.subscriptIndex[selfType] += 1
- return base[position]
- }
-% if Kind == 'MutableCollection':
- set {
- Log.subscriptIndexSet[selfType] += 1
- base[position] = newValue
- }
-% end
- }
-
- public subscript(bounds: Range<Index>) -> SubSequence {
- get {
- Log.subscriptRange[selfType] += 1
- return base[bounds]
- }
-% if Kind == 'MutableCollection':
- set {
- Log.subscriptRangeSet[selfType] += 1
- base[bounds] = newValue
- }
-% end
- }
-
- public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
- Log._failEarlyRangeCheckIndex[selfType] += 1
- base._failEarlyRangeCheck(index, bounds: bounds)
- }
-
- public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
- Log._failEarlyRangeCheckRange[selfType] += 1
- base._failEarlyRangeCheck(range, bounds: bounds)
- }
-
- public func index(after i: Index) -> Index {
- Log.successor[selfType] += 1
- return base.index(after: i)
- }
-
- public func formIndex(after i: inout Index) {
- Log.formSuccessor[selfType] += 1
- base.formIndex(after: &i)
- }
-
- public typealias Indices = Base.Indices
-
- public var indices: Indices {
- Log.indices[selfType] += 1
- return base.indices
- }
-
- public func prefix(upTo end: Index) -> SubSequence {
- Log.prefixUpTo[selfType] += 1
- return base.prefix(upTo: end)
- }
-
- public func prefix(through position: Index) -> SubSequence {
- Log.prefixThrough[selfType] += 1
- return base.prefix(through: position)
- }
-
- public func suffix(from start: Index) -> SubSequence {
- Log.suffixFrom[selfType] += 1
- return base.suffix(from: start)
- }
-
- public var isEmpty: Bool {
- Log.isEmpty[selfType] += 1
- return base.isEmpty
- }
-
- public var count: Int {
- Log.count[selfType] += 1
- return base.count
- }
-
- public func _customIndexOfEquatableElement(
- _ element: Base.Iterator.Element
- ) -> Index?? {
- Log._customIndexOfEquatableElement[selfType] += 1
- return base._customIndexOfEquatableElement(element)
- }
-
- public var first: Base.Iterator.Element? {
- Log.first[selfType] += 1
- return base.first
- }
-
- public func index(_ i: Index, offsetBy n: Int) -> Index {
- Log.advance[selfType] += 1
- return base.index(i, offsetBy: n)
- }
-
- public func index(
- _ i: Index, offsetBy n: Int, limitedBy limit: Index
- ) -> Index? {
- Log.advanceLimit[selfType] += 1
- return base.index(i, offsetBy: n, limitedBy: limit)
- }
-
- public func distance(from start: Index, to end: Index) -> Int {
- Log.distance[selfType] += 1
- return base.distance(from: start, to: end)
- }
-% end
-
-% if Kind == 'MutableCollection':
- public mutating func partition(
- by belongsInSecondPartition: (Iterator.Element) throws -> Bool
- ) rethrows -> Index {
- Log.partitionBy[selfType] += 1
- return try base.partition(by: belongsInSecondPartition)
- }
-
- public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
- _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
- ) rethrows -> R? {
- Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
- let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
- if result != nil {
- Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
- }
- return result
- }
-% end
-
-% if Kind == 'RangeReplaceableCollection':
- public init() {
- self.base = Base()
- Log.init_[selfType] += 1
- }
-
- public init(repeating repeatedValue: Iterator.Element, count: Int) {
- self.base = Base(repeating: repeatedValue, count: count)
- Log.initRepeating[selfType] += 1
- }
-
- public init<S : Sequence>(_ elements: S)
- where S.Iterator.Element == Iterator.Element {
- self.base = Base(elements)
- Log.initWithSequence[selfType] += 1
- }
-
- public mutating func _customRemoveLast() -> Base.Iterator.Element? {
- Log._customRemoveLast[selfType] += 1
- return base._customRemoveLast()
- }
-
- public mutating func _customRemoveLast(_ n: Int) -> Bool {
- Log._customRemoveLastN[selfType] += 1
- return base._customRemoveLast(n)
- }
-
- public mutating func append(_ newElement: Base.Iterator.Element) {
- Log.append[selfType] += 1
- base.append(newElement)
- }
-
- public mutating func append<S : Sequence>(
- contentsOf newElements: S
- ) where S.Iterator.Element == Base.Iterator.Element {
- Log.appendContentsOf[selfType] += 1
- base.append(contentsOf: newElements)
- }
-
- public mutating func insert(
- _ newElement: Base.Iterator.Element, at i: Index
- ) {
- Log.insert[selfType] += 1
- base.insert(newElement, at: i)
- }
-
- public mutating func insert<C : Collection>(
- contentsOf newElements: C, at i: Index
- ) where C.Iterator.Element == Base.Iterator.Element {
- Log.insertContentsOf[selfType] += 1
- base.insert(contentsOf: newElements, at: i)
- }
-
- public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
- Log.removeAll[selfType] += 1
- base.removeAll(keepingCapacity: keepCapacity)
- }
-
- @discardableResult
- public mutating func remove(at index: Index) -> Base.Iterator.Element {
- Log.removeAt[selfType] += 1
- return base.remove(at: index)
- }
-
- @discardableResult
- public mutating func removeFirst() -> Base.Iterator.Element {
- Log.removeFirst[selfType] += 1
- return base.removeFirst()
- }
-
- public mutating func removeFirst(_ n: Int) {
- Log.removeFirstN[selfType] += 1
- base.removeFirst(n)
- }
-
- public mutating func removeSubrange(_ bounds: Range<Index>) {
- Log.removeSubrange[selfType] += 1
- base.removeSubrange(bounds)
- }
-
- public mutating func replaceSubrange<C : Collection>(
- _ bounds: Range<Index>, with newElements: C
- ) where C.Iterator.Element == Base.Iterator.Element {
- Log.replaceSubrange[selfType] += 1
- base.replaceSubrange(bounds, with: newElements)
- }
-
- public mutating func reserveCapacity(_ n: Int) {
- Log.reserveCapacity[selfType] += 1
- base.reserveCapacity(n)
- }
-% end
-% if Traversal in ['Bidirectional', 'RandomAccess']:
- public func index(before i: Index) -> Index {
- BidirectionalCollectionLog.predecessor[selfType] += 1
- return base.index(before: i)
- }
-
- public func formIndex(before i: inout Index) {
- BidirectionalCollectionLog.formPredecessor[selfType] += 1
- base.formIndex(before: &i)
- }
-
- public var last: Iterator.Element? {
- BidirectionalCollectionLog.last[selfType] += 1
- return base.last
- }
-% end
-}
-% end
-% end
-
-//===----------------------------------------------------------------------===//
-// Collections that count calls to `_withUnsafeMutableBufferPointerIfSupported`
-//===----------------------------------------------------------------------===//
-
-% for Traversal in TRAVERSALS:
-% Self = 'BufferAccessLoggingMutable' + collectionForTraversal(Traversal)
-/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
-/// to increment a counter. Calls to this method from within dispatched methods
-/// are uncounted by the standard logging collection wrapper.
-public struct ${Self}<
- Base : MutableCollection & ${collectionForTraversal(Traversal)}
-> : MutableCollection, ${collectionForTraversal(Traversal)}, LoggingType {
-
- public var base: Base
-
- public typealias Log = MutableCollectionLog
-
- public typealias SubSequence = Base.SubSequence
- public typealias Iterator = Base.Iterator
- public typealias Element = Base.Element
-
- public init(wrapping base: Base) {
- self.base = base
- }
-
- public func makeIterator() -> Iterator {
- return base.makeIterator()
- }
-
- public typealias Index = Base.Index
- public typealias Indices = Base.Indices
-
- public var startIndex: Index {
- return base.startIndex
- }
-
- public var endIndex: Index {
- return base.endIndex
- }
-
- public var indices: Indices {
- return base.indices
- }
-
- public subscript(position: Index) -> Element {
- get {
- return base[position]
- }
- set {
- base[position] = newValue
- }
- }
-
- public subscript(bounds: Range<Index>) -> SubSequence {
- get {
- return base[bounds]
- }
- set {
- base[bounds] = newValue
- }
- }
-
- public func index(after i: Index) -> Index {
- return base.index(after: i)
- }
-
-% if Traversal in ['Bidirectional', 'RandomAccess']:
- public func index(before i: Index) -> Index {
- return base.index(before: i)
- }
-% end
-
- public func index(_ i: Index, offsetBy n: Int) -> Index {
- return base.index(i, offsetBy: n)
- }
-
- public func distance(from start: Index, to end: Index) -> Int {
- return base.distance(from: start, to: end)
- }
-
- public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
- _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
- ) rethrows -> R? {
- Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
- let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
- if result != nil {
- Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
- }
- return result
- }
-}
-% end
-
-//===----------------------------------------------------------------------===//
-// Custom assertions
-//===----------------------------------------------------------------------===//
-
-public func expectCustomizable<T : LoggingType>(
- _: T, _ counters: TypeIndexed<Int>, ${TRACE}
-) where
- T.Base : LoggingType,
- T.Log == T.Base.Log {
- let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
- expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
- expectEqual(
- counters[T.self], counters[T.Base.self], message(), stackTrace: newTrace)
-}
-
-public func expectNotCustomizable<T : LoggingType>(
- _: T, _ counters: TypeIndexed<Int>, ${TRACE}
-) where
- T.Base : LoggingType,
- T.Log == T.Base.Log {
- let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
- expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
- expectEqual(0, counters[T.Base.self], message(), stackTrace: newTrace)
-}
diff --git a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift
new file mode 100644
index 0000000..73a3379
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift
@@ -0,0 +1,6060 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import StdlibUnittest
+
+/// State shared by all generators of a MinimalSequence.
+internal class _MinimalIteratorSharedState<T> {
+ internal init(_ data: [T]) {
+ self.data = data
+ }
+
+ internal let data: [T]
+ internal var i: Int = 0
+ internal var underestimatedCount: Int = 0
+}
+
+//===----------------------------------------------------------------------===//
+// MinimalIterator
+//===----------------------------------------------------------------------===//
+
+/// An IteratorProtocol that implements the protocol contract in the most
+/// narrow way possible.
+///
+/// This generator will return `nil` only once.
+public struct MinimalIterator<T> : IteratorProtocol {
+ public init<S : Sequence>(_ s: S) where S.Iterator.Element == T {
+ self._sharedState = _MinimalIteratorSharedState(Array(s))
+ }
+
+ public init(_ data: [T]) {
+ self._sharedState = _MinimalIteratorSharedState(data)
+ }
+
+ internal init(_ _sharedState: _MinimalIteratorSharedState<T>) {
+ self._sharedState = _sharedState
+ }
+
+ public func next() -> T? {
+ if _sharedState.i == _sharedState.data.count {
+ return nil
+ }
+ defer { _sharedState.i += 1 }
+ return _sharedState.data[_sharedState.i]
+ }
+
+ internal let _sharedState: _MinimalIteratorSharedState<T>
+}
+
+// A protocol to identify MinimalIterator.
+public protocol _MinimalIterator {}
+extension MinimalIterator : _MinimalIterator {}
+
+//===----------------------------------------------------------------------===//
+// MinimalSequence
+//===----------------------------------------------------------------------===//
+
+public enum UnderestimatedCountBehavior {
+ /// Return the actual number of elements.
+ case precise
+
+ /// Return the actual number of elements divided by 2.
+ case half
+
+ /// Return an overestimated count. Useful to test how algorithms reserve
+ /// memory.
+ case overestimate
+
+ /// Return the provided value.
+ case value(Int)
+}
+
+/// A Sequence that implements the protocol contract in the most
+/// narrow way possible.
+///
+/// This sequence is consumed when its generator is advanced.
+public struct MinimalSequence<T> : Sequence, CustomDebugStringConvertible {
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ let data = Array(elements)
+ self._sharedState = _MinimalIteratorSharedState(data)
+
+ switch underestimatedCount {
+ case .precise:
+ self._sharedState.underestimatedCount = data.count
+
+ case .half:
+ self._sharedState.underestimatedCount = data.count / 2
+
+ case .overestimate:
+ self._sharedState.underestimatedCount = data.count * 3 + 5
+
+ case .value(let count):
+ self._sharedState.underestimatedCount = count
+ }
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_sharedState)
+ }
+
+ public var underestimatedCount: Int {
+ return Swift.max(0, self._sharedState.underestimatedCount - self._sharedState.i)
+ }
+
+ public var debugDescription: String {
+ return "MinimalSequence(\(_sharedState.data[_sharedState.i..<_sharedState.data.count]))"
+ }
+
+ internal let _sharedState: _MinimalIteratorSharedState<T>
+}
+
+//===----------------------------------------------------------------------===//
+// Index invalidation checking
+//===----------------------------------------------------------------------===//
+
+internal enum _CollectionOperation : Equatable {
+ case reserveCapacity(capacity: Int)
+ case append
+ case appendContentsOf(count: Int)
+ case replaceRange(subRange: Range<Int>, replacementCount: Int)
+ case insert(atIndex: Int)
+ case insertContentsOf(atIndex: Int, count: Int)
+ case removeAtIndex(index: Int)
+ case removeLast
+ case removeRange(subRange: Range<Int>)
+ case removeAll(keepCapacity: Bool)
+
+ internal func _applyTo(
+ elementsLastMutatedStateIds: [Int],
+ endIndexLastMutatedStateId: Int,
+ nextStateId: Int
+ ) -> ([Int], Int) {
+ var newElementsIds = elementsLastMutatedStateIds
+ var newEndIndexId = endIndexLastMutatedStateId
+ switch self {
+ case .reserveCapacity:
+ let invalidIndices = newElementsIds.indices
+ newElementsIds.replaceSubrange(
+ invalidIndices,
+ with: repeatElement(nextStateId, count: invalidIndices.count))
+ newEndIndexId = nextStateId
+
+ case .append:
+ newElementsIds.append(nextStateId)
+ newEndIndexId = nextStateId
+
+ case .appendContentsOf(let count):
+ newElementsIds.append(contentsOf:
+ repeatElement(nextStateId, count: count))
+ newEndIndexId = nextStateId
+
+ case .replaceRange(let subRange, let replacementCount):
+ newElementsIds.replaceSubrange(
+ subRange,
+ with: repeatElement(nextStateId, count: replacementCount))
+
+ let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
+ newElementsIds.replaceSubrange(
+ invalidIndices,
+ with: repeatElement(nextStateId, count: invalidIndices.count))
+ newEndIndexId = nextStateId
+
+ case .insert(let atIndex):
+ newElementsIds.insert(nextStateId, at: atIndex)
+
+ let invalidIndices = atIndex..<newElementsIds.endIndex
+ newElementsIds.replaceSubrange(
+ invalidIndices,
+ with: repeatElement(nextStateId, count: invalidIndices.count))
+ newEndIndexId = nextStateId
+
+ case .insertContentsOf(let atIndex, let count):
+ newElementsIds.insert(
+ contentsOf: repeatElement(nextStateId, count: count),
+ at: atIndex)
+
+ let invalidIndices = atIndex..<newElementsIds.endIndex
+ newElementsIds.replaceSubrange(
+ invalidIndices,
+ with: repeatElement(nextStateId, count: invalidIndices.count))
+ newEndIndexId = nextStateId
+
+ case .removeAtIndex(let index):
+ newElementsIds.remove(at: index)
+
+ let invalidIndices = index..<newElementsIds.endIndex
+ newElementsIds.replaceSubrange(
+ invalidIndices,
+ with: repeatElement(nextStateId, count: invalidIndices.count))
+ newEndIndexId = nextStateId
+
+ case .removeLast:
+ newElementsIds.removeLast()
+ newEndIndexId = nextStateId
+
+ case .removeRange(let subRange):
+ newElementsIds.removeSubrange(subRange)
+
+ let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
+ newElementsIds.replaceSubrange(
+ invalidIndices,
+ with: repeatElement(nextStateId, count: invalidIndices.count))
+ newEndIndexId = nextStateId
+
+ case .removeAll(let keepCapacity):
+ newElementsIds.removeAll(keepingCapacity: keepCapacity)
+ newEndIndexId = nextStateId
+ }
+ return (newElementsIds, newEndIndexId)
+ }
+}
+
+internal func == (
+ lhs: _CollectionOperation,
+ rhs: _CollectionOperation
+) -> Bool {
+ switch (lhs, rhs) {
+ case (.reserveCapacity(let lhsCapacity), .reserveCapacity(let rhsCapacity)):
+ return lhsCapacity == rhsCapacity
+
+ case (.append, .append):
+ return true
+
+ case (.appendContentsOf(let lhsCount), .appendContentsOf(let rhsCount)):
+ return lhsCount == rhsCount
+
+ case (
+ .replaceRange(let lhsSubRange, let lhsReplacementCount),
+ .replaceRange(let rhsSubRange, let rhsReplacementCount)):
+
+ return lhsSubRange == rhsSubRange &&
+ lhsReplacementCount == rhsReplacementCount
+
+ case (.insert(let lhsAtIndex), .insert(let rhsAtIndex)):
+ return lhsAtIndex == rhsAtIndex
+
+ case (
+ .insertContentsOf(let lhsAtIndex, let lhsCount),
+ .insertContentsOf(let rhsAtIndex, let rhsCount)):
+
+ return lhsAtIndex == rhsAtIndex && lhsCount == rhsCount
+
+ case (.removeAtIndex(let lhsIndex), .removeAtIndex(let rhsIndex)):
+ return lhsIndex == rhsIndex
+
+ case (.removeLast, .removeLast):
+ return true
+
+ case (.removeRange(let lhsSubRange), .removeRange(let rhsSubRange)):
+ return lhsSubRange == rhsSubRange
+
+ case (.removeAll(let lhsKeepCapacity), .removeAll(let rhsKeepCapacity)):
+ return lhsKeepCapacity == rhsKeepCapacity
+
+ default:
+ return false
+ }
+}
+
+public struct _CollectionState : Equatable, Hashable {
+ internal static var _nextUnusedState: Int = 0
+ internal static var _namedStates: [String : _CollectionState] = [:]
+
+ internal let _id: Int
+ internal let _elementsLastMutatedStateIds: [Int]
+ internal let _endIndexLastMutatedStateId: Int
+
+ internal init(
+ id: Int,
+ elementsLastMutatedStateIds: [Int],
+ endIndexLastMutatedStateId: Int) {
+ self._id = id
+ self._elementsLastMutatedStateIds = elementsLastMutatedStateIds
+ self._endIndexLastMutatedStateId = endIndexLastMutatedStateId
+ }
+
+ public init(newRootStateForElementCount count: Int) {
+ self._id = _CollectionState._nextUnusedState
+ _CollectionState._nextUnusedState += 1
+ self._elementsLastMutatedStateIds =
+ Array(repeatElement(self._id, count: count))
+ self._endIndexLastMutatedStateId = self._id
+ }
+
+ internal init(name: String, elementCount: Int) {
+ if let result = _CollectionState._namedStates[name] {
+ self = result
+ } else {
+ self = _CollectionState(newRootStateForElementCount: elementCount)
+ _CollectionState._namedStates[name] = self
+ }
+ }
+
+ public var hashValue: Int {
+ return _id.hashValue
+ }
+}
+
+public func == (lhs: _CollectionState, rhs: _CollectionState) -> Bool {
+ return lhs._id == rhs._id
+}
+
+internal struct _CollectionStateTransition {
+ internal let _previousState: _CollectionState
+ internal let _operation: _CollectionOperation
+ internal let _nextState: _CollectionState
+
+ internal static var _allTransitions:
+ [_CollectionState : Box<[_CollectionStateTransition]>] = [:]
+
+ internal init(
+ previousState: _CollectionState,
+ operation: _CollectionOperation,
+ nextState: _CollectionState
+ ) {
+ var transitions =
+ _CollectionStateTransition._allTransitions[previousState]
+ if transitions == nil {
+ transitions = Box<[_CollectionStateTransition]>([])
+ _CollectionStateTransition._allTransitions[previousState] = transitions
+ }
+ if let i = transitions!.value.firstIndex(where: { $0._operation == operation }) {
+ self = transitions!.value[i]
+ return
+ }
+ self._previousState = previousState
+ self._operation = operation
+ self._nextState = nextState
+ transitions!.value.append(self)
+ }
+
+ internal init(
+ previousState: _CollectionState,
+ operation: _CollectionOperation
+ ) {
+ let nextStateId = _CollectionState._nextUnusedState
+ _CollectionState._nextUnusedState += 1
+ let (newElementStates, newEndIndexState) = operation._applyTo(
+ elementsLastMutatedStateIds: previousState._elementsLastMutatedStateIds,
+ endIndexLastMutatedStateId: previousState._endIndexLastMutatedStateId,
+ nextStateId: nextStateId)
+ let nextState = _CollectionState(
+ id: nextStateId,
+ elementsLastMutatedStateIds: newElementStates,
+ endIndexLastMutatedStateId: newEndIndexState)
+ self = _CollectionStateTransition(
+ previousState: previousState,
+ operation: operation,
+ nextState: nextState)
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// MinimalIndex
+//===----------------------------------------------------------------------===//
+
+/// Asserts that the two indices are allowed to participate in a binary
+/// operation.
+internal func _expectCompatibleIndices(
+ _ first: MinimalIndex,
+ _ second: MinimalIndex,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ if first._collectionState._id == second._collectionState._id {
+ // Fast path: the indices are derived from the same state.
+ return
+ }
+
+ // The indices are derived from different states. Check that they point
+ // to a self-consistent view of the collection.
+ if first._collectionState._id > second._collectionState._id {
+ return _expectCompatibleIndices(second, first)
+ }
+
+ func lastMutatedStateId(
+ of i: MinimalIndex,
+ in state: _CollectionState
+ ) -> Int {
+ let offset = i.position
+ if offset == state._elementsLastMutatedStateIds.endIndex {
+ return state._id
+ }
+ return state._elementsLastMutatedStateIds[offset]
+ }
+
+ let newestCollectionState = second._collectionState
+ let expectedFirstIndexLastMutatedStateId =
+ lastMutatedStateId(of: first, in: newestCollectionState)
+
+ expectEqual(
+ expectedFirstIndexLastMutatedStateId,
+ first._collectionState._id,
+ "Indices are not compatible:\n" +
+ "first: \(first)\n" +
+ "second: \(second)\n" +
+ "first element last mutated in state id: \(first._collectionState._id)\n" +
+ "expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
+ "newest collection state: \(newestCollectionState)",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ // To make writing assertions easier, perform a trap.
+ if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
+ fatalError("Indices are not compatible")
+ }
+}
+
+public struct MinimalIndex : Comparable {
+ public init(
+ collectionState: _CollectionState,
+ position: Int,
+ startIndex: Int,
+ endIndex: Int
+ ) {
+ expectTrapping(
+ position,
+ in: startIndex...endIndex)
+ self = MinimalIndex(
+ _collectionState: collectionState,
+ uncheckedPosition: position)
+ }
+
+ internal init(
+ _collectionState: _CollectionState,
+ uncheckedPosition: Int
+ ) {
+ self._collectionState = _collectionState
+ self.position = uncheckedPosition
+ }
+
+ public let _collectionState: _CollectionState
+ public let position: Int
+
+ public static var trapOnRangeCheckFailure = ResettableValue(true)
+
+}
+
+public func == (lhs: MinimalIndex, rhs: MinimalIndex) -> Bool {
+ _expectCompatibleIndices(lhs, rhs)
+ return lhs.position == rhs.position
+}
+
+public func < (lhs: MinimalIndex, rhs: MinimalIndex) -> Bool {
+ _expectCompatibleIndices(lhs, rhs)
+ return lhs.position < rhs.position
+}
+
+
+//===----------------------------------------------------------------------===//
+// MinimalStrideableIndex
+//===----------------------------------------------------------------------===//
+
+/// Asserts that the two indices are allowed to participate in a binary
+/// operation.
+internal func _expectCompatibleIndices(
+ _ first: MinimalStrideableIndex,
+ _ second: MinimalStrideableIndex,
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ if first._collectionState._id == second._collectionState._id {
+ // Fast path: the indices are derived from the same state.
+ return
+ }
+
+ // The indices are derived from different states. Check that they point
+ // to a self-consistent view of the collection.
+ if first._collectionState._id > second._collectionState._id {
+ return _expectCompatibleIndices(second, first)
+ }
+
+ func lastMutatedStateId(
+ of i: MinimalStrideableIndex,
+ in state: _CollectionState
+ ) -> Int {
+ let offset = i.position
+ if offset == state._elementsLastMutatedStateIds.endIndex {
+ return state._id
+ }
+ return state._elementsLastMutatedStateIds[offset]
+ }
+
+ let newestCollectionState = second._collectionState
+ let expectedFirstIndexLastMutatedStateId =
+ lastMutatedStateId(of: first, in: newestCollectionState)
+
+ expectEqual(
+ expectedFirstIndexLastMutatedStateId,
+ first._collectionState._id,
+ "Indices are not compatible:\n" +
+ "first: \(first)\n" +
+ "second: \(second)\n" +
+ "first element last mutated in state id: \(first._collectionState._id)\n" +
+ "expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
+ "newest collection state: \(newestCollectionState)",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+ // To make writing assertions easier, perform a trap.
+ if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
+ fatalError("Indices are not compatible")
+ }
+}
+
+public struct MinimalStrideableIndex : Comparable {
+ public init(
+ collectionState: _CollectionState,
+ position: Int,
+ startIndex: Int,
+ endIndex: Int
+ ) {
+ expectTrapping(
+ position,
+ in: startIndex...endIndex)
+ self = MinimalStrideableIndex(
+ _collectionState: collectionState,
+ uncheckedPosition: position)
+ }
+
+ internal init(
+ _collectionState: _CollectionState,
+ uncheckedPosition: Int
+ ) {
+ self._collectionState = _collectionState
+ self.position = uncheckedPosition
+ }
+
+ public let _collectionState: _CollectionState
+ public let position: Int
+
+ public static var trapOnRangeCheckFailure = ResettableValue(true)
+
+ public var timesAdvancedCalled = ResettableValue(0)
+ public var timesDistanceCalled = ResettableValue(0)
+}
+
+public func == (lhs: MinimalStrideableIndex, rhs: MinimalStrideableIndex) -> Bool {
+ _expectCompatibleIndices(lhs, rhs)
+ return lhs.position == rhs.position
+}
+
+public func < (lhs: MinimalStrideableIndex, rhs: MinimalStrideableIndex) -> Bool {
+ _expectCompatibleIndices(lhs, rhs)
+ return lhs.position < rhs.position
+}
+
+
+extension MinimalStrideableIndex : Strideable {
+ public typealias Stride = Int
+
+ public func distance(to other: MinimalStrideableIndex) -> Int {
+ timesDistanceCalled.value += 1
+ _expectCompatibleIndices(self, other)
+ return other.position - position
+ }
+
+ public func advanced(by n: Int) -> MinimalStrideableIndex {
+ timesAdvancedCalled.value += 1
+ return MinimalStrideableIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: position + n)
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Minimal***[Mutable]?Collection
+//===----------------------------------------------------------------------===//
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalCollection<T> : Collection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ _precondition(start <= end,
+ "Only BidirectionalCollections can have end come before start")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ _precondition(n >= 0,
+ "Only BidirectionalCollections can be advanced by a negative amount")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableCollection<T> : Collection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ _precondition(start <= end,
+ "Only BidirectionalCollections can have end come before start")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ _precondition(n >= 0,
+ "Only BidirectionalCollections can be advanced by a negative amount")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableCollection<T> : Collection, MutableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ _precondition(start <= end,
+ "Only BidirectionalCollections can have end come before start")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ _precondition(n >= 0,
+ "Only BidirectionalCollections can be advanced by a negative amount")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ set {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ _elements[i.position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRangeReplaceableCollection<T> : Collection, MutableCollection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ _precondition(start <= end,
+ "Only BidirectionalCollections can have end come before start")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ _precondition(n >= 0,
+ "Only BidirectionalCollections can be advanced by a negative amount")
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ set {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ _elements[i.position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalBidirectionalCollection<T> : BidirectionalCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalBidirectionalCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableBidirectionalCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableBidirectionalCollection<T> : BidirectionalCollection, MutableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ set {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ _elements[i.position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableBidirectionalCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, MutableCollection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ set {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ _elements[i.position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableBidirectionalCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRandomAccessCollection<T> : RandomAccessCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<MinimalRandomAccessCollection<T>>
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRandomAccessCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRandomAccessCollectionWithStrideableIndex<T> : RandomAccessCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalStrideableIndex
+
+ internal func _index(forPosition i: Int) -> MinimalStrideableIndex {
+ return MinimalStrideableIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalStrideableIndex {
+ return MinimalStrideableIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalStrideableIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalStrideableIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+ public typealias Indices = Range<MinimalStrideableIndex>
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalStrideableIndex,
+ bounds: Range<MinimalStrideableIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalStrideableIndex>,
+ bounds: Range<MinimalStrideableIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalStrideableIndex, to end: MinimalStrideableIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalStrideableIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<MinimalRandomAccessCollectionWithStrideableIndex<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableRandomAccessCollection<T> : RandomAccessCollection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<MinimalRangeReplaceableRandomAccessCollection<T>>
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableRandomAccessCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableRandomAccessCollectionWithStrideableIndex<T> : RandomAccessCollection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalStrideableIndex
+
+ internal func _index(forPosition i: Int) -> MinimalStrideableIndex {
+ return MinimalStrideableIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalStrideableIndex {
+ return MinimalStrideableIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalStrideableIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalStrideableIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+ public typealias Indices = Range<MinimalStrideableIndex>
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalStrideableIndex,
+ bounds: Range<MinimalStrideableIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalStrideableIndex>,
+ bounds: Range<MinimalStrideableIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalStrideableIndex, to end: MinimalStrideableIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalStrideableIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ }
+
+ public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<MinimalRangeReplaceableRandomAccessCollectionWithStrideableIndex<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalStrideableIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalStrideableIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalStrideableIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalStrideableIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalStrideableIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRandomAccessCollection<T> : RandomAccessCollection, MutableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<MinimalMutableRandomAccessCollection<T>>
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ set {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ _elements[i.position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRandomAccessCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+
+ public var underestimatedCount: Int
+
+ internal var _elements: [T]
+ internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRangeReplaceableRandomAccessCollection<T> : RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
+ /// Creates a collection with given contents, but a unique modification
+ /// history. No other instance has the same modification history.
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == T {
+ self._elements = Array(elements)
+
+ self._collectionState = _CollectionState(
+ newRootStateForElementCount: self._elements.count)
+
+ switch underestimatedCount {
+ case .precise:
+ self.underestimatedCount = _elements.count
+
+ case .half:
+ self.underestimatedCount = _elements.count / 2
+
+ case .overestimate:
+ self.underestimatedCount = _elements.count * 3 + 5
+
+ case .value(let count):
+ self.underestimatedCount = count
+ }
+ }
+
+ public init() {
+ self.underestimatedCount = 0
+ self._elements = []
+ self._collectionState =
+ _CollectionState(name: "\(type(of: self))", elementCount: 0)
+ }
+
+ public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+ self.underestimatedCount = 0
+ self._elements = Array(elements)
+ self._collectionState =
+ _CollectionState(newRootStateForElementCount: self._elements.count)
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<T> {
+ timesMakeIteratorCalled.value += 1
+ return MinimalIterator(_elements)
+ }
+
+ public typealias Index = MinimalIndex
+
+ internal func _index(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ collectionState: _collectionState,
+ position: i,
+ startIndex: _elements.startIndex,
+ endIndex: _elements.endIndex)
+ }
+
+ internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+ return MinimalIndex(
+ _collectionState: _collectionState,
+ uncheckedPosition: i)
+ }
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.startIndex)
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return _uncheckedIndex(forPosition: _elements.endIndex)
+ }
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<MinimalMutableRangeReplaceableRandomAccessCollection<T>>
+
+ public func _failEarlyRangeCheck(
+ _ index: MinimalIndex,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: index.position),
+ index)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ index.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func _failEarlyRangeCheck(
+ _ range: Range<MinimalIndex>,
+ bounds: Range<MinimalIndex>
+ ) {
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.lowerBound.position),
+ range.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: range.upperBound.position),
+ range.upperBound)
+
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.lowerBound.position),
+ bounds.lowerBound)
+ _expectCompatibleIndices(
+ _uncheckedIndex(forPosition: bounds.upperBound.position),
+ bounds.upperBound)
+
+ expectTrapping(
+ range.lowerBound.position..<range.upperBound.position,
+ in: bounds.lowerBound.position..<bounds.upperBound.position)
+ }
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _uncheckedIndex(forPosition: i.position + 1)
+ }
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ // FIXME: swift-3-indexing-model: perform a range check and use
+ // return _uncheckedIndex(forPosition: i.position - 1)
+ return _index(forPosition: i.position - 1)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if start != endIndex {
+ _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+ }
+ if end != endIndex {
+ _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+ }
+ return end.position - start.position
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ // FIXME: swift-3-indexing-model: perform a range check properly.
+ if i != endIndex {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ }
+ return _index(forPosition: i.position + n)
+ }
+
+ public subscript(i: MinimalIndex) -> T {
+ get {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ return _elements[i.position]
+ }
+ set {
+ _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+ _elements[i.position] = newValue
+ }
+ }
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableRandomAccessCollection<T>> {
+ get {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+ public mutating func reserveCapacity(_ n: Int) {
+ _willMutate(.reserveCapacity(capacity: n))
+ _elements.reserveCapacity(n)
+ reservedCapacity = Swift.max(reservedCapacity, n)
+ }
+
+ public mutating func append(_ x: T) {
+ _willMutate(.append)
+ _elements.append(x)
+ }
+
+ public mutating func append<S : Sequence>(contentsOf newElements: S)
+ where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.append(contentsOf: newElements)
+ let newCount = count
+ _willMutate(.appendContentsOf(count: newCount - oldCount))
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<MinimalIndex>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == T {
+ let oldCount = count
+ _elements.replaceSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position,
+ with: newElements)
+ let newCount = count
+ _willMutate(.replaceRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+ replacementCount:
+ subRange.upperBound.position - subRange.lowerBound.position
+ + newCount - oldCount))
+ }
+
+ public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+ _willMutate(.insert(atIndex: i.position))
+ _elements.insert(newElement, at: i.position)
+ }
+
+ public mutating func insert<S : Collection>(
+ contentsOf newElements: S, at i: MinimalIndex
+ ) where S.Iterator.Element == T {
+ let oldCount = count
+ _elements.insert(contentsOf: newElements, at: i.position)
+ let newCount = count
+
+ if newCount - oldCount != 0 {
+ _willMutate(.insertContentsOf(
+ atIndex: i.position,
+ count: newCount - oldCount))
+ }
+ }
+
+ @discardableResult
+ public mutating func remove(at i: MinimalIndex) -> T {
+ _willMutate(.removeAtIndex(index: i.position))
+ return _elements.remove(at: i.position)
+ }
+
+ @discardableResult
+ public mutating func removeLast() -> T {
+ _willMutate(.removeLast)
+ return _elements.removeLast()
+ }
+
+ public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+ if !subRange.isEmpty {
+ _willMutate(.removeRange(
+ subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+ }
+ _elements.removeSubrange(
+ subRange.lowerBound.position..<subRange.upperBound.position
+ )
+ }
+
+ public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+ _willMutate(.removeAll(keepCapacity: keepCapacity))
+ // Ignore the value of `keepCapacity`.
+ _elements.removeAll(keepingCapacity: false)
+ }
+
+ internal mutating func _willMutate(_ operation: _CollectionOperation) {
+ _collectionState = _CollectionStateTransition(
+ previousState: _collectionState,
+ operation: operation)._nextState
+ }
+
+ public var underestimatedCount: Int
+ public var reservedCapacity: Int = 0
+
+ internal var _elements: [T]
+ internal var _collectionState: _CollectionState
+}
+
+
+/// A Sequence that uses as many default implementations as
+/// `Sequence` can provide.
+public struct DefaultedSequence<Element> : Sequence {
+ public let base: MinimalSequence<Element>
+
+ public init(base: MinimalSequence<Element>) {
+ self.base = base
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base: MinimalSequence(
+ elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return base.makeIterator()
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+}
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedCollection<Element> : Collection {
+ public typealias Base = MinimalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public let base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+ public typealias Base = MinimalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedForwardRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRangeReplaceableCollection<Element> : Collection, RangeReplaceableCollection {
+ public typealias Base = MinimalRangeReplaceableCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalRangeReplaceableCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public init() {
+ base = Base()
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<DefaultedRangeReplaceableCollection<Element>.Index>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == Element {
+ base.replaceSubrange(subRange, with: newElements)
+ }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+ public typealias Base = MinimalRangeReplaceableCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedForwardRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableCollection<Element> : Collection, MutableCollection {
+ public typealias Base = MinimalMutableCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalMutableCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ set {
+ base[i] = newValue
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+ public typealias Base = MinimalMutableCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedForwardRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRangeReplaceableCollection<Element> : Collection, MutableCollection, RangeReplaceableCollection {
+ public typealias Base = MinimalMutableRangeReplaceableCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalMutableRangeReplaceableCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ set {
+ base[i] = newValue
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+ public init() {
+ base = Base()
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<DefaultedMutableRangeReplaceableCollection<Element>.Index>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == Element {
+ base.replaceSubrange(subRange, with: newElements)
+ }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+ public typealias Base = MinimalMutableRangeReplaceableCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedForwardRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedForwardRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedBidirectionalCollection<Element> : BidirectionalCollection {
+ public typealias Base = MinimalBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public let base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedBidirectionalCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+ public typealias Base = MinimalBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedBidirectionalRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRangeReplaceableBidirectionalCollection<Element> : BidirectionalCollection, RangeReplaceableCollection {
+ public typealias Base = MinimalRangeReplaceableBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalRangeReplaceableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableBidirectionalCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public init() {
+ base = Base()
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<DefaultedRangeReplaceableBidirectionalCollection<Element>.Index>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == Element {
+ base.replaceSubrange(subRange, with: newElements)
+ }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+ public typealias Base = MinimalRangeReplaceableBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedBidirectionalRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableBidirectionalCollection<Element> : BidirectionalCollection, MutableCollection {
+ public typealias Base = MinimalMutableBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalMutableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ set {
+ base[i] = newValue
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableBidirectionalCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+ public typealias Base = MinimalMutableBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedBidirectionalRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRangeReplaceableBidirectionalCollection<Element> : BidirectionalCollection, MutableCollection, RangeReplaceableCollection {
+ public typealias Base = MinimalMutableRangeReplaceableBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalMutableRangeReplaceableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ set {
+ base[i] = newValue
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableBidirectionalCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+ public init() {
+ base = Base()
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<DefaultedMutableRangeReplaceableBidirectionalCollection<Element>.Index>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == Element {
+ base.replaceSubrange(subRange, with: newElements)
+ }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+ public typealias Base = MinimalMutableRangeReplaceableBidirectionalCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedBidirectionalRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedBidirectionalRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRandomAccessCollection<Element> : RandomAccessCollection {
+ public typealias Base = MinimalRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<DefaultedRandomAccessCollection<Element>>
+
+ public let base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRandomAccessCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+ public typealias Base = MinimalRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedRandomAccessRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRandomAccessCollectionWithStrideableIndex<Element> : RandomAccessCollection {
+ public typealias Base = MinimalRandomAccessCollectionWithStrideableIndex<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalStrideableIndex
+
+ public typealias Indices = Range<MinimalStrideableIndex>
+
+ public let base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalRandomAccessCollectionWithStrideableIndex(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalStrideableIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalStrideableIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalStrideableIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<DefaultedRandomAccessCollectionWithStrideableIndex<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+ public typealias Base = MinimalRandomAccessCollectionWithStrideableIndex<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalStrideableIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedRandomAccessRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRangeReplaceableRandomAccessCollection<Element> : RandomAccessCollection, RangeReplaceableCollection {
+ public typealias Base = MinimalRangeReplaceableRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<DefaultedRangeReplaceableRandomAccessCollection<Element>>
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalRangeReplaceableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableRandomAccessCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ }
+
+ public init() {
+ base = Base()
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<DefaultedRangeReplaceableRandomAccessCollection<Element>.Index>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == Element {
+ base.replaceSubrange(subRange, with: newElements)
+ }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+ public typealias Base = MinimalRangeReplaceableRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedRandomAccessRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRandomAccessCollection<Element> : RandomAccessCollection, MutableCollection {
+ public typealias Base = MinimalMutableRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<DefaultedMutableRandomAccessCollection<Element>>
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalMutableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ set {
+ base[i] = newValue
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRandomAccessCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+ public typealias Base = MinimalMutableRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedRandomAccessRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRangeReplaceableRandomAccessCollection<Element> : RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
+ public typealias Base = MinimalMutableRangeReplaceableRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ // FIXME: this shouldn't be necessary, should come by default
+ public typealias Indices = DefaultIndices<DefaultedMutableRangeReplaceableRandomAccessCollection<Element>>
+
+ public var base: Base
+
+ public init(base: Base) {
+ self.base = base
+ }
+
+ public init(_ array: [Element]) {
+ self.base = Base(elements: array)
+ }
+
+ public init(elements: [Element]) {
+ self.base = Base(elements: elements)
+ }
+
+ public init<S : Sequence>(
+ elements: S,
+ underestimatedCount: UnderestimatedCountBehavior = .value(0)
+ ) where S.Iterator.Element == Element {
+ self.init(base:
+ MinimalMutableRangeReplaceableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+ }
+
+ public var underestimatedCount: Int {
+ return base.underestimatedCount
+ }
+
+ public let timesMakeIteratorCalled = ResettableValue(0)
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ timesMakeIteratorCalled.value += 1
+ return base.makeIterator()
+ }
+
+
+ public let timesSuccessorCalled = ResettableValue(0)
+
+ public func index(after i: MinimalIndex) -> MinimalIndex {
+ timesSuccessorCalled.value += 1
+ return base.index(after: i)
+ }
+
+ public let timesPredecessorCalled = ResettableValue(0)
+
+ public func index(before i: MinimalIndex) -> MinimalIndex {
+ timesPredecessorCalled.value += 1
+ return base.index(before: i)
+ }
+
+ public func distance(from start: MinimalIndex, to end: MinimalIndex)
+ -> Int {
+ return base.distance(from: start, to: end)
+ }
+
+ public func index(_ i: Index, offsetBy n: Int) -> Index {
+ return base.index(i, offsetBy: n)
+ }
+
+
+ public let timesStartIndexCalled = ResettableValue(0)
+
+ public var startIndex: MinimalIndex {
+ timesStartIndexCalled.value += 1
+ return base.startIndex
+ }
+
+ public let timesEndIndexCalled = ResettableValue(0)
+
+ public var endIndex: MinimalIndex {
+ timesEndIndexCalled.value += 1
+ return base.endIndex
+ }
+
+ public subscript(i: MinimalIndex) -> Element {
+ get {
+ return base[i]
+ }
+ set {
+ base[i] = newValue
+ }
+ }
+
+ // FIXME: swift-3-indexing-model: use defaults.
+// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+ public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableRandomAccessCollection<Base.Element>> {
+ get {
+ // FIXME: swift-3-indexing-model: range check.
+ return Slice(base: self, bounds: bounds)
+ }
+ set {
+ _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+ }
+ }
+
+ public init() {
+ base = Base()
+ }
+
+ public mutating func replaceSubrange<C>(
+ _ subRange: Range<DefaultedMutableRangeReplaceableRandomAccessCollection<Element>.Index>,
+ with newElements: C
+ ) where C : Collection, C.Iterator.Element == Element {
+ base.replaceSubrange(subRange, with: newElements)
+ }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+ : RangeReplaceableCollection {
+
+ public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+ public typealias Base = MinimalMutableRangeReplaceableRandomAccessCollection<Element>
+ public typealias Iterator = MinimalIterator<Element>
+ public typealias Index = MinimalIndex
+
+ public var base: Base
+ public var startIndex: Index
+ public var endIndex: Index
+
+ public init() {
+ expectSliceType(Self_.self)
+
+ self.base = Base()
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base) {
+ self.base = base
+ self.startIndex = base.startIndex
+ self.endIndex = base.endIndex
+ }
+
+ public init(base: Base, bounds: Range<Index>) {
+ self.base = base
+ self.startIndex = bounds.lowerBound
+ self.endIndex = bounds.upperBound
+ }
+
+ public init(_ array: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: array))
+ }
+
+ public init(elements: [Element]) {
+ self = DefaultedRandomAccessRangeReplaceableSlice(
+ base: Base(elements: elements))
+ }
+
+ public func makeIterator() -> MinimalIterator<Element> {
+ return MinimalIterator(Array(self))
+ }
+
+ public subscript(index: Index) -> Element {
+ Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+ return base[index]
+ }
+
+ public subscript(bounds: Range<Index>) -> Self_ {
+ Index._failEarlyRangeCheck2(
+ rangeStart: bounds.lowerBound,
+ rangeEnd: bounds.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ return DefaultedRandomAccessRangeReplaceableSlice(
+ base: base, bounds: bounds)
+ }
+
+ public mutating func replaceSubrange<
+ C : Collection
+ >(
+ _ subRange: Range<Index>,
+ with newElements: C
+ ) where C.Iterator.Element == Element {
+ let startOffset = startIndex.position
+ let endOffset =
+ endIndex.position
+ - subRange.count
+ + numericCast(newElements.count) as Int
+ Index._failEarlyRangeCheck2(
+ rangeStart: subRange.lowerBound,
+ rangeEnd: subRange.upperBound,
+ boundsStart: startIndex,
+ boundsEnd: endIndex)
+ base.replaceSubrange(subRange, with: newElements)
+ startIndex = base.startIndex.advanced(by: startOffset)
+ endIndex = base.startIndex.advanced(by: endOffset)
+ }
+}
+*/
+
+
+// Local Variables:
+// eval: (read-only-mode 1)
+// End:
diff --git a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
deleted file mode 100644
index ddf5a76..0000000
--- a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
+++ /dev/null
@@ -1,1091 +0,0 @@
-//===--- MinimalCollections.swift.gyb -------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-from gyb_stdlib_support import (
- TRAVERSALS,
- collectionForTraversal,
- collectionTypeName,
- protocolsForCollectionFeatures
-)
-}%
-
-import StdlibUnittest
-
-/// State shared by all generators of a MinimalSequence.
-internal class _MinimalIteratorSharedState<T> {
- internal init(_ data: [T]) {
- self.data = data
- }
-
- internal let data: [T]
- internal var i: Int = 0
- internal var underestimatedCount: Int = 0
-}
-
-//===----------------------------------------------------------------------===//
-// MinimalIterator
-//===----------------------------------------------------------------------===//
-
-/// An IteratorProtocol that implements the protocol contract in the most
-/// narrow way possible.
-///
-/// This generator will return `nil` only once.
-public struct MinimalIterator<T> : IteratorProtocol {
- public init<S : Sequence>(_ s: S) where S.Iterator.Element == T {
- self._sharedState = _MinimalIteratorSharedState(Array(s))
- }
-
- public init(_ data: [T]) {
- self._sharedState = _MinimalIteratorSharedState(data)
- }
-
- internal init(_ _sharedState: _MinimalIteratorSharedState<T>) {
- self._sharedState = _sharedState
- }
-
- public func next() -> T? {
- if _sharedState.i == _sharedState.data.count {
- return nil
- }
- defer { _sharedState.i += 1 }
- return _sharedState.data[_sharedState.i]
- }
-
- internal let _sharedState: _MinimalIteratorSharedState<T>
-}
-
-// A protocol to identify MinimalIterator.
-public protocol _MinimalIterator {}
-extension MinimalIterator : _MinimalIterator {}
-
-//===----------------------------------------------------------------------===//
-// MinimalSequence
-//===----------------------------------------------------------------------===//
-
-public enum UnderestimatedCountBehavior {
- /// Return the actual number of elements.
- case precise
-
- /// Return the actual number of elements divided by 2.
- case half
-
- /// Return an overestimated count. Useful to test how algorithms reserve
- /// memory.
- case overestimate
-
- /// Return the provided value.
- case value(Int)
-}
-
-/// A Sequence that implements the protocol contract in the most
-/// narrow way possible.
-///
-/// This sequence is consumed when its generator is advanced.
-public struct MinimalSequence<T> : Sequence, CustomDebugStringConvertible {
- public init<S : Sequence>(
- elements: S,
- underestimatedCount: UnderestimatedCountBehavior = .value(0)
- ) where S.Iterator.Element == T {
- let data = Array(elements)
- self._sharedState = _MinimalIteratorSharedState(data)
-
- switch underestimatedCount {
- case .precise:
- self._sharedState.underestimatedCount = data.count
-
- case .half:
- self._sharedState.underestimatedCount = data.count / 2
-
- case .overestimate:
- self._sharedState.underestimatedCount = data.count * 3 + 5
-
- case .value(let count):
- self._sharedState.underestimatedCount = count
- }
- }
-
- public let timesMakeIteratorCalled = ResettableValue(0)
-
- public func makeIterator() -> MinimalIterator<T> {
- timesMakeIteratorCalled.value += 1
- return MinimalIterator(_sharedState)
- }
-
- public var underestimatedCount: Int {
- return Swift.max(0, self._sharedState.underestimatedCount - self._sharedState.i)
- }
-
- public var debugDescription: String {
- return "MinimalSequence(\(_sharedState.data[_sharedState.i..<_sharedState.data.count]))"
- }
-
- internal let _sharedState: _MinimalIteratorSharedState<T>
-}
-
-//===----------------------------------------------------------------------===//
-// Index invalidation checking
-//===----------------------------------------------------------------------===//
-
-internal enum _CollectionOperation : Equatable {
- case reserveCapacity(capacity: Int)
- case append
- case appendContentsOf(count: Int)
- case replaceRange(subRange: Range<Int>, replacementCount: Int)
- case insert(atIndex: Int)
- case insertContentsOf(atIndex: Int, count: Int)
- case removeAtIndex(index: Int)
- case removeLast
- case removeRange(subRange: Range<Int>)
- case removeAll(keepCapacity: Bool)
-
- internal func _applyTo(
- elementsLastMutatedStateIds: [Int],
- endIndexLastMutatedStateId: Int,
- nextStateId: Int
- ) -> ([Int], Int) {
- var newElementsIds = elementsLastMutatedStateIds
- var newEndIndexId = endIndexLastMutatedStateId
- switch self {
- case .reserveCapacity:
- let invalidIndices = newElementsIds.indices
- newElementsIds.replaceSubrange(
- invalidIndices,
- with: repeatElement(nextStateId, count: invalidIndices.count))
- newEndIndexId = nextStateId
-
- case .append:
- newElementsIds.append(nextStateId)
- newEndIndexId = nextStateId
-
- case .appendContentsOf(let count):
- newElementsIds.append(contentsOf:
- repeatElement(nextStateId, count: count))
- newEndIndexId = nextStateId
-
- case .replaceRange(let subRange, let replacementCount):
- newElementsIds.replaceSubrange(
- subRange,
- with: repeatElement(nextStateId, count: replacementCount))
-
- let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
- newElementsIds.replaceSubrange(
- invalidIndices,
- with: repeatElement(nextStateId, count: invalidIndices.count))
- newEndIndexId = nextStateId
-
- case .insert(let atIndex):
- newElementsIds.insert(nextStateId, at: atIndex)
-
- let invalidIndices = atIndex..<newElementsIds.endIndex
- newElementsIds.replaceSubrange(
- invalidIndices,
- with: repeatElement(nextStateId, count: invalidIndices.count))
- newEndIndexId = nextStateId
-
- case .insertContentsOf(let atIndex, let count):
- newElementsIds.insert(
- contentsOf: repeatElement(nextStateId, count: count),
- at: atIndex)
-
- let invalidIndices = atIndex..<newElementsIds.endIndex
- newElementsIds.replaceSubrange(
- invalidIndices,
- with: repeatElement(nextStateId, count: invalidIndices.count))
- newEndIndexId = nextStateId
-
- case .removeAtIndex(let index):
- newElementsIds.remove(at: index)
-
- let invalidIndices = index..<newElementsIds.endIndex
- newElementsIds.replaceSubrange(
- invalidIndices,
- with: repeatElement(nextStateId, count: invalidIndices.count))
- newEndIndexId = nextStateId
-
- case .removeLast:
- newElementsIds.removeLast()
- newEndIndexId = nextStateId
-
- case .removeRange(let subRange):
- newElementsIds.removeSubrange(subRange)
-
- let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
- newElementsIds.replaceSubrange(
- invalidIndices,
- with: repeatElement(nextStateId, count: invalidIndices.count))
- newEndIndexId = nextStateId
-
- case .removeAll(let keepCapacity):
- newElementsIds.removeAll(keepingCapacity: keepCapacity)
- newEndIndexId = nextStateId
- }
- return (newElementsIds, newEndIndexId)
- }
-}
-
-internal func == (
- lhs: _CollectionOperation,
- rhs: _CollectionOperation
-) -> Bool {
- switch (lhs, rhs) {
- case (.reserveCapacity(let lhsCapacity), .reserveCapacity(let rhsCapacity)):
- return lhsCapacity == rhsCapacity
-
- case (.append, .append):
- return true
-
- case (.appendContentsOf(let lhsCount), .appendContentsOf(let rhsCount)):
- return lhsCount == rhsCount
-
- case (
- .replaceRange(let lhsSubRange, let lhsReplacementCount),
- .replaceRange(let rhsSubRange, let rhsReplacementCount)):
-
- return lhsSubRange == rhsSubRange &&
- lhsReplacementCount == rhsReplacementCount
-
- case (.insert(let lhsAtIndex), .insert(let rhsAtIndex)):
- return lhsAtIndex == rhsAtIndex
-
- case (
- .insertContentsOf(let lhsAtIndex, let lhsCount),
- .insertContentsOf(let rhsAtIndex, let rhsCount)):
-
- return lhsAtIndex == rhsAtIndex && lhsCount == rhsCount
-
- case (.removeAtIndex(let lhsIndex), .removeAtIndex(let rhsIndex)):
- return lhsIndex == rhsIndex
-
- case (.removeLast, .removeLast):
- return true
-
- case (.removeRange(let lhsSubRange), .removeRange(let rhsSubRange)):
- return lhsSubRange == rhsSubRange
-
- case (.removeAll(let lhsKeepCapacity), .removeAll(let rhsKeepCapacity)):
- return lhsKeepCapacity == rhsKeepCapacity
-
- default:
- return false
- }
-}
-
-public struct _CollectionState : Equatable, Hashable {
- internal static var _nextUnusedState: Int = 0
- internal static var _namedStates: [String : _CollectionState] = [:]
-
- internal let _id: Int
- internal let _elementsLastMutatedStateIds: [Int]
- internal let _endIndexLastMutatedStateId: Int
-
- internal init(
- id: Int,
- elementsLastMutatedStateIds: [Int],
- endIndexLastMutatedStateId: Int) {
- self._id = id
- self._elementsLastMutatedStateIds = elementsLastMutatedStateIds
- self._endIndexLastMutatedStateId = endIndexLastMutatedStateId
- }
-
- public init(newRootStateForElementCount count: Int) {
- self._id = _CollectionState._nextUnusedState
- _CollectionState._nextUnusedState += 1
- self._elementsLastMutatedStateIds =
- Array(repeatElement(self._id, count: count))
- self._endIndexLastMutatedStateId = self._id
- }
-
- internal init(name: String, elementCount: Int) {
- if let result = _CollectionState._namedStates[name] {
- self = result
- } else {
- self = _CollectionState(newRootStateForElementCount: elementCount)
- _CollectionState._namedStates[name] = self
- }
- }
-
- public var hashValue: Int {
- return _id.hashValue
- }
-}
-
-public func == (lhs: _CollectionState, rhs: _CollectionState) -> Bool {
- return lhs._id == rhs._id
-}
-
-internal struct _CollectionStateTransition {
- internal let _previousState: _CollectionState
- internal let _operation: _CollectionOperation
- internal let _nextState: _CollectionState
-
- internal static var _allTransitions:
- [_CollectionState : Box<[_CollectionStateTransition]>] = [:]
-
- internal init(
- previousState: _CollectionState,
- operation: _CollectionOperation,
- nextState: _CollectionState
- ) {
- var transitions =
- _CollectionStateTransition._allTransitions[previousState]
- if transitions == nil {
- transitions = Box<[_CollectionStateTransition]>([])
- _CollectionStateTransition._allTransitions[previousState] = transitions
- }
- if let i = transitions!.value.index(where: { $0._operation == operation }) {
- self = transitions!.value[i]
- return
- }
- self._previousState = previousState
- self._operation = operation
- self._nextState = nextState
- transitions!.value.append(self)
- }
-
- internal init(
- previousState: _CollectionState,
- operation: _CollectionOperation
- ) {
- let nextStateId = _CollectionState._nextUnusedState
- _CollectionState._nextUnusedState += 1
- let (newElementStates, newEndIndexState) = operation._applyTo(
- elementsLastMutatedStateIds: previousState._elementsLastMutatedStateIds,
- endIndexLastMutatedStateId: previousState._endIndexLastMutatedStateId,
- nextStateId: nextStateId)
- let nextState = _CollectionState(
- id: nextStateId,
- elementsLastMutatedStateIds: newElementStates,
- endIndexLastMutatedStateId: newEndIndexState)
- self = _CollectionStateTransition(
- previousState: previousState,
- operation: operation,
- nextState: nextState)
- }
-}
-
-% for Index in ['MinimalIndex', 'MinimalStrideableIndex']:
-
-//===----------------------------------------------------------------------===//
-// ${Index}
-//===----------------------------------------------------------------------===//
-
-/// Asserts that the two indices are allowed to participate in a binary
-/// operation.
-internal func _expectCompatibleIndices(
- _ first: ${Index},
- _ second: ${Index},
- ${TRACE}
-) {
- if first._collectionState._id == second._collectionState._id {
- // Fast path: the indices are derived from the same state.
- return
- }
-
- // The indices are derived from different states. Check that they point
- // to a self-consistent view of the collection.
- if first._collectionState._id > second._collectionState._id {
- return _expectCompatibleIndices(second, first)
- }
-
- func lastMutatedStateId(
- of i: ${Index},
- in state: _CollectionState
- ) -> Int {
- let offset = i.position
- if offset == state._elementsLastMutatedStateIds.endIndex {
- return state._id
- }
- return state._elementsLastMutatedStateIds[offset]
- }
-
- let newestCollectionState = second._collectionState
- let expectedFirstIndexLastMutatedStateId =
- lastMutatedStateId(of: first, in: newestCollectionState)
-
- expectEqual(
- expectedFirstIndexLastMutatedStateId,
- first._collectionState._id,
- "Indices are not compatible:\n" +
- "first: \(first)\n" +
- "second: \(second)\n" +
- "first element last mutated in state id: \(first._collectionState._id)\n" +
- "expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
- "newest collection state: \(newestCollectionState)",
- stackTrace: ${stackTrace})
-
- // To make writing assertions easier, perform a trap.
- if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
- fatalError("Indices are not compatible")
- }
-}
-
-public struct ${Index} : Comparable {
- public init(
- collectionState: _CollectionState,
- position: Int,
- startIndex: Int,
- endIndex: Int
- ) {
- expectTrapping(
- position,
- in: startIndex...endIndex)
- self = ${Index}(
- _collectionState: collectionState,
- uncheckedPosition: position)
- }
-
- internal init(
- _collectionState: _CollectionState,
- uncheckedPosition: Int
- ) {
- self._collectionState = _collectionState
- self.position = uncheckedPosition
- }
-
- public let _collectionState: _CollectionState
- public let position: Int
-
- public static var trapOnRangeCheckFailure = ResettableValue(true)
-
-% if 'Strideable' in Index:
- public var timesAdvancedCalled = ResettableValue(0)
- public var timesDistanceCalled = ResettableValue(0)
-% end
-}
-
-public func == (lhs: ${Index}, rhs: ${Index}) -> Bool {
- _expectCompatibleIndices(lhs, rhs)
- return lhs.position == rhs.position
-}
-
-public func < (lhs: ${Index}, rhs: ${Index}) -> Bool {
- _expectCompatibleIndices(lhs, rhs)
- return lhs.position < rhs.position
-}
-
-% end
-
-extension MinimalStrideableIndex : Strideable {
- public typealias Stride = Int
-
- public func distance(to other: MinimalStrideableIndex) -> Int {
- timesDistanceCalled.value += 1
- _expectCompatibleIndices(self, other)
- return other.position - position
- }
-
- public func advanced(by n: Int) -> MinimalStrideableIndex {
- timesAdvancedCalled.value += 1
- return MinimalStrideableIndex(
- _collectionState: _collectionState,
- uncheckedPosition: position + n)
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Minimal***[Mutable]?Collection
-//===----------------------------------------------------------------------===//
-
-% for Traversal in TRAVERSALS:
-% for Mutable in [ False, True ]:
-% for RangeReplaceable in [ False, True ]:
-% for StrideableIndex in [ False, True ]:
-% Self = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-% Self += 'WithStrideableIndex' if StrideableIndex else ''
-% SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
-% Index = 'MinimalStrideableIndex' if StrideableIndex else 'MinimalIndex'
-% # Only generating MinimalRandomAccessCollectionWithStrideableIndex
-% if not StrideableIndex or (
-% StrideableIndex and Traversal == 'RandomAccess' and
-% not Mutable):
-
-/// A minimal implementation of `Collection` with extra checks.
-public struct ${Self}<T> : ${SelfProtocols} {
- /// Creates a collection with given contents, but a unique modification
- /// history. No other instance has the same modification history.
- public init<S : Sequence>(
- elements: S,
- underestimatedCount: UnderestimatedCountBehavior = .value(0)
- ) where S.Iterator.Element == T {
- self._elements = Array(elements)
-
- self._collectionState = _CollectionState(
- newRootStateForElementCount: self._elements.count)
-
- switch underestimatedCount {
- case .precise:
- self.underestimatedCount = _elements.count
-
- case .half:
- self.underestimatedCount = _elements.count / 2
-
- case .overestimate:
- self.underestimatedCount = _elements.count * 3 + 5
-
- case .value(let count):
- self.underestimatedCount = count
- }
- }
-
-% if RangeReplaceable:
- public init() {
- self.underestimatedCount = 0
- self._elements = []
- self._collectionState =
- _CollectionState(name: "\(type(of: self))", elementCount: 0)
- }
-
- public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
- self.underestimatedCount = 0
- self._elements = Array(elements)
- self._collectionState =
- _CollectionState(newRootStateForElementCount: self._elements.count)
- }
-% end
-
- public let timesMakeIteratorCalled = ResettableValue(0)
-
- public func makeIterator() -> MinimalIterator<T> {
- timesMakeIteratorCalled.value += 1
- return MinimalIterator(_elements)
- }
-
- public typealias Index = ${Index}
-
- internal func _index(forPosition i: Int) -> ${Index} {
- return ${Index}(
- collectionState: _collectionState,
- position: i,
- startIndex: _elements.startIndex,
- endIndex: _elements.endIndex)
- }
-
- internal func _uncheckedIndex(forPosition i: Int) -> ${Index} {
- return ${Index}(
- _collectionState: _collectionState,
- uncheckedPosition: i)
- }
-
- public let timesStartIndexCalled = ResettableValue(0)
-
- public var startIndex: ${Index} {
- timesStartIndexCalled.value += 1
- return _uncheckedIndex(forPosition: _elements.startIndex)
- }
-
- public let timesEndIndexCalled = ResettableValue(0)
-
- public var endIndex: ${Index} {
- timesEndIndexCalled.value += 1
- return _uncheckedIndex(forPosition: _elements.endIndex)
- }
-
-% if StrideableIndex:
- public typealias Indices = Range<${Index}>
-% elif Traversal == 'RandomAccess':
- // FIXME: this shouldn't be necessary, should come by default
- public typealias Indices = DefaultIndices<${Self}<T>>
-% end
-
- public func _failEarlyRangeCheck(
- _ index: ${Index},
- bounds: Range<${Index}>
- ) {
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: index.position),
- index)
-
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: bounds.lowerBound.position),
- bounds.lowerBound)
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: bounds.upperBound.position),
- bounds.upperBound)
-
- expectTrapping(
- index.position,
- in: bounds.lowerBound.position..<bounds.upperBound.position)
- }
-
- public func _failEarlyRangeCheck(
- _ range: Range<${Index}>,
- bounds: Range<${Index}>
- ) {
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: range.lowerBound.position),
- range.lowerBound)
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: range.upperBound.position),
- range.upperBound)
-
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: bounds.lowerBound.position),
- bounds.lowerBound)
- _expectCompatibleIndices(
- _uncheckedIndex(forPosition: bounds.upperBound.position),
- bounds.upperBound)
-
- expectTrapping(
- range.lowerBound.position..<range.upperBound.position,
- in: bounds.lowerBound.position..<bounds.upperBound.position)
- }
-
- public func index(after i: ${Index}) -> ${Index} {
- _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
- return _uncheckedIndex(forPosition: i.position + 1)
- }
-
-% if Traversal in ['Bidirectional', 'RandomAccess']:
- public func index(before i: ${Index}) -> ${Index} {
- // FIXME: swift-3-indexing-model: perform a range check and use
- // return _uncheckedIndex(forPosition: i.position - 1)
- return _index(forPosition: i.position - 1)
- }
-% end
-
- public func distance(from start: ${Index}, to end: ${Index})
- -> Int {
-% if Traversal == 'Forward':
- _precondition(start <= end,
- "Only BidirectionalCollections can have end come before start")
-% end
- // FIXME: swift-3-indexing-model: perform a range check properly.
- if start != endIndex {
- _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
- }
- if end != endIndex {
- _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
- }
- return end.position - start.position
- }
-
- public func index(_ i: Index, offsetBy n: Int) -> Index {
-% if Traversal == 'Forward':
- _precondition(n >= 0,
- "Only BidirectionalCollections can be advanced by a negative amount")
-% end
- // FIXME: swift-3-indexing-model: perform a range check properly.
- if i != endIndex {
- _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
- }
- return _index(forPosition: i.position + n)
- }
-
- public subscript(i: ${Index}) -> T {
- get {
- _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
- return _elements[i.position]
- }
-% if Mutable:
- set {
- _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
- _elements[i.position] = newValue
- }
-% end
- }
-
- public subscript(bounds: Range<${Index}>) -> Slice<${Self}<T>> {
- get {
- _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
- return Slice(base: self, bounds: bounds)
- }
-% if Mutable:
- set {
- _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
- _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
- }
-% end
- }
-
-% if RangeReplaceable:
- public mutating func reserveCapacity(_ n: Int) {
- _willMutate(.reserveCapacity(capacity: n))
- _elements.reserveCapacity(n)
- reservedCapacity = Swift.max(reservedCapacity, n)
- }
-
- public mutating func append(_ x: T) {
- _willMutate(.append)
- _elements.append(x)
- }
-
- public mutating func append<S : Sequence>(contentsOf newElements: S)
- where S.Iterator.Element == T {
- let oldCount = count
- _elements.append(contentsOf: newElements)
- let newCount = count
- _willMutate(.appendContentsOf(count: newCount - oldCount))
- }
-
- public mutating func replaceSubrange<C>(
- _ subRange: Range<${Index}>,
- with newElements: C
- ) where C : Collection, C.Iterator.Element == T {
- let oldCount = count
- _elements.replaceSubrange(
- subRange.lowerBound.position..<subRange.upperBound.position,
- with: newElements)
- let newCount = count
- _willMutate(.replaceRange(
- subRange: subRange.lowerBound.position..<subRange.upperBound.position,
- replacementCount:
- subRange.upperBound.position - subRange.lowerBound.position
- + newCount - oldCount))
- }
-
- public mutating func insert(_ newElement: T, at i: ${Index}) {
- _willMutate(.insert(atIndex: i.position))
- _elements.insert(newElement, at: i.position)
- }
-
- public mutating func insert<S : Collection>(
- contentsOf newElements: S, at i: ${Index}
- ) where S.Iterator.Element == T {
- let oldCount = count
- _elements.insert(contentsOf: newElements, at: i.position)
- let newCount = count
-
- if newCount - oldCount != 0 {
- _willMutate(.insertContentsOf(
- atIndex: i.position,
- count: newCount - oldCount))
- }
- }
-
- @discardableResult
- public mutating func remove(at i: ${Index}) -> T {
- _willMutate(.removeAtIndex(index: i.position))
- return _elements.remove(at: i.position)
- }
-
- @discardableResult
- public mutating func removeLast() -> T {
- _willMutate(.removeLast)
- return _elements.removeLast()
- }
-
- public mutating func removeSubrange(_ subRange: Range<${Index}>) {
- if !subRange.isEmpty {
- _willMutate(.removeRange(
- subRange: subRange.lowerBound.position..<subRange.upperBound.position))
- }
- _elements.removeSubrange(
- subRange.lowerBound.position..<subRange.upperBound.position
- )
- }
-
- public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
- _willMutate(.removeAll(keepCapacity: keepCapacity))
- // Ignore the value of `keepCapacity`.
- _elements.removeAll(keepingCapacity: false)
- }
-
- internal mutating func _willMutate(_ operation: _CollectionOperation) {
- _collectionState = _CollectionStateTransition(
- previousState: _collectionState,
- operation: operation)._nextState
- }
-% end
-
- public var underestimatedCount: Int
-% if RangeReplaceable:
- public var reservedCapacity: Int = 0
-% end
-
- internal var _elements: [T]
-% if RangeReplaceable:
- internal var _collectionState: _CollectionState
-% else:
- internal let _collectionState: _CollectionState
-% end
-}
-
-% end
-% end
-% end
-% end
-% end
-
-/// A Sequence that uses as many default implementations as
-/// `Sequence` can provide.
-public struct DefaultedSequence<Element> : Sequence {
- public let base: MinimalSequence<Element>
-
- public init(base: MinimalSequence<Element>) {
- self.base = base
- }
-
- public init<S : Sequence>(
- elements: S,
- underestimatedCount: UnderestimatedCountBehavior = .value(0)
- ) where S.Iterator.Element == Element {
- self.init(base: MinimalSequence(
- elements: elements, underestimatedCount: underestimatedCount))
- }
-
- public func makeIterator() -> MinimalIterator<Element> {
- return base.makeIterator()
- }
-
- public var underestimatedCount: Int {
- return base.underestimatedCount
- }
-}
-
-% for Traversal in TRAVERSALS:
-% for Mutable in [ False, True ]:
-% for RangeReplaceable in [ False, True ]:
-% for StrideableIndex in [ False, True ]:
-% Self = 'Defaulted' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-% Self += 'WithStrideableIndex' if StrideableIndex else ''
-% Base = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-% Base += 'WithStrideableIndex' if StrideableIndex else ''
-% SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
-% Index = 'MinimalStrideableIndex' if StrideableIndex else 'MinimalIndex'
-% # Only generating DefaultedRandomAccessCollectionWithStrideableIndex
-% if not StrideableIndex or (
-% StrideableIndex and Traversal == 'RandomAccess' and
-% not Mutable and not RangeReplaceable):
-
-/// A Collection that uses as many default implementations as
-/// `Collection` can provide.
-public struct ${Self}<Element> : ${SelfProtocols} {
- public typealias Base = ${Base}<Element>
- public typealias Iterator = MinimalIterator<Element>
- public typealias Index = ${Index}
-
-% if StrideableIndex:
- public typealias Indices = Range<${Index}>
-% elif Traversal == 'RandomAccess':
- // FIXME: this shouldn't be necessary, should come by default
- public typealias Indices = DefaultIndices<${Self}<Element>>
-% end
-
-% if Mutable or RangeReplaceable:
- public var base: Base
-% else:
- public let base: Base
-% end
-
- public init(base: Base) {
- self.base = base
- }
-
- public init(_ array: [Element]) {
- self.base = Base(elements: array)
- }
-
- public init(elements: [Element]) {
- self.base = Base(elements: elements)
- }
-
- public init<S : Sequence>(
- elements: S,
- underestimatedCount: UnderestimatedCountBehavior = .value(0)
- ) where S.Iterator.Element == Element {
- self.init(base:
- ${Base}(elements: elements, underestimatedCount: underestimatedCount))
- }
-
- public var underestimatedCount: Int {
- return base.underestimatedCount
- }
-
- public let timesMakeIteratorCalled = ResettableValue(0)
-
- public func makeIterator() -> MinimalIterator<Element> {
- timesMakeIteratorCalled.value += 1
- return base.makeIterator()
- }
-
-% if not StrideableIndex:
-
- public let timesSuccessorCalled = ResettableValue(0)
-
- public func index(after i: ${Index}) -> ${Index} {
- timesSuccessorCalled.value += 1
- return base.index(after: i)
- }
-
-% if Traversal in ['Bidirectional', 'RandomAccess']:
- public let timesPredecessorCalled = ResettableValue(0)
-
- public func index(before i: ${Index}) -> ${Index} {
- timesPredecessorCalled.value += 1
- return base.index(before: i)
- }
-% end
-
-% if Traversal == 'RandomAccess':
- public func distance(from start: ${Index}, to end: ${Index})
- -> Int {
- return base.distance(from: start, to: end)
- }
-
- public func index(_ i: Index, offsetBy n: Int) -> Index {
- return base.index(i, offsetBy: n)
- }
-% end
-
-% end # if not StrideableIndex
-
- public let timesStartIndexCalled = ResettableValue(0)
-
- public var startIndex: ${Index} {
- timesStartIndexCalled.value += 1
- return base.startIndex
- }
-
- public let timesEndIndexCalled = ResettableValue(0)
-
- public var endIndex: ${Index} {
- timesEndIndexCalled.value += 1
- return base.endIndex
- }
-
- public subscript(i: ${Index}) -> Element {
- get {
- return base[i]
- }
-% if Mutable:
- set {
- base[i] = newValue
- }
-% end
- }
-
- // FIXME: swift-3-indexing-model: use defaults.
-// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
-
- public subscript(bounds: Range<${Index}>) -> Slice<${Self}<Base.Element>> {
- get {
- // FIXME: swift-3-indexing-model: range check.
- return Slice(base: self, bounds: bounds)
- }
-% if Mutable:
- set {
- _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
- }
-% end
- }
-
-% if RangeReplaceable:
- public init() {
- base = Base()
- }
-
- public mutating func replaceSubrange<C>(
- _ subRange: Range<${Self}<Element>.Index>,
- with newElements: C
- ) where C : Collection, C.Iterator.Element == Element {
- base.replaceSubrange(subRange, with: newElements)
- }
-% end
-}
-
-/*
-FIXME: swift-3-indexing-model: uncomment this.
-public struct Defaulted${Traversal}RangeReplaceableSlice<Element>
- : RangeReplaceableCollection {
-
- public typealias Self_ = Defaulted${Traversal}RangeReplaceableSlice<Element>
- public typealias Base = ${Base}<Element>
- public typealias Iterator = MinimalIterator<Element>
- public typealias Index = ${Index}
-
- public var base: Base
- public var startIndex: Index
- public var endIndex: Index
-
- public init() {
- expectSliceType(Self_.self)
-
- self.base = Base()
- self.startIndex = base.startIndex
- self.endIndex = base.endIndex
- }
-
- public init(base: Base) {
- self.base = base
- self.startIndex = base.startIndex
- self.endIndex = base.endIndex
- }
-
- public init(base: Base, bounds: Range<Index>) {
- self.base = base
- self.startIndex = bounds.lowerBound
- self.endIndex = bounds.upperBound
- }
-
- public init(_ array: [Element]) {
- self = Defaulted${Traversal}RangeReplaceableSlice(
- base: Base(elements: array))
- }
-
- public init(elements: [Element]) {
- self = Defaulted${Traversal}RangeReplaceableSlice(
- base: Base(elements: elements))
- }
-
- public func makeIterator() -> MinimalIterator<Element> {
- return MinimalIterator(Array(self))
- }
-
- public subscript(index: Index) -> Element {
- Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
- return base[index]
- }
-
- public subscript(bounds: Range<Index>) -> Self_ {
- Index._failEarlyRangeCheck2(
- rangeStart: bounds.lowerBound,
- rangeEnd: bounds.upperBound,
- boundsStart: startIndex,
- boundsEnd: endIndex)
- return Defaulted${Traversal}RangeReplaceableSlice(
- base: base, bounds: bounds)
- }
-
- public mutating func replaceSubrange<
- C : Collection
- >(
- _ subRange: Range<Index>,
- with newElements: C
- ) where C.Iterator.Element == Element {
- let startOffset = startIndex.position
- let endOffset =
- endIndex.position
- - subRange.count
- + numericCast(newElements.count) as Int
- Index._failEarlyRangeCheck2(
- rangeStart: subRange.lowerBound,
- rangeEnd: subRange.upperBound,
- boundsStart: startIndex,
- boundsEnd: endIndex)
- base.replaceSubrange(subRange, with: newElements)
- startIndex = base.startIndex.advanced(by: startOffset)
- endIndex = base.startIndex.advanced(by: endOffset)
- }
-}
-*/
-
-% end
-% end
-% end
-% end
-% end
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
diff --git a/stdlib/private/StdlibUnittest/CMakeLists.txt b/stdlib/private/StdlibUnittest/CMakeLists.txt
index 5729631..699bc5b 100644
--- a/stdlib/private/StdlibUnittest/CMakeLists.txt
+++ b/stdlib/private/StdlibUnittest/CMakeLists.txt
@@ -15,20 +15,20 @@
add_swift_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
# This file should be listed the first. Module name is inferred from the
# filename.
- StdlibUnittest.swift.gyb
+ StdlibUnittest.swift
- CheckStrideable.swift.gyb
+ CheckStrideable.swift
InspectValue.cpp
InspectValue.swift
InterceptTraps.cpp
LifetimeTracked.swift
- MinimalTypes.swift.gyb
+ MinimalTypes.swift
OpaqueIdentityFunctions.cpp
OpaqueIdentityFunctions.swift
RaceTest.swift
Statistics.swift
StdlibCoreExtras.swift
- StringConvertible.swift.gyb
+ StringConvertible.swift
TestHelpers.swift
TypeIndexed.swift
GetOSVersion.mm
diff --git a/stdlib/private/StdlibUnittest/CheckStrideable.swift.gyb b/stdlib/private/StdlibUnittest/CheckStrideable.swift
similarity index 84%
rename from stdlib/private/StdlibUnittest/CheckStrideable.swift.gyb
rename to stdlib/private/StdlibUnittest/CheckStrideable.swift
index 0f4b7ff..2c15e21 100644
--- a/stdlib/private/StdlibUnittest/CheckStrideable.swift.gyb
+++ b/stdlib/private/StdlibUnittest/CheckStrideable.swift
@@ -10,15 +10,15 @@
//
//===----------------------------------------------------------------------===//
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
public func checkStrideable<S : Strideable>(
instances: [S],
distances: [S.Stride],
distanceOracle: (Int, Int) -> S.Stride,
- ${TRACE}
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
for i in instances.indices {
let first = instances[i]
diff --git a/stdlib/private/StdlibUnittest/MinimalTypes.swift b/stdlib/private/StdlibUnittest/MinimalTypes.swift
new file mode 100644
index 0000000..512a974
--- /dev/null
+++ b/stdlib/private/StdlibUnittest/MinimalTypes.swift
@@ -0,0 +1,388 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+/// A type that does not conform to any protocols.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// conformances.
+public struct OpaqueValue<Underlying> {
+ public var value: Underlying
+ public var identity: Int
+
+ public init(_ value: Underlying) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Underlying, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+}
+
+/// A type that conforms only to `Equatable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalEquatableValue : Equatable {
+ public static var timesEqualEqualWasCalled: Int = 0
+
+ public static var equalImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+
+ public var value: Int
+ public var identity: Int
+
+ public init(_ value: Int) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Int, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public static func == (
+ lhs: MinimalEquatableValue,
+ rhs: MinimalEquatableValue
+ ) -> Bool {
+ MinimalEquatableValue.timesEqualEqualWasCalled += 1
+ return MinimalEquatableValue.equalImpl.value(lhs.value, rhs.value)
+ }
+}
+
+/// A type that conforms only to `Equatable` and `Comparable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalComparableValue : Equatable, Comparable {
+ public static var timesEqualEqualWasCalled = ResettableValue(0)
+ public static var timesLessWasCalled = ResettableValue(0)
+
+ public static var equalImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+ public static var lessImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
+
+ public var value: Int
+ public var identity: Int
+
+ public init(_ value: Int) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Int, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public static func == (
+ lhs: MinimalComparableValue,
+ rhs: MinimalComparableValue
+ ) -> Bool {
+ MinimalComparableValue.timesEqualEqualWasCalled.value += 1
+ return MinimalComparableValue.equalImpl.value(lhs.value, rhs.value)
+ }
+
+ public static func < (
+ lhs: MinimalComparableValue,
+ rhs: MinimalComparableValue
+ ) -> Bool {
+ MinimalComparableValue.timesLessWasCalled.value += 1
+ return MinimalComparableValue.lessImpl.value(lhs.value, rhs.value)
+ }
+}
+
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalHashableValue : Equatable, Hashable {
+ public static var timesEqualEqualWasCalled: Int = 0
+ public static var timesHashIntoWasCalled: Int = 0
+
+ public static var equalImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+ public static var hashIntoImpl =
+ ResettableValue<(Int, inout _Hasher) -> Void>({ $1.combine($0) })
+
+ public var value: Int
+ public var identity: Int
+
+ public init(_ value: Int) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Int, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public static func ==(
+ lhs: MinimalHashableValue,
+ rhs: MinimalHashableValue
+ ) -> Bool {
+ MinimalHashableValue.timesEqualEqualWasCalled += 1
+ return MinimalHashableValue.equalImpl.value(lhs.value, rhs.value)
+ }
+
+ public var hashValue: Int {
+ var hasher = _Hasher()
+ hasher.combine(self)
+ return hasher.finalize()
+ }
+
+ public func _hash(into hasher: inout _Hasher) {
+ MinimalHashableValue.timesHashIntoWasCalled += 1
+ MinimalHashableValue.hashIntoImpl.value(value, &hasher)
+ }
+}
+
+extension MinimalHashableValue: CustomStringConvertible {
+ public var description: String {
+ return "MinimalHashableValue(value: \(value), identity: \(identity))"
+ }
+}
+
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public class MinimalHashableClass : Equatable, Hashable {
+ public static var timesEqualEqualWasCalled: Int = 0
+ public static var timesHashIntoWasCalled: Int = 0
+
+ public static var equalImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+ public static var hashIntoImpl =
+ ResettableValue<(Int, inout _Hasher) -> Void>({ $1.combine($0) })
+
+ public var value: Int
+ public var identity: Int
+
+ public init(_ value: Int) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Int, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public static func == (
+ lhs: MinimalHashableClass,
+ rhs: MinimalHashableClass
+ ) -> Bool {
+ MinimalHashableClass.timesEqualEqualWasCalled += 1
+ return MinimalHashableClass.equalImpl.value(lhs.value, rhs.value)
+ }
+
+ public var hashValue: Int {
+ var hasher = _Hasher()
+ hasher.combine(self)
+ return hasher.finalize()
+ }
+
+ public func _hash(into hasher: inout _Hasher) {
+ MinimalHashableClass.timesHashIntoWasCalled += 1
+ MinimalHashableClass.hashIntoImpl.value(value, &hasher)
+ }
+}
+
+extension MinimalHashableClass: CustomStringConvertible {
+ public var description: String {
+ return "MinimalHashableClass(value: \(value), identity: \(identity))"
+ }
+}
+
+
+
+public var GenericMinimalHashableValue_timesEqualEqualWasCalled: Int = 0
+public var GenericMinimalHashableValue_timesHashIntoWasCalled: Int = 0
+
+public var GenericMinimalHashableValue_equalImpl =
+ ResettableValue<(Any, Any) -> Bool>({ _, _ in
+ fatalError("GenericMinimalHashableValue_equalImpl is not set yet")
+ })
+public var GenericMinimalHashableValue_hashIntoImpl =
+ ResettableValue<(Any, inout _Hasher) -> Void>({ _ in
+ fatalError("GenericMinimalHashableValue_hashIntoImpl is not set yet")
+ })
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct GenericMinimalHashableValue<Wrapped> : Equatable, Hashable {
+ public var value: Wrapped
+ public var identity: Int
+
+ public init(_ value: Wrapped) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Wrapped, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public static func == <Wrapped>(
+ lhs: GenericMinimalHashableValue<Wrapped>,
+ rhs: GenericMinimalHashableValue<Wrapped>
+ ) -> Bool {
+ GenericMinimalHashableValue_timesEqualEqualWasCalled += 1
+ return GenericMinimalHashableValue_equalImpl.value(lhs.value, rhs.value)
+ }
+
+ public var hashValue: Int {
+ var hasher = _Hasher()
+ hasher.combine(self)
+ return hasher.finalize()
+ }
+
+ public func _hash(into hasher: inout _Hasher) {
+ GenericMinimalHashableValue_timesHashIntoWasCalled += 1
+ GenericMinimalHashableValue_hashIntoImpl.value(value, &hasher)
+ }
+}
+
+extension GenericMinimalHashableValue: CustomStringConvertible {
+ public var description: String {
+ return "GenericMinimalHashableValue(value: \(value), identity: \(identity))"
+ }
+}
+
+public var GenericMinimalHashableClass_timesEqualEqualWasCalled: Int = 0
+public var GenericMinimalHashableClass_timesHashIntoWasCalled: Int = 0
+
+public var GenericMinimalHashableClass_equalImpl =
+ ResettableValue<(Any, Any) -> Bool>({ _, _ in
+ fatalError("GenericMinimalHashableClass_equalImpl is not set yet")
+ })
+public var GenericMinimalHashableClass_hashIntoImpl =
+ ResettableValue<(Any, inout _Hasher) -> Void>({ _ in
+ fatalError("GenericMinimalHashableClass_hashIntoImpl is not set yet")
+ })
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public class GenericMinimalHashableClass<Wrapped> : Equatable, Hashable {
+ public var value: Wrapped
+ public var identity: Int
+
+ public init(_ value: Wrapped) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Wrapped, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public static func == <Wrapped>(
+ lhs: GenericMinimalHashableClass<Wrapped>,
+ rhs: GenericMinimalHashableClass<Wrapped>
+ ) -> Bool {
+ GenericMinimalHashableClass_timesEqualEqualWasCalled += 1
+ return GenericMinimalHashableClass_equalImpl.value(lhs.value, rhs.value)
+ }
+
+ public var hashValue: Int {
+ var hasher = _Hasher()
+ hasher.combine(self)
+ return hasher.finalize()
+ }
+
+ public func _hash(into hasher: inout _Hasher) {
+ GenericMinimalHashableClass_timesHashIntoWasCalled += 1
+ GenericMinimalHashableClass_hashIntoImpl.value(value, &hasher)
+ }
+}
+
+extension GenericMinimalHashableClass: CustomStringConvertible {
+ public var description: String {
+ return "GenericMinimalHashableClass(value: \(value), identity: \(identity))"
+ }
+}
+
+
+/// A type that conforms only to `Equatable`, `Comparable`, and `Strideable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalStrideableValue : Equatable, Comparable, Strideable {
+ public static var timesEqualEqualWasCalled = ResettableValue(0)
+ public static var timesLessWasCalled = ResettableValue(0)
+ public static var timesDistanceWasCalled = ResettableValue(0)
+ public static var timesAdvancedWasCalled = ResettableValue(0)
+
+ public static var equalImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+ public static var lessImpl =
+ ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
+
+ public var value: Int
+ public var identity: Int
+
+ public init(_ value: Int) {
+ self.value = value
+ self.identity = 0
+ }
+
+ public init(_ value: Int, identity: Int) {
+ self.value = value
+ self.identity = identity
+ }
+
+ public typealias Stride = Int
+
+ public static func == (
+ lhs: MinimalStrideableValue,
+ rhs: MinimalStrideableValue
+ ) -> Bool {
+ MinimalStrideableValue.timesEqualEqualWasCalled.value += 1
+ return MinimalStrideableValue.equalImpl.value(lhs.value, rhs.value)
+ }
+
+ public static func < (
+ lhs: MinimalStrideableValue,
+ rhs: MinimalStrideableValue
+ ) -> Bool {
+ MinimalStrideableValue.timesLessWasCalled.value += 1
+ return MinimalStrideableValue.lessImpl.value(lhs.value, rhs.value)
+ }
+
+ public func distance(to other: MinimalStrideableValue) -> Stride {
+ MinimalStrideableValue.timesDistanceWasCalled.value += 1
+ return other.value - self.value
+ }
+
+ public func advanced(by n: Stride) -> MinimalStrideableValue {
+ MinimalStrideableValue.timesAdvancedWasCalled.value += 1
+ return MinimalStrideableValue(self.value + n, identity: self.identity)
+ }
+}
+
+
+// Local Variables:
+// eval: (read-only-mode 1)
+// End:
diff --git a/stdlib/private/StdlibUnittest/MinimalTypes.swift.gyb b/stdlib/private/StdlibUnittest/MinimalTypes.swift.gyb
deleted file mode 100644
index 15bb106..0000000
--- a/stdlib/private/StdlibUnittest/MinimalTypes.swift.gyb
+++ /dev/null
@@ -1,255 +0,0 @@
-//===--- MinimalTypes.swift -----------------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-/// A type that does not conform to any protocols.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// conformances.
-public struct OpaqueValue<Underlying> {
- public var value: Underlying
- public var identity: Int
-
- public init(_ value: Underlying) {
- self.value = value
- self.identity = 0
- }
-
- public init(_ value: Underlying, identity: Int) {
- self.value = value
- self.identity = identity
- }
-}
-
-/// A type that conforms only to `Equatable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public struct MinimalEquatableValue : Equatable {
- public static var timesEqualEqualWasCalled: Int = 0
-
- public static var equalImpl =
- ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
-
- public var value: Int
- public var identity: Int
-
- public init(_ value: Int) {
- self.value = value
- self.identity = 0
- }
-
- public init(_ value: Int, identity: Int) {
- self.value = value
- self.identity = identity
- }
-}
-public func == (
- lhs: MinimalEquatableValue,
- rhs: MinimalEquatableValue
-) -> Bool {
- MinimalEquatableValue.timesEqualEqualWasCalled += 1
- return MinimalEquatableValue.equalImpl.value(lhs.value, rhs.value)
-}
-
-/// A type that conforms only to `Equatable` and `Comparable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public struct MinimalComparableValue : Equatable, Comparable {
- public static var timesEqualEqualWasCalled = ResettableValue(0)
- public static var timesLessWasCalled = ResettableValue(0)
-
- public static var equalImpl =
- ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
- public static var lessImpl =
- ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
-
- public var value: Int
- public var identity: Int
-
- public init(_ value: Int) {
- self.value = value
- self.identity = 0
- }
-
- public init(_ value: Int, identity: Int) {
- self.value = value
- self.identity = identity
- }
-}
-
-public func == (
- lhs: MinimalComparableValue,
- rhs: MinimalComparableValue
-) -> Bool {
- MinimalComparableValue.timesEqualEqualWasCalled.value += 1
- return MinimalComparableValue.equalImpl.value(lhs.value, rhs.value)
-}
-
-public func < (
- lhs: MinimalComparableValue,
- rhs: MinimalComparableValue
-) -> Bool {
- MinimalComparableValue.timesLessWasCalled.value += 1
- return MinimalComparableValue.lessImpl.value(lhs.value, rhs.value)
-}
-
-% for (kind, decl_keyword) in [ ('Value', 'struct'), ('Class', 'class') ]:
-% Self = 'MinimalHashable%s' % kind
-
-/// A type that conforms only to `Equatable` and `Hashable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public ${decl_keyword} ${Self} : Equatable, Hashable {
- public static var timesEqualEqualWasCalled: Int = 0
- public static var timesHashValueWasCalled: Int = 0
-
- public static var equalImpl =
- ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
- public static var hashValueImpl =
- ResettableValue<(Int) -> Int>({ $0.hashValue })
-
- public var value: Int
- public var identity: Int
-
- public init(_ value: Int) {
- self.value = value
- self.identity = 0
- }
-
- public init(_ value: Int, identity: Int) {
- self.value = value
- self.identity = identity
- }
-
- public var hashValue: Int {
- ${Self}.timesHashValueWasCalled += 1
- return ${Self}.hashValueImpl.value(value)
- }
-}
-
-public func == (
- lhs: ${Self},
- rhs: ${Self}
-) -> Bool {
- ${Self}.timesEqualEqualWasCalled += 1
- return ${Self}.equalImpl.value(lhs.value, rhs.value)
-}
-
-% end
-
-% for (kind, decl_keyword) in [ ('Value', 'struct'), ('Class', 'class') ]:
-% Self = 'GenericMinimalHashable%s' % kind
-
-public var ${Self}_timesEqualEqualWasCalled: Int = 0
-public var ${Self}_timesHashValueWasCalled: Int = 0
-
-public var ${Self}_equalImpl = ResettableValue<(Any, Any) -> Bool>(
- { _, _ in fatalError("${Self}_equalImpl is not set yet"); () })
-public var ${Self}_hashValueImpl = ResettableValue<(Any) -> Int>(
- { _ in fatalError("${Self}_hashValueImpl is not set yet"); () })
-
-/// A type that conforms only to `Equatable` and `Hashable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public ${decl_keyword} ${Self}<Wrapped> : Equatable, Hashable {
- public var value: Wrapped
- public var identity: Int
-
- public init(_ value: Wrapped) {
- self.value = value
- self.identity = 0
- }
-
- public init(_ value: Wrapped, identity: Int) {
- self.value = value
- self.identity = identity
- }
-
- public var hashValue: Int {
- ${Self}_timesHashValueWasCalled += 1
- return ${Self}_hashValueImpl.value(value)
- }
-}
-
-public func == <Wrapped>(
- lhs: ${Self}<Wrapped>,
- rhs: ${Self}<Wrapped>
-) -> Bool {
- ${Self}_timesEqualEqualWasCalled += 1
- return ${Self}_equalImpl.value(lhs.value, rhs.value)
-}
-
-% end
-
-/// A type that conforms only to `Equatable`, `Comparable`, and `Strideable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public struct MinimalStrideableValue : Equatable, Comparable, Strideable {
- public static var timesEqualEqualWasCalled = ResettableValue(0)
- public static var timesLessWasCalled = ResettableValue(0)
- public static var timesDistanceWasCalled = ResettableValue(0)
- public static var timesAdvancedWasCalled = ResettableValue(0)
-
- public static var equalImpl =
- ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
- public static var lessImpl =
- ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
-
- public var value: Int
- public var identity: Int
-
- public init(_ value: Int) {
- self.value = value
- self.identity = 0
- }
-
- public init(_ value: Int, identity: Int) {
- self.value = value
- self.identity = identity
- }
-
- public typealias Stride = Int
-
- public func distance(to other: MinimalStrideableValue) -> Stride {
- MinimalStrideableValue.timesDistanceWasCalled.value += 1
- return other.value - self.value
- }
-
- public func advanced(by n: Stride) -> MinimalStrideableValue {
- MinimalStrideableValue.timesAdvancedWasCalled.value += 1
- return MinimalStrideableValue(self.value + n, identity: self.identity)
- }
-}
-
-public func == (
- lhs: MinimalStrideableValue,
- rhs: MinimalStrideableValue
-) -> Bool {
- MinimalStrideableValue.timesEqualEqualWasCalled.value += 1
- return MinimalStrideableValue.equalImpl.value(lhs.value, rhs.value)
-}
-
-public func < (
- lhs: MinimalStrideableValue,
- rhs: MinimalStrideableValue
-) -> Bool {
- MinimalStrideableValue.timesLessWasCalled.value += 1
- return MinimalStrideableValue.lessImpl.value(lhs.value, rhs.value)
-}
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
similarity index 71%
rename from stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
rename to stdlib/private/StdlibUnittest/StdlibUnittest.swift
index 98ac5af..d8b2922 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
@@ -1,4 +1,4 @@
-//===--- StdlibUnittest.swift.gyb -----------------------------*- swift -*-===//
+//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -10,9 +10,6 @@
//
//===----------------------------------------------------------------------===//
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
import SwiftPrivate
import SwiftPrivatePthreadExtras
@@ -120,7 +117,11 @@
/// Run `body` and expect a failure to happen.
///
/// The check passes iff `body` triggers one or more failures.
-public func expectFailure(${TRACE}, invoking body: () -> Void) {
+public func expectFailure(
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line, invoking body: () -> Void) {
let startAnyExpectFailed = _anyExpectFailed
_anyExpectFailed = false
body()
@@ -128,7 +129,7 @@
_anyExpectFailed = false
expectTrue(
endAnyExpectFailed, "running `body` should produce an expected failure",
- stackTrace: ${stackTrace}
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
)
_anyExpectFailed = _anyExpectFailed || startAnyExpectFailed
}
@@ -146,49 +147,107 @@
return element
}
-public func expectEqual<T : Equatable>(_ expected: T, _ actual: T, ${TRACE}) {
- expectEqualTest(expected, actual, ${trace}, showFrame: false) {$0 == $1}
+public func expectEqual<T : Equatable>(_ expected: T, _ actual: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
}
public func expectEqual<T : Equatable, U : Equatable>(
- _ expected: (T, U), _ actual: (T, U), ${TRACE}) {
- expectEqualTest(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
- expectEqualTest(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
+ _ expected: (T, U), _ actual: (T, U),
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ expectEqualTest(expected.0, actual.0, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+ expectEqualTest(expected.1, actual.1, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
}
public func expectEqual<T : Equatable, U : Equatable, V : Equatable>(
- _ expected: (T, U, V), _ actual: (T, U, V), ${TRACE}) {
- expectEqualTest(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
- expectEqualTest(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
- expectEqualTest(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
+ _ expected: (T, U, V), _ actual: (T, U, V),
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ expectEqualTest(expected.0, actual.0, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+ expectEqualTest(expected.1, actual.1, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+ expectEqualTest(expected.2, actual.2, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
}
public func expectEqual<T : Equatable, U : Equatable, V : Equatable, W : Equatable>(
- _ expected: (T, U, V, W), _ actual: (T, U, V, W), ${TRACE}) {
- expectEqualTest(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
- expectEqualTest(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
- expectEqualTest(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
- expectEqualTest(expected.3, actual.3, ${trace}, showFrame: false) {$0 == $1}
+ _ expected: (T, U, V, W), _ actual: (T, U, V, W),
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ expectEqualTest(expected.0, actual.0, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+ expectEqualTest(expected.1, actual.1, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+ expectEqualTest(expected.2, actual.2, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+ expectEqualTest(expected.3, actual.3, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
}
-% for (Lhs, Rhs) in [
-% ('String', 'Substring'),
-% ('Substring', 'String'),
-% ('String', 'String'), # this one is to break ambiguity
-% ]:
-public func expectEqual(_ expected: ${Lhs}, _ actual: ${Rhs}, ${TRACE}) {
+public func expectEqual(_ expected: String, _ actual: Substring,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !(expected == actual) {
expectationFailure(
"expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
+ "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace}
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
)
}
}
-% end
+public func expectEqual(_ expected: Substring, _ actual: String,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ if !(expected == actual) {
+ expectationFailure(
+ "expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
+ + "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
+ )
+ }
+}
+public func expectEqual(_ expected: String, _ actual: String,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ if !(expected == actual) {
+ expectationFailure(
+ "expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
+ + "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
+ )
+ }
+}
-public func expectEqualReference(_ expected: AnyObject?, _ actual: AnyObject?, ${TRACE}) {
- expectEqualTest(expected, actual, ${trace}, showFrame: false) {$0 === $1}
+public func expectEqualReference(_ expected: AnyObject?, _ actual: AnyObject?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 === $1}
}
public func expectationFailure(
@@ -205,22 +264,32 @@
// See <rdar://26058520> Generic type constraints incorrectly applied to
// functions with the same name
public func expectEqualTest<T>(
- _ expected: T, _ actual: T, ${TRACE}, sameValue equal: (T, T) -> Bool
+ _ expected: T, _ actual: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line, sameValue equal: (T, T) -> Bool
) {
if !equal(expected, actual) {
expectationFailure(
"expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
+ "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace}
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
)
}
}
-public func expectNotEqual<T : Equatable>(_ expected: T, _ actual: T, ${TRACE}) {
+public func expectNotEqual<T : Equatable>(_ expected: T, _ actual: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if expected == actual {
expectationFailure(
"unexpected value: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace}
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
)
}
}
@@ -228,130 +297,296 @@
// Cannot write a sane set of overloads using generics because of:
// <rdar://problem/17015923> Array -> NSArray implicit conversion insanity
public func expectOptionalEqual<T : Equatable>(
- _ expected: T, _ actual: T?, ${TRACE}
+ _ expected: T, _ actual: T?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectOptionalEqual(expected, actual, ${trace}, showFrame: false) {$0 == $1}
+ expectOptionalEqual(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
}
public func expectOptionalEqual<T>(
- _ expected: T, _ actual: T?, ${TRACE}, sameValue equal: (T, T) -> Bool
+ _ expected: T, _ actual: T?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line, sameValue equal: (T, T) -> Bool
) {
if (actual == nil) || !equal(expected, actual!) {
expectationFailure(
"expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))\n"
+ "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectEqual<T : Equatable>(_ expected: T?, _ actual: T?, ${TRACE}) {
+public func expectEqual<T : Equatable>(_ expected: T?, _ actual: T?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if expected != actual {
expectationFailure(
"expected: \"\(expected.debugDescription)\" (of type \(String(reflecting: type(of: expected))))\n"
+ "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
public func expectNotEqual<T : Equatable>(
- _ expected: T?, _ actual: T?, ${TRACE}
+ _ expected: T?, _ actual: T?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
if expected == actual {
expectationFailure(
"unexpected value: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
// Array<T> is not Equatable if T is. Provide additional overloads.
// Same for Dictionary.
-%for (Generic, EquatableType) in [
-% ('<T : Equatable>', 'ContiguousArray<T>'),
-% ('<T : Equatable>', 'ArraySlice<T>'),
-% ('<T : Equatable>', 'Array<T>'),
-% ('<T, U : Equatable>', 'Dictionary<T, U>')]:
-public func expectEqual${Generic}(
- _ expected: ${EquatableType}, _ actual: ${EquatableType}, ${TRACE}
+public func expectEqual<T : Equatable>(
+ _ expected: ContiguousArray<T>, _ actual: ContiguousArray<T>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectEqualTest(expected, actual, ${trace}, showFrame: false) { $0 == $1 }
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
}
-public func expectOptionalEqual${Generic}(
- _ expected: ${EquatableType}, _ actual: ${EquatableType}?, ${TRACE}) {
+public func expectOptionalEqual<T : Equatable>(
+ _ expected: ContiguousArray<T>, _ actual: ContiguousArray<T>?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if (actual == nil) || expected != actual! {
expectationFailure(
"expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+ "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-%end
+
+public func expectEqual<T : Equatable>(
+ _ expected: ArraySlice<T>, _ actual: ArraySlice<T>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
+}
+
+public func expectOptionalEqual<T : Equatable>(
+ _ expected: ArraySlice<T>, _ actual: ArraySlice<T>?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ if (actual == nil) || expected != actual! {
+ expectationFailure(
+ "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+ + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+}
+
+
+public func expectEqual<T : Equatable>(
+ _ expected: Array<T>, _ actual: Array<T>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
+}
+
+public func expectOptionalEqual<T : Equatable>(
+ _ expected: Array<T>, _ actual: Array<T>?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ if (actual == nil) || expected != actual! {
+ expectationFailure(
+ "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+ + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+}
+
+
+public func expectEqual<T, U : Equatable>(
+ _ expected: Dictionary<T, U>, _ actual: Dictionary<T, U>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
+}
+
+public func expectOptionalEqual<T, U : Equatable>(
+ _ expected: Dictionary<T, U>, _ actual: Dictionary<T, U>?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ if (actual == nil) || expected != actual! {
+ expectationFailure(
+ "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+ + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+}
+
public func expectEqual(
- _ expected: Any.Type, _ actual: Any.Type, ${TRACE}
+ _ expected: Any.Type, _ actual: Any.Type,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectEqualTest(expected, actual, ${trace}, showFrame: false) { $0 == $1 }
+ expectEqualTest(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
}
-public func expectLT<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectLT<T : Comparable>(_ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !(lhs < rhs) {
- expectationFailure("\(lhs) < \(rhs)", trace: ${trace})
+ expectationFailure("\(lhs) < \(rhs)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectLE<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectLE<T : Comparable>(_ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !(lhs <= rhs) {
- expectationFailure("\(lhs) <= \(rhs)", trace: ${trace})
+ expectationFailure("\(lhs) <= \(rhs)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectGT<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectGT<T : Comparable>(_ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !(lhs > rhs) {
- expectationFailure("\(lhs) > \(rhs)", trace: ${trace})
+ expectationFailure("\(lhs) > \(rhs)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectGE<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectGE<T : Comparable>(_ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !(lhs >= rhs) {
- expectationFailure("\(lhs) >= \(rhs)", trace: ${trace})
+ expectationFailure("\(lhs) >= \(rhs)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-% for OtherRange in ['Range', 'ClosedRange']:
extension Range {
- internal func _contains(_ other: ${OtherRange}<Bound>) -> Bool {
+ internal func _contains(_ other: Range<Bound>) -> Bool {
if other.lowerBound < lowerBound { return false }
-% if 'Closed' in OtherRange:
- if upperBound <= other.upperBound { return false }
-% else:
if upperBound < other.upperBound { return false }
-% end
return true
}
}
-% end
+extension Range {
+ internal func _contains(_ other: ClosedRange<Bound>) -> Bool {
+ if other.lowerBound < lowerBound { return false }
+ if upperBound <= other.upperBound { return false }
+ return true
+ }
+}
-% for Range in ['Range', 'ClosedRange']:
public func expectTrapping<Bound>(
- _ point: Bound, in range: ${Range}<Bound>, ${TRACE}
+ _ point: Bound, in range: Range<Bound>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
if !range.contains(point) {
- expectationFailure("\(point) in \(range)", trace: ${trace})
+ expectationFailure("\(point) in \(range)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
_trappingExpectationFailedCallback()
}
}
public func expectTrapping<Bound>(
- _ subRange: ${Range}<Bound>, in range: Range<Bound>, ${TRACE}
+ _ subRange: Range<Bound>, in range: Range<Bound>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
if !range._contains(subRange) {
- expectationFailure("\(subRange) in \(range)", trace: ${trace})
+ expectationFailure("\(subRange) in \(range)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
_trappingExpectationFailedCallback()
}
}
-% end
+public func expectTrapping<Bound>(
+ _ point: Bound, in range: ClosedRange<Bound>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ if !range.contains(point) {
+ expectationFailure("\(point) in \(range)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ _trappingExpectationFailedCallback()
+ }
+}
+
+public func expectTrapping<Bound>(
+ _ subRange: ClosedRange<Bound>, in range: Range<Bound>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ if !range._contains(subRange) {
+ expectationFailure("\(subRange) in \(range)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ _trappingExpectationFailedCallback()
+ }
+}
extension ClosedRange {
internal func _contains(_ other: ClosedRange<Bound>) -> Bool {
@@ -362,10 +597,15 @@
}
public func expectTrapping<Bound>(
- _ subRange: ClosedRange<Bound>, in range: ClosedRange<Bound>, ${TRACE}
+ _ subRange: ClosedRange<Bound>, in range: ClosedRange<Bound>,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
if !range._contains(subRange) {
- expectationFailure("\(subRange) in \(range)", trace: ${trace})
+ expectationFailure("\(subRange) in \(range)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
_trappingExpectationFailedCallback()
}
}
@@ -377,11 +617,12 @@
return x
}
-% for Mutable in ['', 'Mutable']:
-public func expect${Mutable}CollectionType<X : ${Mutable}Collection>(
+public func expectCollectionType<X : Collection>(
_ x: X.Type
) {}
-% end
+public func expectMutableCollectionType<X : MutableCollection>(
+ _ x: X.Type
+) {}
/// A slice is a `Collection` that when sliced returns an instance of
/// itself.
@@ -457,43 +698,77 @@
return AssertionResult(isPass: false)
}
-public func expectUnreachable(${TRACE}) {
- expectationFailure("this code should not be executed", trace: ${trace})
+public func expectUnreachable(
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
+ expectationFailure("this code should not be executed", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
-public func expectUnreachableCatch(_ error: Error, ${TRACE}) {
+public func expectUnreachableCatch(_ error: Error,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
expectationFailure(
- "error should not be thrown: \"\(error)\"", trace: ${trace})
+ "error should not be thrown: \"\(error)\"", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
-public func expectTrue(_ actual: AssertionResult, ${TRACE}) {
+public func expectTrue(_ actual: AssertionResult,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !actual._isPass {
expectationFailure(
- "expected: passed assertion\n\(actual.description)", trace: ${trace})
+ "expected: passed assertion\n\(actual.description)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectFalse(_ actual: AssertionResult, ${TRACE}) {
+public func expectFalse(_ actual: AssertionResult,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if actual._isPass {
expectationFailure(
- "expected: failed assertion\n\(actual.description)", trace: ${trace})
+ "expected: failed assertion\n\(actual.description)", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectTrue(_ actual: Bool, ${TRACE}) {
+public func expectTrue(_ actual: Bool,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if !actual {
- expectationFailure("expected: true", trace: ${trace})
+ expectationFailure("expected: true", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectFalse(_ actual: Bool, ${TRACE}) {
+public func expectFalse(_ actual: Bool,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if actual {
- expectationFailure("expected: false", trace: ${trace})
+ expectationFailure("expected: false", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
public func expectThrows<ErrorType: Error & Equatable>(
- _ expectedError: ErrorType? = nil, _ test: () throws -> Void, ${TRACE}) {
+ _ expectedError: ErrorType? = nil, _ test: () throws -> Void,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
do {
try test()
} catch let error as ErrorType {
@@ -501,29 +776,45 @@
expectEqual(expectedError, error)
}
} catch {
- expectationFailure("unexpected error thrown: \"\(error)\"", trace: ${trace})
+ expectationFailure("unexpected error thrown: \"\(error)\"", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectDoesNotThrow(_ test: () throws -> Void, ${TRACE}) {
+public func expectDoesNotThrow(_ test: () throws -> Void,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
do {
try test()
} catch {
- expectationFailure("unexpected error thrown: \"\(error)\"", trace: ${trace})
+ expectationFailure("unexpected error thrown: \"\(error)\"", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-public func expectNil<T>(_ value: T?, ${TRACE}) {
+public func expectNil<T>(_ value: T?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
if value != nil {
expectationFailure(
- "expected optional to be nil\nactual: \"\(value!)\"", trace: ${trace})
+ "expected optional to be nil\nactual: \"\(value!)\"", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
@discardableResult
-public func expectNotNil<T>(_ value: T?, ${TRACE}) -> T? {
+public func expectNotNil<T>(_ value: T?,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) -> T? {
if value == nil {
- expectationFailure("expected optional to be non-nil", trace: ${trace})
+ expectationFailure("expected optional to be non-nil", trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
return value
}
@@ -1589,7 +1880,7 @@
case windowsAny(reason: String)
case windowsCygnusAny(reason: String)
-
+
case haikuAny(reason: String)
case objCRuntime(/*reason:*/ String)
@@ -1683,7 +1974,7 @@
case .windowsCygnusAny(reason: let reason):
return "windowsCygnusAny(*, reason: \(reason))"
-
+
case .haikuAny(reason: let reason):
return "haikuAny(*, reason: \(reason))"
@@ -1969,7 +2260,7 @@
default:
return false
}
-
+
case .haikuAny:
switch _getRunningOSVersion() {
case .haiku:
@@ -2009,7 +2300,11 @@
_ instances: Instances,
oracle: (Instances.Index, Instances.Index) -> Bool,
allowBrokenTransitivity: Bool = false,
- ${TRACE}
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Instances.Iterator.Element : Equatable
{
@@ -2018,14 +2313,19 @@
Array(instances),
oracle: { oracle(indices[$0], indices[$1]) },
allowBrokenTransitivity: allowBrokenTransitivity,
- ${trace})
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
internal func _checkEquatableImpl<Instance : Equatable>(
_ instances: [Instance],
oracle: (Int, Int) -> Bool,
allowBrokenTransitivity: Bool = false,
- ${TRACE}
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
// For each index (which corresponds to an instance being tested) track the
// set of equal instances.
@@ -2044,7 +2344,7 @@
expectEqual(
predictedXY, oracle(j, i),
"bad oracle: broken symmetry between indices \(i), \(j)",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
let isEqualXY = x == y
expectEqual(
@@ -2054,13 +2354,13 @@
: "expected not equal, found equal\n") +
"lhs (at index \(i)): \(String(reflecting: x))\n" +
"rhs (at index \(j)): \(String(reflecting: y))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
// Not-equal is an inverse of equal.
expectNotEqual(
isEqualXY, x != y,
"lhs (at index \(i)): \(String(reflecting: x))\nrhs (at index \(j)): \(String(reflecting: y))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
if !allowBrokenTransitivity {
// Check transitivity of the predicate represented by the oracle.
@@ -2074,7 +2374,7 @@
expectTrue(
oracle(j, k),
"bad oracle: broken transitivity at indices \(i), \(j), \(k)",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
// No need to check equality between actual values, we will check
// them with the checks above.
}
@@ -2088,49 +2388,135 @@
public func checkEquatable<T : Equatable>(
- _ expectedEqual: Bool, _ lhs: T, _ rhs: T, ${TRACE}
+ _ expectedEqual: Bool, _ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
checkEquatable(
[lhs, rhs],
- oracle: { expectedEqual || $0 == $1 }, ${trace}, showFrame: false)
+ oracle: { expectedEqual || $0 == $1 }, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ showFrame: false)
+}
+
+internal func hash<H: Hashable>(_ value: H, seed: Int? = nil) -> Int {
+ var hasher = _Hasher()
+ if let seed = seed {
+ hasher.combine(seed)
+ }
+ hasher.combine(value)
+ return hasher.finalize()
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// `Hashable`, using `equalityOracle` to generate equality and hashing
+/// expectations from pairs of positions in `instances`.
+public func checkHashable<Instances: Collection>(
+ _ instances: Instances,
+ equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ allowBrokenTransitivity: Bool = false,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where Instances.Iterator.Element: Hashable {
+ checkHashable(
+ instances,
+ equalityOracle: equalityOracle,
+ hashEqualityOracle: equalityOracle,
+ allowBrokenTransitivity: allowBrokenTransitivity,
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+ showFrame: false)
}
/// Test that the elements of `instances` satisfy the semantic
/// requirements of `Hashable`, using `equalityOracle` to generate
-/// equality expectations from pairs of positions in `instances`.
-public func checkHashable<Instances : Collection>(
+/// equality expectations from pairs of positions in `instances`,
+/// and `hashEqualityOracle` to do the same for hashing.
+public func checkHashable<Instances: Collection>(
_ instances: Instances,
equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+ hashEqualityOracle: (Instances.Index, Instances.Index) -> Bool,
allowBrokenTransitivity: Bool = false,
- ${TRACE}
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Instances.Iterator.Element : Hashable {
-
checkEquatable(
instances,
oracle: equalityOracle,
allowBrokenTransitivity: allowBrokenTransitivity,
- ${trace})
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
for i in instances.indices {
let x = instances[i]
for j in instances.indices {
let y = instances[j]
+ let predicted = hashEqualityOracle(i, j)
+ expectEqual(
+ predicted, hashEqualityOracle(j, i),
+ "bad hash oracle: broken symmetry between indices \(i), \(j)",
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
if x == y {
+ expectTrue(
+ predicted,
+ """
+ bad hash oracle: equality must imply hash equality
+ lhs (at index \(i)): \(x)
+ rhs (at index \(j)): \(y)
+ """,
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ }
+ if predicted {
+ expectEqual(
+ hash(x), hash(y),
+ """
+ hash(into:) expected to match, found to differ
+ lhs (at index \(i)): \(x)
+ rhs (at index \(j)): \(y)
+ """,
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectEqual(
x.hashValue, y.hashValue,
- "lhs (at index \(i)): \(x)\nrhs (at index \(j)): \(y)",
- stackTrace: ${stackTrace})
+ """
+ hashValue expected to match, found to differ
+ lhs (at index \(i)): \(x)
+ rhs (at index \(j)): \(y)
+ """,
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ } else {
+ // Try a few different seeds; at least one of them should discriminate
+ // between the hashes. It is extremely unlikely this check will fail
+ // all ten attempts, unless the type's hash encoding is not unique,
+ // or unless the hash equality oracle is wrong.
+ expectTrue(
+ (0..<10).contains { hash(x, seed: $0) != hash(y, seed: $0) },
+ """
+ _hash(into:) expected to differ, found to match
+ lhs (at index \(i)): \(x)
+ rhs (at index \(j)): \(y)
+ """,
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
}
}
public func checkHashable<T : Hashable>(
- expectedEqual: Bool, _ lhs: T, _ rhs: T, ${TRACE}
+ expectedEqual: Bool, _ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
checkHashable(
- [lhs, rhs], equalityOracle: { expectedEqual || $0 == $1 }, ${trace})
+ [lhs, rhs], equalityOracle: { expectedEqual || $0 == $1 }, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
public enum ExpectedComparisonResult {
@@ -2194,13 +2580,18 @@
public func checkComparable<Instances : Collection>(
_ instances: Instances,
oracle: (Instances.Index, Instances.Index) -> ExpectedComparisonResult,
- ${TRACE}
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Instances.Iterator.Element : Comparable {
// Also checks that equality is consistent with comparison and that
// the oracle obeys the equality laws
- checkEquatable(instances, oracle: { oracle($0, $1).isEQ() }, ${trace})
+ checkEquatable(instances, oracle: { oracle($0, $1).isEQ() }, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
for i in instances.indices {
let x = instances[i]
@@ -2209,23 +2600,23 @@
x < x,
"found 'x < x'\n" +
"at index \(i): \(String(reflecting: x))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectFalse(
x > x,
"found 'x > x'\n" +
"at index \(i): \(String(reflecting: x))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectTrue(x <= x,
"found 'x <= x' to be false\n" +
"at index \(i): \(String(reflecting: x))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectTrue(x >= x,
"found 'x >= x' to be false\n" +
"at index \(i): \(String(reflecting: x))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
for j in instances.indices where i != j {
let y = instances[j]
@@ -2236,31 +2627,31 @@
expected.flip(), oracle(j, i),
"bad oracle: missing antisymmetry: "
+ "(\(String(reflecting: i)), \(String(reflecting: j)))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectEqual(expected.isLT(), x < y,
"x < y\n" +
"lhs (at index \(i)): \(String(reflecting: x))\n" +
"rhs (at index \(j)): \(String(reflecting: y))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectEqual(expected.isLE(), x <= y,
"x <= y\n" +
"lhs (at index \(i)): \(String(reflecting: x))\n" +
"rhs (at index \(j)): \(String(reflecting: y))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectEqual(expected.isGE(), x >= y,
"x >= y\n" +
"lhs (at index \(i)): \(String(reflecting: x))\n" +
"rhs (at index \(j)): \(String(reflecting: y))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
expectEqual(expected.isGT(), x > y,
"x > y\n" +
"lhs (at index \(i)): \(String(reflecting: x))\n" +
"rhs (at index \(j)): \(String(reflecting: y))",
- stackTrace: ${stackTrace})
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
for k in instances.indices {
let expected2 = oracle(j, k)
@@ -2269,7 +2660,7 @@
expected, oracle(i, k),
"bad oracle: missing transitivity "
+ "(\(String(reflecting: i)), \(String(reflecting: j)), "
- + "\(String(reflecting: k)))", stackTrace: ${stackTrace})
+ + "\(String(reflecting: k)))", stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
}
@@ -2277,12 +2668,17 @@
}
public func checkComparable<T : Comparable>(
- _ expected: ExpectedComparisonResult, _ lhs: T, _ rhs: T, ${TRACE}
+ _ expected: ExpectedComparisonResult, _ lhs: T, _ rhs: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
checkComparable(
[lhs, rhs],
oracle: { [[ .eq, expected], [ expected.flip(), .eq]][$0][$1] },
- ${trace})
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
@@ -2300,7 +2696,11 @@
(Instances.Index, Instances.Index) -> Strides.Iterator.Element,
advanceOracle:
(Instances.Index, Strides.Index) -> Instances.Iterator.Element,
- ${TRACE}
+
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Instances.Iterator.Element : Strideable,
Instances.Iterator.Element.Stride == Strides.Iterator.Element {
@@ -2311,7 +2711,8 @@
let d = distanceOracle($1, $0);
return d < 0 ? .lt : d == 0 ? .eq : .gt
},
- ${trace})
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
for i in instances.indices {
let x = instances[i]
@@ -2347,12 +2748,17 @@
Expected: Sequence,
Actual: Sequence
>(
- _ expected: Expected, _ actual: Actual, ${TRACE}
+ _ expected: Expected, _ actual: Actual,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Expected.Iterator.Element == Actual.Iterator.Element,
Expected.Iterator.Element : Equatable {
- expectEqualSequence(expected, actual, ${trace}) { $0 == $1 }
+ expectEqualSequence(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) { $0 == $1 }
}
public func expectEqualSequence<
@@ -2361,13 +2767,18 @@
T : Equatable,
U : Equatable
>(
- _ expected: Expected, _ actual: Actual, ${TRACE}
+ _ expected: Expected, _ actual: Actual,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Expected.Iterator.Element == Actual.Iterator.Element,
Expected.Iterator.Element == (T, U) {
expectEqualSequence(
- expected, actual, ${trace}) {
+ expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) {
(lhs: (T, U), rhs: (T, U)) -> Bool in
lhs.0 == rhs.0 && lhs.1 == rhs.1
}
@@ -2377,7 +2788,11 @@
Expected: Sequence,
Actual: Sequence
>(
- _ expected: Expected, _ actual: Actual, ${TRACE},
+ _ expected: Expected, _ actual: Actual,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
) where
Expected.Iterator.Element == Actual.Iterator.Element {
@@ -2385,7 +2800,8 @@
if !expected.elementsEqual(actual, by: sameValue) {
expectationFailure("expected elements: \"\(expected)\"\n"
+ "actual: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
@@ -2393,7 +2809,11 @@
Expected : Sequence,
Actual : Sequence
>(
- _ expected: Expected, _ actual: Actual, ${TRACE},
+ _ expected: Expected, _ actual: Actual,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line,
compare: @escaping (Expected.Iterator.Element, Expected.Iterator.Element)
-> ExpectedComparisonResult
) where
@@ -2404,44 +2824,61 @@
let y: [Actual.Iterator.Element] =
actual.sorted { compare($0, $1).isLT() }
expectEqualSequence(
- x, y, ${trace}, sameValue: { compare($0, $1).isEQ() })
+ x, y, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: { compare($0, $1).isEQ() })
}
public func expectEqualsUnordered<
Expected : Sequence,
Actual : Sequence
>(
- _ expected: Expected, _ actual: Actual, ${TRACE}
+ _ expected: Expected, _ actual: Actual,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Expected.Iterator.Element == Actual.Iterator.Element,
Expected.Iterator.Element : Comparable {
- expectEqualsUnordered(expected, actual, ${trace}) {
+ expectEqualsUnordered(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) {
$0 < $1 ? .lt : $0 == $1 ? .eq : .gt
}
}
public func expectEqualsUnordered<T : Comparable>(
- _ expected: [T], _ actual: [T], ${TRACE}
+ _ expected: [T], _ actual: [T],
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
let x = expected.sorted()
let y = actual.sorted()
- expectEqualSequence(x, y, ${trace})
+ expectEqualSequence(x, y, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
public func expectEqualsUnordered<T : Strideable>(
- _ expected: Range<T>, _ actual: [T], ${TRACE}
+ _ expected: Range<T>, _ actual: [T],
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where T.Stride: SignedInteger {
if expected.count != actual.count {
expectationFailure("expected elements: \"\(expected)\"\n"
+ "actual: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
for e in actual {
if !expected.contains(e) {
expectationFailure("expected elements: \"\(expected)\"\n"
+ "actual: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
}
@@ -2474,7 +2911,11 @@
Actual : Sequence,
T : Comparable
>(
- _ expected: Expected, _ actual: Actual, ${TRACE}
+ _ expected: Expected, _ actual: Actual,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) where
Actual.Iterator.Element == (key: T, value: T),
Expected.Iterator.Element == (T, T) {
@@ -2493,7 +2934,8 @@
return lhs.0 == rhs.0 && lhs.1 == rhs.1
}
- expectEqualSequence(x, y, ${trace}, sameValue: comparePairEquals)
+ expectEqualSequence(x, y, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: comparePairEquals)
}
public func expectEqualFunctionsForDomain<ArgumentType, Result : Equatable>(
@@ -2527,7 +2969,11 @@
}
public func expectEqualUnicodeScalars(
- _ expected: [UInt32], _ actual: String, ${TRACE}) {
+ _ expected: [UInt32], _ actual: String,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line) {
let actualUnicodeScalars = Array(
actual.unicodeScalars.lazy.map { $0.value })
@@ -2535,10 +2981,11 @@
expectationFailure(
"expected elements: \"\(asHex(expected))\"\n"
+ "actual: \"\(asHex(actualUnicodeScalars))\"",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
-// ${'Local Variables'}:
+// Local Variables:
// eval: (read-only-mode 1)
// End:
diff --git a/stdlib/private/StdlibUnittest/StringConvertible.swift.gyb b/stdlib/private/StdlibUnittest/StringConvertible.swift
similarity index 68%
rename from stdlib/private/StdlibUnittest/StringConvertible.swift.gyb
rename to stdlib/private/StdlibUnittest/StringConvertible.swift
index 2ddbfeb..8252ba2 100644
--- a/stdlib/private/StdlibUnittest/StringConvertible.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StringConvertible.swift
@@ -1,4 +1,4 @@
-//===--- StringConvertible.swift.gyb --------------------------*- swift -*-===//
+//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -10,9 +10,6 @@
//
//===----------------------------------------------------------------------===//
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
/// A type that has different `CustomStringConvertible` and
/// `CustomDebugStringConvertible` representations.
@@ -110,43 +107,68 @@
}
public func expectPrinted<T>(
- expectedOneOf patterns: [String], _ object: T, ${TRACE}
+ expectedOneOf patterns: [String], _ object: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
let actual = String(describing: object)
if !patterns.contains(actual) {
expectationFailure(
"expected: any of \(String(reflecting: patterns))\n"
+ "actual: \(String(reflecting: actual))",
- trace: ${trace})
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
public func expectPrinted<T>(
- _ expected: String, _ object: T, ${TRACE}
+ _ expected: String, _ object: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectPrinted(expectedOneOf: [expected], object, ${trace})
+ expectPrinted(expectedOneOf: [expected], object, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
public func expectDebugPrinted<T>(
- expectedOneOf patterns: [String], _ object: T, ${TRACE}
+ expectedOneOf patterns: [String], _ object: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectPrinted(expectedOneOf: patterns, String(reflecting: object), ${trace})
+ expectPrinted(expectedOneOf: patterns, String(reflecting: object), message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
public func expectDebugPrinted<T>(
- _ expected: String, _ object: T, ${TRACE}
+ _ expected: String, _ object: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectDebugPrinted(expectedOneOf: [expected], object, ${trace})
+ expectDebugPrinted(expectedOneOf: [expected], object, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
public func expectDumped<T>(
- _ expected: String, _ object: T, ${TRACE}
+ _ expected: String, _ object: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
var actual = ""
dump(object, to: &actual)
- expectEqual(expected, actual, ${trace})
+ expectEqual(expected, actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
-// ${'Local Variables'}:
+// Local Variables:
// eval: (read-only-mode 1)
// End:
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index e1adb72..47724f1 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -137,12 +137,12 @@
/// tasked with finding the first two days with absences in the session. To
/// find the indices of the two days in question, follow these steps:
///
-/// 1) Call `index(where:)` to find the index of the first element in the
+/// 1) Call `firstIndex(where:)` to find the index of the first element in the
/// `absences` array that is greater than zero.
/// 2) Create a slice of the `absences` array starting after the index found in
/// step 1.
-/// 3) Call `index(where:)` again, this time on the slice created in step 2.
-/// Where in some languages you might pass a starting index into an
+/// 3) Call `firstIndex(where:)` again, this time on the slice created in step
+/// 2. Where in some languages you might pass a starting index into an
/// `indexOf` method to find the second day, in Swift you perform the same
/// operation on a slice of the original array.
/// 4) Print the results using the indices found in steps 1 and 3 on the
@@ -150,9 +150,9 @@
///
/// Here's an implementation of those steps:
///
-/// if let i = absences.index(where: { $0 > 0 }) { // 1
+/// if let i = absences.firstIndex(where: { $0 > 0 }) { // 1
/// let absencesAfterFirst = absences[(i + 1)...] // 2
-/// if let j = absencesAfterFirst.index(where: { $0 > 0 }) { // 3
+/// if let j = absencesAfterFirst.firstIndex(where: { $0 > 0 }) { // 3
/// print("The first day with absences had \(absences[i]).") // 4
/// print("The second day with absences had \(absences[j]).")
/// }
@@ -293,7 +293,7 @@
/// You can replace an existing element with a new value by assigning the new
/// value to the subscript.
///
-/// if let i = students.index(of: "Maxime") {
+/// if let i = students.firstIndex(of: "Maxime") {
/// students[i] = "Max"
/// }
/// // ["Ivy", "Jordell", "Liam", "Max", "Shakia"]
@@ -533,7 +533,7 @@
/// safe to use with `endIndex`. For example:
///
/// let numbers = [10, 20, 30, 40, 50]
- /// if let i = numbers.index(of: 30) {
+ /// if let i = numbers.firstIndex(of: 30) {
/// print(numbers[i ..< numbers.endIndex])
/// }
/// // Prints "[30, 40, 50]"
@@ -784,7 +784,7 @@
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
- /// let i = streetsSlice.index(of: "Evarts") // 4
+ /// let i = streetsSlice.firstIndex(of: "Evarts") // 4
/// print(streets[i!])
/// // Prints "Evarts"
///
@@ -2270,6 +2270,7 @@
@inlinable // FIXME(sil-serialize-all)
public func _hash(into hasher: inout _Hasher) {
+ hasher.combine(count) // discriminator
for element in self {
hasher.combine(element)
}
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index 77d037c..3665c56 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -119,7 +119,7 @@
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
- /// let index = streetsSlice.index(of: "Evarts") // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts") // 4
/// print(streets[index!])
/// // Prints "Evarts"
///
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index dcb73ef..6fe098f 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -161,7 +161,7 @@
/// that position.
///
/// let text = "Buffalo buffalo buffalo buffalo."
-/// if let firstSpace = text.index(of: " ") {
+/// if let firstSpace = text.firstIndex(of: " ") {
/// print(text[..<firstSpace])
/// }
/// // Prints "Buffalo"
@@ -226,7 +226,7 @@
/// You can retrieve the same slice using the string's ranged subscript, which
/// takes a range expression.
///
-/// if let firstSpace = text.index(of: " ") {
+/// if let firstSpace = text.firstIndex(of: " ") {
/// print(text[..<firstSpace]
/// // Prints "Buffalo"
/// }
@@ -373,7 +373,7 @@
/// safe to use with `endIndex`. For example:
///
/// let numbers = [10, 20, 30, 40, 50]
- /// if let index = numbers.index(of: 30) {
+ /// if let index = numbers.firstIndex(of: 30) {
/// print(numbers[index ..< numbers.endIndex])
/// }
/// // Prints "[30, 40, 50]"
@@ -439,7 +439,7 @@
/// original collection. This example searches `streetsSlice` for one of the
/// strings in the slice, and then uses that index in the original array.
///
- /// let index = streetsSlice.index(of: "Evarts")! // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts")! // 4
/// print(streets[index])
/// // "Evarts"
///
@@ -497,7 +497,7 @@
/// but not including, that index:
///
/// let numbers = [10, 20, 30, 40, 50, 60]
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers.prefix(upTo: i))
/// }
/// // Prints "[10, 20, 30]"
@@ -512,7 +512,7 @@
/// half-open range as the collection's subscript. The subscript notation is
/// preferred over `prefix(upTo:)`.
///
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers[..<i])
/// }
/// // Prints "[10, 20, 30]"
@@ -532,7 +532,7 @@
/// that index:
///
/// let numbers = [10, 20, 30, 40, 50, 60]
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers.suffix(from: i))
/// }
/// // Prints "[40, 50, 60]"
@@ -547,7 +547,7 @@
/// from the index as the collection's subscript. The subscript notation is
/// preferred over `suffix(from:)`.
///
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers[i...])
/// }
/// // Prints "[40, 50, 60]"
@@ -568,7 +568,7 @@
/// including, that index:
///
/// let numbers = [10, 20, 30, 40, 50, 60]
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers.prefix(through: i))
/// }
/// // Prints "[10, 20, 30, 40]"
@@ -577,7 +577,7 @@
/// closed range as the collection's subscript. The subscript notation is
/// preferred over `prefix(through:)`.
///
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers[...i])
/// }
/// // Prints "[10, 20, 30, 40]"
@@ -621,8 +621,9 @@
/// of the collection.
var count: Int { get }
- // The following requirement enables dispatching for index(of:) when
+ // The following requirements enable dispatching for firstIndex(of:) when
// the element type is Equatable.
+
/// Returns `Optional(Optional(index))` if an element was found
/// or `Optional(nil)` if an element was determined to be missing;
/// otherwise, `nil`.
@@ -1067,7 +1068,7 @@
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
- /// let index = streetsSlice.index(of: "Evarts") // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts") // 4
/// print(streets[index!])
/// // Prints "Evarts"
///
@@ -1180,7 +1181,7 @@
}
// TODO: swift-3-indexing-model - rename the following to _customIndexOfEquatable(element)?
- /// Customization point for `Collection.index(of:)`.
+ /// Customization point for `Collection.firstIndex(of:)`.
///
/// Define this method if the collection can find an element in less than
/// O(*n*) by exploiting collection-specific knowledge.
@@ -1189,7 +1190,7 @@
/// `Optional(nil)` if the element was not found, or
/// `Optional(Optional(index))` if an element was found.
///
- /// - Complexity: O(`count`).
+ /// - Complexity: Hopefully less than O(`count`).
@inlinable
public // dispatching
func _customIndexOfEquatableElement(_: Iterator.Element) -> Index?? {
@@ -1402,7 +1403,7 @@
/// but not including, that index:
///
/// let numbers = [10, 20, 30, 40, 50, 60]
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers.prefix(upTo: i))
/// }
/// // Prints "[10, 20, 30]"
@@ -1417,7 +1418,7 @@
/// half-open range as the collection's subscript. The subscript notation is
/// preferred over `prefix(upTo:)`.
///
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers[..<i])
/// }
/// // Prints "[10, 20, 30]"
@@ -1440,7 +1441,7 @@
/// that index:
///
/// let numbers = [10, 20, 30, 40, 50, 60]
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers.suffix(from: i))
/// }
/// // Prints "[40, 50, 60]"
@@ -1455,7 +1456,7 @@
/// from the index as the collection's subscript. The subscript notation is
/// preferred over `suffix(from:)`.
///
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers[i...])
/// }
/// // Prints "[40, 50, 60]"
@@ -1479,7 +1480,7 @@
/// including, that index:
///
/// let numbers = [10, 20, 30, 40, 50, 60]
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers.prefix(through: i))
/// }
/// // Prints "[10, 20, 30, 40]"
@@ -1488,7 +1489,7 @@
/// closed range as the collection's subscript. The subscript notation is
/// preferred over `prefix(through:)`.
///
- /// if let i = numbers.index(of: 40) {
+ /// if let i = numbers.firstIndex(of: 40) {
/// print(numbers[...i])
/// }
/// // Prints "[10, 20, 30, 40]"
diff --git a/stdlib/public/core/CollectionAlgorithms.swift b/stdlib/public/core/CollectionAlgorithms.swift
index b7e7425..484585f 100644
--- a/stdlib/public/core/CollectionAlgorithms.swift
+++ b/stdlib/public/core/CollectionAlgorithms.swift
@@ -31,20 +31,20 @@
}
//===----------------------------------------------------------------------===//
-// index(of:)/index(where:)
+// firstIndex(of:)/firstIndex(where:)
//===----------------------------------------------------------------------===//
extension Collection where Element : Equatable {
/// Returns the first index where the specified value appears in the
/// collection.
///
- /// After using `index(of:)` to find the position of a particular element in
- /// a collection, you can use it to access the element by subscripting. This
- /// example shows how you can modify one of the names in an array of
+ /// After using `firstIndex(of:)` to find the position of a particular element
+ /// in a collection, you can use it to access the element by subscripting.
+ /// This example shows how you can modify one of the names in an array of
/// students.
///
/// var students = ["Ben", "Ivy", "Jordell", "Maxime"]
- /// if let i = students.index(of: "Maxime") {
+ /// if let i = students.firstIndex(of: "Maxime") {
/// students[i] = "Max"
/// }
/// print(students)
@@ -54,7 +54,7 @@
/// - Returns: The first index where `element` is found. If `element` is not
/// found in the collection, returns `nil`.
@inlinable
- public func index(of element: Element) -> Index? {
+ public func firstIndex(of element: Element) -> Index? {
if let result = _customIndexOfEquatableElement(element) {
return result
}
@@ -68,6 +68,13 @@
}
return nil
}
+
+ /// Returns the first index where the specified value appears in the
+ /// collection.
+ @inlinable
+ public func index(of _element: Element) -> Index? {
+ return firstIndex(of: _element)
+ }
}
extension Collection {
@@ -80,7 +87,7 @@
/// begins with the letter "A":
///
/// let students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
- /// if let i = students.index(where: { $0.hasPrefix("A") }) {
+ /// if let i = students.firstIndex(where: { $0.hasPrefix("A") }) {
/// print("\(students[i]) starts with 'A'!")
/// }
/// // Prints "Abena starts with 'A'!"
@@ -92,7 +99,7 @@
/// `true`. If no elements in the collection satisfy the given predicate,
/// returns `nil`.
@inlinable
- public func index(
+ public func firstIndex(
where predicate: (Element) throws -> Bool
) rethrows -> Index? {
var i = self.startIndex
@@ -104,6 +111,15 @@
}
return nil
}
+
+ /// Returns the first index in which an element of the collection satisfies
+ /// the given predicate.
+ @inlinable
+ public func index(
+ where _predicate: (Element) throws -> Bool
+ ) rethrows -> Index? {
+ return try firstIndex(where: _predicate)
+ }
}
//===----------------------------------------------------------------------===//
diff --git a/stdlib/public/core/Dictionary.swift b/stdlib/public/core/Dictionary.swift
index ff9e60f..4525f07 100644
--- a/stdlib/public/core/Dictionary.swift
+++ b/stdlib/public/core/Dictionary.swift
@@ -328,11 +328,11 @@
/// provides, see the `DictionaryLiteral` type for an alternative.
///
/// You can search a dictionary's contents for a particular value using the
-/// `contains(where:)` or `index(where:)` methods supplied by default
+/// `contains(where:)` or `firstIndex(where:)` methods supplied by default
/// implementation. The following example checks to see if `imagePaths` contains
/// any paths in the `"/glyphs"` directory:
///
-/// let glyphIndex = imagePaths.index { $0.value.hasPrefix("/glyphs") }
+/// let glyphIndex = imagePaths.firstIndex(where: { $0.value.hasPrefix("/glyphs") })
/// if let index = glyphIndex {
/// print("The '\(imagesPaths[index].key)' image is a glyph.")
/// } else {
@@ -668,10 +668,10 @@
/// this subscript with the resulting value.
///
/// For example, to find the key for a particular value in a dictionary, use
- /// the `index(where:)` method.
+ /// the `firstIndex(where:)` method.
///
/// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
- /// if let index = countryCodes.index(where: { $0.value == "Japan" }) {
+ /// if let index = countryCodes.firstIndex(where: { $0.value == "Japan" }) {
/// print(countryCodes[index])
/// print("Japan's country code is '\(countryCodes[index].key)'.")
/// } else {
diff --git a/stdlib/public/core/ErrorType.swift b/stdlib/public/core/ErrorType.swift
index 8691233..2d9dfd3 100644
--- a/stdlib/public/core/ErrorType.swift
+++ b/stdlib/public/core/ErrorType.swift
@@ -35,7 +35,7 @@
///
/// enum IntParsingError: Error {
/// case overflow
-/// case invalidInput(String)
+/// case invalidInput(Character)
/// }
///
/// The `invalidInput` case includes the invalid character as an associated
@@ -48,8 +48,9 @@
/// extension Int {
/// init(validating input: String) throws {
/// // ...
-/// if !_isValid(s) {
-/// throw IntParsingError.invalidInput(s)
+/// let c = _nextCharacter(from: input)
+/// if !_isValid(c) {
+/// throw IntParsingError.invalidInput(c)
/// }
/// // ...
/// }
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index 3ccea1d..09e2635 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -1225,6 +1225,31 @@
/// The sign for a negative value.
case minus
+
+ // Explicit declarations of otherwise-synthesized members to make them
+ // @inlinable, promising that we will never change the implementation.
+
+ @inlinable
+ public init?(rawValue: Int) {
+ switch rawValue {
+ case 0: self = .plus
+ case 1: self = .minus
+ default: return nil
+ }
+ }
+
+ @inlinable
+ public var rawValue: Int {
+ switch self {
+ case .plus: return 0
+ case .minus: return 1
+ }
+ }
+
+ @inlinable
+ public static func ==(a: FloatingPointSign, b: FloatingPointSign) -> Bool {
+ return a.rawValue == b.rawValue
+ }
}
/// The IEEE 754 floating-point classes.
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 8e531d3..5dfa62f 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -625,23 +625,107 @@
}
}
+// _semantics("optimize.sil.preserve_exclusivity" forces the compiler to
+// generate access markers regardless of the current build settings. This way,
+// user code that accesses keypaths are properly enforced even if the standard
+// library has exclusivity checking internally disabled. The semantic attribute
+// must be consistently applied to both the begin and end unpaired access
+// markers, otherwise the runtime will fail catastrophically and unpredictably.
+// This relies on Swift module serialization occurring before these _semantic
+// function are inlined, since inlining would unpredictably cause the attribute
+// to be dropped.
+//
+// An exclusivity violation will report the caller's stack frame location.
+// Runtime diagnostics will be improved by inlining this function. However, this
+// cannot be marked @transparent because it can't be inlined prior to
+// serialization.
+@inlinable
+@inline(__always)
+@_semantics("optimize.sil.preserve_exclusivity")
+func beginAccessHelper<T>(_ address: Builtin.RawPointer, _ accessRecordPtr: Builtin.RawPointer, _ type: T.Type) {
+ Builtin.beginUnpairedModifyAccess(address, accessRecordPtr, type)
+}
+
+@inlinable
+@inline(__always)
+@_semantics("optimize.sil.preserve_exclusivity")
+func endAccessHelper(_ accessRecordPtr: Builtin.RawPointer) {
+ Builtin.endUnpairedAccess(accessRecordPtr)
+}
+
+@inlinable
+@inline(__always)
+@_semantics("optimize.sil.preserve_exclusivity")
+func instantaneousAccessHelper<T>(_ address: Builtin.RawPointer, _ type: T.Type) {
+ Builtin.performInstantaneousReadAccess(address, T.self)
+}
+
// A class that maintains ownership of another object while a mutable projection
-// into it is underway.
+// into it is underway. The lifetime of the instance of this class is also used
+// to begin and end exclusive 'modify' access to the projected address.
@_fixed_layout // FIXME(sil-serialize-all)
@usableFromInline // FIXME(sil-serialize-all)
-internal final class ClassHolder {
+internal final class ClassHolder<ProjectionType> {
+
+ /// The type of the scratch record passed to the runtime to record
+ /// accesses to guarantee exlcusive access.
+ internal typealias AccessRecord = Builtin.UnsafeValueBuffer
+
@usableFromInline // FIXME(sil-serialize-all)
- internal let previous: AnyObject?
+ internal var previous: AnyObject?
@usableFromInline // FIXME(sil-serialize-all)
- internal let instance: AnyObject
+ internal var instance: AnyObject
@inlinable // FIXME(sil-serialize-all)
internal init(previous: AnyObject?, instance: AnyObject) {
self.previous = previous
self.instance = instance
}
+
@inlinable // FIXME(sil-serialize-all)
- deinit {}
+ internal final class func _create(
+ previous: AnyObject?,
+ instance: AnyObject,
+ accessingAddress address: UnsafeRawPointer,
+ type: ProjectionType.Type
+ ) -> ClassHolder {
+
+ // Tail allocate the UnsafeValueBuffer used as the AccessRecord.
+ // This avoids a second heap allocation since there is no source-level way to
+ // initialize a Builtin.UnsafeValueBuffer type and thus we cannot have a
+ // stored property of that type.
+ let holder: ClassHolder = Builtin.allocWithTailElems_1(self,
+ 1._builtinWordValue,
+ AccessRecord.self)
+
+ // Initialize the ClassHolder's instance variables. This is done via
+ // withUnsafeMutablePointer(to:) because the instance was just allocated with
+ // allocWithTailElems_1 and so we need to make sure to use an initialization
+ // rather than an assignment.
+ withUnsafeMutablePointer(to: &holder.previous) {
+ $0.initialize(to: previous)
+ }
+
+ withUnsafeMutablePointer(to: &holder.instance) {
+ $0.initialize(to: instance)
+ }
+
+ let accessRecordPtr = Builtin.projectTailElems(holder, AccessRecord.self)
+
+ // Begin a 'modify' access to the address. This access is ended in
+ // ClassHolder's deinitializer.
+ beginAccessHelper(address._rawValue, accessRecordPtr, type)
+
+ return holder
+ }
+
+ @inlinable // FIXME(sil-serialize-all)
+ deinit {
+ let accessRecordPtr = Builtin.projectTailElems(self, AccessRecord.self)
+
+ // Ends the access begun in _create().
+ endAccessHelper(accessRecordPtr)
+ }
}
// A class that triggers writeback to a pointer when destroyed.
@@ -1185,7 +1269,14 @@
let baseObj = unsafeBitCast(base, to: AnyObject.self)
let basePtr = UnsafeRawPointer(Builtin.bridgeToRawPointer(baseObj))
defer { _fixLifetime(baseObj) }
- return .continue(basePtr.advanced(by: offset)
+
+ let offsetAddress = basePtr.advanced(by: offset)
+
+ // Perform an instaneous record access on the address in order to
+ // ensure that the read will not conflict with an already in-progress
+ // 'modify' access.
+ instantaneousAccessHelper(offsetAddress._rawValue, NewValue.self)
+ return .continue(offsetAddress
.assumingMemoryBound(to: NewValue.self)
.pointee)
@@ -1244,12 +1335,16 @@
// AnyObject memory can alias any class reference memory, so we can
// assume type here
let object = base.assumingMemoryBound(to: AnyObject.self).pointee
- // The base ought to be kept alive for the duration of the derived access
- keepAlive = keepAlive == nil
- ? object
- : ClassHolder(previous: keepAlive, instance: object)
- return UnsafeRawPointer(Builtin.bridgeToRawPointer(object))
+ let offsetAddress = UnsafeRawPointer(Builtin.bridgeToRawPointer(object))
.advanced(by: offset)
+
+ // Keep the base alive for the duration of the derived access and also
+ // enforce exclusive access to the address.
+ keepAlive = ClassHolder._create(previous: keepAlive, instance: object,
+ accessingAddress: offsetAddress,
+ type: NewValue.self)
+
+ return offsetAddress
case .mutatingGetSet(id: _, get: let rawGet, set: let rawSet,
argument: let argument):
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index d43bdc8..0b3ada7 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -422,7 +422,7 @@
/// i0 != children.endIndex
/// {
/// let grandChildren = Mirror(reflecting: children[i0].value).children
- /// if let i1 = grandChildren.index(where: { $0.label == "two" }) {
+ /// if let i1 = grandChildren.firstIndex(where: { $0.label == "two" }) {
/// let greatGrandChildren =
/// Mirror(reflecting: grandChildren[i1].value).children
/// if let i2 = greatGrandChildren.index(
@@ -459,7 +459,7 @@
let children = Mirror(reflecting: result).children
let position: Children.Index
if case let label as String = e {
- position = children.index { $0.label == label } ?? children.endIndex
+ position = children.firstIndex { $0.label == label } ?? children.endIndex
}
else if let offset = e as? Int {
position = children.index(children.startIndex,
@@ -665,11 +665,11 @@
/// Some operations that are efficient on a dictionary are slower when using
/// `DictionaryLiteral`. In particular, to find the value matching a key, you
/// must search through every element of the collection. The call to
-/// `index(where:)` in the following example must traverse the whole
+/// `firstIndex(where:)` in the following example must traverse the whole
/// collection to find the element that matches the predicate:
///
/// let runner = "Marlies Gohr"
-/// if let index = recordTimes.index(where: { $0.0 == runner }) {
+/// if let index = recordTimes.firstIndex(where: { $0.0 == runner }) {
/// let time = recordTimes[index].1
/// print("\(runner) set a 100m record of \(time) seconds.")
/// } else {
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index b55c1c0..dc1f10b 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -25,7 +25,7 @@
/// modify one of the names in an array of students.
///
/// var students = ["Ben", "Ivy", "Jordell", "Maxime"]
-/// if let i = students.index(of: "Maxime") {
+/// if let i = students.firstIndex(of: "Maxime") {
/// students[i] = "Max"
/// }
/// print(students)
@@ -112,7 +112,7 @@
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
- /// let index = streetsSlice.index(of: "Evarts") // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts") // 4
/// streets[index!] = "Eustace"
/// print(streets[index!])
/// // Prints "Eustace"
@@ -211,7 +211,7 @@
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
- /// let index = streetsSlice.index(of: "Evarts") // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts") // 4
/// streets[index!] = "Eustace"
/// print(streets[index!])
/// // Prints "Eustace"
diff --git a/stdlib/public/core/ObjectIdentifier.swift b/stdlib/public/core/ObjectIdentifier.swift
index 903e49f..60c8211 100644
--- a/stdlib/public/core/ObjectIdentifier.swift
+++ b/stdlib/public/core/ObjectIdentifier.swift
@@ -21,8 +21,8 @@
/// Creates an instance that uniquely identifies the given class instance.
///
- /// The following example creates an example class `A` and compares instances
- /// of the class using their object identifiers and the identical-to
+ /// The following example creates an example class `IntegerRef` and compares
+ /// instances of the class using their object identifiers and the identical-to
/// operator (`===`):
///
/// class IntegerRef {
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index 0130e9a..8e9f34e 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -87,7 +87,7 @@
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
- /// let index = streetsSlice.index(of: "Evarts") // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts") // 4
/// print(streets[index!])
/// // Prints "Evarts"
///
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index 56c227e..4b10690 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -814,7 +814,7 @@
/// of the strings in the slice, and then uses that index in the original
/// array.
///
- /// let index = streetsSlice.index(of: "Evarts") // 4
+ /// let index = streetsSlice.firstIndex(of: "Evarts") // 4
/// print(streets[index!])
/// // "Evarts"
///
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift
index e9531fe..4ad53bd 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -1097,7 +1097,7 @@
public mutating func removeAll(
where predicate: (Element) throws -> Bool
) rethrows {
- if var i = try index(where: predicate) {
+ if var i = try firstIndex(where: predicate) {
var j = index(after: i)
while j != endIndex {
if try !predicate(self[j]) {
diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift
index 97aa7bf..cddbe41 100644
--- a/stdlib/public/core/Reverse.swift
+++ b/stdlib/public/core/Reverse.swift
@@ -129,7 +129,7 @@
///
/// func indexOfLastEven(_ numbers: [Int]) -> Int? {
/// let reversedNumbers = numbers.reversed()
- /// guard let i = reversedNumbers.index(where: { $0 % 2 == 0 })
+ /// guard let i = reversedNumbers.firstIndex(where: { $0 % 2 == 0 })
/// else { return nil }
///
/// return numbers.index(before: i.base)
@@ -152,7 +152,7 @@
/// `"a"` character in a string's character view.
///
/// let name = "Horatio"
- /// let aIndex = name.index(of: "a")!
+ /// let aIndex = name.firstIndex(of: "a")!
/// // name[aIndex] == "a"
///
/// let reversedName = name.reversed()
diff --git a/stdlib/public/core/Set.swift b/stdlib/public/core/Set.swift
index e37f85c..5c956e3 100644
--- a/stdlib/public/core/Set.swift
+++ b/stdlib/public/core/Set.swift
@@ -349,7 +349,7 @@
///
/// - Complexity: O(1)
@inlinable // FIXME(sil-serialize-all)
- public func index(of member: Element) -> Index? {
+ public func firstIndex(of member: Element) -> Index? {
return _variantBuffer.index(forKey: member)
}
@@ -357,7 +357,7 @@
public func _customIndexOfEquatableElement(
_ member: Element
) -> Index?? {
- return Optional(index(of: member))
+ return Optional(firstIndex(of: member))
}
/// The number of elements in the set.
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 0572d4b..edead79 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -362,7 +362,7 @@
/// that point:
///
/// let name = "Marie Curie"
-/// let firstSpace = name.index(of: " ") ?? name.endIndex
+/// let firstSpace = name.firstIndex(of: " ") ?? name.endIndex
/// let firstName = name[..<firstSpace]
/// // firstName == "Marie"
///
@@ -513,7 +513,7 @@
/// of the string up to that point.
///
/// let name = "Marie Curie"
-/// let firstSpace = name.index(of: " ") ?? name.endIndex
+/// let firstSpace = name.firstIndex(of: " ") ?? name.endIndex
/// let firstName = name[..<firstSpace]
/// print(firstName)
/// // Prints "Marie"
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index 263bb63..6c5e87c 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -52,7 +52,7 @@
/// using the `String` type's `init(_:)` initializer.
///
/// let name = "Marie Curie"
- /// if let firstSpace = name.characters.index(of: " ") {
+ /// if let firstSpace = name.characters.firstIndex(of: " ") {
/// let firstName = String(name.characters[..<firstSpace])
/// print(firstName)
/// }
@@ -121,7 +121,7 @@
/// var str = "All this happened, more or less."
/// let afterSpace = str.withMutableCharacters {
/// chars -> String.CharacterView in
- /// if let i = chars.index(of: " ") {
+ /// if let i = chars.firstIndex(of: " ") {
/// let result = chars[chars.index(after: i)...]
/// chars.removeSubrange(i...)
/// return result
@@ -274,7 +274,7 @@
/// letter and then prints the character at the found index:
///
/// let greeting = "Hello, friend!"
- /// if let i = greeting.characters.index(where: { "A"..."Z" ~= $0 }) {
+ /// if let i = greeting.characters.firstIndex(where: { "A"..."Z" ~= $0 }) {
/// print("First capital letter: \(greeting.characters[i])")
/// }
/// // Prints "First capital letter: H"
@@ -361,7 +361,7 @@
/// not including, the first comma (`","`) in the string.
///
/// let str = "All this happened, more or less."
- /// let i = str.characters.index(of: ",")!
+ /// let i = str.characters.firstIndex(of: ",")!
/// let substring = str.characters[str.characters.startIndex ..< i]
/// print(String(substring))
/// // Prints "All this happened"
diff --git a/stdlib/public/core/StringIndexConversions.swift b/stdlib/public/core/StringIndexConversions.swift
index abba2a7..15b5a47 100644
--- a/stdlib/public/core/StringIndexConversions.swift
+++ b/stdlib/public/core/StringIndexConversions.swift
@@ -26,7 +26,7 @@
/// print(cafe)
/// // Prints "Café"
///
- /// let scalarsIndex = cafe.unicodeScalars.index(of: "e")!
+ /// let scalarsIndex = cafe.unicodeScalars.firstIndex(of: "e")!
/// let stringIndex = String.Index(scalarsIndex, within: cafe)!
///
/// print(cafe[...stringIndex])
@@ -67,7 +67,7 @@
/// uses this method find the same position in the string's `utf8` view.
///
/// let cafe = "Café"
- /// if let i = cafe.index(of: "é") {
+ /// if let i = cafe.firstIndex(of: "é") {
/// let j = i.samePosition(in: cafe.utf8)!
/// print(Array(cafe.utf8[j...]))
/// }
@@ -96,7 +96,7 @@
/// uses this method find the same position in the string's `utf16` view.
///
/// let cafe = "Café"
- /// if let i = cafe.index(of: "é") {
+ /// if let i = cafe.firstIndex(of: "é") {
/// let j = i.samePosition(in: cafe.utf16)!
/// print(cafe.utf16[j])
/// }
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift b/stdlib/public/core/StringRangeReplaceableCollection.swift
index 1d6edc2..80e4780 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift
@@ -258,9 +258,9 @@
/// For example, this code finds the first letter after the first space:
///
/// let str = "Greetings, friend! How are you?"
- /// let firstSpace = str.index(of: " ") ?? str.endIndex
+ /// let firstSpace = str.firstIndex(of: " ") ?? str.endIndex
/// let substr = str[firstSpace...]
- /// if let nextCapital = substr.index(where: { $0 >= "A" && $0 <= "Z" }) {
+ /// if let nextCapital = substr.firstIndex(where: { $0 >= "A" && $0 <= "Z" }) {
/// print("Capital after a space: \(str[nextCapital])")
/// }
/// // Prints "Capital after a space: H"
@@ -436,7 +436,7 @@
/// removes the hyphen from the middle of a string.
///
/// var nonempty = "non-empty"
- /// if let i = nonempty.index(of: "-") {
+ /// if let i = nonempty.firstIndex(of: "-") {
/// nonempty.remove(at: i)
/// }
/// print(nonempty)
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index 2713ada..e99d7b7 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -55,7 +55,7 @@
/// `String` type's `init(_:)` initializer.
///
/// let favemoji = "My favorite emoji is 🎉"
- /// if let i = favemoji.utf16.index(where: { $0 >= 128 }) {
+ /// if let i = favemoji.utf16.firstIndex(where: { $0 >= 128 }) {
/// let asciiPrefix = String(favemoji.utf16[..<i])
/// print(asciiPrefix)
/// }
@@ -303,7 +303,7 @@
/// another string's `utf16` view.
///
/// let picnicGuest = "Deserving porcupine"
- /// if let i = picnicGuest.utf16.index(of: 32) {
+ /// if let i = picnicGuest.utf16.firstIndex(of: 32) {
/// let adjective = String(picnicGuest.utf16[..<i])
/// print(adjective)
/// }
@@ -379,7 +379,7 @@
///
/// let cafe = "Café 🍵"
///
- /// let stringIndex = cafe.index(of: "é")!
+ /// let stringIndex = cafe.firstIndex(of: "é")!
/// let utf16Index = String.Index(stringIndex, within: cafe.utf16)!
///
/// print(cafe.utf16[...utf16Index])
@@ -407,7 +407,7 @@
/// position in the string's `unicodeScalars` view.
///
/// let cafe = "Café 🍵"
- /// let i = cafe.utf16.index(of: 32)!
+ /// let i = cafe.utf16.firstIndex(of: 32)!
/// let j = i.samePosition(in: cafe.unicodeScalars)!
/// print(cafe.unicodeScalars[..<j])
/// // Prints "Café"
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index b523234..b7db7e3 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -390,7 +390,7 @@
/// another string's `utf8` view.
///
/// let picnicGuest = "Deserving porcupine"
- /// if let i = picnicGuest.utf8.index(of: 32) {
+ /// if let i = picnicGuest.utf8.firstIndex(of: 32) {
/// let adjective = String(picnicGuest.utf8[..<i])
/// print(adjective)
/// }
@@ -583,7 +583,7 @@
///
/// let cafe = "Café 🍵"
///
- /// let utf16Index = cafe.utf16.index(of: 32)!
+ /// let utf16Index = cafe.utf16.firstIndex(of: 32)!
/// let utf8Index = String.UTF8View.Index(utf16Index, within: cafe.utf8)!
///
/// print(Array(cafe.utf8[..<utf8Index]))
diff --git a/stdlib/public/core/StringUnicodeScalarView.swift b/stdlib/public/core/StringUnicodeScalarView.swift
index 10e6d37..18c7e52 100644
--- a/stdlib/public/core/StringUnicodeScalarView.swift
+++ b/stdlib/public/core/StringUnicodeScalarView.swift
@@ -52,7 +52,7 @@
/// using the `String` type's `init(_:)` initializer.
///
/// let favemoji = "My favorite emoji is 🎉"
- /// if let i = favemoji.unicodeScalars.index(where: { $0.value >= 128 }) {
+ /// if let i = favemoji.unicodeScalars.firstIndex(where: { $0.value >= 128 }) {
/// let asciiPrefix = String(favemoji.unicodeScalars[..<i])
/// print(asciiPrefix)
/// }
@@ -156,7 +156,7 @@
/// at the found index:
///
/// let greeting = "Hello, friend!"
- /// if let i = greeting.unicodeScalars.index(where: { "A"..."Z" ~= $0 }) {
+ /// if let i = greeting.unicodeScalars.firstIndex(where: { "A"..."Z" ~= $0 }) {
/// print("First capital letter: \(greeting.unicodeScalars[i])")
/// print("Unicode scalar value: \(greeting.unicodeScalars[i].value)")
/// }
@@ -277,7 +277,7 @@
/// another string's `unicodeScalars` view.
///
/// let picnicGuest = "Deserving porcupine"
- /// if let i = picnicGuest.unicodeScalars.index(of: " ") {
+ /// if let i = picnicGuest.unicodeScalars.firstIndex(of: " ") {
/// let adjective = String(picnicGuest.unicodeScalars[..<i])
/// print(adjective)
/// }
@@ -474,7 +474,7 @@
///
/// let cafe = "Café 🍵"
///
- /// let utf16Index = cafe.utf16.index(of: 32)!
+ /// let utf16Index = cafe.utf16.firstIndex(of: 32)!
/// let scalarIndex = String.Index(utf16Index, within: cafe.unicodeScalars)!
///
/// print(String(cafe.unicodeScalars[..<scalarIndex]))
@@ -507,7 +507,7 @@
/// in the string.
///
/// let cafe = "Café 🍵"
- /// let i = cafe.unicodeScalars.index(of: "🍵")
+ /// let i = cafe.unicodeScalars.firstIndex(of: "🍵")
/// let j = i.samePosition(in: cafe)!
/// print(cafe[j...])
/// // Prints "🍵"
@@ -625,7 +625,7 @@
/// to, but not including, the first comma (`","`) in the string.
///
/// let str = "All this happened, more or less."
- /// let i = str.unicodeScalars.index(of: ",")!
+ /// let i = str.unicodeScalars.firstIndex(of: ",")!
/// let substring = str.unicodeScalars[str.unicodeScalars.startIndex ..< i]
/// print(String(substring))
/// // Prints "All this happened"
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 2bb2f06..b619c94 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -37,7 +37,7 @@
/// substring of the first sentence:
///
/// let greeting = "Hi there! It's nice to meet you! 👋"
-/// let endOfSentence = greeting.index(of: "!")!
+/// let endOfSentence = greeting.firstIndex(of: "!")!
/// let firstSentence = greeting[...endOfSentence]
/// // firstSentence == "Hi there!"
///
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index bc4fe72..d5fa9a6 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -295,7 +295,7 @@
/// let streetSlice = buffer[2..<buffer.endIndex]
/// print(Array(streetSlice))
/// // Prints "["Channing", "Douglas", "Evarts"]"
- /// let index = streetSlice.index(of: "Evarts") // 4
+ /// let index = streetSlice.firstIndex(of: "Evarts") // 4
/// buffer[index!] = "Eustace"
/// }
/// print(streets.last!)
@@ -306,7 +306,7 @@
/// let streetSlice = buffer[2..<buffer.endIndex]
/// print(Array(streetSlice))
/// // Prints "["Channing", "Douglas", "Evarts"]"
- /// let index = streetSlice.index(of: "Evarts") // 4
+ /// let index = streetSlice.firstIndex(of: "Evarts") // 4
/// print(buffer[index!])
/// // Prints "Evarts"
/// }
diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp
index 0c7dc3e..c578e82 100644
--- a/stdlib/public/runtime/Exclusivity.cpp
+++ b/stdlib/public/runtime/Exclusivity.cpp
@@ -260,6 +260,16 @@
swift_runtime_unreachable("access not found in set");
}
+
+#ifndef NDEBUG
+ /// Only available with asserts. Intended to be used with
+ /// swift_dumpTrackedAccess().
+ void forEach(std::function<void (Access *)> action) {
+ for (auto *iter = Head; iter != nullptr; iter = iter->getNext()) {
+ action(iter);
+ }
+ }
+#endif
};
} // end anonymous namespace
@@ -348,3 +358,17 @@
getAccessSet().remove(access);
}
+
+#ifndef NDEBUG
+
+// Dump the accesses that are currently being tracked by the runtime.
+//
+// This is only intended to be used in the debugger.
+void swift::swift_dumpTrackedAccesses() {
+ getAccessSet().forEach([](Access *a) {
+ fprintf(stderr, "Access. Pointer: %p. PC: %p. AccessAction: %s",
+ a->Pointer, a->PC, getAccessName(a->getAccessAction()));
+ });
+}
+
+#endif
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 4bedefe..227399e 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -263,7 +263,8 @@
}
static const TypeContextDescriptor *
-_findNominalTypeDescriptor(Demangle::NodePointer node) {
+_findNominalTypeDescriptor(Demangle::NodePointer node,
+ Demangle::Demangler &Dem) {
const TypeContextDescriptor *foundNominal = nullptr;
auto &T = TypeMetadataRecords.get();
@@ -275,7 +276,13 @@
return cast<TypeContextDescriptor>(
(const ContextDescriptor *)symbolicNode->getIndex());
- auto mangledName = Demangle::mangleNode(node);
+ auto mangledName =
+ Demangle::mangleNode(node,
+ [&](const void *context) -> NodePointer {
+ return _buildDemanglingForContext(
+ (const ContextDescriptor *) context,
+ {}, false, Dem);
+ });
// Look for an existing entry.
// Find the bucket for the metadata entry.
@@ -696,7 +703,7 @@
#endif
// Look for a nominal type descriptor based on its mangled name.
- return _findNominalTypeDescriptor(node);
+ return _findNominalTypeDescriptor(node, demangler);
}
BuiltProtocolDecl createProtocolDecl(
diff --git a/test/ClangImporter/objc_parse.swift b/test/ClangImporter/objc_parse.swift
index 16f2d2d..cd1a7cb 100644
--- a/test/ClangImporter/objc_parse.swift
+++ b/test/ClangImporter/objc_parse.swift
@@ -509,8 +509,7 @@
}
class IncompleteProtocolAdopter : Incomplete, IncompleteOptional { // expected-error {{type 'IncompleteProtocolAdopter' cannot conform to protocol 'Incomplete' because it has requirements that cannot be satisfied}}
- // expected-error@-1{{type 'IncompleteProtocolAdopter' does not conform to protocol 'Incomplete'}}
- @objc func getObject() -> AnyObject { return self } // expected-note{{candidate has non-matching type '() -> AnyObject'}}
+ @objc func getObject() -> AnyObject { return self }
}
func testNullarySelectorPieces(_ obj: AnyObject) {
diff --git a/test/Compatibility/exhaustive_switch.swift b/test/Compatibility/exhaustive_switch.swift
index a3d3e57..8accf91 100644
--- a/test/Compatibility/exhaustive_switch.swift
+++ b/test/Compatibility/exhaustive_switch.swift
@@ -1,5 +1,5 @@
-// RUN: %target-typecheck-verify-swift -swift-version 3 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
-// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
+// RUN: %target-typecheck-verify-swift -swift-version 3 -enable-resilience
+// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-resilience
func foo(a: Int?, b: Int?) -> Int {
switch (a, b) {
@@ -543,7 +543,7 @@
}
// Make sure we haven't just stopped emitting diagnostics.
- switch OverlyLargeSpaceEnum.case1 { // expected-error {{switch must be exhaustive}} expected-note 12 {{add missing case}} expected-note {{handle unknown values}}
+ switch OverlyLargeSpaceEnum.case1 { // expected-error {{switch must be exhaustive}} expected-note 12 {{add missing case}}
}
}
@@ -840,11 +840,11 @@
// case.
@inlinable
public func testNonExhaustive(_ value: NonExhaustive, _ payload: NonExhaustivePayload, for interval: TemporalProxy, flag: Bool) {
- switch value { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b'}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{none}}
+ switch value { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b'}} {{none}}
case .a: break
}
- switch value { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+ switch value { // no-warning
case .a: break
case .b: break
}
@@ -876,7 +876,7 @@
}
// Test being part of other spaces.
- switch value as Optional { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.some(_)'}}
+ switch value as Optional { // no-warning
case .a?: break
case .b?: break
case nil: break
@@ -894,7 +894,7 @@
@unknown case _: break
} // no-warning
- switch (value, flag) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, false)'}}
+ switch (value, flag) { // no-warning
case (.a, _): break
case (.b, false): break
case (_, true): break
@@ -907,7 +907,7 @@
@unknown case _: break
} // no-warning
- switch (flag, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(false, _)'}}
+ switch (flag, value) { // no-warning
case (_, .a): break
case (false, .b): break
case (true, _): break
@@ -920,7 +920,7 @@
@unknown case _: break
} // no-warning
- switch (value, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, _)'}}
+ switch (value, value) { // no-warning
case (.a, _), (_, .a): break
case (.b, _), (_, .b): break
}
@@ -932,21 +932,13 @@
} // no-warning
// Test interaction with @_downgrade_exhaustivity_check.
- switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
- // expected-note@-1 {{add missing case: '(_, .milliseconds(_))'}}
- // expected-note@-2 {{add missing case: '(_, .microseconds(_))'}}
- // expected-note@-3 {{add missing case: '(_, .nanoseconds(_))'}}
- // expected-note@-4 {{add missing case: '(_, .never)'}}
+ switch (value, interval) { // no-warning
case (_, .seconds): break
case (.a, _): break
case (.b, _): break
}
- switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
- // expected-note@-1 {{add missing case: '(_, .seconds(_))'}}
- // expected-note@-2 {{add missing case: '(_, .milliseconds(_))'}}
- // expected-note@-3 {{add missing case: '(_, .microseconds(_))'}}
- // expected-note@-4 {{add missing case: '(_, .nanoseconds(_))'}}
+ switch (value, interval) { // no-warning
case (_, .never): break
case (.a, _): break
case (.b, _): break
@@ -954,11 +946,11 @@
// Test payloaded enums.
- switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(_)'}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{none}}
+ switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(_)'}} {{none}}
case .a: break
}
- switch payload { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+ switch payload { // no-warning
case .a: break
case .b: break
}
@@ -980,7 +972,7 @@
@unknown case _: break
}
- switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(true)'}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{none}}
+ switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(true)'}} {{none}}
case .a: break
case .b(false): break
}
diff --git a/test/Compatibility/ownership_protocol.swift b/test/Compatibility/ownership_protocol.swift
index 4fbfa6c..c8f62b7 100644
--- a/test/Compatibility/ownership_protocol.swift
+++ b/test/Compatibility/ownership_protocol.swift
@@ -4,9 +4,15 @@
class SomeClass {}
protocol P {
- weak var foo: SomeClass? { get set } // expected-warning {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
- unowned var foo2: SomeClass { get set } // expected-warning {{'unowned' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
- weak var foo3: Int? { get set } // expected-error {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
- unowned var foo4: Int { get set } // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+ // expected-warning@+1 {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+ weak var foo: SomeClass? { get set }
+ // expected-warning@+1 {{'unowned' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+ unowned var foo2: SomeClass { get set }
+ // expected-warning@+2 {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+ // expected-error@+1 {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
+ weak var foo3: Int? { get set }
+ // expected-warning@+2 {{'unowned' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+ // expected-error@+1 {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+ unowned var foo4: Int { get set }
}
diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift
index b6af7f8..752e33a 100644
--- a/test/Constraints/members.swift
+++ b/test/Constraints/members.swift
@@ -463,3 +463,6 @@
}
}
}
+
+// rdar://problem/39514009 - don't crash when trying to diagnose members with special names
+print("hello")[0] // expected-error {{value of tuple type '()' has no member 'subscript'}}
diff --git a/test/Driver/batch_mode_with_WMO_or_index.swift b/test/Driver/batch_mode_with_WMO_or_index.swift
index 2c2462a..92ec9e9 100644
--- a/test/Driver/batch_mode_with_WMO_or_index.swift
+++ b/test/Driver/batch_mode_with_WMO_or_index.swift
@@ -13,6 +13,18 @@
// RUN: %FileCheck -check-prefix CHECK-INDEX %s <%t/stderr_batch_index
// CHECK-INDEX: warning: ignoring '-enable-batch-mode' because '-index-file' was also specified
//
+// The following test is verifying that -disable-batch-mode overrides an earlier
+// -enable-batch-mode and silences the warning about mixing batch mode with
+// -index-file. Tools that take an existing command line and add -index-file can
+// thus add -disable-batch-mode without having to otherwise interpret the
+// arguments.
+//
+// RUN: %swiftc_driver -disable-batch-mode -index-file %S/../Inputs/empty.swift -### 2>%t/stderr_nobatch_index | %FileCheck %s
+// RUN: %swiftc_driver -enable-batch-mode -index-file %S/../Inputs/empty.swift -disable-batch-mode -### 2>%t/stderr_batch_nobatch_index | %FileCheck %s
+// RUN: %FileCheck -allow-empty -check-prefix CHECK-INDEX-DISABLED %s <%t/stderr_nobatch_index
+// RUN: %FileCheck -allow-empty -check-prefix CHECK-INDEX-DISABLED %s <%t/stderr_batch_nobatch_index
+// CHECK-INDEX-DISABLED-NOT: warning
+//
// This next one is a regression test for a specific failure in the past: wmo +
// batch mode should not just result in wmo, but also preserve the num-threads
// argument and (crucially) the resulting fact that the single wmo subprocess
diff --git a/test/Driver/createCompilerInvocation.swift b/test/Driver/createCompilerInvocation.swift
index 5dc6fcb..0151cd7 100644
--- a/test/Driver/createCompilerInvocation.swift
+++ b/test/Driver/createCompilerInvocation.swift
@@ -3,5 +3,7 @@
// RUN: %swift-ide-test_plain -test-createCompilerInvocation -c %s %S/Input/main.swift %S/Input/lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header 2>&1
// RUN: not %swift-ide-test_plain -test-createCompilerInvocation -typecheck %s -emit-module-path %t.swiftmodule 2>&1 | %FileCheck --check-prefix=CHECK-FAIL %s
// RUN: not %swift-ide-test_plain -test-createCompilerInvocation -v 2>&1 | %FileCheck --check-prefix=CHECK-FAIL %s
+// RUN: %swift-ide-test_plain -test-createCompilerInvocation %s -enable-batch-mode 2>&1 | %FileCheck -allow-empty -check-prefix=CHECK-NOWARN %s
// CHECK-FAIL: error: unable to create a CompilerInvocation
+// CHECK-NOWARN-NOT: warning
diff --git a/test/Driver/options.swift b/test/Driver/options.swift
index e9807c4..91d5d4c 100644
--- a/test/Driver/options.swift
+++ b/test/Driver/options.swift
@@ -129,3 +129,7 @@
// RUN: %swiftc_driver -driver-print-jobs -assume-single-threaded %s | %FileCheck -check-prefix=ASSUME_SINGLE_THREADED %s
// ASSUME_SINGLE_THREADED: swift
// ASSUME_SINGLE_THREADED: -frontend {{.*}} -assume-single-threaded
+
+// RUN: not %swiftc_driver -incremental -autolink-force-load %s 2>&1 | %FileCheck -check-prefix=AUTOLINK_FORCE_LOAD %s
+// RUN: not %swiftc_driver -autolink-force-load -incremental %s 2>&1 | %FileCheck -check-prefix=AUTOLINK_FORCE_LOAD %s
+// AUTOLINK_FORCE_LOAD: error: '-autolink-force-load' is not supported with '-incremental'
diff --git a/test/IDE/complete_from_stdlib.swift b/test/IDE/complete_from_stdlib.swift
index 561fbde..ecaea90 100644
--- a/test/IDE/complete_from_stdlib.swift
+++ b/test/IDE/complete_from_stdlib.swift
@@ -93,7 +93,7 @@
// PRIVATE_NOMINAL_MEMBERS_2A: Begin completions
// PRIVATE_NOMINAL_MEMBERS_2A-DAG: map({#(transform): (C.Element) throws -> T##(C.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
// PRIVATE_NOMINAL_MEMBERS_2A: End completions
-// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2A-NOT: Decl{{.*}}: last
+// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2A-NOT: Decl{{.*}}: index({#before: Comparable#})
func protocolExtCollection1b(_ a: Collection) {
a.#^PRIVATE_NOMINAL_MEMBERS_2B^#
@@ -102,7 +102,7 @@
// PRIVATE_NOMINAL_MEMBERS_2B: Begin completions
// PRIVATE_NOMINAL_MEMBERS_2B-DAG: map({#(transform): (Collection.Element) throws -> T##(Collection.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
// PRIVATE_NOMINAL_MEMBERS_2B: End completions
-// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2B-NOT: Decl{{.*}}: last
+// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2B-NOT: Decl{{.*}}: index({#before: Comparable#})
func protocolExtCollection2<C : Collection where C.Index : BidirectionalIndex>(_ a: C) {
a.#^PRIVATE_NOMINAL_MEMBERS_3^#
@@ -111,9 +111,9 @@
// PRIVATE_NOMINAL_MEMBERS_3: Begin completions
// PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceMethod]/Super: map({#(transform): (C.Element) throws -> T##(C.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
// PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceVar]/Super: lazy[#LazySequence<Collection>#]{{; name=.+}}
-// PRIVATE_NOMINAL_MEMBERS_3-DAG: index({#where: (C.Element) throws -> Bool##(C.Element) throws -> Bool#})[' rethrows'][#Comparable?#]{{; name=.+}}
+// PRIVATE_NOMINAL_MEMBERS_3-DAG: firstIndex({#where: (C.Element) throws -> Bool##(C.Element) throws -> Bool#})[' rethrows'][#Comparable?#]{{; name=.+}}
// PRIVATE_NOMINAL_MEMBERS_3: End completions
-// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_3-NOT: Decl{{.*}}: index({#({{.*}}): Self.Iterator.Element
+// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_3-NOT: Decl{{.*}}: firstIndex({#({{.*}}): Self.Iterator.Element
func protocolExtArray<T : Equatable>(_ a: [T]) {
a.#^PRIVATE_NOMINAL_MEMBERS_4^#
@@ -121,8 +121,8 @@
// PRIVATE_NOMINAL_MEMBERS_4: Begin completions
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super: map({#(transform): (Equatable) throws -> T##(Equatable) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceVar]/Super: last[#Equatable?#]{{; name=.+}}
-// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super: index({#of: Equatable#})[#Int?#]{{; name=.+}}
-// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super: index({#where: (Equatable) throws -> Bool##(Equatable) throws -> Bool#})[' rethrows'][#Int?#]{{; name=.+}}
+// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super: firstIndex({#of: Equatable#})[#Int?#]{{; name=.+}}
+// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super: firstIndex({#where: (Equatable) throws -> Bool##(Equatable) throws -> Bool#})[' rethrows'][#Int?#]{{; name=.+}}
// PRIVATE_NOMINAL_MEMBERS_4: End completions
func testArchetypeReplacement1<FOO : Equatable>(_ a: [FOO]) {
diff --git a/test/IRGen/big_types_corner_cases.swift b/test/IRGen/big_types_corner_cases.swift
index 2cce0b7..d716d41 100644
--- a/test/IRGen/big_types_corner_cases.swift
+++ b/test/IRGen/big_types_corner_cases.swift
@@ -208,7 +208,7 @@
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$SSayy22big_types_corner_cases9BigStructVcSgGMa"
// CHECK: [[CALL1:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[CALL2:%.*]] = call i8** @"$SSayy22big_types_corner_cases9BigStructVcSgGSayxGs10CollectionsWl
-// CHECK: call swiftcc void @"$Ss10CollectionPsE5index5where5IndexQzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegnr_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIggdzo_ACytIegnr_SgSbsAE_pIegndzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
+// CHECK: call swiftcc void @"$Ss10CollectionPsE10firstIndex5where0C0QzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegnr_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIggdzo_ACytIegnr_SgSbsAE_pIegndzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
// CHECK: ret void
// CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases7TestBigC5test2yyF"(%T22big_types_corner_cases7TestBigC* swiftself)
@@ -222,7 +222,7 @@
func test() {
let arr = [Handler?]()
- let d = arr.index(where: { _ in true })
+ let d = arr.firstIndex(where: { _ in true })
}
func test2() {
diff --git a/test/IRGen/coverage.swift b/test/IRGen/coverage.swift
deleted file mode 100644
index aaac44a..0000000
--- a/test/IRGen/coverage.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-sil -o - | %FileCheck %s --check-prefix=SIL
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-ir -o - | %FileCheck %s --check-prefix=IR
-
-// IR-NOT: __llvm_coverage_names
-// IR-NOT: __profn
-
-// SIL-DAG: sil hidden @$S8coverage2f1yyF
-// SIL-DAG: string_literal utf8 "{{.*}}coverage.swift:{{.*}}$S8coverage2f1yyF"
-internal func f1() {}
-
-// SIL-DAG: sil private @$S8coverage2f233_[[F2HASH:[_a-zA-Z0-9]+]]
-// SIL-DAG: string_literal utf8 "{{.*}}coverage.swift:$S8coverage2f233_[[F2HASH]]"
-private func f2() {}
-
-// SIL-DAG: sil @$S8coverage2f3yyF
-// SIL-DAG: string_literal utf8 "$S8coverage2f3yyF"
-public func f3() {
- f1();
- f2();
-}
diff --git a/test/IRGen/outlined_copy_addr.swift b/test/IRGen/outlined_copy_addr.swift
index b68a57b..63f2356 100644
--- a/test/IRGen/outlined_copy_addr.swift
+++ b/test/IRGen/outlined_copy_addr.swift
@@ -37,7 +37,7 @@
var otherHelper: OtherInternal<T>? = nil
// CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S11outcopyaddr9MyPrivateVyACyxGxcfC"(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.P) {{.*}} {
- // CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* %self)
+ // CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* {{%.*}})
// CHECK: ret
init(_: T) { }
}
diff --git a/test/IRGen/preserve_exclusivity.swift b/test/IRGen/preserve_exclusivity.swift
new file mode 100644
index 0000000..119eea3
--- /dev/null
+++ b/test/IRGen/preserve_exclusivity.swift
@@ -0,0 +1,136 @@
+// RUN: %target-swift-frontend -parse-stdlib -emit-ir -Onone %s | %FileCheck --check-prefix=IR-Onone %s
+//
+// Check that access markers in @_semantics("optimize.sil.preserve_exclusivity") functions generate runtime calls.
+
+// RUN: %target-swift-frontend -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-ir -O %s | %FileCheck --check-prefix=IR-O %s
+//
+// Check that the -O pipeline preserves the runtime calls for @_semantics("optimize.sil.preserve_exclusivity") functions.
+
+@_silgen_name("marker1")
+func marker1() -> ()
+
+@_silgen_name("marker2")
+func marker2() -> ()
+
+@_silgen_name("marker3")
+func marker3() -> ()
+
+@_silgen_name("marker4")
+func marker4() -> ()
+
+@_silgen_name("marker5")
+func marker5() -> ()
+
+@_silgen_name("marker6")
+func marker6() -> ()
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O: call void @swift_beginAccess
+// IR-O-NEXT: ret void
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker1()
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8endNoOptyyBpF"(i8*)
+// IR-Onone: call void @swift_endAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8endNoOptyyBpF"(i8*)
+// IR-O: call void @swift_endAccess
+// IR-O-NEXT: ret void
+@_semantics("optimize.sil.preserve_exclusivity")
+public func endNoOpt(_ address: Builtin.RawPointer) {
+ marker2()
+ Builtin.endUnpairedAccess(address)
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9readNoOptyyBp_xmtlF"(i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9readNoOptyyBp_xmtlF"(i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O: call void @swift_beginAccess
+// IR-O: ret void
+@_semantics("optimize.sil.preserve_exclusivity")
+public func readNoOpt<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker3()
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// Make sure testNoOpt properly inlines in our functions.
+//
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9testNoOptyyBpF"(i8*)
+// IR-O: call swiftcc void @marker1
+// IR-O: call void @swift_beginAccess
+// IR-O: call swiftcc void @marker2
+// IR-O: call void @swift_endAccess
+// IR-O: call swiftcc void @marker3
+// IR-O: call void @swift_beginAccess
+// IR-O: ret void
+public func testNoOpt(_ k1: Builtin.RawPointer) {
+ beginNoOpt(k1, k1, Builtin.RawPointer.self)
+ endNoOpt(k1)
+ readNoOpt(k1, Builtin.RawPointer.self)
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8beginOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8beginOptyyBp_BpxmtlF"(i8*{{.*}}, i8*{{.*}}, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O-NEXT: entry
+// IR-O-NEXT: call swiftcc void @marker4
+// IR-O-NEXT: ret void
+
+public func beginOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker4()
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity6endOptyyBpF"(i8*)
+// IR-Onone: call void @swift_endAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity6endOptyyBpF"(i8*{{.*}})
+// IR-O-NEXT: entry
+// IR-O-NEXT: call swiftcc void @marker5
+// IR-O-NEXT: ret void
+
+public func endOpt(_ address: Builtin.RawPointer) {
+ marker5()
+ Builtin.endUnpairedAccess(address)
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7readOptyyBp_xmtlF"(i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7readOptyyBp_xmtlF"(i8*{{.*}}, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O-NEXT: entry
+// IR-O-NEXT: call swiftcc void @marker6
+// IR-O-NEXT: ret void
+
+public func readOpt<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker6()
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// Make sure testOpt properly inlines in our functions.
+//
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7testOptyyBpF"(i8*{{.*}})
+// IR-O: call swiftcc void @marker4
+// IR-O: call swiftcc void @marker5
+// IR-O: call swiftcc void @marker6
+// IR-O: ret void
+public func testOpt(_ k1: Builtin.RawPointer) {
+ beginOpt(k1, k1, Builtin.RawPointer.self)
+ endOpt(k1)
+ readOpt(k1, Builtin.RawPointer.self)
+}
diff --git a/test/Interpreter/SDK/Foundation_test.swift b/test/Interpreter/SDK/Foundation_test.swift
index f41b2a3..e43b844 100644
--- a/test/Interpreter/SDK/Foundation_test.swift
+++ b/test/Interpreter/SDK/Foundation_test.swift
@@ -163,8 +163,8 @@
expectEqual("{0, 5}", NSStringFromRange(nsrFromPartial))
let s = "Hello, 🌎!"
- let b = s.index(of: ",")!
- let e = s.index(of: "!")!
+ let b = s.firstIndex(of: ",")!
+ let e = s.firstIndex(of: "!")!
let nsr = NSRange(b..<e, in: s)
expectEqual(nsr.location, 5)
expectEqual(nsr.length, 4)
diff --git a/test/Interpreter/SDK/equatable_hashable.swift b/test/Interpreter/SDK/equatable_hashable.swift
index 1a4d700..c99f7ce 100644
--- a/test/Interpreter/SDK/equatable_hashable.swift
+++ b/test/Interpreter/SDK/equatable_hashable.swift
@@ -32,7 +32,7 @@
func test_Equatable() {
// CHECK-NEXT: Found 2.5 at index 1
let array: [NSNumber] = [1, 2.5, 3.14159]
- if let index = array.index(of: 2.5) {
+ if let index = array.firstIndex(of: 2.5) {
print("Found \(array[index]) at index \(index)")
} else {
print("Did not find 2.5?")
diff --git a/test/Interpreter/enforce_exclusive_access.swift b/test/Interpreter/enforce_exclusive_access.swift
index fe4e811..4b34899 100644
--- a/test/Interpreter/enforce_exclusive_access.swift
+++ b/test/Interpreter/enforce_exclusive_access.swift
@@ -241,26 +241,95 @@
}
class ClassWithStoredProperty {
- var f = 7
+ final var f = 7
}
-// FIXME: This should trap with a modify/modify violation at run time.
-ExclusiveAccessTestSuite.test("KeyPathClassStoredProp")
+ExclusiveAccessTestSuite.test("KeyPathInoutDirectWriteClassStoredProp")
.skip(.custom(
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
-// .crashOutputMatches("Previous access (a modification) started at")
-// .crashOutputMatches("Current access (a modification) started at")
+ .crashOutputMatches("Previous access (a modification) started at")
+ .crashOutputMatches("Current access (a modification) started at")
.code
{
let getF = \ClassWithStoredProperty.f
let c = ClassWithStoredProperty()
-// expectCrashLater()
+ expectCrashLater()
+ modifyAndPerform(&c[keyPath: getF]) {
+ c.f = 12
+ }
+}
+
+ExclusiveAccessTestSuite.test("KeyPathInoutDirectReadClassStoredProp")
+ .skip(.custom(
+ { _isFastAssertConfiguration() },
+ reason: "this trap is not guaranteed to happen in -Ounchecked"))
+ .crashOutputMatches("Previous access (a modification) started at")
+ .crashOutputMatches("Current access (a read) started at")
+ .code
+{
+ let getF = \ClassWithStoredProperty.f
+ let c = ClassWithStoredProperty()
+
+ expectCrashLater()
+ modifyAndPerform(&c[keyPath: getF]) {
+ let x = c.f
+ _blackHole(x)
+ }
+}
+
+// Unlike inout accesses, read-only inout-to-pointer conversions on key paths for
+// final stored-properties do not perform a long-term read access. Instead, they
+// materialize a location on the stack, perform an instantaneous read
+// from the storage indicated by the key path and write the read value to the
+// stack location. The stack location is then passed as the pointer for the
+// inout-to-pointer conversion.
+//
+// This means that there is no conflict between a read-only inout-to-pointer
+// conversion of the key path location for a call and an access to the
+// the same location within the call.
+ExclusiveAccessTestSuite.test("KeyPathReadOnlyInoutToPtrDirectWriteClassStoredProp") {
+ let getF = \ClassWithStoredProperty.f
+ let c = ClassWithStoredProperty()
+
+ // This performs an instantaneous read
+ readAndPerform(&c[keyPath: getF]) {
+ c.f = 12 // no-trap
+ }
+}
+
+ExclusiveAccessTestSuite.test("SequentialKeyPathWritesDontOverlap") {
+ let getF = \ClassWithStoredProperty.f
+ let c = ClassWithStoredProperty()
+
+ c[keyPath: getF] = 7
+ c[keyPath: getF] = 8 // no-trap
+ c[keyPath: getF] += c[keyPath: getF] + 1 // no-trap
+}
+
+// This does not trap, for now, because the standard library (and thus KeyPath) is
+// compiled in Swift 3 mode and we currently log rather than trap in Swift mode.
+ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathWriteClassStoredProp")
+{
+ let getF = \ClassWithStoredProperty.f
+ let c = ClassWithStoredProperty()
+
modifyAndPerform(&c[keyPath: getF]) {
c[keyPath: getF] = 12
}
}
+// This does not currently trap because the standard library is compiled in Swift 3 mode,
+// which logs.
+ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathReadClassStoredProp") {
+ let getF = \ClassWithStoredProperty.f
+ let c = ClassWithStoredProperty()
+
+ modifyAndPerform(&c[keyPath: getF]) {
+ let y = c[keyPath: getF]
+ _blackHole(y)
+ }
+}
runAllTests()
diff --git a/test/Interpreter/enforce_exclusive_access_backtrace.swift b/test/Interpreter/enforce_exclusive_access_backtrace.swift
index 3c9485f..b50b114 100644
--- a/test/Interpreter/enforce_exclusive_access_backtrace.swift
+++ b/test/Interpreter/enforce_exclusive_access_backtrace.swift
@@ -17,12 +17,18 @@
closure()
}
+func writeAndPerform<T>(_ _: UnsafeMutablePointer<T>, closure: () ->()) {
+ closure()
+}
+
var globalX = X()
withUnsafePointer(to: &globalX) { _ = fputs(String(format: "globalX: 0x%lx\n", Int(bitPattern: $0)), stderr) }
// CHECK: globalX: [[ADDR:0x.*]]
+fputs("Global Access\n", stderr);
readAndPerform(&globalX) {
globalX = X()
+ // CHECK-LABEL: Global Access
// CHECK: Simultaneous accesses to [[ADDR]], but modification requires exclusive access.
// CHECK: Previous access (a read) started at a.out`main + {{.*}} (0x{{.*}}).
// CHECK: Current access (a modification) started at:
@@ -30,3 +36,42 @@
// CHECK: a.out {{.*}} readAndPerform
// CHECK: a.out {{.*}} main
}
+
+class C {
+ final var f = 7
+}
+
+var c = C()
+withUnsafePointer(to: &c.f) { _ = fputs(String(format: "c.f: 0x%lx\n", Int(bitPattern: $0)), stderr) }
+// CHECK: c.f: [[C_F_ADDR:0x.*]]
+
+// Key path accesses are performed in the Standard Library. The Standard Library
+// is currently compiled in Swift 3 mode and the compiler currently logs conflicts
+// (rather than trapping on them) code compiled in Swift 3 mode. For this reason
+// conflicts where the second conflicting access is via a key path will log rather than
+// trap.
+
+fputs("Overlapping Key Path Write Accesses\n", stderr);
+writeAndPerform(&c[keyPath: \C.f]) {
+ c[keyPath: \C.f] = 8
+ // CHECK-LABEL: Overlapping Key Path Write Accesses
+ // CHECK: Simultaneous accesses to [[C_F_ADDR]], but modification requires exclusive access.
+ // CHECK: Previous access (a modification)
+ // CHECK: Current access (a modification)
+ // CHECK: a.out {{.*}} closure
+ // CHECK: a.out {{.*}} writeAndPerform
+ // CHECK: a.out {{.*}} main
+}
+
+fputs("Overlapping Key Path Write Access and Key Path Read Access\n", stderr);
+writeAndPerform(&c[keyPath: \C.f]) {
+ let x = c[keyPath: \C.f]
+ _blackHole(x)
+ // CHECK-LABEL: Overlapping Key Path Write Access and Key Path Read Access
+ // CHECK: Simultaneous accesses to [[C_F_ADDR]], but modification requires exclusive access.
+ // CHECK: Previous access (a modification)
+ // CHECK: Current access (a read)
+ // CHECK: a.out {{.*}} closure
+ // CHECK: a.out {{.*}} writeAndPerform
+ // CHECK: a.out {{.*}} main
+}
diff --git a/test/NameBinding/name_lookup_min_max_conditional_conformance.swift b/test/NameBinding/name_lookup_min_max_conditional_conformance.swift
new file mode 100644
index 0000000..c9847c5
--- /dev/null
+++ b/test/NameBinding/name_lookup_min_max_conditional_conformance.swift
@@ -0,0 +1,58 @@
+// RUN: %target-typecheck-verify-swift
+
+extension Range {
+ func f(_ value: Bound) -> Bound {
+ return max(lowerBound, min(value, upperBound))
+ // expected-warning@-1{{use of 'max' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Range' which comes via a conditional conformance}}
+ // expected-note@-2{{use 'Swift.' to continue to reference the global function}}
+ // expected-warning@-3{{use of 'min' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Range' which comes via a conditional conformance}}
+ // expected-note@-4{{use 'Swift.' to continue to reference the global function}}
+ }
+}
+
+protocol ContainsMinMax {}
+extension ContainsMinMax {
+ func max() {}
+ func min() {}
+}
+
+func foo(_: Int, _: Int) {}
+// expected-note@-1 {{'foo' declared here}}
+
+protocol ContainsFoo {}
+extension ContainsFoo {
+ func foo() {}
+}
+
+struct NonConditional: ContainsMinMax, ContainsFoo {}
+
+extension NonConditional {
+ func f() {
+ _ = max(1, 2)
+ // expected-error@-1{{use of 'max' refers to instance method}}
+ // expected-note@-2{{use 'Swift.' to reference the global function}}
+ _ = min(3, 4)
+ // expected-error@-1{{use of 'min' refers to instance method}}
+ // expected-note@-2{{use 'Swift.' to reference the global function}}
+ _ = foo(5, 6)
+ // expected-error@-1{{use of 'foo' refers to instance method}}
+ // expected-note@-2{{use 'name_lookup_min_max_conditional_conformance.' to reference the global function}}
+ }
+}
+
+struct Conditional<T> {}
+extension Conditional: ContainsMinMax where T: ContainsMinMax {}
+extension Conditional: ContainsFoo where T: ContainsFoo {}
+
+extension Conditional {
+ func f() {
+ _ = max(1, 2)
+ // expected-warning@-1{{use of 'max' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Conditional' which comes via a conditional conformance}}
+ // expected-note@-2{{use 'Swift.' to continue to reference the global function}}
+ _ = min(3, 4)
+ // expected-warning@-1{{use of 'min' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Conditional' which comes via a conditional conformance}}
+ // expected-note@-2{{use 'Swift.' to continue to reference the global function}}
+ _ = foo(5, 6)
+ // expected-error@-1{{type 'T' does not conform to protocol 'ContainsFoo'}}
+ }
+}
diff --git a/test/SILGen/Inputs/coverage_imports.swift b/test/Profiler/Inputs/coverage_imports.swift
similarity index 100%
rename from test/SILGen/Inputs/coverage_imports.swift
rename to test/Profiler/Inputs/coverage_imports.swift
diff --git a/test/SILGen/coverage_class.swift b/test/Profiler/coverage_class.swift
similarity index 100%
rename from test/SILGen/coverage_class.swift
rename to test/Profiler/coverage_class.swift
diff --git a/test/SILGen/coverage_closures.swift b/test/Profiler/coverage_closures.swift
similarity index 70%
rename from test/SILGen/coverage_closures.swift
rename to test/Profiler/coverage_closures.swift
index 6fdf8d9..255767d 100644
--- a/test/SILGen/coverage_closures.swift
+++ b/test/Profiler/coverage_closures.swift
@@ -1,4 +1,44 @@
-// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_closures %s | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sil -module-name coverage_closures %s | %FileCheck %s
+
+func bar(arr: [(Int32) -> Int32]) {
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32) -> Swift.Int32 in coverage_closures.bar
+// CHECK-NEXT: [[@LINE+1]]:13 -> [[@LINE+1]]:42 : 0
+ for a in [{ (b : Int32) -> Int32 in b }] {
+ a(0)
+ }
+}
+
+func foo() {
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+1]]:12 -> [[@LINE+1]]:59 : 0
+ let c1 = { (i1 : Int32, i2 : Int32) -> Bool in i1 < i2 }
+
+// CHECK-LABEL: sil_coverage_map {{.*}}// f1 #1 ((Swift.Int32, Swift.Int32) -> Swift.Bool) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+1]]:55 -> {{.*}}:4 : 0
+ func f1(_ closure : (Int32, Int32) -> Bool) -> Bool {
+// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> Swift.Bool in f1
+// CHECK-NEXT: [[@LINE+1]]:29 -> [[@LINE+1]]:42 : 0
+ return closure(0, 1) && closure(1, 0)
+ }
+
+ f1(c1)
+
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:27 : 0
+ f1 { i1, i2 in i1 > i2 }
+
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #3 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+3]]:6 -> [[@LINE+3]]:48 : 0
+// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> {{.*}} in coverage_closures.foo
+// CHECK-NEXT: [[@LINE+1]]:36 -> [[@LINE+1]]:46 : 0
+ f1 { left, right in left == 0 || right == 1 }
+}
+
+// SR-2615: Implicit constructor decl has no body, and shouldn't be mapped
+struct C1 {
+// CHECK-NOT: sil_coverage_map{{.*}}errors
+ private var errors = [String]()
+}
// rdar://39200851: Closure in init method covered twice
@@ -12,60 +52,3 @@
}
}
}
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_closures.bar
-// CHECK-NEXT: [[@LINE+9]]:35 -> [[@LINE+13]]:2 : 0
-// CHECK-NEXT: [[@LINE+9]]:44 -> [[@LINE+11]]:4 : 1
-// CHECK-NEXT: [[@LINE+10]]:4 -> [[@LINE+11]]:2 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32) -> Swift.Int32 in coverage_closures.bar
-// CHECK-NEXT: [[@LINE+4]]:13 -> [[@LINE+4]]:42 : 0
-// CHECK-NEXT: }
-
-func bar(arr: [(Int32) -> Int32]) {
- for a in [{ (b : Int32) -> Int32 in b }] {
- a(0)
- }
-}
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_closures.foo
-func foo() {
- let c1 = { (i1 : Int32, i2 : Int32) -> Bool in i1 < i2 }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// f1 #1 ((Swift.Int32, Swift.Int32) -> Swift.Bool) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE+5]]:55 -> [[@LINE+7]]:4 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> Swift.Bool in f1
-// CHECK-NEXT: [[@LINE+2]]:29 -> [[@LINE+2]]:42 : 0
- func f1(_ closure : (Int32, Int32) -> Bool) -> Bool {
- return closure(0, 1) && closure(1, 0)
- }
-
- f1(c1)
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:27 : 0
- f1 { i1, i2 in i1 > i2 }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #3 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE+5]]:6 -> [[@LINE+5]]:48 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> {{.*}} in coverage_closures.foo
-// CHECK-NEXT: [[@LINE+1]]:36 -> [[@LINE+1]]:46 : 0
- f1 { left, right in left == 0 || right == 1 }
-}
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE-27]]:12 -> [[@LINE-27]]:59 : 0
-
-// SR-2615: Implicit constructor decl has no body, and shouldn't be mapped
-struct C1 {
-// CHECK-NOT: sil_coverage_map{{.*}}errors
- private var errors = [String]()
-}
-
-bar(arr: [{ x in x }])
-foo()
-let _ = C2()
diff --git a/test/SILGen/coverage_curry.swift b/test/Profiler/coverage_curry.swift
similarity index 100%
rename from test/SILGen/coverage_curry.swift
rename to test/Profiler/coverage_curry.swift
diff --git a/test/SILGen/coverage_default_args.swift b/test/Profiler/coverage_default_args.swift
similarity index 100%
rename from test/SILGen/coverage_default_args.swift
rename to test/Profiler/coverage_default_args.swift
diff --git a/test/SILGen/coverage_deinit.swift b/test/Profiler/coverage_deinit.swift
similarity index 100%
rename from test/SILGen/coverage_deinit.swift
rename to test/Profiler/coverage_deinit.swift
diff --git a/test/SILGen/coverage_exceptions.swift b/test/Profiler/coverage_exceptions.swift
similarity index 100%
rename from test/SILGen/coverage_exceptions.swift
rename to test/Profiler/coverage_exceptions.swift
diff --git a/test/SILGen/coverage_force_emission.swift b/test/Profiler/coverage_force_emission.swift
similarity index 100%
rename from test/SILGen/coverage_force_emission.swift
rename to test/Profiler/coverage_force_emission.swift
diff --git a/test/SILGen/coverage_guard.swift b/test/Profiler/coverage_guard.swift
similarity index 100%
rename from test/SILGen/coverage_guard.swift
rename to test/Profiler/coverage_guard.swift
diff --git a/test/SILGen/coverage_if.swift b/test/Profiler/coverage_if.swift
similarity index 100%
rename from test/SILGen/coverage_if.swift
rename to test/Profiler/coverage_if.swift
diff --git a/test/Profiler/coverage_irgen.swift b/test/Profiler/coverage_irgen.swift
new file mode 100644
index 0000000..9360522
--- /dev/null
+++ b/test/Profiler/coverage_irgen.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-sil -o - -module-name=irgen | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-ir -o - -module-name=irgen | %FileCheck %s --check-prefix=IR
+
+// IR-NOT: __llvm_coverage_names
+// IR-NOT: __profn
+
+// SIL: sil hidden @$S5irgen2f1yyF
+// SIL: string_literal utf8 "{{.*}}coverage_irgen.swift:{{.*}}$S5irgen2f1yyF"
+internal func f1() {}
+
+// SIL: sil private @$S5irgen2f2[[F2HASH:[_a-zA-Z0-9]+]]
+// SIL: string_literal utf8 "{{.*}}coverage_irgen.swift:$S5irgen2f2[[F2HASH]]"
+private func f2() {}
+
+// SIL: sil @$S5irgen2f3yyF
+// SIL: string_literal utf8 "$S5irgen2f3yyF"
+public func f3() {
+ f1()
+ f2()
+}
diff --git a/test/IRGen/coverage_ignored.swift b/test/Profiler/coverage_irgen_ignored.swift
similarity index 100%
rename from test/IRGen/coverage_ignored.swift
rename to test/Profiler/coverage_irgen_ignored.swift
diff --git a/test/SILGen/coverage_label.swift b/test/Profiler/coverage_label.swift
similarity index 100%
rename from test/SILGen/coverage_label.swift
rename to test/Profiler/coverage_label.swift
diff --git a/test/SILGen/coverage_member_closure.swift b/test/Profiler/coverage_member_closure.swift
similarity index 100%
rename from test/SILGen/coverage_member_closure.swift
rename to test/Profiler/coverage_member_closure.swift
diff --git a/test/SILGen/coverage_nested_func.swift b/test/Profiler/coverage_nested_func.swift
similarity index 100%
rename from test/SILGen/coverage_nested_func.swift
rename to test/Profiler/coverage_nested_func.swift
diff --git a/test/Profiler/coverage_primary_file.swift b/test/Profiler/coverage_primary_file.swift
new file mode 100644
index 0000000..03b3faf
--- /dev/null
+++ b/test/Profiler/coverage_primary_file.swift
@@ -0,0 +1,27 @@
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_primary_file %s %S/Inputs/coverage_imports.swift | %FileCheck %s -check-prefix=ALL
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_primary_file -primary-file %s %S/Inputs/coverage_imports.swift | %FileCheck %s -check-prefix=PRIMARY
+
+// ALL: sil_coverage_map {{.*}} // closure #1 () -> Swift.Int in coverage_primary_file.Box.x.getter : Swift.Int
+// ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(y: Swift.Int) -> coverage_primary_file.Box
+// ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(z: Swift.String) -> coverage_primary_file.Box
+// ALL: sil_coverage_map {{.*}} // coverage_primary_file.main() -> ()
+// ALL: sil_coverage_map {{.*}} // __ntd_Box
+
+// PRIMARY-NOT: sil_coverage_map
+// PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(y: Swift.Int) -> coverage_primary_file.Box
+// PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(z: Swift.String) -> coverage_primary_file.Box
+// PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.main() -> ()
+// PRIMARY-NOT: sil_coverage_map
+
+extension Box {
+ init(y: Int) { self.init() }
+}
+
+extension Box {
+ init(z: String) { self.init() }
+}
+
+func main() {
+ var b = Box()
+ let _ = b.x
+}
diff --git a/test/SILGen/coverage_smoke.swift b/test/Profiler/coverage_smoke.swift
similarity index 100%
rename from test/SILGen/coverage_smoke.swift
rename to test/Profiler/coverage_smoke.swift
diff --git a/test/SILGen/coverage_switch.swift b/test/Profiler/coverage_switch.swift
similarity index 100%
rename from test/SILGen/coverage_switch.swift
rename to test/Profiler/coverage_switch.swift
diff --git a/test/SILGen/coverage_ternary.swift b/test/Profiler/coverage_ternary.swift
similarity index 100%
rename from test/SILGen/coverage_ternary.swift
rename to test/Profiler/coverage_ternary.swift
diff --git a/test/SILGen/coverage_toplevel.swift b/test/Profiler/coverage_toplevel.swift
similarity index 100%
rename from test/SILGen/coverage_toplevel.swift
rename to test/Profiler/coverage_toplevel.swift
diff --git a/test/SILGen/coverage_uikit.swift b/test/Profiler/coverage_uikit.swift
similarity index 100%
rename from test/SILGen/coverage_uikit.swift
rename to test/Profiler/coverage_uikit.swift
diff --git a/test/SILGen/coverage_var_init.swift b/test/Profiler/coverage_var_init.swift
similarity index 100%
rename from test/SILGen/coverage_var_init.swift
rename to test/Profiler/coverage_var_init.swift
diff --git a/test/SILGen/coverage_while.swift b/test/Profiler/coverage_while.swift
similarity index 100%
rename from test/SILGen/coverage_while.swift
rename to test/Profiler/coverage_while.swift
diff --git a/test/IRGen/coverage_with_asan.swift b/test/Profiler/coverage_with_asan.swift
similarity index 100%
rename from test/IRGen/coverage_with_asan.swift
rename to test/Profiler/coverage_with_asan.swift
diff --git a/test/SILGen/instrprof_basic.swift b/test/Profiler/instrprof_basic.swift
similarity index 100%
rename from test/SILGen/instrprof_basic.swift
rename to test/Profiler/instrprof_basic.swift
diff --git a/test/SILGen/instrprof_operators.swift b/test/Profiler/instrprof_operators.swift
similarity index 100%
rename from test/SILGen/instrprof_operators.swift
rename to test/Profiler/instrprof_operators.swift
diff --git a/test/SILGen/pgo_checked_cast.swift b/test/Profiler/pgo_checked_cast.swift
similarity index 100%
rename from test/SILGen/pgo_checked_cast.swift
rename to test/Profiler/pgo_checked_cast.swift
diff --git a/test/SILGen/pgo_foreach.swift b/test/Profiler/pgo_foreach.swift
similarity index 100%
rename from test/SILGen/pgo_foreach.swift
rename to test/Profiler/pgo_foreach.swift
diff --git a/test/SILGen/pgo_guard.swift b/test/Profiler/pgo_guard.swift
similarity index 100%
rename from test/SILGen/pgo_guard.swift
rename to test/Profiler/pgo_guard.swift
diff --git a/test/SILGen/pgo_if.swift b/test/Profiler/pgo_if.swift
similarity index 100%
rename from test/SILGen/pgo_if.swift
rename to test/Profiler/pgo_if.swift
diff --git a/test/SILGen/pgo_repeatwhile.swift b/test/Profiler/pgo_repeatwhile.swift
similarity index 100%
rename from test/SILGen/pgo_repeatwhile.swift
rename to test/Profiler/pgo_repeatwhile.swift
diff --git a/test/SILGen/pgo_switchenum.swift b/test/Profiler/pgo_switchenum.swift
similarity index 100%
rename from test/SILGen/pgo_switchenum.swift
rename to test/Profiler/pgo_switchenum.swift
diff --git a/test/SILGen/pgo_while.swift b/test/Profiler/pgo_while.swift
similarity index 100%
rename from test/SILGen/pgo_while.swift
rename to test/Profiler/pgo_while.swift
diff --git a/test/Prototypes/BigInt.swift b/test/Prototypes/BigInt.swift
index f042f99..ada80ab 100644
--- a/test/Prototypes/BigInt.swift
+++ b/test/Prototypes/BigInt.swift
@@ -712,7 +712,7 @@
return 0
}
- let i = _data.index(where: { $0 != 0 })!
+ let i = _data.firstIndex(where: { $0 != 0 })!
_sanityCheck(_data[i] != 0)
return i * Word.bitWidth + _data[i].trailingZeroBitCount
}
diff --git a/test/Prototypes/CollectionTransformers.swift b/test/Prototypes/CollectionTransformers.swift
index 55f5b5c..8027b26 100644
--- a/test/Prototypes/CollectionTransformers.swift
+++ b/test/Prototypes/CollectionTransformers.swift
@@ -680,7 +680,7 @@
_runningThreadsMutex.withLock {
_submissionQueuesMutex.withLock {
_workDequesMutex.withLock {
- let i = _runningThreads.index { $0 === thread }!
+ let i = _runningThreads.firstIndex { $0 === thread }!
ForkJoinPool._threadRegistry[thread._tid!] = nil
_runningThreads.remove(at: i)
_submissionQueues.remove(at: i)
diff --git a/test/Reflection/capture_descriptors.sil b/test/Reflection/capture_descriptors.sil
index 8e63021..4bb334c 100644
--- a/test/Reflection/capture_descriptors.sil
+++ b/test/Reflection/capture_descriptors.sil
@@ -41,8 +41,7 @@
// CHECK: - Capture types:
// CHECK-NEXT: (struct Swift.Int)
-// CHECK-NEXT: (sil_box
-// CHECK-NEXT: (struct Swift.Int))
+// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-NEXT: (existential_metatype
// CHECK-NEXT: (protocol_composition
// CHECK-NEXT: (protocol capture_descriptors.P)))
@@ -76,8 +75,7 @@
// CHECK: - Capture types:
// CHECK-NEXT: (struct Swift.Int)
-// CHECK-NEXT: (sil_box
-// CHECK-NEXT: (struct Swift.String))
+// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-NEXT: - Metadata sources:
diff --git a/test/Reflection/typeref_decoding.swift b/test/Reflection/typeref_decoding.swift
index 9ffcc80..6e8c0b8 100644
--- a/test/Reflection/typeref_decoding.swift
+++ b/test/Reflection/typeref_decoding.swift
@@ -708,8 +708,7 @@
// CHECK: CAPTURE DESCRIPTORS:
// CHECK: ====================
// CHECK: - Capture types:
-// CHECK: (sil_box
-// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (builtin Builtin.NativeObject)
// CHECK: - Metadata sources:
// CHECK: (generic_type_parameter depth=0 index=0)
// CHECK: (closure_binding index=0)
diff --git a/test/Reflection/typeref_decoding_asan.swift b/test/Reflection/typeref_decoding_asan.swift
index 3532397..9a40e21 100644
--- a/test/Reflection/typeref_decoding_asan.swift
+++ b/test/Reflection/typeref_decoding_asan.swift
@@ -708,8 +708,7 @@
// CHECK: CAPTURE DESCRIPTORS:
// CHECK: ====================
// CHECK: - Capture types:
-// CHECK: (sil_box
-// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (builtin Builtin.NativeObject)
// CHECK: - Metadata sources:
// CHECK: (generic_type_parameter depth=0 index=0)
// CHECK: (closure_binding index=0)
diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift
index 588c682..d8ef79f 100644
--- a/test/SILGen/builtins.swift
+++ b/test/SILGen/builtins.swift
@@ -370,31 +370,27 @@
}
// CHECK-LABEL: sil hidden @$S8builtins25beginUnpairedModifyAccess{{[_0-9a-zA-Z]*}}F
-// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
-// CHECK: [[P2A_SCRATCH:%.*]] = pointer_to_address %1
-// CHECK: begin_unpaired_access [modify] [dynamic] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
-// CHECK: [[RESULT:%.*]] = tuple ()
-// CHECK: [[RETURN:%.*]] = tuple ()
-// CHECK: return [[RETURN]] : $()
-// CHECK: } // end sil function '$S8builtins25beginUnpairedModifyAccess{{[_0-9a-zA-Z]*}}F'
func beginUnpairedModifyAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
+ // CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+ // CHECK: [[P2A_SCRATCH:%.*]] = pointer_to_address %1
+ // CHECK: begin_unpaired_access [modify] [dynamic] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
+ // CHECK: [[RESULT:%.*]] = tuple ()
+ // CHECK: [[RETURN:%.*]] = tuple ()
+ // CHECK: return [[RETURN]] : $()
+
Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
}
-// CHECK-LABEL: sil hidden @$S8builtins17endUnpairedAccess{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.RawPointer) -> () {
-// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
-// CHECK: end_unpaired_access [dynamic] [[P2A_ADDR]]
-// CHECK: } // end sil function '$S8builtins17endUnpairedAccess{{[_0-9a-zA-Z]*}}F'
-func endUnpairedAccess(address: Builtin.RawPointer) {
- Builtin.endUnpairedAccess(address)
-}
-
// CHECK-LABEL: sil hidden @$S8builtins30performInstantaneousReadAccess{{[_0-9a-zA-Z]*}}F
-// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
-// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P2A_ADDR]] : $*T1
-// CHECK-NEXT: end_access [[ACCESS]] : $*T1
-// CHECK: } // end sil function '$S8builtins30performInstantaneousReadAccess{{[_0-9a-zA-Z]*}}F'
func performInstantaneousReadAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
+ // CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+ // CHECK: [[SCRATCH:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+ // CHECK: begin_unpaired_access [read] [dynamic] [no_nested_conflict] [[P2A_ADDR]] : $*T1, [[SCRATCH]] : $*Builtin.UnsafeValueBuffer
+ // CHECK-NOT: end_{{.*}}access
+ // CHECK: [[RESULT:%.*]] = tuple ()
+ // CHECK: [[RETURN:%.*]] = tuple ()
+ // CHECK: return [[RETURN]] : $()
+
Builtin.performInstantaneousReadAccess(address, ty1);
}
diff --git a/test/SILGen/coverage_decls.swift b/test/SILGen/coverage_decls.swift
deleted file mode 100644
index 5843cb8..0000000
--- a/test/SILGen/coverage_decls.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_decls -primary-file %s %S/Inputs/coverage_imports.swift | %FileCheck %s
-
-// CHECK: sil_coverage_map {{.*}} $S14coverage_decls4mainyyF
-// CHECK-NOT: sil_coverage_map
-
-func main() {
- var b = Box()
- let _ = b.x
-}
diff --git a/test/SILGen/enum_raw_representable.swift b/test/SILGen/enum_raw_representable.swift
new file mode 100644
index 0000000..60bea14
--- /dev/null
+++ b/test/SILGen/enum_raw_representable.swift
@@ -0,0 +1,12 @@
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -enable-resilience %s | %FileCheck -check-prefix=CHECK-RESILIENT %s
+
+public enum E: Int {
+ case a, b, c
+}
+
+// CHECK-DAG: sil [serialized] @$S22enum_raw_representable1EO0B5ValueACSgSi_tcfC
+// CHECK-DAG: sil [serialized] @$S22enum_raw_representable1EO0B5ValueSivg
+
+// CHECK-RESILIENT-DAG: sil @$S22enum_raw_representable1EO0B5ValueACSgSi_tcfC
+// CHECK-RESILIENT-DAG: sil @$S22enum_raw_representable1EO0B5ValueSivg
diff --git a/test/SILGen/preserve_exclusivity.swift b/test/SILGen/preserve_exclusivity.swift
new file mode 100644
index 0000000..7902e3d
--- /dev/null
+++ b/test/SILGen/preserve_exclusivity.swift
@@ -0,0 +1,118 @@
+// RUN: %target-swift-frontend -parse-stdlib -emit-silgen %s | %FileCheck --check-prefix=SILGEN %s
+//
+// Check that SILGen emits the correct SIL attributes for @_semantics("optimize.sil.preserve_exclusivity")/
+
+// RUN: %target-swift-frontend -parse-stdlib -parse-stdlib -emit-sil -Onone %s | %FileCheck --check-prefix=CANONICAL %s
+//
+// Check that -Onone pipeline does not eliminate the attribute or access markers.
+
+@_silgen_name("marker1")
+func marker1() -> ()
+
+@_silgen_name("marker2")
+func marker2() -> ()
+
+@_silgen_name("marker3")
+func marker3() -> ()
+
+@_silgen_name("marker4")
+func marker4() -> ()
+
+@_silgen_name("marker5")
+func marker5() -> ()
+
+@_silgen_name("marker6")
+func marker6() -> ()
+
+// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// SILGEN: begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF
+
+// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CANONICAL: begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker1()
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity8endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// SILGEN: end_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity8endNoOptyyBpF'
+
+// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity8endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CANONICAL: end_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity8endNoOptyyBpF'
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func endNoOpt(_ address: Builtin.RawPointer) {
+ marker2()
+ Builtin.endUnpairedAccess(address)
+}
+
+// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity9readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// SILGEN: begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity9readNoOptyyBp_BpmtF'
+
+// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity9readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CANONICAL: begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity9readNoOptyyBp_BpmtF'
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func readNoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+ marker3()
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+public func testNoOpt(_ k1: Builtin.RawPointer) {
+ beginNoOpt(k1, k1, Builtin.RawPointer.self)
+ endNoOpt(k1)
+ readNoOpt(k1, Builtin.RawPointer.self)
+}
+
+// SILGEN-LABEL: sil @$S20preserve_exclusivity8beginOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// SILGEN: begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity8beginOptyyBp_BpxmtlF'
+
+// CANONICAL-LABEL: sil @$S20preserve_exclusivity8beginOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CANONICAL: begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity8beginOptyyBp_BpxmtlF'
+
+public func beginOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker4()
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// SILGEN-LABEL: sil @$S20preserve_exclusivity6endOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// SILGEN: end_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity6endOptyyBpF'
+
+// CANONICAL-LABEL: sil @$S20preserve_exclusivity6endOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CANONICAL: end_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity6endOptyyBpF'
+
+public func endOpt(_ address: Builtin.RawPointer) {
+ marker5()
+ Builtin.endUnpairedAccess(address)
+}
+
+// SILGEN-LABEL: sil @$S20preserve_exclusivity7readOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// SILGEN: begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity7readOptyyBp_BpmtF'
+
+// CANONICAL-LABEL: sil @$S20preserve_exclusivity7readOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CANONICAL: begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity7readOptyyBp_BpmtF'
+
+public func readOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+ marker6()
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+public func testOpt(_ k1: Builtin.RawPointer) {
+ beginOpt(k1, k1, Builtin.RawPointer.self)
+ endOpt(k1)
+ readOpt(k1, Builtin.RawPointer.self)
+}
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 969e2f0..bb8389a 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -513,7 +513,7 @@
}
var a: Int {
- // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+ // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
willSet(newA) {
// CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
// CHECK-NEXT: debug_value %0
@@ -548,7 +548,7 @@
// CHECK-NEXT: assign [[ZERO]] to [[AADDR]]
}
- // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+ // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
didSet {
// CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
// CHECK-NEXT: debug
@@ -626,7 +626,7 @@
// CHECK: properties.zero.unsafeMutableAddressor
// CHECK: return
- // CHECK-LABEL: sil hidden @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
+ // CHECK-LABEL: sil private @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
didSet {
// The didSet implementation needs to call takeInt.
takeInt(global_observing_property)
diff --git a/test/SILGen/properties_swift4.swift b/test/SILGen/properties_swift4.swift
index 9cfc5b4..a51a951 100644
--- a/test/SILGen/properties_swift4.swift
+++ b/test/SILGen/properties_swift4.swift
@@ -13,7 +13,7 @@
}
var a: Int {
- // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+ // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
willSet(newA) {
// CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
@@ -57,7 +57,7 @@
// CHECK-NEXT: end_access [[WRITE]] : $*DidSetWillSetTests
}
- // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+ // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
didSet {
(self).a = zero // reassign, but don't infinite loop.
diff --git a/test/SILGen/properties_swift5.swift b/test/SILGen/properties_swift5.swift
index 0e86b85..c847011 100644
--- a/test/SILGen/properties_swift5.swift
+++ b/test/SILGen/properties_swift5.swift
@@ -13,7 +13,7 @@
}
var a: Int {
- // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+ // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
willSet(newA) {
// CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
@@ -59,7 +59,7 @@
// CHECK-NEXT: end_access [[WRITE]] : $*DidSetWillSetTests
}
- // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+ // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
didSet {
(self).a = zero // reassign, but don't infinite loop, as accessing on 'self'.
diff --git a/test/SILOptimizer/definite_init_diagnostics.swift b/test/SILOptimizer/definite_init_diagnostics.swift
index 9b54328..f49732d 100644
--- a/test/SILOptimizer/definite_init_diagnostics.swift
+++ b/test/SILOptimizer/definite_init_diagnostics.swift
@@ -111,7 +111,7 @@
weak var w1 : SomeClass?
_ = w1 // ok: default-initialized
- // expected-warning@+3 {{instance will be immediately deallocated as 'w2' is a 'weak' variable}}
+ // expected-warning@+3 {{instance will be immediately deallocated because variable 'w2' is 'weak'}}
// expected-note@+2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@+1 {{'w2' declared here}}
weak var w2 = SomeClass()
@@ -124,7 +124,7 @@
unowned var u1 : SomeClass // expected-note {{variable defined here}}
_ = u1 // expected-error {{variable 'u1' used before being initialized}}
- // expected-warning@+3 {{instance will be immediately deallocated as 'u2' is an 'unowned' variable}}
+ // expected-warning@+3 {{instance will be immediately deallocated because variable 'u2' is 'unowned'}}
// expected-note@+2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@+1 {{'u2' declared here}}
unowned let u2 = SomeClass()
diff --git a/test/SILOptimizer/preserve_exclusivity.swift b/test/SILOptimizer/preserve_exclusivity.swift
new file mode 100644
index 0000000..9ba7e28
--- /dev/null
+++ b/test/SILOptimizer/preserve_exclusivity.swift
@@ -0,0 +1,150 @@
+// RUN: %target-swift-frontend -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-sil -O %s | %FileCheck %s
+//
+// The -O pipeline should respect
+// @_semantics("optimize.sil.preserve_exclusivity") and avoid eliminating access
+// markers as long as the semantics call is not inlined.
+
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -parse-stdlib -emit-module -O -primary-file %s -emit-module-path %t/preserve_exclusivity.swiftmodule
+// RUN: %target-sil-opt %t/preserve_exclusivity.swiftmodule -emit-sorted-sil -verify -o - | %FileCheck --check-prefix=DESERIALIZED %s
+//
+// Access markers cannot be stripped prior to module serialization, even when their functions are inlined.
+
+@usableFromInline
+@_silgen_name("marker1")
+func marker1() -> ()
+
+@usableFromInline
+@_silgen_name("marker2")
+func marker2() -> ()
+
+@usableFromInline
+@_silgen_name("marker3")
+func marker3() -> ()
+
+@usableFromInline
+@_silgen_name("marker4")
+func marker4() -> ()
+
+@usableFromInline
+@_silgen_name("marker5")
+func marker5() -> ()
+
+@usableFromInline
+@_silgen_name("marker6")
+func marker6() -> ()
+
+// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CHECK: begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF'
+
+// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// DESERIALIZED: begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF'
+
+@inlinable
+@_semantics("optimize.sil.preserve_exclusivity")
+public func f1_beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker1()
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f2___endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CHECK: end_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f2___endNoOptyyBpF'
+
+// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f2___endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED: end_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f2___endNoOptyyBpF'
+
+@inlinable
+@_semantics("optimize.sil.preserve_exclusivity")
+public func f2___endNoOpt(_ address: Builtin.RawPointer) {
+ marker2()
+ Builtin.endUnpairedAccess(address)
+}
+
+// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CHECK: begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF
+
+// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// DESERIALIZED: begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF
+
+@inlinable
+@_semantics("optimize.sil.preserve_exclusivity")
+public func f3__readNoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+ marker3()
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f4__testNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED: marker1
+// DESERIALIZED: begin_unpaired_access
+// DESERIALIZED: marker2
+// DESERIALIZED: end_unpaired_access
+// DESERIALIZED: marker3
+// DESERIALIZED: begin_unpaired_access
+// DESERIALIZED: return
+
+@inlinable
+public func f4__testNoOpt(_ k1: Builtin.RawPointer) {
+ f1_beginNoOpt(k1, k1, Builtin.RawPointer.self)
+ f2___endNoOpt(k1)
+ f3__readNoOpt(k1, Builtin.RawPointer.self)
+}
+
+// CHECK-LABEL: sil @$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CHECK-NOT: begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF'
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// DESERIALIZED-NOT: begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF'
+
+@inlinable
+public func f5_beginDoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+ marker4()
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// CHECK-LABEL: sil @$S20preserve_exclusivity13f6___endDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CHECK-NOT: end_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f6___endDoOptyyBpF'
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f6___endDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED-NOT: end_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f6___endDoOptyyBpF'
+
+@inlinable
+public func f6___endDoOpt(_ address: Builtin.RawPointer) {
+ marker5()
+ Builtin.endUnpairedAccess(address)
+}
+
+// CHECK-LABEL: sil @$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CHECK-NOT: begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF'
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// DESERIALIZED-NOT: begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF'
+
+@inlinable
+public func f7__readDoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+ marker6()
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f8__testDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED: marker4
+// DESERIALIZED: marker5
+// DESERIALIZED: marker6
+// DESERIALIZED: return
+@inlinable
+public func f8__testDoOpt(_ k1: Builtin.RawPointer) {
+ f5_beginDoOpt(k1, k1, Builtin.RawPointer.self)
+ f6___endDoOpt(k1)
+ f7__readDoOpt(k1, Builtin.RawPointer.self)
+}
diff --git a/test/Sema/diag_unowned_immediate_deallocation.swift b/test/Sema/diag_unowned_immediate_deallocation.swift
index 17fee42..56a79ea 100644
--- a/test/Sema/diag_unowned_immediate_deallocation.swift
+++ b/test/Sema/diag_unowned_immediate_deallocation.swift
@@ -15,256 +15,256 @@
class D : C {}
func testWeakVariableBindingDiag() throws {
- weak var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+ weak var c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c1' declared here}}
// expected-note@-3 {{'c1' declared here}}
- c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+ c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c2: C? = ModuleName.C() // expected-warning {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+ weak var c2: C? = ModuleName.C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c2' declared here}}
// expected-note@-3 {{'c2' declared here}}
- c2 = C() // expected-warning {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+ c2 = C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c3: C? = D() // expected-warning {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+ weak var c3: C? = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c3' declared here}}
// expected-note@-3 {{'c3' declared here}}
- c3 = D() // expected-warning {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+ c3 = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c4' is a 'weak' variable}}
+ weak var c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c4' declared here}}
// expected-note@-3 {{'c4' declared here}}
- c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c4' is a 'weak' variable}}
+ c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c5: C? = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c5' is a 'weak' variable}}
+ weak var c5: C? = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c5' declared here}}
// expected-note@-3 {{'c5' declared here}}
- c5 = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c5' is a 'weak' variable}}
+ c5 = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c6: C? = D(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c6' is a 'weak' variable}}
+ weak var c6: C? = D(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c6' declared here}}
// expected-note@-3 {{'c6' declared here}}
- c6 = D(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c6' is a 'weak' variable}}
+ c6 = D(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is a 'weak' variable}}
+ weak var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c7' declared here}}
// expected-note@-3 {{'c7' declared here}}
- c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is a 'weak' variable}}
+ c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c8: C? = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is a 'weak' variable}}
+ weak var c8: C? = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c8' declared here}}
// expected-note@-3 {{'c8' declared here}}
- c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is a 'weak' variable}}
+ c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c9: C? = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is a 'weak' variable}}
+ weak var c9: C? = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c9' declared here}}
// expected-note@-3 {{'c9' declared here}}
- c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is a 'weak' variable}}
+ c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is a 'weak' variable}}
+ weak var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c10' declared here}}
// expected-note@-3 {{'c10' declared here}}
- c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is a 'weak' variable}}
+ c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c11: C? = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is a 'weak' variable}}
+ weak var c11: C? = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c11' declared here}}
// expected-note@-3 {{'c11' declared here}}
- c11 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is a 'weak' variable}}
+ c11 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c12: C? = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is a 'weak' variable}}
+ weak var c12: C? = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c12' declared here}}
// expected-note@-3 {{'c12' declared here}}
- c12 = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is a 'weak' variable}}
+ c12 = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c13' is a 'weak' variable}}
+ weak var c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c13' declared here}}
// expected-note@-3 {{'c13' declared here}}
- c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c13' is a 'weak' variable}}
+ c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c14: C? = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c14' is a 'weak' variable}}
+ weak var c14: C? = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c14' declared here}}
// expected-note@-3 {{'c14' declared here}}
- c14 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c14' is a 'weak' variable}}
+ c14 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- weak var c15: C? = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c15' is a 'weak' variable}}
+ weak var c15: C? = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c15' declared here}}
// expected-note@-3 {{'c15' declared here}}
- c15 = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c15' is a 'weak' variable}}
+ c15 = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
_ = c1; _ = c2; _ = c3; _ = c4; _ = c5; _ = c6; _ = c7; _ = c8; _ = c9; _ = c10; _ = c11; _ = c12; _ = c13; _ = c14; _ = c15
}
func testUnownedVariableBindingDiag() throws {
- unowned(unsafe) var c = C() // expected-warning {{instance will be immediately deallocated as 'c' is an 'unowned' variable}}
+ unowned(unsafe) var c = C() // expected-warning {{instance will be immediately deallocated because variable 'c' is 'unowned(unsafe)'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c' declared here}}
// expected-note@-3 {{'c' declared here}}
- c = C() // expected-warning {{instance will be immediately deallocated as 'c' is an 'unowned' variable}}
+ c = C() // expected-warning {{instance will be immediately deallocated because variable 'c' is 'unowned(unsafe)'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+ unowned var c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c1' declared here}}
// expected-note@-3 {{'c1' declared here}}
- c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+ c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c2: C = ModuleName.C() // expected-warning {{instance will be immediately deallocated as 'c2' is an 'unowned' variable}}
+ unowned var c2: C = ModuleName.C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c2' declared here}}
// expected-note@-3 {{'c2' declared here}}
- c2 = C() // expected-warning {{instance will be immediately deallocated as 'c2' is an 'unowned' variable}}
+ c2 = C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c3: C = D() // expected-warning {{instance will be immediately deallocated as 'c3' is an 'unowned' variable}}
+ unowned var c3: C = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c3' declared here}}
// expected-note@-3 {{'c3' declared here}}
- c3 = D() // expected-warning {{instance will be immediately deallocated as 'c3' is an 'unowned' variable}}
+ c3 = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+ unowned var c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c4' declared here}}
// expected-note@-3 {{'c4' declared here}}
- c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+ c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c5: C = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+ unowned var c5: C = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c5' declared here}}
// expected-note@-3 {{'c5' declared here}}
- c5 = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+ c5 = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c6: C = D(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+ unowned var c6: C = D(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c6' declared here}}
// expected-note@-3 {{'c6' declared here}}
- c6 = D(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+ c6 = D(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is an 'unowned' variable}}
+ unowned var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c7' declared here}}
// expected-note@-3 {{'c7' declared here}}
- c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is an 'unowned' variable}}
+ c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c8: C = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is an 'unowned' variable}}
+ unowned var c8: C = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c8' declared here}}
// expected-note@-3 {{'c8' declared here}}
- c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is an 'unowned' variable}}
+ c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c9: C = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is an 'unowned' variable}}
+ unowned var c9: C = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c9' declared here}}
// expected-note@-3 {{'c9' declared here}}
- c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is an 'unowned' variable}}
+ c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is an 'unowned' variable}}
+ unowned var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c10' declared here}}
// expected-note@-3 {{'c10' declared here}}
- c10 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is an 'unowned' variable}}
+ c10 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c11: C = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is an 'unowned' variable}}
+ unowned var c11: C = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c11' declared here}}
// expected-note@-3 {{'c11' declared here}}
- c11 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is an 'unowned' variable}}
+ c11 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c12: C = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is an 'unowned' variable}}
+ unowned var c12: C = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c12' declared here}}
// expected-note@-3 {{'c12' declared here}}
- c12 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is an 'unowned' variable}}
+ c12 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c13' is an 'unowned' variable}}
+ unowned var c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c13' declared here}}
// expected-note@-3 {{'c13' declared here}}
- c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c13' is an 'unowned' variable}}
+ c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c14: C = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c14' is an 'unowned' variable}}
+ unowned var c14: C = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c14' declared here}}
// expected-note@-3 {{'c14' declared here}}
- c14 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c14' is an 'unowned' variable}}
+ c14 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- unowned var c15: C = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c15' is an 'unowned' variable}}
+ unowned var c15: C = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c15' declared here}}
// expected-note@-3 {{'c15' declared here}}
- c15 = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c15' is an 'unowned' variable}}
+ c15 = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
_ = c; _ = c1; _ = c2; _ = c3; _ = c4; _ = c5; _ = c6; _ = c7; _ = c8; _ = c9; _ = c10; _ = c11; _ = c12; _ = c13; _ = c14; _ = c15
@@ -272,24 +272,24 @@
func testMultipleBindingDiag() {
weak var c1 = C(), c2: C? = C(), c3: C? = D()
- // expected-warning@-1 {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'c1' declared here}}
- // expected-warning@-4 {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+ // expected-warning@-4 {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
// expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-6 {{'c2' declared here}}
- // expected-warning@-7 {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+ // expected-warning@-7 {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
// expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-9 {{'c3' declared here}}
unowned let c4 = C(), c5: C = C(), c6: C = D()
- // expected-warning@-1 {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'c4' declared here}}
- // expected-warning@-4 {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+ // expected-warning@-4 {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
// expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-6 {{'c5' declared here}}
- // expected-warning@-7 {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+ // expected-warning@-7 {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
// expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-9 {{'c6' declared here}}
@@ -298,24 +298,24 @@
func testTupleAndParenBinding() throws {
weak var ((c1), c2, c3): (C?, C?, C?) = (C() as C, (D()), try D(throwing: ()))
- // expected-warning@-1 {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'c1' declared here}}
- // expected-warning@-4 {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+ // expected-warning@-4 {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
// expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-6 {{'c2' declared here}}
- // expected-warning@-7 {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+ // expected-warning@-7 {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
// expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-9 {{'c3' declared here}}
unowned let ((c4), c5, c6): (C, C, C) = (C() as C, (D()), try D(throwing: ()))
- // expected-warning@-1 {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'c4' declared here}}
- // expected-warning@-4 {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+ // expected-warning@-4 {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
// expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-6 {{'c5' declared here}}
- // expected-warning@-7 {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+ // expected-warning@-7 {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
// expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-9 {{'c6' declared here}}
@@ -323,65 +323,65 @@
}
func testInitializationThroughClassArchetypeDiag<T : ClassProtocol>(_ t: T, _ p: ClassProtocol) throws {
- weak var t1: T? = T() // expected-warning {{instance will be immediately deallocated as 't1' is a 'weak' variable}}
+ weak var t1: T? = T() // expected-warning {{instance will be immediately deallocated because variable 't1' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'t1' declared here}}
- weak var t2: ClassProtocol? = T(failable: ()) // expected-warning {{instance will be immediately deallocated as 't2' is a 'weak' variable}}
+ weak var t2: ClassProtocol? = T(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 't2' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'t2' declared here}}
- unowned let t3 = try type(of: t).init(throwing: ()) // expected-warning {{instance will be immediately deallocated as 't3' is an 'unowned' variable}}
+ unowned let t3 = try type(of: t).init(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 't3' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'t3' declared here}}
- unowned(unsafe) let t4 = type(of: p).init() // expected-warning {{instance will be immediately deallocated as 't4' is an 'unowned' variable}}
+ unowned(unsafe) let t4 = type(of: p).init() // expected-warning {{instance will be immediately deallocated because variable 't4' is 'unowned(unsafe)'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'t4' declared here}}
let optionalTType: T.Type? = T.self
let optionalPType: ClassProtocol.Type? = type(of: p)
- weak var t5 = optionalTType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated as 't5' is a 'weak' variable}}
+ weak var t5 = optionalTType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 't5' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'t5' declared here}}
- unowned(unsafe) let t6 = try (optionalPType?.init(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 't6' is an 'unowned' variable}}
+ unowned(unsafe) let t6 = try (optionalPType?.init(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 't6' is 'unowned(unsafe)'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'t6' declared here}}
_ = t1; _ = t2; _ = t3; _ = t4; _ = t5; _ = t6
}
-weak var topLevelC = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC' is a 'weak' variable}}
+weak var topLevelC = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'topLevelC' declared here}}
// expected-note@-3 {{'topLevelC' declared here}}
-topLevelC = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC' is a 'weak' variable}}
+topLevelC = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
-unowned var topLevelC1 = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC1' is an 'unowned' variable}}
+unowned var topLevelC1 = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'topLevelC1' declared here}}
// expected-note@-3 {{'topLevelC1' declared here}}
-topLevelC1 = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC1' is an 'unowned' variable}}
+topLevelC1 = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
struct S {
weak var c: C? // expected-note {{'c' declared here}}
- unowned var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+ unowned var c1 = C() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c1' declared here}}
// expected-note@-3 {{'c1' declared here}}
mutating func foo() {
- c = D() // expected-warning {{instance will be immediately deallocated as 'c' is a 'weak' property}}
+ c = D() // expected-warning {{instance will be immediately deallocated because property 'c' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- c1 = D() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+ c1 = D() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
}
}
@@ -389,27 +389,27 @@
class C1 {
weak var c: C? // expected-note {{'c' declared here}}
- unowned var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+ unowned var c1 = C() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c1' declared here}}
// expected-note@-3 {{'c1' declared here}}
func foo() {
- c = D() // expected-warning {{instance will be immediately deallocated as 'c' is a 'weak' property}}
+ c = D() // expected-warning {{instance will be immediately deallocated because property 'c' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
- c1 = D() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+ c1 = D() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
}
}
func testInitializationThroughMetaclassDiag(_ t: C.Type) {
- weak var c1: C? = t.init() // expected-warning {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+ weak var c1: C? = t.init() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c1' declared here}}
let optionaCType: C.Type? = t
- weak var c2 = optionaCType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+ weak var c2 = optionaCType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c2' declared here}}
@@ -417,19 +417,19 @@
}
func testInitializationThroughTupleElementDiag() {
- unowned var c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+ unowned var c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'c1' declared here}}
// expected-note@-3 {{'c1' declared here}}
- c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+ c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
unowned let (c2, c3) = ((C() as C, C()) as (C, C), 5).0
- // expected-warning@-1 {{instance will be immediately deallocated as 'c2' is an 'unowned' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'c2' is 'unowned'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'c2' declared here}}
- // expected-warning@-4 {{instance will be immediately deallocated as 'c3' is an 'unowned' variable}}
+ // expected-warning@-4 {{instance will be immediately deallocated because variable 'c3' is 'unowned'}}
// expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-6 {{'c3' declared here}}
@@ -440,7 +440,7 @@
func testGenericWeakClassDiag() {
weak var e = E<String>()
- // expected-warning@-1 {{instance will be immediately deallocated as 'e' is a 'weak' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'e' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'e' declared here}}
diff --git a/test/Sema/diag_unowned_immediate_deallocation_global.swift b/test/Sema/diag_unowned_immediate_deallocation_global.swift
index 5867f3b..3212aaa 100644
--- a/test/Sema/diag_unowned_immediate_deallocation_global.swift
+++ b/test/Sema/diag_unowned_immediate_deallocation_global.swift
@@ -4,11 +4,11 @@
init() {}
}
-weak var globalC = C() // expected-warning {{instance will be immediately deallocated as 'globalC' is a 'weak' variable}}
+weak var globalC = C() // expected-warning {{instance will be immediately deallocated because variable 'globalC' is 'weak'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'globalC' declared here}}
-unowned var globalC1 = C() // expected-warning {{instance will be immediately deallocated as 'globalC1' is an 'unowned' variable}}
+unowned var globalC1 = C() // expected-warning {{instance will be immediately deallocated because variable 'globalC1' is 'unowned'}}
// expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-2 {{'globalC1' declared here}}
diff --git a/test/Sema/exhaustive_switch.swift b/test/Sema/exhaustive_switch.swift
index 8ebbd02..69f243e 100644
--- a/test/Sema/exhaustive_switch.swift
+++ b/test/Sema/exhaustive_switch.swift
@@ -1,4 +1,5 @@
-// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
+// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-resilience
+// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
func foo(a: Int?, b: Int?) -> Int {
switch (a, b) {
@@ -852,7 +853,7 @@
case .a: break
}
- switch value { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+ switch value { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
case .a: break
case .b: break
}
@@ -884,7 +885,7 @@
}
// Test being part of other spaces.
- switch value as Optional { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.some(_)'}}
+ switch value as Optional { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.some(_)'}}
case .a?: break
case .b?: break
case nil: break
@@ -902,7 +903,7 @@
case nil: break
} // no-warning
- switch (value, flag) { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, false)'}}
+ switch (value, flag) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, false)'}}
case (.a, _): break
case (.b, false): break
case (_, true): break
@@ -915,7 +916,7 @@
@unknown case _: break
} // no-warning
- switch (flag, value) { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(false, _)'}}
+ switch (flag, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(false, _)'}}
case (_, .a): break
case (false, .b): break
case (true, _): break
@@ -928,7 +929,7 @@
@unknown case _: break
} // no-warning
- switch (value, value) { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, _)'}}
+ switch (value, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, _)'}}
case (.a, _), (_, .a): break
case (.b, _), (_, .b): break
}
@@ -940,7 +941,7 @@
} // no-warning
// Test interaction with @_downgrade_exhaustivity_check.
- switch (value, interval) { // expected-error {{switch must be exhaustive}} {{none}}
+ switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
// expected-note@-1 {{add missing case: '(_, .milliseconds(_))'}}
// expected-note@-2 {{add missing case: '(_, .microseconds(_))'}}
// expected-note@-3 {{add missing case: '(_, .nanoseconds(_))'}}
@@ -950,7 +951,7 @@
case (.b, _): break
}
- switch (value, interval) { // expected-error {{switch must be exhaustive}} {{none}}
+ switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
// expected-note@-1 {{add missing case: '(_, .seconds(_))'}}
// expected-note@-2 {{add missing case: '(_, .milliseconds(_))'}}
// expected-note@-3 {{add missing case: '(_, .microseconds(_))'}}
@@ -965,7 +966,7 @@
case .a: break
}
- switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+ switch payload { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
case .a: break
case .b: break
}
diff --git a/test/Sema/exhaustive_switch_testable.swift b/test/Sema/exhaustive_switch_testable.swift
index c261434..a6db6da 100644
--- a/test/Sema/exhaustive_switch_testable.swift
+++ b/test/Sema/exhaustive_switch_testable.swift
@@ -1,7 +1,7 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -swift-version 5 -enable-resilience -enable-testing %S/Inputs/exhaustive_switch_testable_helper.swift -emit-module -o %t
-// RUN: %target-swift-frontend -typecheck %s -swift-version 5 -enable-nonfrozen-enum-exhaustivity-diagnostics -I %t -DTESTABLE -verify
-// RUN: not %target-swift-frontend -typecheck %s -swift-version 5 -enable-nonfrozen-enum-exhaustivity-diagnostics -I %t 2>&1 | %FileCheck -check-prefix=VERIFY-NON-FROZEN %s
+// RUN: %target-swift-frontend -typecheck %s -swift-version 5 -I %t -DTESTABLE -verify
+// RUN: %target-swift-frontend -typecheck %s -swift-version 5 -I %t 2>&1 | %FileCheck -check-prefix=VERIFY-NON-FROZEN %s
#if TESTABLE
@testable import exhaustive_switch_testable_helper
@@ -17,7 +17,7 @@
}
func testNonFrozen(_ e: NonFrozenEnum) -> Int {
- // VERIFY-NON-FROZEN: exhaustive_switch_testable.swift:[[@LINE+1]]:{{[0-9]+}}: error: switch must be exhaustive
+ // VERIFY-NON-FROZEN: exhaustive_switch_testable.swift:[[@LINE+1]]:{{[0-9]+}}: warning: switch must be exhaustive
switch e {
case .a: return 1
case .b, .c: return 2
diff --git a/test/SourceKit/CompileNotifications/args.swift b/test/SourceKit/CompileNotifications/args.swift
index 8e89a8e..fd01bf2 100644
--- a/test/SourceKit/CompileNotifications/args.swift
+++ b/test/SourceKit/CompileNotifications/args.swift
@@ -2,16 +2,14 @@
// ARGS1: {
// ARGS1: key.notification: source.notification.compile-will-start
// ARGS1: key.filepath: "[[PATH:.*]]"
-// ARGS1: key.compilerargs: [
-// ARGS1-NEXT: [[PATH]]
-// ARGS1-NEXT: ]
+// ARGS1: key.compilerargs-string: "
+// ARGS1-LINE: [[PATH]]
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -j 1000 | %FileCheck %s -check-prefix=ARGS2
// ARGS2: {
// ARGS2: key.notification: source.notification.compile-will-start
// ARGS2: key.filepath: "[[PATH:.*]]"
-// ARGS2: key.compilerargs: [
-// ARGS2-NEXT: [[PATH]]
-// ARGS2-NEXT: "-j"
-// ARGS2-NEXT: "1000"
-// ARGS2-NEXT: ]
+// ARGS2: key.compilerargs-string: "
+// ARGS2-LINE: [[PATH]]
+// ARGS2-LINE: -j
+// ARGS2-LINE: 1000
diff --git a/test/SourceKit/CompileNotifications/diagnostics.swift b/test/SourceKit/CompileNotifications/diagnostics.swift
index 9d5eba8..83ea2ae 100644
--- a/test/SourceKit/CompileNotifications/diagnostics.swift
+++ b/test/SourceKit/CompileNotifications/diagnostics.swift
@@ -64,3 +64,7 @@
// INVALID_ARG_CLANG-NEXT: key.severity: source.diagnostic.severity.warning,
// INVALID_ARG_CLANG-NEXT: key.offset: 0
// INVALID_ARG_CLANG-NEXT: key.description: "argument unused
+
+// Ignore the spurious -wmo + -enable-batch-mode warning.
+// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -enable-batch-mode | %FileCheck %s -check-prefix=NODIAGS
+// RUN: %sourcekitd-test -req=track-compiles == -req=complete -offset=0 %s -- %s -enable-batch-mode | %FileCheck %s -check-prefix=NODIAGS
diff --git a/test/api-digester/Outputs/apinotes-migrator-gen-revert.json b/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
new file mode 100644
index 0000000..2ddd405
--- /dev/null
+++ b/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
@@ -0,0 +1,238 @@
+[
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertDictionaryKeyUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertDictionaryKeyUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertOptionalDictionaryKeyUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertOptionalDictionaryKeyUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertArrayMemberUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertArrayMemberUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertOptionalArrayMemberUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertOptionalArrayMemberUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1:0",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(cm)animalStatusSingleOptionalAttribute:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "RevertSimpleOptionalStringRepresentableUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(cm)animalStatusSingleOptionalAttribute:",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "TypeRewritten",
+ "ChildIndex": "1",
+ "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(cm)animalStatusSingleAttribute:",
+ "LeftComment": "AnimalAttributeName",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "TypeDecl",
+ "NodeAnnotation": "Rename",
+ "ChildIndex": "0",
+ "LeftUsr": "c:objc(pl)TypeWithMethod",
+ "LeftComment": "SwiftTypeWithMethodRight",
+ "RightUsr": "",
+ "RightComment": "SwiftTypeWithMethodLeft",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "TypeMemberDiffItem",
+ "Usr": "c:@ANTGlobalValue",
+ "OldPrintedName": "newMember",
+ "OldTypeName": "NewType",
+ "NewPrintedName": "oldMember",
+ "NewTypeName": "OldType"
+ },
+ {
+ "DiffItemKind": "TypeMemberDiffItem",
+ "Usr": "c:objc(pl)TypeWithMethod(cm)plusPrint",
+ "OldPrintedName": "plusPrint()",
+ "OldTypeName": "SwiftTypeWithMethodRight",
+ "NewPrintedName": "plusPrint()",
+ "NewTypeName": "SwiftTypeWithMethodLeft"
+ }
+]
\ No newline at end of file
diff --git a/test/api-digester/apinotes-migrator-gen.swift b/test/api-digester/apinotes-migrator-gen.swift
index 6967dd3..6966ac9 100644
--- a/test/api-digester/apinotes-migrator-gen.swift
+++ b/test/api-digester/apinotes-migrator-gen.swift
@@ -6,3 +6,5 @@
// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -swift-version 4 -I %S/Inputs/APINotesRight
// RUN: %api-digester -compare-sdk --input-paths %t.dump1.json -input-paths %t.dump2.json -o %t.result -json
// RUN: diff -u %S/Outputs/apinotes-migrator-gen.json %t.result
+// RUN: %api-digester -compare-sdk --input-paths %t.dump2.json -input-paths %t.dump1.json -o %t.result -json
+// RUN: diff -u %S/Outputs/apinotes-migrator-gen-revert.json %t.result
diff --git a/test/api-digester/stdlib-stable.json b/test/api-digester/stdlib-stable.json
index f2f0e16..6f63b55 100644
--- a/test/api-digester/stdlib-stable.json
+++ b/test/api-digester/stdlib-stable.json
@@ -74020,7 +74020,7 @@
{
"kind": "Function",
"name": "index",
- "printedName": "index(of:)",
+ "printedName": "firstIndex(of:)",
"declKind": "Func",
"usr": "s:FesRxs10CollectionWx8Iterator7Element_s9EquatablerS_5indexFT2ofWxS0_S1___GSqwx5Index_",
"location": "",
@@ -78173,7 +78173,7 @@
{
"kind": "Function",
"name": "index",
- "printedName": "index(of:)",
+ "printedName": "firstIndex(of:)",
"declKind": "Func",
"usr": "s:FVs3Set5indexFT2ofx_GSqGVs8SetIndexx__",
"location": "",
diff --git a/test/attr/attributes.swift b/test/attr/attributes.swift
index b5c8a5a..18f87e0 100644
--- a/test/attr/attributes.swift
+++ b/test/attr/attributes.swift
@@ -159,12 +159,12 @@
var weak7 : Int // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
weak
var weak8 : Class? = Ty0()
-// expected-warning@-1 {{instance will be immediately deallocated as 'weak8' is a 'weak' variable}}
+// expected-warning@-1 {{instance will be immediately deallocated because variable 'weak8' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'weak8' declared here}}
unowned var weak9 : Class = Ty0()
-// expected-warning@-1 {{instance will be immediately deallocated as 'weak9' is an 'unowned' variable}}
+// expected-warning@-1 {{instance will be immediately deallocated because variable 'weak9' is 'unowned'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'weak9' declared here}}
diff --git a/test/attr/open.swift b/test/attr/open.swift
index 8da60b8..521d9ae 100644
--- a/test/attr/open.swift
+++ b/test/attr/open.swift
@@ -49,7 +49,6 @@
open class AnOpenClass {
open func openMethod() {}
open var openVar: Int = 0
- open let openLet: Int = 1 // Should this be allowed?
open typealias MyInt = Int // expected-error {{only classes and overridable class members can be declared 'open'; use 'public'}}
open subscript(_: MarkerForOpenSubscripts) -> Int {
return 0
diff --git a/test/attr/open_swift4.swift b/test/attr/open_swift4.swift
new file mode 100644
index 0000000..0fc71ed
--- /dev/null
+++ b/test/attr/open_swift4.swift
@@ -0,0 +1,12 @@
+// RUN: %target-typecheck-verify-swift -swift-version 3
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+open class AnOpenClass {
+ open let openLet: Int = 1 // expected-warning {{'let' properties are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+ open static func test() {} // expected-warning {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
+
+final public class NonOpenClass {
+ open func test() {} // expected-warning {{members of 'final' classes are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+ open static func test() {} // expected-warning {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
diff --git a/test/attr/open_swift5.swift b/test/attr/open_swift5.swift
new file mode 100644
index 0000000..0423008
--- /dev/null
+++ b/test/attr/open_swift5.swift
@@ -0,0 +1,11 @@
+// RUN: %target-typecheck-verify-swift -swift-version 5
+
+open class AnOpenClass {
+ open let openLet: Int = 1 // expected-error {{'let' properties are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+ open static func test() {} // expected-error {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
+
+final public class NonOpenClass {
+ open func test() {} // expected-error {{members of 'final' classes are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+ open static func test() {} // expected-error {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
diff --git a/test/decl/ext/Inputs/extension-generic-objc-protocol.h b/test/decl/ext/Inputs/extension-generic-objc-protocol.h
new file mode 100644
index 0000000..4e8d268
--- /dev/null
+++ b/test/decl/ext/Inputs/extension-generic-objc-protocol.h
@@ -0,0 +1,19 @@
+@import Foundation;
+
+@interface OBJCGeneric<T> : NSObject
+@end
+
+@interface OBJCGenericSubclass<T, U>: OBJCGeneric<T>
+@end
+
+@interface OBJCNongenericSubclass: OBJCGenericSubclass<id, id>
+@end
+
+@protocol OBJCProtocol1
+@end
+
+@protocol OBJCProtocol2
+@end
+
+@protocol OBJCProtocol3
+@end
diff --git a/test/decl/ext/extension-generic-objc-protocol.swift b/test/decl/ext/extension-generic-objc-protocol.swift
index 0a58265..ddfc085 100644
--- a/test/decl/ext/extension-generic-objc-protocol.swift
+++ b/test/decl/ext/extension-generic-objc-protocol.swift
@@ -1,10 +1,12 @@
-// RUN: %target-swift-frontend -typecheck -verify %s
+// RUN: %target-swift-frontend -import-objc-header %S/Inputs/extension-generic-objc-protocol.h -typecheck -verify %s
// REQUIRES: objc_interop
import Foundation
@objc protocol P {}
+@objc protocol Q {}
+@objc protocol R {}
public class C1<T> {}
extension C1: P {}
@@ -27,3 +29,32 @@
extension SubInner: P {}
// expected-error@-1 {{conformance of subclass of a class from generic context 'SubInner' to @objc protocol 'P' cannot be in an extension}}
+
+// Lightweight generic ObjC classes can still be extended to conform.
+
+extension OBJCGeneric: OBJCProtocol1 {}
+extension OBJCGeneric: P {}
+extension OBJCGenericSubclass: OBJCProtocol2 {}
+extension OBJCGenericSubclass: Q {}
+extension OBJCNongenericSubclass: OBJCProtocol3 {}
+extension OBJCNongenericSubclass: R {}
+
+public class SwiftSubclassOfObjCGeneric: OBJCGeneric<AnyObject> {}
+
+extension SwiftSubclassOfObjCGeneric: OBJCProtocol2 {}
+extension SwiftSubclassOfObjCGeneric: Q {}
+
+public class SwiftGenericSubclassOfObjCGeneric<T: AnyObject>
+ : OBJCGeneric<AnyObject>
+{}
+
+extension SwiftGenericSubclassOfObjCGeneric: OBJCProtocol2 {} // expected-error {{cannot be in an extension}}
+extension SwiftGenericSubclassOfObjCGeneric: Q {} // expected-error {{cannot be in an extension}}
+
+public class SwiftNongenericSubclassOfGenericSubclassOfObjCGeneric
+ : SwiftGenericSubclassOfObjCGeneric<AnyObject>
+{}
+
+extension SwiftNongenericSubclassOfGenericSubclassOfObjCGeneric: OBJCProtocol3 {} // expected-error {{cannot be in an extension}}
+extension SwiftNongenericSubclassOfGenericSubclassOfObjCGeneric: R {} // expected-error {{cannot be in an extension}}
+
diff --git a/test/decl/protocol/ownership_protocol.swift b/test/decl/protocol/ownership_protocol.swift
index b998a81..2fa4dac 100644
--- a/test/decl/protocol/ownership_protocol.swift
+++ b/test/decl/protocol/ownership_protocol.swift
@@ -3,10 +3,16 @@
class SomeClass {}
protocol P {
- weak var foo: SomeClass? { get set } // expected-error {{'weak' cannot be applied to a property declaration in a protocol}}
- unowned var foo2: SomeClass { get set } // expected-error {{'unowned' cannot be applied to a property declaration in a protocol}}
- weak var foo3: Int? { get set } // expected-error {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
- unowned var foo4: Int { get set } // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+ // expected-error@+1 {{'weak' cannot be applied to a property declaration in a protocol}}
+ weak var foo: SomeClass? { get set }
+ // expected-error@+1 {{'unowned' cannot be applied to a property declaration in a protocol}}
+ unowned var foo2: SomeClass { get set }
+ // expected-error@+2 {{'weak' cannot be applied to a property declaration in a protocol}}
+ // expected-error@+1 {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
+ weak var foo3: Int? { get set }
+ // expected-error@+2 {{'unowned' cannot be applied to a property declaration in a protocol}}
+ // expected-error@+1 {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+ unowned var foo4: Int { get set }
var foo9: SomeClass? { get }
}
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index e0558fa..4c7ab82 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -465,6 +465,7 @@
// rdar://problem/18168866
protocol FirstProtocol {
+ // expected-warning@+1 {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
weak var delegate : SecondProtocol? { get } // expected-error{{'weak' must not be applied to non-class-bound 'SecondProtocol'; consider adding a protocol conformance that has a class bound}}
}
diff --git a/test/decl/protocol/special/coding/Inputs/class_missing_init_multi1.swift b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi1.swift
new file mode 100644
index 0000000..4e720b7
--- /dev/null
+++ b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi1.swift
@@ -0,0 +1,3 @@
+class C1 : Decodable {
+ let str: String
+}
diff --git a/test/decl/protocol/special/coding/Inputs/class_missing_init_multi2.swift b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi2.swift
new file mode 100644
index 0000000..82c142e
--- /dev/null
+++ b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi2.swift
@@ -0,0 +1,3 @@
+class C2 : Decodable {
+ let c: C1
+}
diff --git a/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift b/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift
index 7071933..cfe2497 100644
--- a/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift
+++ b/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift
@@ -8,12 +8,12 @@
}
weak var x: NestedClass? = NestedClass()
- // expected-warning@-1 {{instance will be immediately deallocated as 'x' is a 'weak' property}}
+ // expected-warning@-1 {{instance will be immediately deallocated because property 'x' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'x' declared here}}
unowned var y: NestedClass = NestedClass()
- // expected-warning@-1 {{instance will be immediately deallocated as 'y' is an 'unowned' property}}
+ // expected-warning@-1 {{instance will be immediately deallocated because property 'y' is 'unowned'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'y' declared here}}
diff --git a/test/decl/protocol/special/coding/class_missing_init_multi.swift b/test/decl/protocol/special/coding/class_missing_init_multi.swift
new file mode 100644
index 0000000..b6b394c
--- /dev/null
+++ b/test/decl/protocol/special/coding/class_missing_init_multi.swift
@@ -0,0 +1,8 @@
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi1.swift %S/Inputs/class_missing_init_multi2.swift
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi2.swift %S/Inputs/class_missing_init_multi1.swift
+
+// RUN: %target-typecheck-verify-swift -verify -primary-file %S/Inputs/class_missing_init_multi1.swift %S/Inputs/class_missing_init_multi2.swift
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi1.swift -primary-file %S/Inputs/class_missing_init_multi2.swift
+
+// RUN: %target-typecheck-verify-swift -verify -primary-file %S/Inputs/class_missing_init_multi2.swift %S/Inputs/class_missing_init_multi1.swift
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi2.swift -primary-file %S/Inputs/class_missing_init_multi1.swift
diff --git a/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift b/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift
index 7f98b2a..2d02f4a 100644
--- a/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift
+++ b/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift
@@ -8,12 +8,12 @@
}
weak var x: NestedClass? = NestedClass()
- // expected-warning@-1 {{instance will be immediately deallocated as 'x' is a 'weak' property}}
+ // expected-warning@-1 {{instance will be immediately deallocated because property 'x' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'x' declared here}}
unowned var y: NestedClass = NestedClass()
- // expected-warning@-1 {{instance will be immediately deallocated as 'y' is an 'unowned' property}}
+ // expected-warning@-1 {{instance will be immediately deallocated because property 'y' is 'unowned'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'y' declared here}}
diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift
index dac9213..c74e41d 100644
--- a/test/decl/var/properties.swift
+++ b/test/decl/var/properties.swift
@@ -114,7 +114,7 @@
// applied to the getter.
weak
var foo: SomeClass? = SomeClass() // expected-warning {{variable 'foo' was written to, but never read}}
- // expected-warning@-1 {{instance will be immediately deallocated as 'foo' is a 'weak' variable}}
+ // expected-warning@-1 {{instance will be immediately deallocated because variable 'foo' is 'weak'}}
// expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
// expected-note@-3 {{'foo' declared here}}
return 0
@@ -1106,16 +1106,16 @@
}
class OwnershipBadSub : OwnershipBase {
- override weak var strongVar: AnyObject? { // expected-error {{cannot override strong property with weak property}}
+ override weak var strongVar: AnyObject? { // expected-error {{cannot override 'strong' property with 'weak' property}}
didSet {}
}
- override unowned var weakVar: AnyObject? { // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'AnyObject?'}}
+ override unowned var weakVar: AnyObject? { // expected-error {{'unowned' variable cannot have optional type}}
didSet {}
}
override weak var unownedVar: AnyObject { // expected-error {{'weak' variable should have optional type 'AnyObject?'}}
didSet {}
}
- override unowned var unownedUnsafeVar: AnyObject { // expected-error {{cannot override unowned(unsafe) property with unowned property}}
+ override unowned var unownedUnsafeVar: AnyObject { // expected-error {{cannot override 'unowned(unsafe)' property with 'unowned' property}}
didSet {}
}
}
diff --git a/test/refactoring/RefactoringKind/crashers.swift b/test/refactoring/RefactoringKind/crashers.swift
index fd0faa0..1bb893b 100644
--- a/test/refactoring/RefactoringKind/crashers.swift
+++ b/test/refactoring/RefactoringKind/crashers.swift
@@ -11,3 +11,12 @@
// RUN: %refactor -source-filename %s -pos=6:5 -end-pos=6:13 | %FileCheck %s -check-prefix=CHECK1
// RUN: %refactor -source-filename %s -pos=8:1 -end-pos=8:13 | %FileCheck %s -check-prefix=CHECK1
// CHECK1: Action begins
+
+// rdar://33972653
+func test() {
+ break FOO
+ continue FOO
+}
+
+// RUN: %refactor -source-filename %s -pos=17:3 -end-pos=18:15 | %FileCheck %s -check-prefix=CHECK2
+// CHECK2: Action begins
diff --git a/test/stdlib/CodableMultifile.swift b/test/stdlib/CodableMultifile.swift
new file mode 100644
index 0000000..cdfc541
--- /dev/null
+++ b/test/stdlib/CodableMultifile.swift
@@ -0,0 +1,79 @@
+// RUN: %empty-directory(%t)
+// RUN: cp %s %t/main.swift
+// RUN: %target-build-swift %t/main.swift %S/Inputs/CodableMultifileOther.swift -module-name main -o %t/main
+// RUN: %target-run %t/main
+// REQUIRES: executable_test
+
+// FIXME: This test could run on Linux too, if we could either use
+// corelibs-foundation, or implement a mock Encoder for testing.
+
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import Foundation
+
+var CodableMultifileTestSuite = TestSuite("CodableMultifile")
+
+// The first test doesn't synthesize encode(to:) at all.
+CodableMultifileTestSuite.test("1") {
+ let derived = DerivedFirst()
+
+ // Make sure the vtable offset matches between this translation unit and
+ // the other file, which requires us to force the encode(to:) member when
+ // type checking this translation unit.
+ expectEqual(false, derived.derivedMember)
+}
+
+// The second test synthesizes init(from:) before encode(to:).
+
+// We define a wrapper so that the virtual method BaseSecond.encode(to:) method
+// is called from outside its module. If we use the conformance of BaseSecond
+// to Codable, we don't expose the bug because the virtual method call is
+// encapsulated in the conformance, which is emitted in the same translation unit
+// as BaseSecond.
+struct WrapperSecond : Encodable {
+ let base: BaseSecond
+
+ func encode(to encoder: Encoder) throws {
+ try base.encode(to: encoder)
+ }
+}
+
+CodableMultifileTestSuite.test("2") {
+ // Make sure we synthesize the init(from:) member before encode(to:) in
+ // this translation unit.
+ _ = BaseSecond.init(from:)
+
+ let base = WrapperSecond(base: BaseSecond())
+ let encoder = JSONEncoder()
+
+ expectEqual(
+ "{\"baseMember\":2}",
+ String(data: try! encoder.encode(base), encoding: .utf8)!)
+}
+
+// The third test synthesizes encode(to:) before init(from:).
+
+// See above.
+struct WrapperThird : Encodable {
+ let base: BaseThird
+
+ func encode(to encoder: Encoder) throws {
+ try base.encode(to: encoder)
+ }
+}
+
+CodableMultifileTestSuite.test("3") {
+ // Make sure we synthesize the encode(to:) member before init(from:) in
+ // this translation unit.
+ _ = BaseThird.encode(to:)
+
+ let base = WrapperThird(base: BaseThird())
+ let encoder = JSONEncoder()
+
+ expectEqual(
+ "{\"baseMember\":3}",
+ String(data: try! encoder.encode(base), encoding: .utf8)!)
+}
+
+runAllTests()
diff --git a/test/stdlib/ErrorBridgedStatic.swift b/test/stdlib/ErrorBridgedStatic.swift
index 7638c15..8ac9677 100644
--- a/test/stdlib/ErrorBridgedStatic.swift
+++ b/test/stdlib/ErrorBridgedStatic.swift
@@ -8,6 +8,9 @@
// REQUIRES: objc_interop
// REQUIRES: static_stdlib
+// rdar://39473208
+// REQUIRES: asserts
+
import StdlibUnittest
class Bar: Foo {
diff --git a/test/stdlib/ErrorHandling.swift b/test/stdlib/ErrorHandling.swift
index ea5d427..945b0dc 100644
--- a/test/stdlib/ErrorHandling.swift
+++ b/test/stdlib/ErrorHandling.swift
@@ -95,9 +95,9 @@
// TODO: Some way to check string was deallocated?
}
-ErrorHandlingTests.test("ErrorHandling/index(where:)") {
+ErrorHandlingTests.test("ErrorHandling/firstIndex(where:)") {
do {
- let _: Int? = try [1, 2, 3].index {
+ let _: Int? = try [1, 2, 3].firstIndex {
throw SillyError.JazzHands
return $0 == $0
}
diff --git a/test/stdlib/FloatingPoint.swift.gyb b/test/stdlib/FloatingPoint.swift.gyb
index fa98f1b..ab8658e 100644
--- a/test/stdlib/FloatingPoint.swift.gyb
+++ b/test/stdlib/FloatingPoint.swift.gyb
@@ -4,10 +4,6 @@
// RUN: %line-directive %t/FloatingPoint.swift -- %target-run %t/a.out
// REQUIRES: executable_test
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
import Swift
import StdlibUnittest
@@ -64,14 +60,24 @@
#if arch(i386) || arch(x86_64)
% end
func expectBitwiseEqual(
- _ expected: ${FloatTy}, _ actual: ${FloatTy}, ${TRACE}
+ _ expected: ${FloatTy}, _ actual: ${FloatTy},
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectEqual(expected.bitPattern, actual.bitPattern, ${trace})
+ expectEqual(expected.bitPattern, actual.bitPattern, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
func expectBitwiseEqual(
- bitPattern expected: ${BitPatternTy}, _ actual: ${FloatTy}, ${TRACE}
+ bitPattern expected: ${BitPatternTy}, _ actual: ${FloatTy},
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
) {
- expectBitwiseEqual(${FloatTy}(bitPattern: expected), actual, ${trace})
+ expectBitwiseEqual(${FloatTy}(bitPattern: expected), actual, message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
% if FloatTy == 'Float80':
#endif
diff --git a/test/stdlib/IndexOfRenaming.swift b/test/stdlib/IndexOfRenaming.swift
new file mode 100644
index 0000000..7b332d6
--- /dev/null
+++ b/test/stdlib/IndexOfRenaming.swift
@@ -0,0 +1,8 @@
+// RUN: %target-typecheck-verify-swift
+
+let a = [10, 20, 30, 40, 50, 60]
+
+_ = a.index(of: 30)
+_ = a.firstIndex(of: 30)
+_ = a.index(where: { $0 > 30 })
+_ = a.firstIndex(where: { $0 > 30 })
diff --git a/test/stdlib/Inputs/CodableMultifileOther.swift b/test/stdlib/Inputs/CodableMultifileOther.swift
new file mode 100644
index 0000000..e527353
--- /dev/null
+++ b/test/stdlib/Inputs/CodableMultifileOther.swift
@@ -0,0 +1,21 @@
+class BaseFirst: Codable {
+ var baseMember = 1
+
+ init() {}
+}
+
+class DerivedFirst: BaseFirst {
+ var derivedMember = false
+}
+
+class BaseSecond: Codable {
+ var baseMember = 2
+
+ init() {}
+}
+
+class BaseThird: Codable {
+ var baseMember = 3
+
+ init() {}
+}
diff --git a/test/stdlib/Inputs/Mirror/MirrorOther.swift b/test/stdlib/Inputs/Mirror/MirrorOther.swift
new file mode 100644
index 0000000..ee9c176
--- /dev/null
+++ b/test/stdlib/Inputs/Mirror/MirrorOther.swift
@@ -0,0 +1,7 @@
+struct OtherStruct {
+ let a: OtherOuter.Inner
+ let b: OtherOuterGeneric<Int>.Inner<String>
+}
+
+struct OtherOuter {}
+struct OtherOuterGeneric<T> {}
diff --git a/test/stdlib/Mirror.swift b/test/stdlib/Mirror.swift
index 1f23fb3..14ab6b3 100644
--- a/test/stdlib/Mirror.swift
+++ b/test/stdlib/Mirror.swift
@@ -10,13 +10,14 @@
//
//===----------------------------------------------------------------------===//
// RUN: %empty-directory(%t)
+// RUN: cp %s %t/main.swift
//
// RUN: if [ %target-runtime == "objc" ]; \
// RUN: then \
// RUN: %target-clang %S/Inputs/Mirror/Mirror.mm -c -o %t/Mirror.mm.o -g && \
-// RUN: %target-build-swift %s -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
+// RUN: %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
// RUN: else \
-// RUN: %target-build-swift %s -o %t/Mirror; \
+// RUN: %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -o %t/Mirror; \
// RUN: fi
// RUN: %target-run %t/Mirror
// REQUIRES: executable_test
@@ -111,7 +112,7 @@
let description = y.testDescription
expectEqual(
"[nil: \"a\", nil: \"b\", nil: \"c\", nil: \"",
- description[description.startIndex..<description.index(of: "d")!])
+ description[description.startIndex..<description.firstIndex(of: "d")!])
}
mirrors.test("LabeledStructure") {
@@ -222,6 +223,12 @@
//===----------------------------------------------------------------------===//
//===--- Class Support ----------------------------------------------------===//
+class DullClass {}
+
+mirrors.test("ClassReflection") {
+ expectEqual(.`class`, Mirror(reflecting: DullClass()).displayStyle)
+}
+
mirrors.test("Class/Root/Uncustomized") {
class A { var a: Int = 1 }
@@ -358,6 +365,7 @@
#if _runtime(_ObjC)
import Foundation
+import MirrorObjC
//===--- ObjC Base Classes ------------------------------------------------===//
@@ -464,6 +472,14 @@
}
}
}
+
+mirrors.test("ObjC") {
+ // Some Foundation classes lie about their ivars, which would crash
+ // a mirror; make sure we are not automatically exposing ivars of
+ // Objective-C classes from the default mirror implementation.
+ expectEqual(0, Mirror(reflecting: HasIVars()).children.count)
+}
+
#endif // _runtime(_ObjC)
//===--- Suppressed Superclass Mirrors ------------------------------------===//
@@ -643,7 +659,7 @@
}
}
-//===--- End Class Support ------------------------------------------------===//
+//===--- Miscellaneous ----------------------------------------------------===//
//===----------------------------------------------------------------------===//
mirrors.test("Addressing") {
@@ -766,16 +782,6 @@
}
}
-#if _runtime(_ObjC)
-import MirrorObjC
-mirrors.test("ObjC") {
- // Some Foundation classes lie about their ivars, which would crash
- // a mirror; make sure we are not automatically exposing ivars of
- // Objective-C classes from the default mirror implementation.
- expectEqual(0, Mirror(reflecting: HasIVars()).children.count)
-}
-#endif
-
mirrors.test("String.init") {
expectEqual("42", String(42))
expectEqual("42", String("42"))
@@ -783,6 +789,949 @@
expectEqual("\"42\"", String(reflecting: "42"))
}
+//===--- Structs ----------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+struct StructWithDefaultMirror {
+ let s: String
+
+ init (_ s: String) {
+ self.s = s
+ }
+}
+
+mirrors.test("Struct/NonGeneric/DefaultMirror") {
+ do {
+ var output = ""
+ dump(StructWithDefaultMirror("123"), to: &output)
+ expectEqual("▿ Mirror.StructWithDefaultMirror\n - s: \"123\"\n", output)
+ }
+
+ do {
+ // Build a String around an interpolation as a way of smoke-testing that
+ // the internal _Mirror implementation gets memory management right.
+ var output = ""
+ dump(StructWithDefaultMirror("\(456)"), to: &output)
+ expectEqual("▿ Mirror.StructWithDefaultMirror\n - s: \"456\"\n", output)
+ }
+
+ expectEqual(
+ .`struct`,
+ Mirror(reflecting: StructWithDefaultMirror("")).displayStyle)
+}
+
+struct GenericStructWithDefaultMirror<T, U> {
+ let first: T
+ let second: U
+}
+
+mirrors.test("Struct/Generic/DefaultMirror") {
+ do {
+ var value = GenericStructWithDefaultMirror<Int, [Any?]>(
+ first: 123,
+ second: ["abc", 456, 789.25])
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ Mirror.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" +
+ " - first: 123\n" +
+ " ▿ second: 3 elements\n" +
+ " ▿ Optional(\"abc\")\n" +
+ " - some: \"abc\"\n" +
+ " ▿ Optional(456)\n" +
+ " - some: 456\n" +
+ " ▿ Optional(789.25)\n" +
+ " - some: 789.25\n"
+
+ expectEqual(expected, output)
+
+ }
+}
+
+//===--- Enums ------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+enum NoPayloadEnumWithDefaultMirror {
+ case A, ß
+}
+
+mirrors.test("Enum/NoPayload/DefaultMirror") {
+ do {
+ let value: [NoPayloadEnumWithDefaultMirror] =
+ [.A, .ß]
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 2 elements\n" +
+ " - Mirror.NoPayloadEnumWithDefaultMirror.A\n" +
+ " - Mirror.NoPayloadEnumWithDefaultMirror.ß\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+enum SingletonNonGenericEnumWithDefaultMirror {
+ case OnlyOne(Int)
+}
+
+mirrors.test("Enum/SingletonNonGeneric/DefaultMirror") {
+ do {
+ let value = SingletonNonGenericEnumWithDefaultMirror.OnlyOne(5)
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ Mirror.SingletonNonGenericEnumWithDefaultMirror.OnlyOne\n" +
+ " - OnlyOne: 5\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+enum SingletonGenericEnumWithDefaultMirror<T> {
+ case OnlyOne(T)
+}
+
+mirrors.test("Enum/SingletonGeneric/DefaultMirror") {
+ do {
+ let value = SingletonGenericEnumWithDefaultMirror.OnlyOne("IIfx")
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ Mirror.SingletonGenericEnumWithDefaultMirror<Swift.String>.OnlyOne\n" +
+ " - OnlyOne: \"IIfx\"\n"
+
+ expectEqual(expected, output)
+ }
+ expectEqual(0, LifetimeTracked.instances)
+ do {
+ let value = SingletonGenericEnumWithDefaultMirror.OnlyOne(
+ LifetimeTracked(0))
+ expectEqual(1, LifetimeTracked.instances)
+ var output = ""
+ dump(value, to: &output)
+ }
+ expectEqual(0, LifetimeTracked.instances)
+}
+
+enum SinglePayloadNonGenericEnumWithDefaultMirror {
+ case Cat
+ case Dog
+ case Volleyball(String, Int)
+}
+
+mirrors.test("Enum/SinglePayloadNonGeneric/DefaultMirror") {
+ do {
+ let value: [SinglePayloadNonGenericEnumWithDefaultMirror] =
+ [.Cat,
+ .Dog,
+ .Volleyball("Wilson", 2000)]
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 3 elements\n" +
+ " - Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Cat\n" +
+ " - Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Dog\n" +
+ " ▿ Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Volleyball\n" +
+ " ▿ Volleyball: (2 elements)\n" +
+ " - .0: \"Wilson\"\n" +
+ " - .1: 2000\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+enum SinglePayloadGenericEnumWithDefaultMirror<T, U> {
+ case Well
+ case Faucet
+ case Pipe(T, U)
+}
+
+mirrors.test("Enum/SinglePayloadGeneric/DefaultMirror") {
+ do {
+ let value: [SinglePayloadGenericEnumWithDefaultMirror<Int, [Int]>] =
+ [.Well,
+ .Faucet,
+ .Pipe(408, [415])]
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 3 elements\n" +
+ " - Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Well\n" +
+ " - Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Faucet\n" +
+ " ▿ Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Pipe\n" +
+ " ▿ Pipe: (2 elements)\n" +
+ " - .0: 408\n" +
+ " ▿ .1: 1 element\n" +
+ " - 415\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+enum MultiPayloadTagBitsNonGenericEnumWithDefaultMirror {
+ case Plus
+ case SE30
+ case Classic(mhz: Int)
+ case Performa(model: Int)
+}
+
+mirrors.test("Enum/MultiPayloadTagBitsNonGeneric/DefaultMirror") {
+ do {
+ let value: [MultiPayloadTagBitsNonGenericEnumWithDefaultMirror] =
+ [.Plus,
+ .SE30,
+ .Classic(mhz: 16),
+ .Performa(model: 220)]
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 4 elements\n" +
+ " - Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" +
+ " - Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" +
+ " ▿ Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" +
+ " ▿ Classic: (1 element)\n" +
+ " - mhz: 16\n" +
+ " ▿ Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" +
+ " ▿ Performa: (1 element)\n" +
+ " - model: 220\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+class Floppy {
+ let capacity: Int
+
+ init(capacity: Int) { self.capacity = capacity }
+}
+
+class CDROM {
+ let capacity: Int
+
+ init(capacity: Int) { self.capacity = capacity }
+}
+
+enum MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror {
+ case MacWrite
+ case MacPaint
+ case FileMaker
+ case ClarisWorks(floppy: Floppy)
+ case HyperCard(cdrom: CDROM)
+}
+
+mirrors.test("Enum/MultiPayloadSpareBitsNonGeneric/DefaultMirror") {
+ do {
+ let value: [MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror] =
+ [.MacWrite,
+ .MacPaint,
+ .FileMaker,
+ .ClarisWorks(floppy: Floppy(capacity: 800)),
+ .HyperCard(cdrom: CDROM(capacity: 600))]
+
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 5 elements\n" +
+ " - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacWrite\n" +
+ " - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" +
+ " - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" +
+ " ▿ Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
+ " ▿ ClarisWorks: (1 element)\n" +
+ " ▿ floppy: Mirror.Floppy #0\n" +
+ " - capacity: 800\n" +
+ " ▿ Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" +
+ " ▿ HyperCard: (1 element)\n" +
+ " ▿ cdrom: Mirror.CDROM #1\n" +
+ " - capacity: 600\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+enum MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror {
+ case MacWrite
+ case MacPaint
+ case FileMaker
+ case ClarisWorks(floppy: Bool)
+ case HyperCard(cdrom: Bool)
+}
+
+mirrors.test("Enum/MultiPayloadTagBitsSmallNonGeneric/DefaultMirror") {
+ do {
+ let value: [MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror] =
+ [.MacWrite,
+ .MacPaint,
+ .FileMaker,
+ .ClarisWorks(floppy: true),
+ .HyperCard(cdrom: false)]
+
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 5 elements\n" +
+ " - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacWrite\n" +
+ " - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" +
+ " - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" +
+ " ▿ Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
+ " ▿ ClarisWorks: (1 element)\n" +
+ " - floppy: true\n" +
+ " ▿ Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" +
+ " ▿ HyperCard: (1 element)\n" +
+ " - cdrom: false\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+enum MultiPayloadGenericEnumWithDefaultMirror<T, U> {
+ case IIe
+ case IIgs
+ case Centris(ram: T)
+ case Quadra(hdd: U)
+ case PowerBook170
+ case PowerBookDuo220
+}
+
+mirrors.test("Enum/MultiPayloadGeneric/DefaultMirror") {
+ do {
+ let value: [MultiPayloadGenericEnumWithDefaultMirror<Int, String>] =
+ [.IIe,
+ .IIgs,
+ .Centris(ram: 4096),
+ .Quadra(hdd: "160MB"),
+ .PowerBook170,
+ .PowerBookDuo220]
+
+ var output = ""
+ dump(value, to: &output)
+
+ let expected =
+ "▿ 6 elements\n" +
+ " - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" +
+ " - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" +
+ " ▿ Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" +
+ " ▿ Centris: (1 element)\n" +
+ " - ram: 4096\n" +
+ " ▿ Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" +
+ " ▿ Quadra: (1 element)\n" +
+ " - hdd: \"160MB\"\n" +
+ " - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" +
+ " - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n"
+
+ expectEqual(expected, output)
+ }
+ expectEqual(0, LifetimeTracked.instances)
+ do {
+ let value = MultiPayloadGenericEnumWithDefaultMirror<LifetimeTracked,
+ LifetimeTracked>
+ .Quadra(hdd: LifetimeTracked(0))
+ expectEqual(1, LifetimeTracked.instances)
+ var output = ""
+ dump(value, to: &output)
+ }
+ expectEqual(0, LifetimeTracked.instances)
+}
+
+enum Foo<T> {
+ indirect case Foo(Int)
+ case Bar(T)
+}
+
+enum List<T> {
+ case Nil
+ indirect case Cons(first: T, rest: List<T>)
+}
+
+mirrors.test("Enum/IndirectGeneric/DefaultMirror") {
+ let x = Foo<String>.Foo(22)
+ let y = Foo<String>.Bar("twenty-two")
+
+ expectEqual("\(x)", "Foo(22)")
+ expectEqual("\(y)", "Bar(\"twenty-two\")")
+
+ let list = List.Cons(first: 0, rest: .Cons(first: 1, rest: .Nil))
+ expectEqual("Cons(first: 0, rest: Mirror.List<Swift.Int>.Cons(first: 1, rest: Mirror.List<Swift.Int>.Nil))",
+ "\(list)")
+}
+
+enum MyError: Error {
+ case myFirstError(LifetimeTracked)
+}
+
+mirrors.test("Enum/CaseName/Error") {
+ // Just make sure this doesn't leak.
+ let e: Error = MyError.myFirstError(LifetimeTracked(0))
+ _ = String(describing: e)
+}
+
+class Brilliant : CustomReflectable {
+ let first: Int
+ let second: String
+
+ init(_ fst: Int, _ snd: String) {
+ self.first = fst
+ self.second = snd
+ }
+
+ var customMirror: Mirror {
+ return Mirror(self, children: ["first": first, "second": second, "self": self])
+ }
+}
+
+//===--- Custom mirrors ---------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+/// Subclasses inherit their parents' custom mirrors.
+class Irradiant : Brilliant {
+ init() {
+ super.init(400, "")
+ }
+}
+
+mirrors.test("CustomMirror") {
+ do {
+ var output = ""
+ dump(Brilliant(123, "four five six"), to: &output)
+
+ let expected =
+ "▿ Mirror.Brilliant #0\n" +
+ " - first: 123\n" +
+ " - second: \"four five six\"\n" +
+ " ▿ self: Mirror.Brilliant #0\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var output = ""
+ dump(Brilliant(123, "four five six"), to: &output, maxDepth: 0)
+ expectEqual("▹ Mirror.Brilliant #0\n", output)
+ }
+
+ do {
+ var output = ""
+ dump(Brilliant(123, "four five six"), to: &output, maxItems: 3)
+
+ let expected =
+ "▿ Mirror.Brilliant #0\n" +
+ " - first: 123\n" +
+ " - second: \"four five six\"\n" +
+ " (1 more child)\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var output = ""
+ dump(Brilliant(123, "four five six"), to: &output, maxItems: 2)
+
+ let expected =
+ "▿ Mirror.Brilliant #0\n" +
+ " - first: 123\n" +
+ " (2 more children)\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var output = ""
+ dump(Brilliant(123, "four five six"), to: &output, maxItems: 1)
+
+ let expected =
+ "▿ Mirror.Brilliant #0\n" +
+ " (3 children)\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("CustomMirrorIsInherited") {
+ do {
+ var output = ""
+ dump(Irradiant(), to: &output)
+
+ let expected =
+ "▿ Mirror.Brilliant #0\n" +
+ " - first: 400\n" +
+ " - second: \"\"\n" +
+ " ▿ self: Mirror.Brilliant #0\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+//===--- Metatypes --------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+protocol SomeNativeProto {}
+extension Int: SomeNativeProto {}
+
+class SomeClass {}
+
+mirrors.test("MetatypeMirror") {
+ do {
+ var output = ""
+ let concreteMetatype = Int.self
+ dump(concreteMetatype, to: &output)
+
+ let expectedInt = "- Swift.Int #0\n"
+ expectEqual(expectedInt, output)
+
+ let anyMetatype: Any.Type = Int.self
+ output = ""
+ dump(anyMetatype, to: &output)
+ expectEqual(expectedInt, output)
+
+ let nativeProtocolMetatype: SomeNativeProto.Type = Int.self
+ output = ""
+ dump(nativeProtocolMetatype, to: &output)
+ expectEqual(expectedInt, output)
+
+ let concreteClassMetatype = SomeClass.self
+ let expectedSomeClass = "- Mirror.SomeClass #0\n"
+ output = ""
+ dump(concreteClassMetatype, to: &output)
+ expectEqual(expectedSomeClass, output)
+
+ let nativeProtocolConcreteMetatype = SomeNativeProto.self
+ let expectedNativeProtocolConcrete = "- Mirror.SomeNativeProto #0\n"
+ output = ""
+ dump(nativeProtocolConcreteMetatype, to: &output)
+ expectEqual(expectedNativeProtocolConcrete, output)
+ }
+}
+
+//===--- Tuples -----------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+mirrors.test("TupleMirror") {
+ do {
+ var output = ""
+ let tuple =
+ (Brilliant(384, "seven six eight"), StructWithDefaultMirror("nine"))
+ dump(tuple, to: &output)
+
+ let expected =
+ "▿ (2 elements)\n" +
+ " ▿ .0: Mirror.Brilliant #0\n" +
+ " - first: 384\n" +
+ " - second: \"seven six eight\"\n" +
+ " ▿ self: Mirror.Brilliant #0\n" +
+ " ▿ .1: Mirror.StructWithDefaultMirror\n" +
+ " - s: \"nine\"\n"
+
+ expectEqual(expected, output)
+
+ expectEqual(.tuple, Mirror(reflecting: tuple).displayStyle)
+ }
+
+ do {
+ // A tuple of stdlib types with mirrors.
+ var output = ""
+ let tuple = (1, 2.5, false, "three")
+ dump(tuple, to: &output)
+
+ let expected =
+ "▿ (4 elements)\n" +
+ " - .0: 1\n" +
+ " - .1: 2.5\n" +
+ " - .2: false\n" +
+ " - .3: \"three\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // A nested tuple.
+ var output = ""
+ let tuple = (1, ("Hello", "World"))
+ dump(tuple, to: &output)
+
+ let expected =
+ "▿ (2 elements)\n" +
+ " - .0: 1\n" +
+ " ▿ .1: (2 elements)\n" +
+ " - .0: \"Hello\"\n" +
+ " - .1: \"World\"\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+//===--- Standard library types -------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+mirrors.test("String/Mirror") {
+ do {
+ var output = ""
+ dump("", to: &output)
+
+ let expected =
+ "- \"\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+0061 LATIN SMALL LETTER A
+ // U+304B HIRAGANA LETTER KA
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ // U+1F425 FRONT-FACING BABY CHICK
+ var output = ""
+ dump("\u{61}\u{304b}\u{3099}\u{1f425}", to: &output)
+
+ let expected =
+ "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("String.UTF8View/Mirror") {
+ // U+0061 LATIN SMALL LETTER A
+ // U+304B HIRAGANA LETTER KA
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ var output = ""
+ dump("\u{61}\u{304b}\u{3099}".utf8, to: &output)
+
+ let expected =
+ "▿ UTF8View(\"\u{61}\u{304b}\u{3099}\")\n" +
+ " - 97\n" +
+ " - 227\n" +
+ " - 129\n" +
+ " - 139\n" +
+ " - 227\n" +
+ " - 130\n" +
+ " - 153\n"
+
+ expectEqual(expected, output)
+}
+
+mirrors.test("String.UTF16View/Mirror") {
+ // U+0061 LATIN SMALL LETTER A
+ // U+304B HIRAGANA LETTER KA
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ // U+1F425 FRONT-FACING BABY CHICK
+ var output = ""
+ dump("\u{61}\u{304b}\u{3099}\u{1f425}".utf16, to: &output)
+
+ let expected =
+ "▿ StringUTF16(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
+ " - 97\n" +
+ " - 12363\n" +
+ " - 12441\n" +
+ " - 55357\n" +
+ " - 56357\n"
+
+ expectEqual(expected, output)
+}
+
+mirrors.test("String.UnicodeScalarView/Mirror") {
+ // U+0061 LATIN SMALL LETTER A
+ // U+304B HIRAGANA LETTER KA
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ // U+1F425 FRONT-FACING BABY CHICK
+ var output = ""
+ dump("\u{61}\u{304b}\u{3099}\u{1f425}".unicodeScalars, to: &output)
+
+ let expected =
+ "▿ StringUnicodeScalarView(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
+ " - \"\u{61}\"\n" +
+ " - \"\\u{304B}\"\n" +
+ " - \"\\u{3099}\"\n" +
+ " - \"\\u{0001F425}\"\n"
+
+ expectEqual(expected, output)
+}
+
+mirrors.test("Character/Mirror") {
+ do {
+ // U+0061 LATIN SMALL LETTER A
+ let input: Character = "\u{61}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\u{61}\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+304B HIRAGANA LETTER KA
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ let input: Character = "\u{304b}\u{3099}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\u{304b}\u{3099}\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+1F425 FRONT-FACING BABY CHICK
+ let input: Character = "\u{1f425}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\u{1f425}\"\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("UnicodeScalar") {
+ do {
+ // U+0061 LATIN SMALL LETTER A
+ let input: UnicodeScalar = "\u{61}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\u{61}\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+304B HIRAGANA LETTER KA
+ let input: UnicodeScalar = "\u{304b}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\\u{304B}\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ let input: UnicodeScalar = "\u{3099}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\\u{3099}\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+1F425 FRONT-FACING BABY CHICK
+ let input: UnicodeScalar = "\u{1f425}"
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- \"\\u{0001F425}\"\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("Bool") {
+ do {
+ var output = ""
+ dump(false, to: &output)
+
+ let expected =
+ "- false\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var output = ""
+ dump(true, to: &output)
+
+ let expected =
+ "- true\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+// FIXME: these tests should cover Float80.
+// FIXME: these tests should be automatically generated from the list of
+// available floating point types.
+mirrors.test("Float") {
+ do {
+ var output = ""
+ dump(Float.nan, to: &output)
+
+ let expected =
+ "- nan\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var output = ""
+ dump(Float.infinity, to: &output)
+
+ let expected =
+ "- inf\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var input: Float = 42.125
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- 42.125\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("Double") {
+ do {
+ var output = ""
+ dump(Double.nan, to: &output)
+
+ let expected =
+ "- nan\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var output = ""
+ dump(Double.infinity, to: &output)
+
+ let expected =
+ "- inf\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ var input: Double = 42.125
+ var output = ""
+ dump(input, to: &output)
+
+ let expected =
+ "- 42.125\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("StaticString/Mirror") {
+ do {
+ var output = ""
+ dump("" as StaticString, to: &output)
+
+ let expected =
+ "- \"\"\n"
+
+ expectEqual(expected, output)
+ }
+
+ do {
+ // U+0061 LATIN SMALL LETTER A
+ // U+304B HIRAGANA LETTER KA
+ // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+ // U+1F425 FRONT-FACING BABY CHICK
+ var output = ""
+ dump("\u{61}\u{304b}\u{3099}\u{1f425}" as StaticString, to: &output)
+
+ let expected =
+ "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
+
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("DictionaryIterator/Mirror") {
+ let d: [MinimalHashableValue : OpaqueValue<Int>] =
+ [ MinimalHashableValue(0) : OpaqueValue(0) ]
+
+ var output = ""
+ dump(d.makeIterator(), to: &output)
+
+ let expected =
+ "- Swift.DictionaryIterator<StdlibUnittest.MinimalHashableValue, StdlibUnittest.OpaqueValue<Swift.Int>>\n"
+
+ expectEqual(expected, output)
+}
+
+mirrors.test("SetIterator/Mirror") {
+ let s: Set<MinimalHashableValue> = [ MinimalHashableValue(0)]
+
+ var output = ""
+ dump(s.makeIterator(), to: &output)
+
+ let expected =
+ "- Swift.SetIterator<StdlibUnittest.MinimalHashableValue>\n"
+
+ expectEqual(expected, output)
+}
+
+//===--- Regressions ------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+// A struct type and class type whose NominalTypeDescriptor.FieldNames
+// data is exactly eight bytes long. FieldNames data of exactly
+// 4 or 8 or 16 bytes was once miscompiled on arm64.
+struct EightByteFieldNamesStruct {
+ let abcdef = 42
+}
+class EightByteFieldNamesClass {
+ let abcdef = 42
+}
+
+mirrors.test("FieldNamesBug") {
+ do {
+ let expected =
+ "▿ Mirror.EightByteFieldNamesStruct\n" +
+ " - abcdef: 42\n"
+ var output = ""
+ dump(EightByteFieldNamesStruct(), to: &output)
+ expectEqual(expected, output)
+ }
+
+ do {
+ let expected =
+ "▿ Mirror.EightByteFieldNamesClass #0\n" +
+ " - abcdef: 42\n"
+ var output = ""
+ dump(EightByteFieldNamesClass(), to: &output)
+ expectEqual(expected, output)
+ }
+}
+
+mirrors.test("MirrorMirror") {
+ var object = 1
+ var mirror = Mirror(reflecting: object)
+ var mirrorMirror = Mirror(reflecting: mirror)
+
+ expectEqual(0, mirrorMirror.children.count)
+}
+
+mirrors.test("OpaquePointer/null") {
+ // Don't crash on null pointers. rdar://problem/19708338
+ let pointer: OpaquePointer? = nil
+ let mirror = Mirror(reflecting: pointer)
+ expectEqual(0, mirror.children.count)
+}
+
struct a<b> {
enum c{}
}
@@ -791,11 +1740,34 @@
var constraints: [Int: a<f>.c] = [:]
}
-mirrors.test("field with generic nested type") {
+mirrors.test("GenericNestedTypeField") {
let x = e<d>()
expectTrue(type(of: Mirror(reflecting: x).children.first!.value)
== [Int: a<d>.c].self)
}
+extension OtherOuter {
+ struct Inner {}
+}
+
+extension OtherOuterGeneric {
+ struct Inner<U> {}
+}
+
+mirrors.test("SymbolicReferenceInsideType") {
+ let s = OtherStruct(a: OtherOuter.Inner(),
+ b: OtherOuterGeneric<Int>.Inner<String>())
+
+ var output = ""
+ dump(s, to: &output)
+
+ let expected =
+ "▿ Mirror.OtherStruct\n" +
+ " - a: Mirror.OtherOuter.Inner\n" +
+ " - b: Mirror.OtherOuterGeneric<Swift.Int>.Inner<Swift.String>\n"
+
+ expectEqual(expected, output)
+}
+
runAllTests()
diff --git a/test/stdlib/PrintFloat.swift.gyb b/test/stdlib/PrintFloat.swift.gyb
index 90b4314..e689206 100644
--- a/test/stdlib/PrintFloat.swift.gyb
+++ b/test/stdlib/PrintFloat.swift.gyb
@@ -5,10 +5,6 @@
// RUN: %line-directive %t/FloatingPointPrinting.swift -- %target-run %t/main.out --locale ru_RU.UTF-8
// REQUIRES: executable_test
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
import StdlibUnittest
#if os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
import Glibc
@@ -347,11 +343,22 @@
// Verify that a particular value provides a specific description string.
// Also check that the generated strings actually satisfy our
// accuracy requirements.
-fileprivate func expectDescription(_ expected: String, _ object: ${FloatType}, ${TRACE}) {
- expectEqual(expected, object.description, ${trace})
- expectEqual(expected, object.debugDescription, ${trace})
- expectAccurateDescription(object, ${trace})
- }
+fileprivate func expectDescription(_ expected: String, _ object: ${FloatType},
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
+ expectEqual(expected, object.description,
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectEqual(expected, object.debugDescription,
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+ expectAccurateDescription(object,
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
// Verify our key requirements:
//
@@ -364,7 +371,12 @@
// * Close. If there is more than one accurate and short value, we want the one
// that is closest (as an infinitely-precise real number) to the original
// binary float (interpreted as an infinitely-precise real number).
-fileprivate func expectAccurateDescription(_ object: ${FloatType}, ${TRACE}) {
+fileprivate func expectAccurateDescription(_ object: ${FloatType},
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) {
if !object.isFinite {
return
}
@@ -376,11 +388,15 @@
let text = object.debugDescription
if let roundTrip = ${FloatType}(text) {
if object != roundTrip {
- expectationFailure("Round-trip inaccuracy: \(object) != \(roundTrip)", trace: ${trace})
+ expectationFailure("Round-trip inaccuracy: \(object) != \(roundTrip)",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
return
}
} else {
- expectationFailure("Failed to parse \(text)", trace: ${trace})
+ expectationFailure("Failed to parse \(text)",
+ trace: message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
return
}
@@ -397,9 +413,16 @@
% end
// Special helper for NaN values
-fileprivate func expectNaN<T>(_ expected: String, _ object: T, ${TRACE}) where T: FloatingPoint & CustomDebugStringConvertible & CustomStringConvertible {
+fileprivate func expectNaN<T>(_ expected: String, _ object: T,
+ _ message: @autoclosure () -> String = "",
+ stackTrace: SourceLocStack = SourceLocStack(),
+ showFrame: Bool = true,
+ file: String = #file, line: UInt = #line
+) where T: FloatingPoint & CustomDebugStringConvertible & CustomStringConvertible {
// Regular description always returns "nan"
- expectEqual("nan", object.description, ${trace})
+ expectEqual("nan", object.description,
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
// debugDescription prints full details about NaNs, which is tricky to test
// because NaNs often get truncated: various implementations force all NaNs
@@ -409,7 +432,9 @@
#if arch(x86_64)
// Verify the exact debugDescription value only on x86_64, where we
// know the exact expected String:
- expectEqual(expected, object.debugDescription, ${trace})
+ expectEqual(expected, object.debugDescription,
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
#endif
// On all platforms, we verify that the generated debugDescription text
@@ -428,7 +453,9 @@
// Fixed text "nan"
if actual.prefix(3) != "nan" {
- expectationFailure("Badly formatted NaN debug description (expected 'nan'): \(object.debugDescription)", trace: ${trace})
+ expectationFailure("Badly formatted NaN debug description (expected 'nan'): \(object.debugDescription)", trace:
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
return
}
actual = String(actual.dropFirst(3))
@@ -439,7 +466,9 @@
while !actual.isEmpty {
if actual.hasPrefix(")") {
if actual != ")" {
- expectationFailure("Malformed NaN: extra text after payload: \(object.debugDescription)", trace: ${trace})
+ expectationFailure("Malformed NaN: extra text after payload: \(object.debugDescription)", trace:
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
return
} else {
@@ -447,9 +476,13 @@
}
actual = String(actual.dropFirst())
}
- expectationFailure("Malformed NaN: no closing parenthesis after payload: \(object.debugDescription)", trace: ${trace})
+ expectationFailure("Malformed NaN: no closing parenthesis after payload: \(object.debugDescription)", trace:
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
} else if !actual.isEmpty {
- expectationFailure("Badly formatted NaN debug description has invalid text after 'nan'. Expected '(0x': \(object.debugDescription)", trace: ${trace})
+ expectationFailure("Badly formatted NaN debug description has invalid text after 'nan'. Expected '(0x': \(object.debugDescription)", trace:
+ message(),
+ stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
@@ -481,7 +514,7 @@
// this logic to help verify that the output does not depend on
// the C locale.
PrintTests.setUp {
- if let localeArgIndex = CommandLine.arguments.index(of: "--locale") {
+ if let localeArgIndex = CommandLine.arguments.firstIndex(of: "--locale") {
let locale = CommandLine.arguments[localeArgIndex + 1]
expectEqual("ru_RU.UTF-8", locale)
setlocale(LC_ALL, locale)
diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb
index 67ee2bf..e181db7 100644
--- a/test/stdlib/Runtime.swift.gyb
+++ b/test/stdlib/Runtime.swift.gyb
@@ -602,385 +602,8 @@
expectEqual("▿ 2 elements\n - 42\n - 4242\n", output)
}
-struct StructWithDefaultMirror {
- let s: String
- init (_ s: String) {
- self.s = s
- }
-}
-
-Reflection.test("Struct/NonGeneric/DefaultMirror") {
- do {
- var output = ""
- dump(StructWithDefaultMirror("123"), to: &output)
- expectEqual("▿ a.StructWithDefaultMirror\n - s: \"123\"\n", output)
- }
-
- do {
- // Build a String around an interpolation as a way of smoke-testing that
- // the internal _Mirror implementation gets memory management right.
- var output = ""
- dump(StructWithDefaultMirror("\(456)"), to: &output)
- expectEqual("▿ a.StructWithDefaultMirror\n - s: \"456\"\n", output)
- }
-
- expectEqual(
- .`struct`,
- Mirror(reflecting: StructWithDefaultMirror("")).displayStyle)
-}
-
-struct GenericStructWithDefaultMirror<T, U> {
- let first: T
- let second: U
-}
-
-Reflection.test("Struct/Generic/DefaultMirror") {
- do {
- var value = GenericStructWithDefaultMirror<Int, [Any?]>(
- first: 123,
- second: ["abc", 456, 789.25])
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ a.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" +
- " - first: 123\n" +
- " ▿ second: 3 elements\n" +
- " ▿ Optional(\"abc\")\n" +
- " - some: \"abc\"\n" +
- " ▿ Optional(456)\n" +
- " - some: 456\n" +
- " ▿ Optional(789.25)\n" +
- " - some: 789.25\n"
-
- expectEqual(expected, output)
-
- }
-}
-
-enum NoPayloadEnumWithDefaultMirror {
- case A, ß
-}
-
-Reflection.test("Enum/NoPayload/DefaultMirror") {
- do {
- let value: [NoPayloadEnumWithDefaultMirror] =
- [.A, .ß]
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 2 elements\n" +
- " - a.NoPayloadEnumWithDefaultMirror.A\n" +
- " - a.NoPayloadEnumWithDefaultMirror.ß\n"
-
- expectEqual(expected, output)
- }
-}
-
-enum SingletonNonGenericEnumWithDefaultMirror {
- case OnlyOne(Int)
-}
-
-Reflection.test("Enum/SingletonNonGeneric/DefaultMirror") {
- do {
- let value = SingletonNonGenericEnumWithDefaultMirror.OnlyOne(5)
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ a.SingletonNonGenericEnumWithDefaultMirror.OnlyOne\n" +
- " - OnlyOne: 5\n"
-
- expectEqual(expected, output)
- }
-}
-
-enum SingletonGenericEnumWithDefaultMirror<T> {
- case OnlyOne(T)
-}
-
-Reflection.test("Enum/SingletonGeneric/DefaultMirror") {
- do {
- let value = SingletonGenericEnumWithDefaultMirror.OnlyOne("IIfx")
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ a.SingletonGenericEnumWithDefaultMirror<Swift.String>.OnlyOne\n" +
- " - OnlyOne: \"IIfx\"\n"
-
- expectEqual(expected, output)
- }
- expectEqual(0, LifetimeTracked.instances)
- do {
- let value = SingletonGenericEnumWithDefaultMirror.OnlyOne(
- LifetimeTracked(0))
- expectEqual(1, LifetimeTracked.instances)
- var output = ""
- dump(value, to: &output)
- }
- expectEqual(0, LifetimeTracked.instances)
-}
-
-enum SinglePayloadNonGenericEnumWithDefaultMirror {
- case Cat
- case Dog
- case Volleyball(String, Int)
-}
-
-Reflection.test("Enum/SinglePayloadNonGeneric/DefaultMirror") {
- do {
- let value: [SinglePayloadNonGenericEnumWithDefaultMirror] =
- [.Cat,
- .Dog,
- .Volleyball("Wilson", 2000)]
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 3 elements\n" +
- " - a.SinglePayloadNonGenericEnumWithDefaultMirror.Cat\n" +
- " - a.SinglePayloadNonGenericEnumWithDefaultMirror.Dog\n" +
- " ▿ a.SinglePayloadNonGenericEnumWithDefaultMirror.Volleyball\n" +
- " ▿ Volleyball: (2 elements)\n" +
- " - .0: \"Wilson\"\n" +
- " - .1: 2000\n"
-
- expectEqual(expected, output)
- }
-}
-
-enum SinglePayloadGenericEnumWithDefaultMirror<T, U> {
- case Well
- case Faucet
- case Pipe(T, U)
-}
-
-Reflection.test("Enum/SinglePayloadGeneric/DefaultMirror") {
- do {
- let value: [SinglePayloadGenericEnumWithDefaultMirror<Int, [Int]>] =
- [.Well,
- .Faucet,
- .Pipe(408, [415])]
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 3 elements\n" +
- " - a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Well\n" +
- " - a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Faucet\n" +
- " ▿ a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Pipe\n" +
- " ▿ Pipe: (2 elements)\n" +
- " - .0: 408\n" +
- " ▿ .1: 1 element\n" +
- " - 415\n"
-
- expectEqual(expected, output)
- }
-}
-
-enum MultiPayloadTagBitsNonGenericEnumWithDefaultMirror {
- case Plus
- case SE30
- case Classic(mhz: Int)
- case Performa(model: Int)
-}
-
-Reflection.test("Enum/MultiPayloadTagBitsNonGeneric/DefaultMirror") {
- do {
- let value: [MultiPayloadTagBitsNonGenericEnumWithDefaultMirror] =
- [.Plus,
- .SE30,
- .Classic(mhz: 16),
- .Performa(model: 220)]
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 4 elements\n" +
- " - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" +
- " - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" +
- " ▿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" +
- " ▿ Classic: (1 element)\n" +
- " - mhz: 16\n" +
- " ▿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" +
- " ▿ Performa: (1 element)\n" +
- " - model: 220\n"
-
- expectEqual(expected, output)
- }
-}
-
-class Floppy {
- let capacity: Int
-
- init(capacity: Int) { self.capacity = capacity }
-}
-
-class CDROM {
- let capacity: Int
-
- init(capacity: Int) { self.capacity = capacity }
-}
-
-enum MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror {
- case MacWrite
- case MacPaint
- case FileMaker
- case ClarisWorks(floppy: Floppy)
- case HyperCard(cdrom: CDROM)
-}
-
-Reflection.test("Enum/MultiPayloadSpareBitsNonGeneric/DefaultMirror") {
- do {
- let value: [MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror] =
- [.MacWrite,
- .MacPaint,
- .FileMaker,
- .ClarisWorks(floppy: Floppy(capacity: 800)),
- .HyperCard(cdrom: CDROM(capacity: 600))]
-
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 5 elements\n" +
- " - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacWrite\n" +
- " - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" +
- " - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" +
- " ▿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
- " ▿ ClarisWorks: (1 element)\n" +
- " ▿ floppy: a.Floppy #0\n" +
- " - capacity: 800\n" +
- " ▿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" +
- " ▿ HyperCard: (1 element)\n" +
- " ▿ cdrom: a.CDROM #1\n" +
- " - capacity: 600\n"
-
- expectEqual(expected, output)
- }
-}
-
-enum MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror {
- case MacWrite
- case MacPaint
- case FileMaker
- case ClarisWorks(floppy: Bool)
- case HyperCard(cdrom: Bool)
-}
-
-Reflection.test("Enum/MultiPayloadTagBitsSmallNonGeneric/DefaultMirror") {
- do {
- let value: [MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror] =
- [.MacWrite,
- .MacPaint,
- .FileMaker,
- .ClarisWorks(floppy: true),
- .HyperCard(cdrom: false)]
-
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 5 elements\n" +
- " - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacWrite\n" +
- " - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" +
- " - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" +
- " ▿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
- " ▿ ClarisWorks: (1 element)\n" +
- " - floppy: true\n" +
- " ▿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" +
- " ▿ HyperCard: (1 element)\n" +
- " - cdrom: false\n"
-
- expectEqual(expected, output)
- }
-}
-
-enum MultiPayloadGenericEnumWithDefaultMirror<T, U> {
- case IIe
- case IIgs
- case Centris(ram: T)
- case Quadra(hdd: U)
- case PowerBook170
- case PowerBookDuo220
-}
-
-Reflection.test("Enum/MultiPayloadGeneric/DefaultMirror") {
- do {
- let value: [MultiPayloadGenericEnumWithDefaultMirror<Int, String>] =
- [.IIe,
- .IIgs,
- .Centris(ram: 4096),
- .Quadra(hdd: "160MB"),
- .PowerBook170,
- .PowerBookDuo220]
-
- var output = ""
- dump(value, to: &output)
-
- let expected =
- "▿ 6 elements\n" +
- " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" +
- " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" +
- " ▿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" +
- " ▿ Centris: (1 element)\n" +
- " - ram: 4096\n" +
- " ▿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" +
- " ▿ Quadra: (1 element)\n" +
- " - hdd: \"160MB\"\n" +
- " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" +
- " - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n"
-
- expectEqual(expected, output)
- }
- expectEqual(0, LifetimeTracked.instances)
- do {
- let value = MultiPayloadGenericEnumWithDefaultMirror<LifetimeTracked,
- LifetimeTracked>
- .Quadra(hdd: LifetimeTracked(0))
- expectEqual(1, LifetimeTracked.instances)
- var output = ""
- dump(value, to: &output)
- }
- expectEqual(0, LifetimeTracked.instances)
-}
-
-enum Foo<T> {
- indirect case Foo(Int)
- case Bar(T)
-}
-
-enum List<T> {
- case Nil
- indirect case Cons(first: T, rest: List<T>)
-}
-
-Reflection.test("Enum/IndirectGeneric/DefaultMirror") {
- let x = Foo<String>.Foo(22)
- let y = Foo<String>.Bar("twenty-two")
-
- expectEqual("\(x)", "Foo(22)")
- expectEqual("\(y)", "Bar(\"twenty-two\")")
-
- let list = List.Cons(first: 0, rest: .Cons(first: 1, rest: .Nil))
- expectEqual("Cons(first: 0, rest: a.List<Swift.Int>.Cons(first: 1, rest: a.List<Swift.Int>.Nil))",
- "\(list)")
-}
-
-enum MyError: Error {
- case myFirstError(LifetimeTracked)
-}
-
-Reflection.test("Enum/CaseName/Error") {
- // Just make sure this doesn't leak.
- let e: Error = MyError.myFirstError(LifetimeTracked(0))
- _ = String(describing: e)
-}
-
-class Brilliant : CustomReflectable {
+class Brilliant {
let first: Int
let second: String
@@ -988,74 +611,6 @@
self.first = fst
self.second = snd
}
-
- var customMirror: Mirror {
- return Mirror(self, children: ["first": first, "second": second, "self": self])
- }
-}
-
-/// Subclasses inherit their parents' custom mirrors.
-class Irradiant : Brilliant {
- init() {
- super.init(400, "")
- }
-}
-
-Reflection.test("CustomMirror") {
- do {
- var output = ""
- dump(Brilliant(123, "four five six"), to: &output)
-
- let expected =
- "▿ a.Brilliant #0\n" +
- " - first: 123\n" +
- " - second: \"four five six\"\n" +
- " ▿ self: a.Brilliant #0\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var output = ""
- dump(Brilliant(123, "four five six"), to: &output, maxDepth: 0)
- expectEqual("▹ a.Brilliant #0\n", output)
- }
-
- do {
- var output = ""
- dump(Brilliant(123, "four five six"), to: &output, maxItems: 3)
-
- let expected =
- "▿ a.Brilliant #0\n" +
- " - first: 123\n" +
- " - second: \"four five six\"\n" +
- " (1 more child)\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var output = ""
- dump(Brilliant(123, "four five six"), to: &output, maxItems: 2)
-
- let expected =
- "▿ a.Brilliant #0\n" +
- " - first: 123\n" +
- " (2 more children)\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var output = ""
- dump(Brilliant(123, "four five six"), to: &output, maxItems: 1)
-
- let expected =
- "▿ a.Brilliant #0\n" +
- " (3 children)\n"
-
- expectEqual(expected, output)
- }
}
Reflection.test("ObjectIdentifier/Hashable,Comparable") {
@@ -1102,475 +657,6 @@
}
-Reflection.test("CustomMirrorIsInherited") {
- do {
- var output = ""
- dump(Irradiant(), to: &output)
-
- let expected =
- "▿ a.Brilliant #0\n" +
- " - first: 400\n" +
- " - second: \"\"\n" +
- " ▿ self: a.Brilliant #0\n"
-
- expectEqual(expected, output)
- }
-}
-
-protocol SomeNativeProto {}
-extension Int: SomeNativeProto {}
-
-Reflection.test("MetatypeMirror") {
- do {
- var output = ""
- let concreteMetatype = Int.self
- dump(concreteMetatype, to: &output)
-
- let expectedInt = "- Swift.Int #0\n"
- expectEqual(expectedInt, output)
-
- let anyMetatype: Any.Type = Int.self
- output = ""
- dump(anyMetatype, to: &output)
- expectEqual(expectedInt, output)
-
- let nativeProtocolMetatype: SomeNativeProto.Type = Int.self
- output = ""
- dump(nativeProtocolMetatype, to: &output)
- expectEqual(expectedInt, output)
-
- let concreteClassMetatype = SomeClass.self
- let expectedSomeClass = "- a.SomeClass #0\n"
- output = ""
- dump(concreteClassMetatype, to: &output)
- expectEqual(expectedSomeClass, output)
-
- let nativeProtocolConcreteMetatype = SomeNativeProto.self
- let expectedNativeProtocolConcrete = "- a.SomeNativeProto #0\n"
- output = ""
- dump(nativeProtocolConcreteMetatype, to: &output)
- expectEqual(expectedNativeProtocolConcrete, output)
- }
-}
-
-Reflection.test("TupleMirror") {
- do {
- var output = ""
- let tuple =
- (Brilliant(384, "seven six eight"), StructWithDefaultMirror("nine"))
- dump(tuple, to: &output)
-
- let expected =
- "▿ (2 elements)\n" +
- " ▿ .0: a.Brilliant #0\n" +
- " - first: 384\n" +
- " - second: \"seven six eight\"\n" +
- " ▿ self: a.Brilliant #0\n" +
- " ▿ .1: a.StructWithDefaultMirror\n" +
- " - s: \"nine\"\n"
-
- expectEqual(expected, output)
-
- expectEqual(.tuple, Mirror(reflecting: tuple).displayStyle)
- }
-
- do {
- // A tuple of stdlib types with mirrors.
- var output = ""
- let tuple = (1, 2.5, false, "three")
- dump(tuple, to: &output)
-
- let expected =
- "▿ (4 elements)\n" +
- " - .0: 1\n" +
- " - .1: 2.5\n" +
- " - .2: false\n" +
- " - .3: \"three\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // A nested tuple.
- var output = ""
- let tuple = (1, ("Hello", "World"))
- dump(tuple, to: &output)
-
- let expected =
- "▿ (2 elements)\n" +
- " - .0: 1\n" +
- " ▿ .1: (2 elements)\n" +
- " - .0: \"Hello\"\n" +
- " - .1: \"World\"\n"
-
- expectEqual(expected, output)
- }
-}
-
-class DullClass {}
-
-Reflection.test("ClassReflection") {
- expectEqual(.`class`, Mirror(reflecting: DullClass()).displayStyle)
-}
-
-Reflection.test("String/Mirror") {
- do {
- var output = ""
- dump("", to: &output)
-
- let expected =
- "- \"\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+0061 LATIN SMALL LETTER A
- // U+304B HIRAGANA LETTER KA
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- // U+1F425 FRONT-FACING BABY CHICK
- var output = ""
- dump("\u{61}\u{304b}\u{3099}\u{1f425}", to: &output)
-
- let expected =
- "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
-
- expectEqual(expected, output)
- }
-}
-
-Reflection.test("String.UTF8View/Mirror") {
- // U+0061 LATIN SMALL LETTER A
- // U+304B HIRAGANA LETTER KA
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- var output = ""
- dump("\u{61}\u{304b}\u{3099}".utf8, to: &output)
-
- let expected =
- "▿ UTF8View(\"\u{61}\u{304b}\u{3099}\")\n" +
- " - 97\n" +
- " - 227\n" +
- " - 129\n" +
- " - 139\n" +
- " - 227\n" +
- " - 130\n" +
- " - 153\n"
-
- expectEqual(expected, output)
-}
-
-Reflection.test("String.UTF16View/Mirror") {
- // U+0061 LATIN SMALL LETTER A
- // U+304B HIRAGANA LETTER KA
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- // U+1F425 FRONT-FACING BABY CHICK
- var output = ""
- dump("\u{61}\u{304b}\u{3099}\u{1f425}".utf16, to: &output)
-
- let expected =
- "▿ StringUTF16(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
- " - 97\n" +
- " - 12363\n" +
- " - 12441\n" +
- " - 55357\n" +
- " - 56357\n"
-
- expectEqual(expected, output)
-}
-
-Reflection.test("String.UnicodeScalarView/Mirror") {
- // U+0061 LATIN SMALL LETTER A
- // U+304B HIRAGANA LETTER KA
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- // U+1F425 FRONT-FACING BABY CHICK
- var output = ""
- dump("\u{61}\u{304b}\u{3099}\u{1f425}".unicodeScalars, to: &output)
-
- let expected =
- "▿ StringUnicodeScalarView(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
- " - \"\u{61}\"\n" +
- " - \"\\u{304B}\"\n" +
- " - \"\\u{3099}\"\n" +
- " - \"\\u{0001F425}\"\n"
-
- expectEqual(expected, output)
-}
-
-Reflection.test("Character/Mirror") {
- do {
- // U+0061 LATIN SMALL LETTER A
- let input: Character = "\u{61}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\u{61}\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+304B HIRAGANA LETTER KA
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- let input: Character = "\u{304b}\u{3099}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\u{304b}\u{3099}\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+1F425 FRONT-FACING BABY CHICK
- let input: Character = "\u{1f425}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\u{1f425}\"\n"
-
- expectEqual(expected, output)
- }
-}
-
-Reflection.test("UnicodeScalar") {
- do {
- // U+0061 LATIN SMALL LETTER A
- let input: UnicodeScalar = "\u{61}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\u{61}\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+304B HIRAGANA LETTER KA
- let input: UnicodeScalar = "\u{304b}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\\u{304B}\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- let input: UnicodeScalar = "\u{3099}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\\u{3099}\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+1F425 FRONT-FACING BABY CHICK
- let input: UnicodeScalar = "\u{1f425}"
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- \"\\u{0001F425}\"\n"
-
- expectEqual(expected, output)
- }
-}
-
-Reflection.test("Bool") {
- do {
- var output = ""
- dump(false, to: &output)
-
- let expected =
- "- false\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var output = ""
- dump(true, to: &output)
-
- let expected =
- "- true\n"
-
- expectEqual(expected, output)
- }
-}
-
-// FIXME: these tests should cover Float80.
-// FIXME: these tests should be automatically generated from the list of
-// available floating point types.
-Reflection.test("Float") {
- do {
- var output = ""
- dump(Float.nan, to: &output)
-
- let expected =
- "- nan\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var output = ""
- dump(Float.infinity, to: &output)
-
- let expected =
- "- inf\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var input: Float = 42.125
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- 42.125\n"
-
- expectEqual(expected, output)
- }
-}
-
-Reflection.test("Double") {
- do {
- var output = ""
- dump(Double.nan, to: &output)
-
- let expected =
- "- nan\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var output = ""
- dump(Double.infinity, to: &output)
-
- let expected =
- "- inf\n"
-
- expectEqual(expected, output)
- }
-
- do {
- var input: Double = 42.125
- var output = ""
- dump(input, to: &output)
-
- let expected =
- "- 42.125\n"
-
- expectEqual(expected, output)
- }
-}
-
-// A struct type and class type whose NominalTypeDescriptor.FieldNames
-// data is exactly eight bytes long. FieldNames data of exactly
-// 4 or 8 or 16 bytes was once miscompiled on arm64.
-struct EightByteFieldNamesStruct {
- let abcdef = 42
-}
-class EightByteFieldNamesClass {
- let abcdef = 42
-}
-
-Reflection.test("FieldNamesBug") {
- do {
- let expected =
- "▿ a.EightByteFieldNamesStruct\n" +
- " - abcdef: 42\n"
- var output = ""
- dump(EightByteFieldNamesStruct(), to: &output)
- expectEqual(expected, output)
- }
-
- do {
- let expected =
- "▿ a.EightByteFieldNamesClass #0\n" +
- " - abcdef: 42\n"
- var output = ""
- dump(EightByteFieldNamesClass(), to: &output)
- expectEqual(expected, output)
- }
-}
-
-Reflection.test("MirrorMirror") {
- var object = 1
- var mirror = Mirror(reflecting: object)
- var mirrorMirror = Mirror(reflecting: mirror)
-
- expectEqual(0, mirrorMirror.children.count)
-}
-
-Reflection.test("OpaquePointer/null") {
- // Don't crash on null pointers. rdar://problem/19708338
- let pointer: OpaquePointer? = nil
- let mirror = Mirror(reflecting: pointer)
- expectEqual(0, mirror.children.count)
-}
-
-Reflection.test("StaticString/Mirror") {
- do {
- var output = ""
- dump("" as StaticString, to: &output)
-
- let expected =
- "- \"\"\n"
-
- expectEqual(expected, output)
- }
-
- do {
- // U+0061 LATIN SMALL LETTER A
- // U+304B HIRAGANA LETTER KA
- // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
- // U+1F425 FRONT-FACING BABY CHICK
- var output = ""
- dump("\u{61}\u{304b}\u{3099}\u{1f425}" as StaticString, to: &output)
-
- let expected =
- "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
-
- expectEqual(expected, output)
- }
-}
-
-Reflection.test("DictionaryIterator/Mirror") {
- let d: [MinimalHashableValue : OpaqueValue<Int>] =
- [ MinimalHashableValue(0) : OpaqueValue(0) ]
-
- var output = ""
- dump(d.makeIterator(), to: &output)
-
- let expected =
- "- Swift.DictionaryIterator<StdlibUnittest.MinimalHashableValue, StdlibUnittest.OpaqueValue<Swift.Int>>\n"
-
- expectEqual(expected, output)
-}
-
-Reflection.test("SetIterator/Mirror") {
- let s: Set<MinimalHashableValue> = [ MinimalHashableValue(0)]
-
- var output = ""
- dump(s.makeIterator(), to: &output)
-
- let expected =
- "- Swift.SetIterator<StdlibUnittest.MinimalHashableValue>\n"
-
- expectEqual(expected, output)
-}
var BitTwiddlingTestSuite = TestSuite("BitTwiddling")
diff --git a/test/stdlib/SetTraps.swift b/test/stdlib/SetTraps.swift
index a1c3a77..668ca8f 100644
--- a/test/stdlib/SetTraps.swift
+++ b/test/stdlib/SetTraps.swift
@@ -51,7 +51,7 @@
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
var s: Set<Int> = [ 10 ]
- let index = s.index(of: 10)!
+ let index = s.firstIndex(of: 10)!
s.remove(at: index)
expectFalse(s.contains(10))
expectCrashLater()
diff --git a/test/stdlib/subString.swift b/test/stdlib/subString.swift
index 8fa3258..7fd6b15 100644
--- a/test/stdlib/subString.swift
+++ b/test/stdlib/subString.swift
@@ -43,7 +43,7 @@
expectNotEqual(s.dropLast(2), s.dropLast(1))
expectEqual(s.dropFirst(1), s.dropFirst(1))
expectTrue(s != s[...].dropFirst(1))
- let i = emoji.index(of: "😄")!
+ let i = emoji.firstIndex(of: "😄")!
expectEqual("😄👍🏽" as String, emoji[i...].prefix(2))
expectTrue("😄👍🏽🇫🇷👩👩👧👦🙈😡🇧🇪" as String == emoji[i...].dropLast(2))
expectTrue("🇫🇷👩👩👧👦🙈😡🇧🇪" as String == emoji[i...].dropLast(2).dropFirst(2))
diff --git a/tools/SourceKit/include/SourceKit/Support/Tracing.h b/tools/SourceKit/include/SourceKit/Support/Tracing.h
index 8fc2ad9..87cc03c 100644
--- a/tools/SourceKit/include/SourceKit/Support/Tracing.h
+++ b/tools/SourceKit/include/SourceKit/Support/Tracing.h
@@ -28,7 +28,7 @@
struct SwiftArguments {
std::string PrimaryFile;
- std::vector<std::string> Args;
+ std::string Arguments;
};
enum class OperationKind : uint64_t {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 0313270..56a42a4 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -795,8 +795,8 @@
trace::TracedOperation TracedOp(trace::OperationKind::PerformSema);
trace::SwiftInvocation TraceInfo;
if (TracedOp.enabled()) {
- TraceInfo.Args.PrimaryFile = InvokRef->Impl.Opts.PrimaryFile;
- TraceInfo.Args.Args = InvokRef->Impl.Opts.Args;
+ trace::initTraceInfo(TraceInfo, InvokRef->Impl.Opts.PrimaryFile,
+ InvokRef->Impl.Opts.Args);
}
ASTUnitRef ASTRef = new ASTUnit(++ASTUnitGeneration, MgrImpl.Stats);
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
index d3398de..59b1b92 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
@@ -865,7 +865,6 @@
continue;
}
}
- llvm_unreachable("exit is on null byte");
}
static void translateFilterRules(ArrayRef<FilterRule> rawFilterRules,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
index f07a3fd..0240b10 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
@@ -198,11 +198,25 @@
// IndexSource
//===----------------------------------------------------------------------===//
+template <typename Str>
+static void initTraceInfoImpl(trace::SwiftInvocation &SwiftArgs,
+ StringRef InputFile,
+ ArrayRef<Str> Args) {
+ llvm::raw_string_ostream OS(SwiftArgs.Args.Arguments);
+ interleave(Args, [&OS](StringRef arg) { OS << arg; }, [&OS] { OS << ' '; });
+ SwiftArgs.Args.PrimaryFile = InputFile;
+}
+
void trace::initTraceInfo(trace::SwiftInvocation &SwiftArgs,
StringRef InputFile,
ArrayRef<const char *> Args) {
- SwiftArgs.Args.Args.assign(Args.begin(), Args.end());
- SwiftArgs.Args.PrimaryFile = InputFile;
+ initTraceInfoImpl(SwiftArgs, InputFile, Args);
+}
+
+void trace::initTraceInfo(trace::SwiftInvocation &SwiftArgs,
+ StringRef InputFile,
+ ArrayRef<std::string> Args) {
+ initTraceInfoImpl(SwiftArgs, InputFile, Args);
}
void SwiftLangSupport::indexSource(StringRef InputFile,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index 715eee6..d50a62c 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -516,6 +516,9 @@
void initTraceInfo(trace::SwiftInvocation &SwiftArgs,
StringRef InputFile,
ArrayRef<const char *> Args);
+ void initTraceInfo(trace::SwiftInvocation &SwiftArgs,
+ StringRef InputFile,
+ ArrayRef<std::string> Args);
}
/// When we cannot build any more clang modules, close the .pcm / files to
diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h
index 29f7da7..18e6e62 100644
--- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h
+++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h
@@ -351,7 +351,7 @@
sourcekitd_variant_t
sourcekitd_response_get_value(sourcekitd_response_t resp);
-SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL SOURCEKITD_WARN_RESULT
+SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT
sourcekitd_variant_type_t
sourcekitd_variant_get_type(sourcekitd_variant_t obj);
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 9df7cba..dbfb4af 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -2711,7 +2711,7 @@
Dict.set(KeyCompileID, std::to_string(OpId));
Dict.set(KeyFilePath, Inv.Args.PrimaryFile);
// FIXME: OperationKind
- Dict.set(KeyCompilerArgs, Inv.Args.Args);
+ Dict.set(KeyCompilerArgsString, Inv.Args.Arguments);
sourcekitd::postNotification(RespBuilder.createResponse());
}
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
index f30f00f..37d6e90 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
@@ -583,9 +583,9 @@
#define XPC_OBJ(var) ((xpc_object_t)(var).data[1])
#define CUSTOM_BUF_KIND(xobj) \
- ((CustomBufferKind)*(uint64_t*)xpc_data_get_bytes_ptr(xobj))
+ ((CustomBufferKind)*(const uint64_t*)xpc_data_get_bytes_ptr(xobj))
#define CUSTOM_BUF_START(xobj) \
- ((void*)(((uint64_t*)xpc_data_get_bytes_ptr(xobj))+1))
+ ((const void*)(((const uint64_t*)xpc_data_get_bytes_ptr(xobj))+1))
static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) {
xpc_object_t obj = XPC_OBJ(var);
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 4798c77..03fcf9e 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -70,6 +70,7 @@
// The following two are for testing purposes
DeserializeDiffItems,
DeserializeSDK,
+ GenerateNameCorrectionTemplate,
};
} // end anonymous namespace
@@ -141,7 +142,10 @@
"Deserialize diff items in a JSON file"),
clEnumValN(ActionType::DeserializeSDK,
"deserialize-sdk",
- "Deserialize sdk digester in a JSON file")));
+ "Deserialize sdk digester in a JSON file"),
+ clEnumValN(ActionType::GenerateNameCorrectionTemplate,
+ "generate-name-correction",
+ "Generate name correction template")));
static llvm::cl::list<std::string>
SDKJsonPaths("input-paths",
@@ -2727,15 +2731,13 @@
}
bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
- if (!IsVisitingLeft)
- return false;
-
// We only care if this the top-level type node.
if (!L->isTopLevelType() || !R->isTopLevelType())
return false;
StringRef KeyChangedTo;
- if (L->getTypeKind() == KnownTypeKind::Optional &&
- R->getTypeKind() == KnownTypeKind::Optional) {
+ bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
+ R->getTypeKind() == KnownTypeKind::Optional;
+ if (HasOptional) {
// Detect [String: Any]? to [StringRepresentableStruct: Any]? Chnage
KeyChangedTo =
detectDictionaryKeyChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
@@ -2745,10 +2747,16 @@
KeyChangedTo = detectDictionaryKeyChangeInternal(L, R);
}
if (!KeyChangedTo.empty()) {
- L->annotate(L->getTypeKind() == KnownTypeKind::Optional ?
+ if (IsVisitingLeft) {
+ L->annotate(HasOptional ?
NodeAnnotation::OptionalDictionaryKeyUpdate :
NodeAnnotation::DictionaryKeyUpdate);
- L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+ L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+ } else {
+ R->annotate(HasOptional ?
+ NodeAnnotation::RevertOptionalDictionaryKeyUpdate :
+ NodeAnnotation::RevertDictionaryKeyUpdate);
+ }
return true;
}
return false;
@@ -2769,14 +2777,13 @@
}
bool detectArrayMemberChange(SDKNodeType* L, SDKNodeType *R) {
- if (!IsVisitingLeft)
- return false;
// We only care if this the top-level type node.
if (!L->isTopLevelType() || !R->isTopLevelType())
return false;
StringRef KeyChangedTo;
- if (L->getTypeKind() == KnownTypeKind::Optional &&
- R->getTypeKind() == KnownTypeKind::Optional) {
+ bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
+ R->getTypeKind() == KnownTypeKind::Optional;
+ if (HasOptional) {
// Detect [String]? to [StringRepresentableStruct]? Chnage
KeyChangedTo =
detectArrayMemberChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
@@ -2786,18 +2793,22 @@
KeyChangedTo = detectArrayMemberChangeInternal(L, R);
}
if (!KeyChangedTo.empty()) {
- L->annotate(L->getTypeKind() == KnownTypeKind::Optional ?
+ if (IsVisitingLeft) {
+ L->annotate(HasOptional ?
NodeAnnotation::OptionalArrayMemberUpdate :
NodeAnnotation::ArrayMemberUpdate);
- L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+ L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+ } else {
+ R->annotate(HasOptional ?
+ NodeAnnotation::RevertOptionalArrayMemberUpdate :
+ NodeAnnotation::RevertArrayMemberUpdate);
+ }
return true;
}
return false;
}
bool detectSimpleStringRepresentableUpdate(SDKNodeType *L, SDKNodeType *R) {
- if (!IsVisitingLeft)
- return false;
if (!L->isTopLevelType() || !R->isTopLevelType())
return false;
StringRef KeyChangedTo;
@@ -2813,11 +2824,15 @@
KeyChangedTo = getStringRepresentableChange(L, R);
}
if (!KeyChangedTo.empty()) {
- L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
- if (HasOptional) {
- L->annotate(NodeAnnotation::SimpleOptionalStringRepresentableUpdate);
+ if (IsVisitingLeft) {
+ L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+ L->annotate(HasOptional ?
+ NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
+ NodeAnnotation::SimpleStringRepresentableUpdate);
} else {
- L->annotate(NodeAnnotation::SimpleStringRepresentableUpdate);
+ R->annotate(HasOptional ?
+ NodeAnnotation::RevertSimpleOptionalStringRepresentableUpdate:
+ NodeAnnotation::RevertSimpleStringRepresentableUpdate);
}
return true;
}
@@ -3965,6 +3980,33 @@
return 0;
}
+static int deserializeNameCorrection(APIDiffItemStore &Store,
+ StringRef OutputPath) {
+ std::error_code EC;
+ llvm::raw_fd_ostream FS(OutputPath, EC, llvm::sys::fs::F_None);
+ std::set<NameCorrectionInfo> Result;
+ for (auto *Item: Store.getAllDiffItems()) {
+ if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
+ if (CI->DiffKind == NodeAnnotation::Rename) {
+ auto NewName = CI->getNewName();
+ auto Module = CI->ModuleName;
+ DeclNameViewer Viewer(NewName);
+ auto HasUnderScore =
+ [](StringRef S) { return S.find('_') != StringRef::npos; };
+ auto Args = Viewer.args();
+ if (HasUnderScore(Viewer.base()) ||
+ std::any_of(Args.begin(), Args.end(), HasUnderScore)) {
+ Result.insert(NameCorrectionInfo(NewName, NewName, Module));
+ }
+ }
+ }
+ }
+ std::vector<NameCorrectionInfo> Vec;
+ Vec.insert(Vec.end(), Result.begin(), Result.end());
+ APIDiffItemStore::serialize(FS, Vec);
+ return EC.value();
+}
+
/// Mostly for testing purposes, this function de-serializes the SDK dump in
/// dumpPath and re-serialize them to OutputPath. If the tool performs correctly,
/// the contents in dumpPath and OutputPath should be identical.
@@ -4029,6 +4071,13 @@
else
return deserializeSDKDump(options::SDKJsonPaths[0], options::OutputFile);
}
+ case ActionType::GenerateNameCorrectionTemplate: {
+ APIDiffItemStore Store;
+ auto &Paths = options::SDKJsonPaths;
+ for (unsigned I = 0; I < Paths.size(); I ++)
+ Store.addStorePath(Paths[I]);
+ return deserializeNameCorrection(Store, options::OutputFile);
+ }
case ActionType::None:
llvm::errs() << "Action required\n";
llvm::cl::PrintHelpMessage();
diff --git a/utils/build-script-impl b/utils/build-script-impl
index a580e6c..b46a7cb 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -3483,7 +3483,7 @@
fi
LIT_EXECUTABLE_PATH="${LLVM_SOURCE_DIR}/utils/lit/lit.py"
- FILECHECK_EXECUTABLE_PATH="$(build_directory_bin ${LOCAL_HOST} llvm)/FileCheck"
+ LLVM_BIN_DIR="$(build_directory_bin ${LOCAL_HOST} llvm)"
echo "-- Test Installable Package --"
call rm -rf "${PKG_TESTS_SANDBOX_PARENT}"
call mkdir -p "${PKG_TESTS_SANDBOX}"
@@ -3491,7 +3491,7 @@
call tar xzf "${package_for_host}"
with_pushd "${PKG_TESTS_SOURCE_DIR}" \
- call python "${LIT_EXECUTABLE_PATH}" . -sv --param package-path="${PKG_TESTS_SANDBOX}" --param filecheck="${FILECHECK_EXECUTABLE_PATH}" --param test-exec-root="${PKG_TESTS_TEMPS}"
+ call python "${LIT_EXECUTABLE_PATH}" . -sv --param package-path="${PKG_TESTS_SANDBOX}" --param test-exec-root="${PKG_TESTS_TEMPS}" --param llvm-bin-dir="${LLVM_BIN_DIR}"
fi
fi
}
diff --git a/utils/gyb_sourcekit_support/UIDs.py b/utils/gyb_sourcekit_support/UIDs.py
index df4443b..52e7990 100644
--- a/utils/gyb_sourcekit_support/UIDs.py
+++ b/utils/gyb_sourcekit_support/UIDs.py
@@ -154,6 +154,7 @@
KEY('ActionUID', 'key.actionuid'),
KEY('ActionUnavailableReason', 'key.actionunavailablereason'),
KEY('CompileID', 'key.compileid'),
+ KEY('CompilerArgsString', 'key.compilerargs-string'),
]
diff --git a/utils/gyb_stdlib_unittest_support.py b/utils/gyb_stdlib_unittest_support.py
deleted file mode 100644
index f3a7940..0000000
--- a/utils/gyb_stdlib_unittest_support.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# ===--- gyb_stdlib_unittest_support.py --------------*- coding: utf-8 -*-===//
-#
-# This source file is part of the Swift.org open source project
-#
-# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-# Licensed under Apache License v2.0 with Runtime Library Exception
-#
-# See https://swift.org/LICENSE.txt for license information
-# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-
-TRACE = '''
- _ message: @autoclosure () -> String = "",
- stackTrace: SourceLocStack = SourceLocStack(),
- showFrame: Bool = true,
- file: String = #file, line: UInt = #line'''
-
-stackTrace = 'stackTrace.pushIf(showFrame, file: file, line: line)'
-
-trace = 'message(),\n stackTrace: ' + stackTrace
diff --git a/utils/update-checkout-config.json b/utils/update-checkout-config.json
index 039c2df..d4588f1 100644
--- a/utils/update-checkout-config.json
+++ b/utils/update-checkout-config.json
@@ -202,8 +202,8 @@
"swift-corelibs-xctest": "swift-4.2-branch",
"swift-corelibs-foundation": "swift-4.2-branch",
"swift-corelibs-libdispatch": "swift-4.2-branch",
- "swift-integration-tests": "master",
- "swift-xcode-playground-support": "master",
+ "swift-integration-tests": "swift-4.2-branch",
+ "swift-xcode-playground-support": "swift-4.2-branch",
"ninja": "release"
}
},
diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift
index 826f224..bcb2c653 100644
--- a/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift
+++ b/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift
@@ -1,4 +1,4 @@
// RUN: not %target-swift-frontend %s -typecheck
let a = [1]
-_ = a.index(of: a.min()) // a.min() returns an optional
+_ = a.firstIndex(of: a.min()) // a.min() returns an optional
diff --git a/validation-test/compiler_crashers_2/0153-rdar39130543.swift b/validation-test/compiler_crashers_2/0153-rdar39130543.swift
index 40d25aa..3a9f7fd 100644
--- a/validation-test/compiler_crashers_2/0153-rdar39130543.swift
+++ b/validation-test/compiler_crashers_2/0153-rdar39130543.swift
@@ -1,4 +1,5 @@
// RUN: not --crash %target-swift-frontend %s -emit-ir
+// REQUIRES: asserts
protocol P20 { }
diff --git a/validation-test/compiler_crashers_2/0123-rdar31164540.swift b/validation-test/compiler_crashers_2_fixed/0123-rdar31164540.swift
similarity index 99%
rename from validation-test/compiler_crashers_2/0123-rdar31164540.swift
rename to validation-test/compiler_crashers_2_fixed/0123-rdar31164540.swift
index 0f3f306..a908f98 100644
--- a/validation-test/compiler_crashers_2/0123-rdar31164540.swift
+++ b/validation-test/compiler_crashers_2_fixed/0123-rdar31164540.swift
@@ -1,4 +1,4 @@
-// RUN: not --crash %target-swift-frontend -parse-stdlib -DBUILDING_OUTSIDE_STDLIB %s -emit-ir
+// RUN: not %target-swift-frontend -parse-stdlib -DBUILDING_OUTSIDE_STDLIB %s -emit-ir
// REQUIRES: objc_interop
//===----------------------------------------------------------------------===//
diff --git a/validation-test/compiler_crashers_2_fixed/0139-rdar36278079.swift b/validation-test/compiler_crashers_2_fixed/0139-rdar36278079.swift
new file mode 100644
index 0000000..e89e20f
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0139-rdar36278079.swift
@@ -0,0 +1,19 @@
+// RUN: not %target-swift-frontend -typecheck %s
+
+struct S {
+ // presence of a static instance seems to be
+ // necessary to cause this problem
+ static let s = S()
+}
+
+protocol P {
+ associatedtype T
+ init(t: T)
+}
+
+extension S: P {
+// Uncomment to stop assertion:
+// init(t: Int) {
+// self = S()
+// }
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0153-rdar36497404.swift b/validation-test/compiler_crashers_2_fixed/0153-rdar36497404.swift
new file mode 100644
index 0000000..ff06aac
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0153-rdar36497404.swift
@@ -0,0 +1,44 @@
+// RUN: %target-build-swift -emit-module -o %t %s
+
+public protocol P1 {}
+public protocol P2 {}
+
+public protocol P3 {
+ static func a()
+
+ func b()
+ func b<I: P1>(_: (I) -> Void)
+
+ static func c<I: P1>(_: I)
+ static func d()
+ static func d<I: P1>(_: ([(I, I)]) -> Void)
+ static func d<I: P1>(_: ([I: I]) -> Void)
+ static func d<Q: P1>(_: Q)
+
+ static func e<Q: P1, I: P2>(_: Q, _: (I) -> Void)
+ static func f<Q: P1, I: P2>(_: Q, _: (I) -> Void)
+
+ func g<I: P1>(_: I)
+}
+
+public extension P3 {
+ static func a() {}
+
+ func b() {}
+ func b<I: P1>(_: (I) -> Void) {}
+
+ static func c<I: P1>(_: I) {}
+
+ static func d() {}
+ static func d<I: P1>(_: ([(I, I)]) -> Void) {}
+ static func d<I: P1>(_: ([I: I]) -> Void) {}
+ static func d<Q: P1>(_: Q) {}
+
+ static func e<Q: P1, I: P2>(_: Q, _: (I) -> Void) {}
+ static func f<Q: P1, I: P2>(_: Q, _: (I) -> Void) {}
+
+ func g<I: P1>(_: I) {}
+}
+
+struct S: P3 {
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0154-sr7457.swift b/validation-test/compiler_crashers_2_fixed/0154-sr7457.swift
new file mode 100644
index 0000000..808206d
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0154-sr7457.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-frontend %s -emit-ir
+protocol Proto { }
+
+class Class {
+ func foo<A>(callback: (A) -> Void) where A: Proto {
+ }
+
+ func foo<A, B>(callback: (A, B) -> Void) where A: Proto, B: Proto {
+ }
+}
+
+class Child: Class {
+ override func foo<A>(callback: (A) -> Void) where A : Proto {
+ }
+}
+
diff --git a/validation-test/compiler_crashers_2_fixed/0155-sr7364.swift b/validation-test/compiler_crashers_2_fixed/0155-sr7364.swift
new file mode 100644
index 0000000..e065a1a
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0155-sr7364.swift
@@ -0,0 +1,22 @@
+// RUN: not %target-swift-frontend %s -emit-ir
+
+
+public protocol E {
+ associatedtype F
+
+ static func g(_: F) -> Self
+}
+
+internal enum CF {
+ case f
+}
+
+internal enum CE: E {
+ case f(CF)
+
+ static func g(_ f: CF) -> CE {
+ return CE.f(f)
+ }
+
+ static let cf = CE.g(.f)
+}
diff --git a/validation-test/stdlib/AnyHashable.swift.gyb b/validation-test/stdlib/AnyHashable.swift.gyb
index fcdefb0..05084ad 100644
--- a/validation-test/stdlib/AnyHashable.swift.gyb
+++ b/validation-test/stdlib/AnyHashable.swift.gyb
@@ -58,7 +58,7 @@
let AnyHashableTests = TestSuite("AnyHashableTests")
AnyHashableTests.test("CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable") {
- var v = AnyHashable(CustomPrintableValue(1))
+ let v = AnyHashable(CustomPrintableValue(1))
expectPrinted("(value: 1).description", v)
expectDebugPrinted("AnyHashable((value: 1).debugDescription)", v)
expectDumped(
@@ -117,8 +117,8 @@
${wrapped}_equalImpl.value = {
($0 as! ${payload}).value == ($1 as! ${payload}).value
}
- ${wrapped}_hashValueImpl.value = {
- ($0 as! ${payload}).value
+ ${wrapped}_hashIntoImpl.value = {
+ $1.combine(($0 as! ${payload}).value)
}
let xs = (0...5).flatMap {
[ ${wrapped}(${payload}($0), identity: 0),
@@ -142,7 +142,7 @@
var xs: [AnyHashable] = []
% for wrapped in ['MinimalHashableValue', 'MinimalHashableClass']:
- xs += (0...5).flatMap {
+ xs += (0..<6).flatMap {
[ ${wrapped}($0, identity: 0),
${wrapped}($0, identity: 1) ].map(AnyHashable.init)
}
@@ -157,25 +157,31 @@
}
return (lhs as! LifetimeTracked) == (rhs as! LifetimeTracked)
}
- ${wrapped}_hashValueImpl.value = {
- payload in
+ ${wrapped}_hashIntoImpl.value = { payload, hasher in
if let x = payload as? OpaqueValue<Int> {
- return x.value
+ hasher.combine(x.value)
+ return
}
- return (payload as! LifetimeTracked).value
+ hasher.combine((payload as! LifetimeTracked).value)
}
% end
% for wrapped in ['GenericMinimalHashableValue', 'GenericMinimalHashableClass']:
% for payload in [ 'OpaqueValue<Int>', 'LifetimeTracked' ]:
- xs += (0...5).flatMap {
+ xs += (0..<6).flatMap {
[ ${wrapped}(${payload}($0), identity: 0),
${wrapped}(${payload}($0), identity: 1) ].map(AnyHashable.init)
}
% end
% end
- checkHashable(xs, equalityOracle: { $0 / 2 == $1 / 2 })
+ checkHashable(
+ xs,
+ equalityOracle: { $0 / 2 == $1 / 2 },
+ // FIXME: Types that hash the same way will produce hash collisions when
+ // converted to AnyHashable. Arguably, the type id should be used as a hash
+ // discriminator.
+ hashEqualityOracle: { $0 / 2 % 6 == $1 / 2 % 6 })
}
% for (kw, name) in [
@@ -305,8 +311,8 @@
GenericMinimalHashableValue_equalImpl.value = {
($0 as! ${payload}).value == ($1 as! ${payload}).value
}
- GenericMinimalHashableValue_hashValueImpl.value = {
- ($0 as! ${payload}).value
+ GenericMinimalHashableValue_hashIntoImpl.value = { v, hasher in
+ hasher.combine((v as! ${payload}).value)
}
let xs = (-2...2).flatMap {
[ ${genericWrapped}(
@@ -373,8 +379,8 @@
GenericMinimalHashableValue_equalImpl.value = {
($0 as! ${payload}).value == ($1 as! ${payload}).value
}
- GenericMinimalHashableValue_hashValueImpl.value = {
- ($0 as! ${payload}).value
+ GenericMinimalHashableValue_hashIntoImpl.value = { v, hasher in
+ hasher.combine((v as! ${payload}).value)
}
// If the custom representation has its own custom representation,
// we ignore it.
@@ -437,18 +443,20 @@
init(_ value: Int) {
self.value = value
}
- ${'override' if 'ObjC' in prefix else ''} var hashValue: Int {
+% if 'ObjC' in prefix:
+ override var hash: Int {
return value
}
-% if 'ObjC' in prefix:
override func isEqual(_ object: Any?) -> Bool {
guard let rhs = object as? ${hashable_base.full_name} else {
return false
}
return self.value == rhs.value
}
-% end
-% if not 'ObjC' in prefix:
+% else:
+ var hashValue: Int {
+ return value
+ }
static func == ${hashable_base.generic_parameters_decl} (
lhs: ${hashable_base.full_name},
rhs: ${hashable_base.full_name}
@@ -575,18 +583,27 @@
AnyHashableTests.test("AnyHashable(CFBitVector)/Hashable, .base") {
let bitVectors: [CFBitVector] =
interestingBitVectorArrays.map(CFBitVector.makeImmutable)
+ let hashEqualityOracle: (Int, Int) -> Bool = {
+ // CFBitVector returns its count as the hash.
+ interestingBitVectorArrays[$0].count == interestingBitVectorArrays[$1].count
+ }
let arrays = bitVectors.map { $0.asArray }
func isEq(_ lhs: [[UInt8]], _ rhs: [[UInt8]]) -> Bool {
return zip(lhs, rhs).map { $0 == $1 }.reduce(true, { $0 && $1 })
}
expectEqualTest(interestingBitVectorArrays, arrays, sameValue: isEq)
- checkHashable(bitVectors, equalityOracle: { $0 == $1 })
+ checkHashable(
+ bitVectors,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
do {
expectEqual(.foreignClass, SwiftRuntime.metadataKind(of: bitVectors.first!))
let anyHashables = bitVectors.map(AnyHashable.init)
- checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+ checkHashable(anyHashables,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
let v = anyHashables.first!.base
expectTrue(type(of: v) is CFBitVector.Type)
@@ -600,7 +617,9 @@
SwiftRuntime.metadataKind(of: bitVectorsAsAnyObjects.first!))
let anyHashables = bitVectorsAsAnyObjects.map(AnyHashable.init)
- checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+ checkHashable(anyHashables,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
let v = anyHashables.first!.base
expectTrue(type(of: v) is CFBitVector.Type)
@@ -612,12 +631,19 @@
// CFBitVector.
let bitVectors: [CFMutableBitVector] =
interestingBitVectorArrays.map(CFMutableBitVector.makeMutable)
+ let hashEqualityOracle: (Int, Int) -> Bool = {
+ // CFBitVector returns its count as the hash.
+ interestingBitVectorArrays[$0].count == interestingBitVectorArrays[$1].count
+ }
let arrays = bitVectors.map { $0.asArray }
func isEq(_ lhs: [[UInt8]], _ rhs: [[UInt8]]) -> Bool {
return zip(lhs, rhs).map { $0 == $1 }.reduce(true, { $0 && $1 })
}
expectEqualTest(interestingBitVectorArrays, arrays, sameValue: isEq)
- checkHashable(bitVectors, equalityOracle: { $0 == $1 })
+ checkHashable(
+ bitVectors,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
do {
expectEqual(
@@ -625,7 +651,10 @@
SwiftRuntime.metadataKind(of: bitVectors.first!))
let anyHashables = bitVectors.map(AnyHashable.init)
- checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+ checkHashable(
+ anyHashables,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
let v = anyHashables.first!.base
expectTrue(type(of: v) is CFMutableBitVector.Type)
@@ -634,14 +663,20 @@
let bitVectorsAsAnyObjects: [NSObject] = bitVectors.map {
($0 as AnyObject) as! NSObject
}
- checkHashable(bitVectorsAsAnyObjects, equalityOracle: { $0 == $1 })
+ checkHashable(
+ bitVectorsAsAnyObjects,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
expectEqual(
.objCClassWrapper,
SwiftRuntime.metadataKind(of: bitVectorsAsAnyObjects.first!))
let anyHashables = bitVectorsAsAnyObjects.map(AnyHashable.init)
- checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+ checkHashable(
+ anyHashables,
+ equalityOracle: { $0 == $1 },
+ hashEqualityOracle: hashEqualityOracle)
let v = anyHashables.first!.base
expectTrue(type(of: v) is CFMutableBitVector.Type)
@@ -717,10 +752,14 @@
.caseC(LifetimeTracked(2)), .caseC(LifetimeTracked(2)),
]
expectEqual(.enum, SwiftRuntime.metadataKind(of: xs.first!))
- checkHashable(xs, equalityOracle: { $0 / 2 == $1 / 2 })
+ checkHashable(
+ xs,
+ equalityOracle: { $0 / 2 == $1 / 2 },
+ hashEqualityOracle: { $0 / 4 == $1 / 4 })
checkHashable(
xs.map(AnyHashable.init),
- equalityOracle: { $0 / 2 == $1 / 2 })
+ equalityOracle: { $0 / 2 == $1 / 2 },
+ hashEqualityOracle: { $0 / 4 == $1 / 4 })
}
AnyHashableTests.test("AnyHashable(MinimalHashableRCSwiftError).base") {
@@ -763,8 +802,16 @@
return lhs == rhs
}
- checkHashable(values, equalityOracle: equalityOracle,
- allowBrokenTransitivity: true)
+ func hashEqualityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
+ // Elements in [0, 3] hash the same, as do elements in [4, 7].
+ return lhs / 4 == rhs / 4
+ }
+
+ checkHashable(
+ values,
+ equalityOracle: equalityOracle,
+ hashEqualityOracle: hashEqualityOracle,
+ allowBrokenTransitivity: true)
}
AnyHashableTests.test("AnyHashable(Set)/Hashable") {
@@ -789,8 +836,10 @@
}
}
- checkHashable(values, equalityOracle: equalityOracle,
- allowBrokenTransitivity: true)
+ checkHashable(
+ values,
+ equalityOracle: equalityOracle,
+ allowBrokenTransitivity: true)
}
AnyHashableTests.test("AnyHashable(Array)/Hashable") {
@@ -902,6 +951,12 @@
.caseC(LifetimeTracked(1)), .caseC(LifetimeTracked(1)),
.caseC(LifetimeTracked(2)), .caseC(LifetimeTracked(2)),
]
+ checkHashable(
+ swiftErrors,
+ equalityOracle: { $0 / 2 == $1 / 2 },
+ hashEqualityOracle: { $0 / 4 == $1 / 4 },
+ allowBrokenTransitivity: false)
+
let nsErrors: [NSError] = swiftErrors.flatMap {
swiftError -> [NSError] in
let bridgedNSError = swiftError as NSError
@@ -938,16 +993,23 @@
return false
}
+ func hashEqualityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
+ // Every NSError that has the same domain and code hash the same way.
+ return lhs / 8 == rhs / 8
+ }
+
// FIXME: transitivity is broken because pure `NSError`s can compare equal to
// Swift errors with payloads just based on the domain and code, and Swift
// errors with payloads don't compare equal when payloads differ.
checkHashable(
nsErrors,
equalityOracle: equalityOracle,
+ hashEqualityOracle: hashEqualityOracle,
allowBrokenTransitivity: true)
checkHashable(
nsErrors.map(AnyHashable.init),
equalityOracle: equalityOracle,
+ hashEqualityOracle: hashEqualityOracle,
allowBrokenTransitivity: true)
// FIXME(id-as-any): run `checkHashable` on an array of mixed
diff --git a/validation-test/stdlib/Arrays.swift.gyb b/validation-test/stdlib/Arrays.swift.gyb
index 8f81059..2bd0b6b 100644
--- a/validation-test/stdlib/Arrays.swift.gyb
+++ b/validation-test/stdlib/Arrays.swift.gyb
@@ -190,21 +190,55 @@
}
ArrayTestSuite.test("Hashable") {
- let a1: Array<Int> = [1, 2, 3]
- let a2: Array<Int> = [1, 3, 2]
- let a3: Array<Int> = [3, 1, 2]
- let a4: Array<Int> = [1, 2]
- let a5: Array<Int> = [1]
- let a6: Array<Int> = []
- let a7: Array<Int> = [1, 1, 1]
- checkHashable([a1, a2, a3, a4, a5, a6, a7], equalityOracle: { $0 == $1 })
+ let a1: [Array<Int>] = [
+ [1, 2, 3],
+ [1, 3, 2],
+ [3, 1, 2],
+ [1, 2],
+ [1],
+ [],
+ [1, 1, 1]
+ ]
+ checkHashable(a1, equalityOracle: { $0 == $1 })
- let aa1: Array<Array<Int>> = [[], [1], [1, 2], [2, 1]]
- let aa2: Array<Array<Int>> = [[], [1], [2, 1], [2, 1]]
- let aa3: Array<Array<Int>> = [[1], [], [2, 1], [2, 1]]
- let aa4: Array<Array<Int>> = [[1], [], [2, 1], [2]]
- let aa5: Array<Array<Int>> = [[1], [], [2, 1]]
- checkHashable([aa1, aa2, aa3, aa4, aa5], equalityOracle: { $0 == $1 })
+ let a2: [Array<Array<Int>>] = [
+ [[], [1], [1, 2], [2, 1]],
+ [[], [1], [2, 1], [2, 1]],
+ [[1], [], [2, 1], [2, 1]],
+ [[1], [], [2, 1], [2]],
+ [[1], [], [2, 1]]
+ ]
+ checkHashable(a2, equalityOracle: { $0 == $1 })
+
+ // These arrays share the same sequence of leaf integers, but they must
+ // still all hash differently.
+ let a3: [Array<Array<Int>>] = [
+ // Grouping changes must perturb the hash.
+ [[1], [2], [3], [4], [5]],
+ [[1, 2], [3], [4], [5]],
+
+ [[1], [2, 3], [4], [5]],
+ [[1], [2], [3, 4], [5]],
+ [[1], [2], [3], [4, 5]],
+
+ [[1, 2, 3], [4], [5]],
+ [[1], [2, 3, 4], [5]],
+ [[1], [2], [3, 4, 5]],
+
+ [[1, 2, 3, 4], [5]],
+ [[1], [2, 3, 4, 5]],
+
+ [[1, 2], [3, 4], [5]],
+ [[1], [2, 3], [4, 5]],
+ [[1, 2, 3, 4, 5]],
+
+ // Empty arrays must perturb the hash.
+ [[], [1], [2], [3], [4], [5]],
+ [[1], [], [2], [3], [4], [5]],
+ [[1], [2], [3], [4], [5], []],
+ [[1], [], [], [2], [3], [], [4], [], [5]],
+ ]
+ checkHashable(a3, equalityOracle: { $0 == $1 })
}
diff --git a/validation-test/stdlib/CollectionCasts.swift.gyb b/validation-test/stdlib/CollectionCasts.swift.gyb
index 3c39a10..5748fcc 100644
--- a/validation-test/stdlib/CollectionCasts.swift.gyb
+++ b/validation-test/stdlib/CollectionCasts.swift.gyb
@@ -47,7 +47,6 @@
}
%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
classKeys = ('Derived', 'Base')
classValues = classKeys + ('AnyObject', 'Any')
nonClassKeys = ('Int',)
diff --git a/validation-test/stdlib/CollectionType.swift.gyb b/validation-test/stdlib/CollectionType.swift.gyb
index 7ecf241..130e366 100644
--- a/validation-test/stdlib/CollectionType.swift.gyb
+++ b/validation-test/stdlib/CollectionType.swift.gyb
@@ -624,12 +624,12 @@
}
//===----------------------------------------------------------------------===//
-// index(of:)
+// firstIndex(of:)
//===----------------------------------------------------------------------===//
-CollectionTypeTests.test("index(of:)/WhereElementIsEquatable/dispatch") {
+CollectionTypeTests.test("firstIndex(of:)/WhereElementIsEquatable/dispatch") {
let tester = CollectionLog.dispatchTester([MinimalEquatableValue(1)])
- _ = tester.index(of: MinimalEquatableValue(1))
+ _ = tester.firstIndex(of: MinimalEquatableValue(1))
expectCustomizable(tester, tester.log._customIndexOfEquatableElement)
}
@@ -640,14 +640,14 @@
C : Collection
>(_ collection: C, _ element: C.Iterator.Element) -> C.Index?
where C.Iterator.Element : Equatable {
- return collection.index(of: element)
+ return collection.firstIndex(of: element)
}
func callStaticFind_(
_ set: Set<MinimalHashableValue>,
_ element: MinimalHashableValue
) -> Set<MinimalHashableValue>.Index? {
- return set.index(of: element)
+ return set.firstIndex(of: element)
}
% for dispatch in [ 'Static', 'Generic' ]:
@@ -659,7 +659,7 @@
let s = Set<MinimalHashableValue>(
test.sequence.map { MinimalHashableValue($0.value) })
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
+ MinimalHashableValue.timesHashIntoWasCalled = 0
expectEqual(
test.expected
.map { _ in MinimalHashableValue(test.element.value) },
@@ -671,11 +671,11 @@
0, MinimalHashableValue.timesEqualEqualWasCalled,
stackTrace: SourceLocStack().with(test.loc))
expectEqual(
- 0, MinimalHashableValue.timesHashValueWasCalled,
+ 0, MinimalHashableValue.timesHashIntoWasCalled,
stackTrace: SourceLocStack().with(test.loc))
} else {
expectNotEqual(
- 0, MinimalHashableValue.timesHashValueWasCalled,
+ 0, MinimalHashableValue.timesHashIntoWasCalled,
stackTrace: SourceLocStack().with(test.loc))
}
if test.expected != nil {
@@ -702,7 +702,7 @@
func _test_indicesOf(_ element: Iterator.Element) -> [Index] {
var result: [Index] = []
var tail = self[startIndex..<endIndex]
- while let foundIndex = tail.index(of: element) {
+ while let foundIndex = tail.firstIndex(of: element) {
result.append(foundIndex)
tail = tail[index(after: foundIndex)..<endIndex]
}
@@ -710,7 +710,7 @@
}
}
-CollectionTypeTests.test("index(of:)/ContinueSearch") {
+CollectionTypeTests.test("firstIndex(of:)/ContinueSearch") {
do {
let c = MinimalCollection(elements: [] as [MinimalEquatableValue])
expectEqualSequence(
diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index 4061f91..4c28044 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -274,13 +274,13 @@
do {
var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
+ MinimalHashableValue.timesHashIntoWasCalled = 0
expectNil(d2[MinimalHashableValue(42)])
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
@@ -330,14 +330,14 @@
do {
var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
MinimalHashableClass.timesEqualEqualWasCalled = 0
- MinimalHashableClass.timesHashValueWasCalled = 0
+ MinimalHashableClass.timesHashIntoWasCalled = 0
expectNil(d2[MinimalHashableClass(42)])
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
}
}
@@ -864,13 +864,13 @@
do {
var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
+ MinimalHashableValue.timesHashIntoWasCalled = 0
expectNil(d2.index(forKey: MinimalHashableValue(42)))
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
@@ -901,13 +901,13 @@
do {
var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
MinimalHashableClass.timesEqualEqualWasCalled = 0
- MinimalHashableClass.timesHashValueWasCalled = 0
+ MinimalHashableClass.timesHashIntoWasCalled = 0
expectNil(d2.index(forKey: MinimalHashableClass(42)))
// If the dictionary is empty, we shouldn't be computing the hash value of
// the provided key.
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
}
}
@@ -1398,9 +1398,9 @@
var lastKey: MinimalHashableValue = d2.first!.key
for i in d2.indices { lastKey = d2[i].key }
- // index(where:) - linear search
+ // firstIndex(where:) - linear search
MinimalHashableValue.timesEqualEqualWasCalled = 0
- let j = d2.index(where: { (k, _) in k == lastKey })!
+ let j = d2.firstIndex(where: { (k, _) in k == lastKey })!
expectGE(MinimalHashableValue.timesEqualEqualWasCalled, 8)
// index(forKey:) - O(1) bucket + linear search
@@ -1408,9 +1408,9 @@
let k = d2.index(forKey: lastKey)!
expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
- // keys.index(of:) - O(1) bucket + linear search
+ // keys.firstIndex(of:) - O(1) bucket + linear search
MinimalHashableValue.timesEqualEqualWasCalled = 0
- let l = d2.keys.index(of: lastKey)!
+ let l = d2.keys.firstIndex(of: lastKey)!
#if swift(>=4.0)
expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
#endif
@@ -1713,13 +1713,13 @@
uniqueKeysWithValues: d1.lazy.map { (MinimalHashableValue($0), $1) })
expectEqual(d3.count, 3)
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
+ MinimalHashableValue.timesHashIntoWasCalled = 0
// Calling mapValues shouldn't ever recalculate any hashes.
let d4 = d3.mapValues(String.init)
expectEqual(d4.count, d3.count)
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
@@ -4464,11 +4464,11 @@
expectOptionalEqual(4, d3["four"])
expectOptionalEqual(5, d3["five"])
- expectEqual(3, d.values[d.keys.index(of: "three")!])
- expectEqual(4, d.values[d.keys.index(of: "four")!])
+ expectEqual(3, d.values[d.keys.firstIndex(of: "three")!])
+ expectEqual(4, d.values[d.keys.firstIndex(of: "four")!])
- expectEqual(3, d3.values[d3.keys.index(of: "three")!])
- expectEqual(4, d3.values[d3.keys.index(of: "four")!])
+ expectEqual(3, d3.values[d3.keys.firstIndex(of: "three")!])
+ expectEqual(4, d3.values[d3.keys.firstIndex(of: "four")!])
}
}
diff --git a/validation-test/stdlib/ExistentialCollection.swift.gyb b/validation-test/stdlib/ExistentialCollection.swift.gyb
index 4e98beb..9bee9b1 100644
--- a/validation-test/stdlib/ExistentialCollection.swift.gyb
+++ b/validation-test/stdlib/ExistentialCollection.swift.gyb
@@ -358,7 +358,7 @@
let a1 = ContiguousArray(fc0)
expectEqual(a0, a1)
for e in a0 {
- let i = fc0.index(of: e)
+ let i = fc0.firstIndex(of: e)
expectNotNil(i)
expectEqual(e, fc0[i!])
}
@@ -386,7 +386,7 @@
let a1 = ContiguousArray(bc0.lazy.reversed())
expectEqual(a0, a1)
for e in a0 {
- let i = bc0.index(of: e)
+ let i = bc0.firstIndex(of: e)
expectNotNil(i)
expectEqual(e, bc0[i!])
}
@@ -421,7 +421,7 @@
let a1 = ContiguousArray(rc0.lazy.reversed())
expectEqual(a0, a1)
for e in a0 {
- let i = rc0.index(of: e)
+ let i = rc0.firstIndex(of: e)
expectNotNil(i)
expectEqual(e, rc0[i!])
}
diff --git a/validation-test/stdlib/ObjectiveC.swift b/validation-test/stdlib/ObjectiveC.swift
index 3e9a038..7dd5b98 100644
--- a/validation-test/stdlib/ObjectiveC.swift
+++ b/validation-test/stdlib/ObjectiveC.swift
@@ -10,6 +10,9 @@
var ObjectiveCTests = TestSuite("ObjectiveC")
class NSObjectWithCustomHashable : NSObject {
+ var _value: Int
+ var _hashValue: Int
+
init(value: Int, hashValue: Int) {
self._value = value
self._hashValue = hashValue
@@ -20,24 +23,22 @@
return self._value == other_._value
}
- override var hashValue: Int {
+ override var hash: Int {
return _hashValue
}
-
- var _value: Int
- var _hashValue: Int
}
ObjectiveCTests.test("NSObject/Hashable") {
- let instances: [(order: Int, object: NSObject)] = [
- (10, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
- (10, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
- (20, NSObjectWithCustomHashable(value: 20, hashValue: 100)),
- (30, NSObjectWithCustomHashable(value: 30, hashValue: 300)),
+ let instances: [(order: Int, hashOrder: Int, object: NSObject)] = [
+ (10, 1, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
+ (10, 1, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
+ (20, 1, NSObjectWithCustomHashable(value: 20, hashValue: 100)),
+ (30, 2, NSObjectWithCustomHashable(value: 30, hashValue: 300)),
]
checkHashable(
instances.map { $0.object },
- equalityOracle: { instances[$0].order == instances[$1].order })
+ equalityOracle: { instances[$0].order == instances[$1].order },
+ hashEqualityOracle: { instances[$0].hashOrder == instances[$1].hashOrder })
}
runAllTests()
diff --git a/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb b/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
index 89bb34c..9f9421a 100644
--- a/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
+++ b/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
@@ -100,6 +100,13 @@
import Swift
import SwiftShims
+// This prototype is only partially implemented, and it relies on specific hash
+// values. To keep it working, define an alternative hashing interface emulating
+// pre-SE-0206 Hashable.
+protocol LegacyHashable: Equatable {
+ var legacyHashValue: Int { get }
+}
+
//
// Standard library extras
//
@@ -252,7 +259,7 @@
var keyCount: Int
}
-struct _PVSparseVectorNodePointer<Key : Hashable, Value>
+struct _PVSparseVectorNodePointer<Key : LegacyHashable, Value>
: CustomReflectable {
typealias _Self = _PVSparseVectorNodePointer
@@ -917,7 +924,7 @@
}
}
-struct _PVArrayNodePointer<Key : Hashable, Value>
+struct _PVArrayNodePointer<Key : LegacyHashable, Value>
: CustomReflectable {
typealias _Self = _PVArrayNodePointer
@@ -1158,7 +1165,7 @@
var keyCount: Int
}
-struct _PVCollisionNodePointer<Key : Hashable, Value>
+struct _PVCollisionNodePointer<Key : LegacyHashable, Value>
: CustomReflectable {
typealias _Self = _PVCollisionNodePointer
@@ -1461,7 +1468,7 @@
}
}
-struct _PVAnyNodePointer<Key : Hashable, Value>
+struct _PVAnyNodePointer<Key : LegacyHashable, Value>
: CustomReflectable, Equatable {
let taggedPointer: UnsafeMutableRawPointer
@@ -1654,7 +1661,8 @@
return lhs.taggedPointer == rhs.taggedPointer
}
-final internal class _NativePVDictionaryStorageRef<Key : Hashable, Value> {
+final internal
+class _NativePVDictionaryStorageRef<Key : LegacyHashable, Value> {
var _rootNode: _PVAnyNodePointer<Key, Value>?
var _count: Int
@@ -1675,7 +1683,7 @@
}
}
-struct _NativePVDictionaryStorage<Key : Hashable, Value> {
+struct _NativePVDictionaryStorage<Key : LegacyHashable, Value> {
var _storageRef: _NativePVDictionaryStorageRef<Key, Value>
var _rootNode: _PVAnyNodePointer<Key, Value>? {
@@ -1715,13 +1723,13 @@
func assertingGet(key: Key) -> Value {
let valuePointer = _rootNode!.unsafeMaybeGet(
- key: key, hashValue: key.hashValue, depth: 0)
+ key: key, hashValue: key.legacyHashValue, depth: 0)
return valuePointer!.pointee
}
func maybeGet(key: Key) -> Value? {
let valuePointer = _rootNode?.unsafeMaybeGet(
- key: key, hashValue: key.hashValue, depth: 0)
+ key: key, hashValue: key.legacyHashValue, depth: 0)
return valuePointer.map { $0.pointee }
}
@@ -1748,7 +1756,7 @@
}
mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
- let hashValue = key.hashValue
+ let hashValue = key.legacyHashValue
guard let oldRootNode = _rootNode else {
let layout = _PVSparseVectorNodeLayoutParameters(
childNodeCount: 0,
@@ -1787,7 +1795,7 @@
guard let oldRootNode = _rootNode else {
return nil
}
- let hashValue = key.hashValue
+ let hashValue = key.legacyHashValue
let isUnique = isKnownUniquelyReferenced(&_storageRef)
let (oldValue, newRootNode) = oldRootNode.removeValue(
forKey: key,
@@ -1858,6 +1866,12 @@
expectEqualSequence([ 0, 4, 5, 7, 31 ], Array(bm.setBitIndices))
}
+extension MinimalHashableValue: LegacyHashable {
+ var legacyHashValue: Int {
+ return self.value % 10000
+ }
+}
+
var PersistentVectorTests = TestSuite("PersistentVector")
PersistentVectorTests.test("sizeof") {
@@ -1993,10 +2007,6 @@
print("---------------------------------------")
}
- MinimalHashableValue.hashValueImpl.value = {
- return $0 % 10000
- }
-
typealias MyDictionary = _NativePVDictionaryStorage<
MinimalHashableValue, OpaqueValue<Int>
>
diff --git a/validation-test/stdlib/SequenceType.swift.gyb b/validation-test/stdlib/SequenceType.swift.gyb
index 9f8f19e..5af4e46 100644
--- a/validation-test/stdlib/SequenceType.swift.gyb
+++ b/validation-test/stdlib/SequenceType.swift.gyb
@@ -573,7 +573,7 @@
let s = Set<MinimalHashableValue>(
test.sequence.map { MinimalHashableValue($0.value) })
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
+ MinimalHashableValue.timesHashIntoWasCalled = 0
expectEqual(
test.expected != nil,
call${dispatch}Contains(s, MinimalHashableValue(test.element.value)),
@@ -583,11 +583,11 @@
0, MinimalHashableValue.timesEqualEqualWasCalled,
stackTrace: SourceLocStack().with(test.loc))
expectEqual(
- 0, MinimalHashableValue.timesHashValueWasCalled,
+ 0, MinimalHashableValue.timesHashIntoWasCalled,
stackTrace: SourceLocStack().with(test.loc))
} else {
expectNotEqual(
- 0, MinimalHashableValue.timesHashValueWasCalled,
+ 0, MinimalHashableValue.timesHashIntoWasCalled,
stackTrace: SourceLocStack().with(test.loc))
}
if test.expected != nil {
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index 93c1a56..1d3fa36 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -442,13 +442,13 @@
do {
var s2: Set<MinimalHashableValue> = []
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
+ MinimalHashableValue.timesHashIntoWasCalled = 0
expectFalse(s2.contains(MinimalHashableValue(42)))
// If the set is empty, we shouldn't be computing the hash value of the
// provided key.
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
@@ -488,13 +488,13 @@
do {
var s2: Set<MinimalHashableClass> = []
MinimalHashableClass.timesEqualEqualWasCalled = 0
- MinimalHashableClass.timesHashValueWasCalled = 0
+ MinimalHashableClass.timesHashIntoWasCalled = 0
expectFalse(s2.contains(MinimalHashableClass(42)))
// If the set is empty, we shouldn't be computing the hash value of the
// provided key.
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
}
}
@@ -599,10 +599,10 @@
// Find an existing key.
do {
- var foundIndex1 = s.index(of: 1010)!
+ var foundIndex1 = s.firstIndex(of: 1010)!
expectEqual(identity1, s._rawIdentifier())
- var foundIndex2 = s.index(of: 1010)!
+ var foundIndex2 = s.firstIndex(of: 1010)!
expectEqual(foundIndex1, foundIndex2)
expectEqual(1010, s[foundIndex1])
@@ -611,7 +611,7 @@
// Try to find a key that is not present.
do {
- var foundIndex1 = s.index(of: 1111)
+ var foundIndex1 = s.firstIndex(of: 1111)
expectNil(foundIndex1)
expectEqual(identity1, s._rawIdentifier())
}
@@ -619,13 +619,13 @@
do {
var s2: Set<MinimalHashableValue> = []
MinimalHashableValue.timesEqualEqualWasCalled = 0
- MinimalHashableValue.timesHashValueWasCalled = 0
- expectNil(s2.index(of: MinimalHashableValue(42)))
+ MinimalHashableValue.timesHashIntoWasCalled = 0
+ expectNil(s2.firstIndex(of: MinimalHashableValue(42)))
// If the set is empty, we shouldn't be computing the hash value of the
// provided key.
expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
}
}
@@ -635,10 +635,10 @@
// Find an existing key.
do {
- var foundIndex1 = s.index(of: TestKeyTy(1010))!
+ var foundIndex1 = s.firstIndex(of: TestKeyTy(1010))!
expectEqual(identity1, s._rawIdentifier())
- var foundIndex2 = s.index(of: TestKeyTy(1010))!
+ var foundIndex2 = s.firstIndex(of: TestKeyTy(1010))!
expectEqual(foundIndex1, foundIndex2)
expectEqual(TestKeyTy(1010), s[foundIndex1])
@@ -647,7 +647,7 @@
// Try to find a key that is not present.
do {
- var foundIndex1 = s.index(of: TestKeyTy(1111))
+ var foundIndex1 = s.firstIndex(of: TestKeyTy(1111))
expectNil(foundIndex1)
expectEqual(identity1, s._rawIdentifier())
}
@@ -655,13 +655,13 @@
do {
var s2: Set<MinimalHashableClass> = []
MinimalHashableClass.timesEqualEqualWasCalled = 0
- MinimalHashableClass.timesHashValueWasCalled = 0
- expectNil(s2.index(of: MinimalHashableClass(42)))
+ MinimalHashableClass.timesHashIntoWasCalled = 0
+ expectNil(s2.firstIndex(of: MinimalHashableClass(42)))
// If the set is empty, we shouldn't be computing the hash value of the
// provided key.
expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
- expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+ expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
}
}
@@ -671,7 +671,7 @@
var s = getCOWFastSet()
var identity1 = s._rawIdentifier()
- let foundIndex1 = s.index(of: 1010)!
+ let foundIndex1 = s.firstIndex(of: 1010)!
expectEqual(identity1, s._rawIdentifier())
expectEqual(1010, s[foundIndex1])
@@ -680,7 +680,7 @@
expectEqual(1010, removed)
expectEqual(identity1, s._rawIdentifier())
- expectNil(s.index(of: 1010))
+ expectNil(s.firstIndex(of: 1010))
}
do {
@@ -691,7 +691,7 @@
expectEqual(identity1, s1._rawIdentifier())
expectEqual(identity1, s2._rawIdentifier())
- var foundIndex1 = s2.index(of: 1010)!
+ var foundIndex1 = s2.firstIndex(of: 1010)!
expectEqual(1010, s2[foundIndex1])
expectEqual(identity1, s1._rawIdentifier())
expectEqual(identity1, s2._rawIdentifier())
@@ -701,7 +701,7 @@
expectEqual(identity1, s1._rawIdentifier())
expectNotEqual(identity1, s2._rawIdentifier())
- expectNil(s2.index(of: 1010))
+ expectNil(s2.firstIndex(of: 1010))
}
}
@@ -711,7 +711,7 @@
var s = getCOWSlowSet()
var identity1 = s._rawIdentifier()
- let foundIndex1 = s.index(of: TestKeyTy(1010))!
+ let foundIndex1 = s.firstIndex(of: TestKeyTy(1010))!
expectEqual(identity1, s._rawIdentifier())
expectEqual(TestKeyTy(1010), s[foundIndex1])
@@ -720,7 +720,7 @@
expectEqual(TestKeyTy(1010), removed)
expectEqual(identity1, s._rawIdentifier())
- expectNil(s.index(of: TestKeyTy(1010)))
+ expectNil(s.firstIndex(of: TestKeyTy(1010)))
}
do {
@@ -731,7 +731,7 @@
expectEqual(identity1, s1._rawIdentifier())
expectEqual(identity1, s2._rawIdentifier())
- var foundIndex1 = s2.index(of: TestKeyTy(1010))!
+ var foundIndex1 = s2.firstIndex(of: TestKeyTy(1010))!
expectEqual(TestKeyTy(1010), s2[foundIndex1])
expectEqual(identity1, s1._rawIdentifier())
expectEqual(identity1, s2._rawIdentifier())
@@ -741,7 +741,7 @@
expectEqual(identity1, s1._rawIdentifier())
expectNotEqual(identity1, s2._rawIdentifier())
- expectNil(s2.index(of: TestKeyTy(1010)))
+ expectNil(s2.firstIndex(of: TestKeyTy(1010)))
}
}
@@ -1354,17 +1354,17 @@
expectTrue(isCocoaSet(s))
// Find an existing key.
- var member = s[s.index(of: TestObjCKeyTy(1010))!]
+ var member = s[s.firstIndex(of: TestObjCKeyTy(1010))!]
expectEqual(TestObjCKeyTy(1010), member)
- member = s[s.index(of: TestObjCKeyTy(2020))!]
+ member = s[s.firstIndex(of: TestObjCKeyTy(2020))!]
expectEqual(TestObjCKeyTy(2020), member)
- member = s[s.index(of: TestObjCKeyTy(3030))!]
+ member = s[s.firstIndex(of: TestObjCKeyTy(3030))!]
expectEqual(TestObjCKeyTy(3030), member)
// Try to find a key that does not exist.
- expectNil(s.index(of: TestObjCKeyTy(4040)))
+ expectNil(s.firstIndex(of: TestObjCKeyTy(4040)))
expectEqual(identity1, s._rawIdentifier())
}
@@ -1373,17 +1373,17 @@
var identity1 = s._rawIdentifier()
do {
- var member = s[s.index(of: TestBridgedKeyTy(1010))!]
+ var member = s[s.firstIndex(of: TestBridgedKeyTy(1010))!]
expectEqual(TestBridgedKeyTy(1010), member)
- member = s[s.index(of: TestBridgedKeyTy(2020))!]
+ member = s[s.firstIndex(of: TestBridgedKeyTy(2020))!]
expectEqual(TestBridgedKeyTy(2020), member)
- member = s[s.index(of: TestBridgedKeyTy(3030))!]
+ member = s[s.firstIndex(of: TestBridgedKeyTy(3030))!]
expectEqual(TestBridgedKeyTy(3030), member)
}
- expectNil(s.index(of: TestBridgedKeyTy(4040)))
+ expectNil(s.firstIndex(of: TestBridgedKeyTy(4040)))
expectEqual(identity1, s._rawIdentifier())
}
@@ -1649,7 +1649,7 @@
let identity1 = s._rawIdentifier()
expectTrue(isCocoaSet(s))
- let foundIndex1 = s.index(of: TestObjCKeyTy(1010))!
+ let foundIndex1 = s.firstIndex(of: TestObjCKeyTy(1010))!
expectEqual(TestObjCKeyTy(1010), s[foundIndex1])
expectEqual(identity1, s._rawIdentifier())
@@ -1658,7 +1658,7 @@
expectTrue(isNativeSet(s))
expectEqual(2, s.count)
expectEqual(TestObjCKeyTy(1010), removedElement)
- expectNil(s.index(of: TestObjCKeyTy(1010)))
+ expectNil(s.firstIndex(of: TestObjCKeyTy(1010)))
}
SetTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAt")
@@ -1667,7 +1667,7 @@
let identity1 = s._rawIdentifier()
expectTrue(isNativeSet(s))
- let foundIndex1 = s.index(of: TestBridgedKeyTy(1010))!
+ let foundIndex1 = s.firstIndex(of: TestBridgedKeyTy(1010))!
expectEqual(1010, s[foundIndex1].value)
expectEqual(identity1, s._rawIdentifier())
@@ -1676,7 +1676,7 @@
expectTrue(isNativeSet(s))
expectEqual(1010, removedElement.value)
expectEqual(2, s.count)
- expectNil(s.index(of: TestBridgedKeyTy(1010)))
+ expectNil(s.firstIndex(of: TestBridgedKeyTy(1010)))
}
SetTestSuite.test("BridgedFromObjC.Verbatim.Remove") {
@@ -3171,7 +3171,7 @@
SetTestSuite.test("memberAtIndex") {
let s1 = Set([1010, 2020, 3030])
- let foundIndex = s1.index(of: 1010)!
+ let foundIndex = s1.firstIndex(of: 1010)!
expectEqual(1010, s1[foundIndex])
}
@@ -3345,12 +3345,12 @@
expectFalse(Set<Int>()._customContainsEquatableElement(1010)!)
}
-SetTestSuite.test("index(of:)") {
+SetTestSuite.test("firstIndex(of:)") {
let s1 = Set([1010, 2020, 3030, 4040, 5050, 6060])
- let foundIndex1 = s1.index(of: 1010)!
+ let foundIndex1 = s1.firstIndex(of: 1010)!
expectEqual(1010, s1[foundIndex1])
- expectNil(s1.index(of: 999))
+ expectNil(s1.firstIndex(of: 999))
}
SetTestSuite.test("popFirst") {
@@ -3381,10 +3381,10 @@
// Test removing from the startIndex, the middle, and the end of a set.
for i in 1...3 {
var s = Set<Int>([1010, 2020, 3030])
- let removed = s.remove(at: s.index(of: i*1010)!)
+ let removed = s.remove(at: s.firstIndex(of: i*1010)!)
expectEqual(i*1010, removed)
expectEqual(2, s.count)
- expectNil(s.index(of: i*1010))
+ expectNil(s.firstIndex(of: i*1010))
let origKeys: [Int] = [1010, 2020, 3030]
expectEqual(origKeys.filter { $0 != (i*1010) }, [Int](s).sorted())
}
diff --git a/validation-test/stdlib/SetAnyHashableExtensions.swift b/validation-test/stdlib/SetAnyHashableExtensions.swift
index 3b53df3..3ab8cea 100644
--- a/validation-test/stdlib/SetAnyHashableExtensions.swift
+++ b/validation-test/stdlib/SetAnyHashableExtensions.swift
@@ -43,13 +43,13 @@
let s: Set<AnyHashable> = [
AnyHashable(1010), AnyHashable(2020), AnyHashable(3030.0)
]
- expectEqual(AnyHashable(1010), s[s.index(of: 1010)!])
- expectEqual(AnyHashable(2020), s[s.index(of: 2020)!])
- expectEqual(AnyHashable(3030.0), s[s.index(of: 3030.0)!])
+ expectEqual(AnyHashable(1010), s[s.firstIndex(of: 1010)!])
+ expectEqual(AnyHashable(2020), s[s.firstIndex(of: 2020)!])
+ expectEqual(AnyHashable(3030.0), s[s.firstIndex(of: 3030.0)!])
- expectNil(s.index(of: 1010.0))
- expectNil(s.index(of: 2020.0))
- expectNil(s.index(of: 3030))
+ expectNil(s.firstIndex(of: 1010.0))
+ expectNil(s.firstIndex(of: 2020.0))
+ expectNil(s.firstIndex(of: 3030))
}
SetTests.test("insert<Hashable>(_:)") {